diff --git a/.gitignore b/.gitignore index a2a1041..4d42b15 100644 --- a/.gitignore +++ b/.gitignore @@ -43,6 +43,9 @@ build/Release node_modules/ jspm_packages/ +# Builds +build/ + # Snowpack dependency directory (https://snowpack.dev/) web_modules/ diff --git a/default.code-workspace b/default.code-workspace new file mode 100644 index 0000000..b6dbc59 --- /dev/null +++ b/default.code-workspace @@ -0,0 +1,21 @@ +{ + "folders": [ + { + "name": "RayLab Root", + "path": "./" + }, + { + "name": "Virtual Renderer", + "path": "./packages/renderer-virtual" + }, + { + "name": "WebGL Renderer", + "path": "./packages/renderer-webgl" + }, + { + "name": "WebGL Debugger", + "path": "./packages/renderer-debugger" + } + ], + "settings": {} +} \ No newline at end of file diff --git a/engine/RayLab.ts b/engine/RayLab.ts new file mode 100644 index 0000000..8a0d927 --- /dev/null +++ b/engine/RayLab.ts @@ -0,0 +1,2 @@ +export { Vector2D, Vector3D, Vector4D } from "@engine/math" +export { TreeNode } from "@engine/kernel" \ No newline at end of file diff --git a/engine/kernel/Kernel.ts b/engine/kernel/Kernel.ts new file mode 100644 index 0000000..d854556 --- /dev/null +++ b/engine/kernel/Kernel.ts @@ -0,0 +1 @@ +export { TreeNode } from "./TreeNode"; \ No newline at end of file diff --git a/engine/kernel/TreeNode.ts b/engine/kernel/TreeNode.ts new file mode 100644 index 0000000..9b95ec6 --- /dev/null +++ b/engine/kernel/TreeNode.ts @@ -0,0 +1,234 @@ + +/** + * A tree type data structure used to build scene and ... + * @copyright MrKBear 2022 + * @typeParam T - Child type of `TreeNode` + */ +class TreeNode> implements Iterable { + + /** + * Record all child nodes when this node is the root node. + * @remarks + * Only maintained when the node is the root node. \ + * The array is arranged in depth first traversal order. + */ + private _progenyNodes: Array | undefined = [ ]; + + /** + * Whether the structure of the current tree has changed. + * @remarks + * Only maintained when the node is the root node. + */ + private _isStructUpdated = false; + + /** + * @remarks + * When a node is just created, it defaults the root node. \ + * So this `rootNode` points to itself. + */ + private _rootNode: T | this = this; + + private _parentNode: T | undefined = void 0; + + private _childNodes: Array = []; + + /** + * Pointer to the root node. + */ + public get rootNode(): T | this { return this._rootNode; } + + /** + * Pointer to the parent node. + */ + public get parentNode(): T | undefined { return this._parentNode; } + + /** + * Points to the children of the current node. + */ + public get childNodes(): ReadonlyArray { return this._childNodes; } + + /** + * Is this a root node? + */ + public get isRootNode(): boolean { return !this._parentNode && this._rootNode === this; } + + /** + * Depth first traverses the current `TreeNode` and its children `TreeNode`. + * @remarks + * This will use {@link https://en.wikipedia.org/wiki/Tree_traversal#Pre-order,_NLR Pre-order (NLR) algorithm}. \ + * So... Do not call this getter frequently. + * @example + * ``` javascript + * // ❌ Deprecated implementation !!! + * for (let i = 0; i < treeNode.progenyNodes.length; i++) { + * doSomeThing(treeNode.progenyNodes[i]); + * } + * + * // ✔️ Best Practices + * treeNode.progenyNodes.forEach((progenyNode)=> { + * doSomeThing(progenyNode); + * }); + * + * // ✔️ Best Practices + * for(const progenyNode of treeNode.progenyNodes) { + * doSomeThing(progenyNode); + * } + * ``` + * @return Progeny nodes list. + */ + public get progenyNodes(): ReadonlyArray { + + if (this.isRootNode && !this._isStructUpdated && this._progenyNodes) { + return this._progenyNodes; + } + + else { + const cacheArray: Array = []; + const stack: Array = this._childNodes.slice().reverse(); + + while (stack.length > 0) { + const currentNode: T | undefined = stack.pop(); + + if (currentNode) { + cacheArray.push(currentNode); + + // Push all child nodes in reverse order + for (let i = currentNode.childNodes.length - 1; i >= 0; i --) { + stack.push(currentNode.childNodes[i]); + } + } + } + + if (this.isRootNode) { + this._progenyNodes = cacheArray; + this._isStructUpdated = false; + } + + return cacheArray; + } + } + + /** + * An iterator implementation for {@link TreeNode.progenyNodes} + * @see {@link TreeNode.progenyNodes} + */ + public *[Symbol.iterator](): Iterator { yield * this.progenyNodes; } + + /** + * Remove `nodes` from child nodes. + * @param nodes - Nodes to be deleted. + * @returns Success Times. + */ + public removeChild(...nodes: ReadonlyArray): number { + + let successCount = 0; + for (const node of nodes) { + + let removeNodesIndex = -1; + for (let i = 0; i < this._childNodes.length; i++) { + + if (this._childNodes[i] === node) { + removeNodesIndex = i; + } + } + + if (removeNodesIndex < 0) { + continue; + } + + // Perform the remove operation + this._childNodes.splice(removeNodesIndex, 1); + + node._parentNode = void 0; + node._rootNode = node; + node.markStructUpdated(); + + for (const progeny of node.progenyNodes) { + progeny._rootNode = node; + } + + successCount ++; + } + + if (successCount) { + this._rootNode.markStructUpdated(); + } + + return successCount; + } + + /** + * Remove this node from the parent node + * @returns Success or not. + */ + public removeFromParent(): number { + + if (this.isRootNode) { + return 0; + } + + else { + return this._parentNode!.removeChild(this); + } + } + + /** + * Append `nodes` into child nodes. + * @param node - Nodes to be added. + * @returns Success Times. + */ + public appendChild(...nodes: ReadonlyArray): number { + + let successCount = 0; + for (const node of nodes) { + + if (!node.isRootNode) { + node.removeFromParent(); + } + + for (const progeny of node.progenyNodes) { + progeny._rootNode = this._rootNode; + } + + node._rootNode = this._rootNode; + node._parentNode = this; + node._progenyNodes = void 0; + + this._childNodes.push(node); + + successCount ++; + } + + if (successCount) { + this._rootNode.markStructUpdated(); + } + + return successCount; + } + + /** + * Mark that the current tree structure has been updated + * @returns true + */ + public markStructUpdated(): boolean { + if (this.isRootNode) { + return this._isStructUpdated = true; + } + else { + return this.rootNode.markStructUpdated(); + } + } +} + +class B extends TreeNode { b(){}; } +class A extends TreeNode { a(){}; } +class C extends A { c(){}; } +const a = new A(); +const b = new B(); +const c = new C(); +a.rootNode.rootNode.appendChild(c); +// a.rootNode.rootNode.appendChild(a); + +console.log(a); + +export { TreeNode }; \ No newline at end of file diff --git a/engine/math/Math.ts b/engine/math/Math.ts new file mode 100644 index 0000000..5a7b16e --- /dev/null +++ b/engine/math/Math.ts @@ -0,0 +1,3 @@ +export { Vector2D } from "./Vector2D"; +export { Vector3D } from "./Vector3D"; +export { Vector4D } from "./Vector4D"; \ No newline at end of file diff --git a/engine/math/UpdatedRecorder.ts b/engine/math/UpdatedRecorder.ts new file mode 100644 index 0000000..14d4741 --- /dev/null +++ b/engine/math/UpdatedRecorder.ts @@ -0,0 +1,54 @@ + +/** + * Type of update status can be recorded + * An update flag is used here to implement data lazy calculation + * @copyright MrKBear 2022 + */ +abstract class UpdatedRecorder { + + /** + * The flag for recorded update status + * @defaultValue `true` + */ + protected updateFlag: boolean = true; + + /** + * Initialize and set the default update status + * @param updateFlag update status + */ + public constructor(updateFlag: boolean = true) { + this.updateFlag = updateFlag; + } + + /** + * Return the update status + * @returns update status + */ + public isUpdated(): boolean { + return this.updateFlag; + } + + /** + * Set update status `false` + * @returns update status + */ + public unsetUpdated(): false { + return this.updateFlag = false; + } + + /** + * Automatically detect and reset update status + * @returns update status + */ + public testAndUnsetUpdate(): boolean { + if (this.updateFlag) { + this.updateFlag = false; + return true; + } + else { + return false; + } + } +} + +export { UpdatedRecorder }; \ No newline at end of file diff --git a/engine/math/Vector2D.ts b/engine/math/Vector2D.ts new file mode 100644 index 0000000..d2daba5 --- /dev/null +++ b/engine/math/Vector2D.ts @@ -0,0 +1,83 @@ +import { UpdatedRecorder } from "./UpdatedRecorder"; + +/** + * A vector with two dimensions + */ +class Vector2D extends UpdatedRecorder implements ArrayLike, Iterable { + + private value0: number = 0; + private value1: number = 0; + + readonly [n: number]: number; + + /** + * Vector length + */ + public get length(): number { + return 2; + }; + + public override toString(): string { + return `Vector2D(${this.value0},${this.value1})`; + } + + /** + * Enumerate this vector + */ + public *[Symbol.iterator](): Iterator { + yield this.value0; + yield this.value1; + } + + /** + * The first component of this vector + */ + public get [0](): number { + return this.value0; + } + + public set [0](newValue: number) { + if (!this.updateFlag && this.value0 !== newValue) { + this.updateFlag = true; + } + this.value0 = newValue; + } + + /** + * The second component of this vector + */ + public get [1](): number { + return this.value1; + } + + public set [1](newValue: number) { + if (!this.updateFlag && this.value1 !== newValue) { + this.updateFlag = true; + } + this.value1 = newValue; + } + + /** + * X component of the vector + */ + public get x(): number { + return this.value0; + } + + public set x(newValue: number) { + this[0] = newValue; + } + + /** + * Y component of the vector + */ + public get y(): number { + return this.value1; + } + + public set y(newValue: number) { + this[1] = newValue; + } +} + +export { Vector2D }; \ No newline at end of file diff --git a/engine/math/Vector3D.ts b/engine/math/Vector3D.ts new file mode 100644 index 0000000..e8c90e2 --- /dev/null +++ b/engine/math/Vector3D.ts @@ -0,0 +1,110 @@ +import { UpdatedRecorder } from "./UpdatedRecorder"; + +/** + * A vector with three dimensions + */ +class Vector3D extends UpdatedRecorder implements ArrayLike, Iterable { + + private value0: number = 0; + private value1: number = 0; + private value2: number = 0; + + readonly [n: number]: number; + + /** + * Vector length + */ + public get length(): number { + return 3; + }; + + public override toString(): string { + return `Vector3D(${this.value0},${this.value1},${this.value2})`; + } + + /** + * Enumerate this vector + */ + public *[Symbol.iterator](): Iterator { + yield this.value0; + yield this.value1; + yield this.value2; + } + + /** + * The first component of this vector + */ + public get [0](): number { + return this.value0; + } + + public set [0](newValue: number) { + if (!this.updateFlag && this.value0 !== newValue) { + this.updateFlag = true; + } + this.value0 = newValue; + } + + /** + * The second component of this vector + */ + public get [1](): number { + return this.value1; + } + + public set [1](newValue: number) { + if (!this.updateFlag && this.value1 !== newValue) { + this.updateFlag = true; + } + this.value1 = newValue; + } + + /** + * The third component of this vector + */ + public get [2](): number { + return this.value2; + } + + public set [2](newValue: number) { + if (!this.updateFlag && this.value2 !== newValue) { + this.updateFlag = true; + } + this.value2 = newValue; + } + + /** + * X component of the vector + */ + public get x(): number { + return this.value0; + } + + public set x(newValue: number) { + this[0] = newValue; + } + + /** + * Y component of the vector + */ + public get y(): number { + return this.value1; + } + + public set y(newValue: number) { + this[1] = newValue; + } + + /** + * Z component of the vector + */ + public get z(): number { + return this.value2; + } + + public set z(newValue: number) { + this[2] = newValue; + } +} + +export { Vector3D }; \ No newline at end of file diff --git a/engine/math/Vector4D.ts b/engine/math/Vector4D.ts new file mode 100644 index 0000000..305432e --- /dev/null +++ b/engine/math/Vector4D.ts @@ -0,0 +1,137 @@ +import { UpdatedRecorder } from "./UpdatedRecorder"; + +/** + * A vector with four dimensions + */ +class Vector4D extends UpdatedRecorder implements ArrayLike, Iterable { + + private value0: number = 0; + private value1: number = 0; + private value2: number = 0; + private value3: number = 0; + + readonly [n: number]: number; + + /** + * Vector length + */ + public get length(): number { + return 4; + }; + + public override toString(): string { + return `Vector4D(${this.value0},${this.value1},${this.value2},${this.value3})`; + } + + /** + * Enumerate this vector + */ + public *[Symbol.iterator](): Iterator { + yield this.value0; + yield this.value1; + yield this.value2; + yield this.value3; + } + + /** + * The first component of this vector + */ + public get [0](): number { + return this.value0; + } + + public set [0](newValue: number) { + if (!this.updateFlag && this.value0 !== newValue) { + this.updateFlag = true; + } + this.value0 = newValue; + } + + /** + * The second component of this vector + */ + public get [1](): number { + return this.value1; + } + + public set [1](newValue: number) { + if (!this.updateFlag && this.value1 !== newValue) { + this.updateFlag = true; + } + this.value1 = newValue; + } + + /** + * The third component of this vector + */ + public get [2](): number { + return this.value2; + } + + public set [2](newValue: number) { + if (!this.updateFlag && this.value2 !== newValue) { + this.updateFlag = true; + } + this.value2 = newValue; + } + + /** + * The fourth component of this vector + */ + public get [3](): number { + return this.value3; + } + + public set [3](newValue: number) { + if (!this.updateFlag && this.value3 !== newValue) { + this.updateFlag = true; + } + this.value3 = newValue; + } + + /** + * X component of the vector + */ + public get x(): number { + return this.value0; + } + + public set x(newValue: number) { + this[0] = newValue; + } + + /** + * Y component of the vector + */ + public get y(): number { + return this.value1; + } + + public set y(newValue: number) { + this[1] = newValue; + } + + /** + * Z component of the vector + */ + public get z(): number { + return this.value2; + } + + public set z(newValue: number) { + this[2] = newValue; + } + + /** + * W component of the vector + */ + public get w(): number { + return this.value3; + } + + public set w(newValue: number) { + this[3] = newValue; + } +} + +export { Vector4D }; \ No newline at end of file diff --git a/engine/virtual-renderer/VirtualRenderer.ts b/engine/virtual-renderer/VirtualRenderer.ts new file mode 100644 index 0000000..c4a5c62 --- /dev/null +++ b/engine/virtual-renderer/VirtualRenderer.ts @@ -0,0 +1,7 @@ +export * from "./command/Command"; +export * from "./command/CommandSet"; +export * from "./command/CommandType"; +export * from "./command/RenderCommand"; +export * from "./command/ClearCommand"; +export * from "./resource/Resource"; +export * from "./resource/ResourceType"; \ No newline at end of file diff --git a/engine/virtual-renderer/command/ClearCommand.ts b/engine/virtual-renderer/command/ClearCommand.ts new file mode 100644 index 0000000..785d63c --- /dev/null +++ b/engine/virtual-renderer/command/ClearCommand.ts @@ -0,0 +1,9 @@ +import type { Command } from "./Command"; +import type { CommandType } from "./CommandType"; + +interface ClearCommand extends Command { + + type: CommandType.Clear +} + +export type { ClearCommand }; \ No newline at end of file diff --git a/engine/virtual-renderer/command/Command.ts b/engine/virtual-renderer/command/Command.ts new file mode 100644 index 0000000..64aae9d --- /dev/null +++ b/engine/virtual-renderer/command/Command.ts @@ -0,0 +1,16 @@ +import type { CommandTypeSet } from "./CommandType"; + +interface Command { + + /** + * Define the type of command. + */ + type: CommandTypeSet; + + /** + * Unique identification of the command for feedback. + */ + id?: string | number; +} + +export type { Command }; \ No newline at end of file diff --git a/engine/virtual-renderer/command/CommandSet.ts b/engine/virtual-renderer/command/CommandSet.ts new file mode 100644 index 0000000..1a4a882 --- /dev/null +++ b/engine/virtual-renderer/command/CommandSet.ts @@ -0,0 +1,6 @@ +import type { RenderCommand } from "./RenderCommand"; +import type { ClearCommand } from "./ClearCommand"; + +type CommandSet = RenderCommand | ClearCommand; + +export type { CommandSet }; \ No newline at end of file diff --git a/engine/virtual-renderer/command/CommandType.ts b/engine/virtual-renderer/command/CommandType.ts new file mode 100644 index 0000000..5fede24 --- /dev/null +++ b/engine/virtual-renderer/command/CommandType.ts @@ -0,0 +1,15 @@ + +namespace CommandType { + + export type Render = "RENDER" | 100_001; + + export type Resource = "RESOURCE" | 100_002; + + export type Clear = "CLEAR" | 100_003; + + export type Execute = "EXECUTE" | 100_004; +} + +type CommandTypeSet = CommandType.Render | CommandType.Resource | CommandType.Clear | CommandType.Execute; + +export type { CommandType, CommandTypeSet }; \ No newline at end of file diff --git a/engine/virtual-renderer/command/RenderCommand.ts b/engine/virtual-renderer/command/RenderCommand.ts new file mode 100644 index 0000000..b04bf7a --- /dev/null +++ b/engine/virtual-renderer/command/RenderCommand.ts @@ -0,0 +1,12 @@ +import type { Command } from "./Command"; +import type { CommandType } from "./CommandType"; + +/** + * Rendering command are used to execute gl programs. + */ +interface RenderCommand extends Command { + + type: CommandType.Render +} + +export type { RenderCommand }; \ No newline at end of file diff --git a/engine/virtual-renderer/renderer/Renderer.ts b/engine/virtual-renderer/renderer/Renderer.ts new file mode 100644 index 0000000..01049f5 --- /dev/null +++ b/engine/virtual-renderer/renderer/Renderer.ts @@ -0,0 +1,8 @@ +import type { CommandSet } from "../command/CommandSet" + +interface Renderer { + + executeCommand: (commands: CommandSet[] | CommandSet) => void; +} + +export type { Renderer }; \ No newline at end of file diff --git a/engine/virtual-renderer/resource/Resource.ts b/engine/virtual-renderer/resource/Resource.ts new file mode 100644 index 0000000..dae32df --- /dev/null +++ b/engine/virtual-renderer/resource/Resource.ts @@ -0,0 +1,10 @@ +import type { ResourceSet } from "./ResourceType"; + +interface Resource { + + type: ResourceSet; + + id: string | number; +} + +export type { Resource }; \ No newline at end of file diff --git a/engine/virtual-renderer/resource/ResourceType.ts b/engine/virtual-renderer/resource/ResourceType.ts new file mode 100644 index 0000000..542c8e9 --- /dev/null +++ b/engine/virtual-renderer/resource/ResourceType.ts @@ -0,0 +1,9 @@ + +namespace ResourceType { + + export type Shader = "SHADER" | 100_001; +} + +type ResourceSet = ResourceType.Shader; + +export type { ResourceType, ResourceSet }; \ No newline at end of file diff --git a/engine/virtual-renderer/resource/Shader.ts b/engine/virtual-renderer/resource/Shader.ts new file mode 100644 index 0000000..e69de29 diff --git a/engine/webgl-renderer/webglRenderer.ts b/engine/webgl-renderer/webglRenderer.ts new file mode 100644 index 0000000..cb3177b --- /dev/null +++ b/engine/webgl-renderer/webglRenderer.ts @@ -0,0 +1,2 @@ +import type * as VRenderer from "virtual-renderer"; + diff --git a/package.json b/package.json new file mode 100644 index 0000000..7d03f3a --- /dev/null +++ b/package.json @@ -0,0 +1,16 @@ +{ + "private": "true", + "name": "ray-lab", + "version": "1.0.0", + "description": "WebGL rendering engine based on native TypeScript.", + "scripts": { + "hmr-engine": "webpack serve --config ./webpack/Config.js --mode development --env entry=freeTest" + }, + "keywords": [ + "ray", + "ray-lab", + "3d", + "gl" + ], + "author": "MrKBear" +} \ No newline at end of file diff --git a/packages/renderer-debugger/index.html b/packages/renderer-debugger/index.html new file mode 100644 index 0000000..0d0b8d6 --- /dev/null +++ b/packages/renderer-debugger/index.html @@ -0,0 +1,13 @@ + + + + + + + Ray Lay Renderer Debugger + + +
+ + + \ No newline at end of file diff --git a/packages/renderer-debugger/package.json b/packages/renderer-debugger/package.json new file mode 100644 index 0000000..e2aeab1 --- /dev/null +++ b/packages/renderer-debugger/package.json @@ -0,0 +1,25 @@ +{ + "private": "true", + "name": "@ray-lab/renderer-debugger", + "version": "1.0.0", + "description": "", + "scripts": { + "dev": "vite" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "@ray-lab/renderer-virtual": "workspace:*", + "@ray-lab/renderer-webgl": "workspace:*", + "vue": "^3.2.45" + }, + "devDependencies": { + "@types/node": "^18.11.18", + "@vitejs/plugin-vue": "^4.0.0", + "@vue/tsconfig": "^0.1.3", + "typescript": "^4.9.4", + "vite": "^4.0.4", + "vite-plugin-vue-setup-extend": "^0.4.0" + } +} diff --git a/packages/renderer-debugger/source/App.vue b/packages/renderer-debugger/source/App.vue new file mode 100644 index 0000000..b1dbde1 --- /dev/null +++ b/packages/renderer-debugger/source/App.vue @@ -0,0 +1,38 @@ + + + + + \ No newline at end of file diff --git a/packages/renderer-debugger/source/main.ts b/packages/renderer-debugger/source/main.ts new file mode 100644 index 0000000..0a36e33 --- /dev/null +++ b/packages/renderer-debugger/source/main.ts @@ -0,0 +1,5 @@ +import { createApp } from "vue"; +import AppVue from "./App.vue"; + +const oneMapApp = createApp(AppVue); +oneMapApp.mount("#app"); \ No newline at end of file diff --git a/packages/renderer-debugger/tsconfig.json b/packages/renderer-debugger/tsconfig.json new file mode 100644 index 0000000..f18a693 --- /dev/null +++ b/packages/renderer-debugger/tsconfig.json @@ -0,0 +1,28 @@ +{ + "extends": "@vue/tsconfig/tsconfig.web.json", + + "include": [ + "./source/**/*", + "./source/**/*.vue" + ], + + "exclude": [ + "node_modules", + "build" + ], + + "compilerOptions": { + "strict": true, + "alwaysStrict": true, + "baseUrl": "./", + "module": "ESNext", + "moduleResolution": "Node", + "useDefineForClassFields": true, + }, + + "references": [ + { + "path": "./tsconfig.vite.json" + } + ] +} \ No newline at end of file diff --git a/packages/renderer-debugger/tsconfig.vite.json b/packages/renderer-debugger/tsconfig.vite.json new file mode 100644 index 0000000..c2d3a30 --- /dev/null +++ b/packages/renderer-debugger/tsconfig.vite.json @@ -0,0 +1,8 @@ +{ + "extends": "@vue/tsconfig/tsconfig.node.json", + "include": ["vite.config.*", "vitest.config.*", "cypress.config.*"], + "compilerOptions": { + "composite": true, + "types": ["node"] + } +} diff --git a/packages/renderer-debugger/vite.config.ts b/packages/renderer-debugger/vite.config.ts new file mode 100644 index 0000000..cf0f564 --- /dev/null +++ b/packages/renderer-debugger/vite.config.ts @@ -0,0 +1,20 @@ +import { defineConfig, type UserConfig, type ConfigEnv } from "vite"; +import { default as vuePlugin } from "@vitejs/plugin-vue"; +import { default as VueSetupExtend } from 'vite-plugin-vue-setup-extend'; +import { resolve } from "path"; + +const projectPath = resolve(__dirname, "./"); +const buildPath = resolve(projectPath, "./build"); + +async function viteConfig({ command, mode }: ConfigEnv): Promise { + + return { + root: projectPath, + build: { + outDir: buildPath, + }, + plugins: [vuePlugin(), VueSetupExtend()] + } +} + +export default defineConfig(viteConfig); \ No newline at end of file diff --git a/packages/renderer-virtual/package.json b/packages/renderer-virtual/package.json new file mode 100644 index 0000000..3330f9a --- /dev/null +++ b/packages/renderer-virtual/package.json @@ -0,0 +1,20 @@ +{ + "name": "@ray-lab/renderer-virtual", + "version": "1.0.0", + "description": "Renderer Common Interface.", + "scripts": { + "build": "rollup -c rollup.config.js" + }, + "type": "module", + "types": "./build/virtual-renderer.d.ts", + "keywords": [ + "renderer-virtual", + "renderer" + ], + "author": "MrKBear", + "devDependencies": { + "rollup": "^3.9.1", + "rollup-plugin-ts": "^3.0.2", + "typescript": "^4.9.4" + } +} \ No newline at end of file diff --git a/packages/renderer-virtual/rollup.config.js b/packages/renderer-virtual/rollup.config.js new file mode 100644 index 0000000..2b4f179 --- /dev/null +++ b/packages/renderer-virtual/rollup.config.js @@ -0,0 +1,20 @@ +import tsPlugin from "rollup-plugin-ts"; + +/** + * @type {import("rollup").RollupOptions} + */ +const rollupConfig = { + + input: "./source/virtual-renderer.ts", + + output: [ + { + file: "./build/virtual-renderer.d.ts", + format: "esm" + } + ], + + plugins: [tsPlugin()], +}; + +export default rollupConfig; \ No newline at end of file diff --git a/packages/renderer-virtual/source/command/ClearCommand.ts b/packages/renderer-virtual/source/command/ClearCommand.ts new file mode 100644 index 0000000..785d63c --- /dev/null +++ b/packages/renderer-virtual/source/command/ClearCommand.ts @@ -0,0 +1,9 @@ +import type { Command } from "./Command"; +import type { CommandType } from "./CommandType"; + +interface ClearCommand extends Command { + + type: CommandType.Clear +} + +export type { ClearCommand }; \ No newline at end of file diff --git a/packages/renderer-virtual/source/command/Command.ts b/packages/renderer-virtual/source/command/Command.ts new file mode 100644 index 0000000..64aae9d --- /dev/null +++ b/packages/renderer-virtual/source/command/Command.ts @@ -0,0 +1,16 @@ +import type { CommandTypeSet } from "./CommandType"; + +interface Command { + + /** + * Define the type of command. + */ + type: CommandTypeSet; + + /** + * Unique identification of the command for feedback. + */ + id?: string | number; +} + +export type { Command }; \ No newline at end of file diff --git a/packages/renderer-virtual/source/command/CommandSet.ts b/packages/renderer-virtual/source/command/CommandSet.ts new file mode 100644 index 0000000..1a4a882 --- /dev/null +++ b/packages/renderer-virtual/source/command/CommandSet.ts @@ -0,0 +1,6 @@ +import type { RenderCommand } from "./RenderCommand"; +import type { ClearCommand } from "./ClearCommand"; + +type CommandSet = RenderCommand | ClearCommand; + +export type { CommandSet }; \ No newline at end of file diff --git a/packages/renderer-virtual/source/command/CommandType.ts b/packages/renderer-virtual/source/command/CommandType.ts new file mode 100644 index 0000000..5fede24 --- /dev/null +++ b/packages/renderer-virtual/source/command/CommandType.ts @@ -0,0 +1,15 @@ + +namespace CommandType { + + export type Render = "RENDER" | 100_001; + + export type Resource = "RESOURCE" | 100_002; + + export type Clear = "CLEAR" | 100_003; + + export type Execute = "EXECUTE" | 100_004; +} + +type CommandTypeSet = CommandType.Render | CommandType.Resource | CommandType.Clear | CommandType.Execute; + +export type { CommandType, CommandTypeSet }; \ No newline at end of file diff --git a/packages/renderer-virtual/source/command/RenderCommand.ts b/packages/renderer-virtual/source/command/RenderCommand.ts new file mode 100644 index 0000000..b04bf7a --- /dev/null +++ b/packages/renderer-virtual/source/command/RenderCommand.ts @@ -0,0 +1,12 @@ +import type { Command } from "./Command"; +import type { CommandType } from "./CommandType"; + +/** + * Rendering command are used to execute gl programs. + */ +interface RenderCommand extends Command { + + type: CommandType.Render +} + +export type { RenderCommand }; \ No newline at end of file diff --git a/packages/renderer-virtual/source/renderer/Renderer.ts b/packages/renderer-virtual/source/renderer/Renderer.ts new file mode 100644 index 0000000..242c0e7 --- /dev/null +++ b/packages/renderer-virtual/source/renderer/Renderer.ts @@ -0,0 +1,8 @@ +import type { CommandSet } from "command/CommandSet" + +interface Renderer { + + executeCommand: (commands: CommandSet[] | CommandSet) => void; +} + +export type { Renderer }; \ No newline at end of file diff --git a/packages/renderer-virtual/source/resource/Resource.ts b/packages/renderer-virtual/source/resource/Resource.ts new file mode 100644 index 0000000..dae32df --- /dev/null +++ b/packages/renderer-virtual/source/resource/Resource.ts @@ -0,0 +1,10 @@ +import type { ResourceSet } from "./ResourceType"; + +interface Resource { + + type: ResourceSet; + + id: string | number; +} + +export type { Resource }; \ No newline at end of file diff --git a/packages/renderer-virtual/source/resource/ResourceType.ts b/packages/renderer-virtual/source/resource/ResourceType.ts new file mode 100644 index 0000000..542c8e9 --- /dev/null +++ b/packages/renderer-virtual/source/resource/ResourceType.ts @@ -0,0 +1,9 @@ + +namespace ResourceType { + + export type Shader = "SHADER" | 100_001; +} + +type ResourceSet = ResourceType.Shader; + +export type { ResourceType, ResourceSet }; \ No newline at end of file diff --git a/packages/renderer-virtual/source/resource/Shader.ts b/packages/renderer-virtual/source/resource/Shader.ts new file mode 100644 index 0000000..e69de29 diff --git a/packages/renderer-virtual/source/virtual-renderer.ts b/packages/renderer-virtual/source/virtual-renderer.ts new file mode 100644 index 0000000..7e9a595 --- /dev/null +++ b/packages/renderer-virtual/source/virtual-renderer.ts @@ -0,0 +1,7 @@ +export * from "command/Command"; +export * from "command/CommandSet"; +export * from "command/CommandType"; +export * from "command/RenderCommand"; +export * from "command/ClearCommand"; +export * from "resource/Resource"; +export * from "resource/ResourceType"; \ No newline at end of file diff --git a/packages/renderer-virtual/tsconfig.json b/packages/renderer-virtual/tsconfig.json new file mode 100644 index 0000000..5bf233a --- /dev/null +++ b/packages/renderer-virtual/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "strict": true, + "declaration": true, + "declarationDir": "build", + "baseUrl": "./", + "lib": [ + "ESNext" + ], + "paths": { + "command/*": ["./source/command/*"], + "common/*": ["./source/common/*"], + "resource/*": ["./source/resource/*"], + "renderer/*": ["./source/renderer/*"] + } + }, + "include": [ + "./source/**/*" + ], + "exclude": [ + "node_modules", + "build" + ] +} \ No newline at end of file diff --git a/packages/renderer-webgl/package.json b/packages/renderer-webgl/package.json new file mode 100644 index 0000000..ec1072a --- /dev/null +++ b/packages/renderer-webgl/package.json @@ -0,0 +1,23 @@ +{ + "name": "@ray-lab/renderer-webgl", + "version": "1.0.0", + "description": "", + "main": "./build/webgl-renderer.js", + "scripts": { + "build": "rollup -c rollup.config.js" + }, + "type": "module", + "types": "./build/webgl-renderer.d.ts", + "keywords": [], + "author": "MrKBear", + "license": "ISC", + "dependencies": { + "@juggle/resize-observer": "^3.4.0", + "@ray-lab/renderer-virtual": "workspace:*" + }, + "devDependencies": { + "rollup": "^3.9.1", + "rollup-plugin-ts": "^3.0.2", + "typescript": "^4.9.4" + } +} diff --git a/packages/renderer-webgl/rollup.config.js b/packages/renderer-webgl/rollup.config.js new file mode 100644 index 0000000..211b9bc --- /dev/null +++ b/packages/renderer-webgl/rollup.config.js @@ -0,0 +1,20 @@ +import tsPlugin from "rollup-plugin-ts"; + +/** + * @type {import("rollup").RollupOptions} + */ +const rollupConfig = { + + input: "./source/webgl-renderer.ts", + + output: [ + { + file: "./build/webgl-renderer.js", + format: "esm" + } + ], + + plugins: [tsPlugin()], +}; + +export default rollupConfig; \ No newline at end of file diff --git a/packages/renderer-webgl/source/kernel/CommandHandler.ts b/packages/renderer-webgl/source/kernel/CommandHandler.ts new file mode 100644 index 0000000..a1f547d --- /dev/null +++ b/packages/renderer-webgl/source/kernel/CommandHandler.ts @@ -0,0 +1,6 @@ + +class CommandHandler { + +} + +export { CommandHandler }; \ No newline at end of file diff --git a/packages/renderer-webgl/source/kernel/CommandInterpreter.ts b/packages/renderer-webgl/source/kernel/CommandInterpreter.ts new file mode 100644 index 0000000..6b3a5df --- /dev/null +++ b/packages/renderer-webgl/source/kernel/CommandInterpreter.ts @@ -0,0 +1,10 @@ +import type { CommandHandler } from "./CommandHandler"; + +class CommandInterpreter { + + public addCommandHandler(commandHandler: CommandHandler) { + + } + + public removeCommandHandler() {} +} \ No newline at end of file diff --git a/packages/renderer-webgl/source/kernel/EventEmitter.ts b/packages/renderer-webgl/source/kernel/EventEmitter.ts new file mode 100644 index 0000000..1b7605d --- /dev/null +++ b/packages/renderer-webgl/source/kernel/EventEmitter.ts @@ -0,0 +1,105 @@ + +/** + * Allowed event name. + */ +type EventName = string | number | symbol; +type EventHandler = (value?: Value) => any; + +/** + * An internally used event emitter model. + */ +class EventEmitter = {}> { + + private eventMap = new Map>; + + /** + * Add a listener for a given event. + * @param event - event name. + * @param handler - event handler. + */ + public addListener(event: T, handler: EventHandler): void { + let handlerSet = this.eventMap.get(event); + if (!handlerSet) { + handlerSet = new Set(); + this.eventMap.set(event, handlerSet); + } + handlerSet.add(handler); + } + + /** + * Alias of `EventEmitter.addListener`. + */ + public declare on: (event: T, handler: EventHandler) => void; + + /** + * Remove the listeners of a given event. + * @param event - event name. + * @param handler - event handler. + */ + public removeListener(event: T, handler: EventHandler) { + let handlerSet = this.eventMap.get(event); + if (handlerSet) { + handlerSet.delete(handler); + } + } + + /** + * Alias of `EventEmitter.removeListener`. + */ + public declare off: (event: T, handler: EventHandler) => void; + + /** + * Remove all listeners of a given event. + * @param event - event name. + * @param handler - event handler. + */ + public removeAllListener(event: T) { + this.eventMap.set(event, new Set()); + } + + /** + * Alias of `EventEmitter.removeAllListener`. + */ + public declare offAll: (event: T) => void; + + /** + * emit event. + */ + public emit(...param: EventMap[T] extends void ? [T] : [T, EventMap[T]]) { + let handlerSet = this.eventMap.get(param[0]); + if (handlerSet) { + for (const handler of handlerSet) { + handler(param[1]); + } + } + } + + /** + * Remove all listeners. + */ + public clearAllListener() { + this.eventMap.clear(); + this.eventMap = new Map(); + } + + /** + * Get the number of listeners for a given event. + * @param event - event name. + */ + public listenerCount(event: T): number { + let handlerSet = this.eventMap.get(event); + if (handlerSet) { + return handlerSet.size; + } + else { + return 0; + } + } +} + +// Register alias. +EventEmitter.prototype.on = EventEmitter.prototype.addListener; +EventEmitter.prototype.off = EventEmitter.prototype.removeListener; +EventEmitter.prototype.offAll = EventEmitter.prototype.removeAllListener; + +export { EventEmitter }; \ No newline at end of file diff --git a/packages/renderer-webgl/source/kernel/ResourceHandler.ts b/packages/renderer-webgl/source/kernel/ResourceHandler.ts new file mode 100644 index 0000000..e69de29 diff --git a/packages/renderer-webgl/source/kernel/ResourcePool.ts b/packages/renderer-webgl/source/kernel/ResourcePool.ts new file mode 100644 index 0000000..e69de29 diff --git a/packages/renderer-webgl/source/kernel/WebGLCanvas.ts b/packages/renderer-webgl/source/kernel/WebGLCanvas.ts new file mode 100644 index 0000000..773ebbc --- /dev/null +++ b/packages/renderer-webgl/source/kernel/WebGLCanvas.ts @@ -0,0 +1,335 @@ +import { ResizeObserver as ResizeObserverPolyfill } from '@juggle/resize-observer'; +import { EventEmitter } from "./EventEmitter"; + +const ResizeObserver = window.ResizeObserver || ResizeObserverPolyfill; + +interface WebGLCanvasOption { + + /** + * Canvas element for outputting renderer images. + * If a string is passed in: + * Here will try `document.getElementById` and then `document.querySelector` + * until a valid canvas element is found. + */ + canvas?: HTMLCanvasElement | OffscreenCanvas | string; + + /** + * Initialize with WebGL context. + */ + context?: WebGLRenderingContext | WebGL2RenderingContext; + + /** + * Parent node of canvas. + */ + container?: HTMLElement | string; + + /** + * Automatically adjust width and height to parent node width and height. + */ + autoResize?: boolean; + + /** + * Width of Canvas. + * It will become invalid when autoResize is set. + */ + width?: number; + + /** + * Height of Canvas. + * It will become invalid when autoResize is set. + */ + height?: number; + + /** + * Whether to use offline canvas. + */ + isOffScreen?: boolean; + + /** + * WebGL context attributes. + */ + contextAttributes?: WebGLContextAttributes; +} + +type WebGLCanvasEventMap = { + + /** + * Emit When the canvas size changes. + */ + "resize": void; +}; + +class WebGLCanvas extends EventEmitter { + + public readonly canvas: HTMLCanvasElement | OffscreenCanvas; + + public readonly context: WebGLRenderingContext | WebGL2RenderingContext; + + public readonly glVersion: 0 | 1 | 2; + + public readonly isOffScreen: boolean; + + public constructor(userOption?: WebGLCanvasOption) { + + super(); + + const option: WebGLCanvasOption = userOption ?? {}; + + let targetCanvas: HTMLCanvasElement | OffscreenCanvas | undefined = void 0; + let targetContext: WebGLRenderingContext | WebGL2RenderingContext | undefined = void 0; + let targetGLVersion: 0 | 1 | 2 = 0; + let targetIsOffScreen: boolean = false; + + if (option.canvas instanceof HTMLCanvasElement || option.canvas instanceof OffscreenCanvas) { + targetCanvas = option.canvas; + } + + else if (typeof option.canvas === "string") { + + let findTarget: HTMLElement | null = null; + + findTarget = document.getElementById(option.canvas); + + if (findTarget instanceof HTMLCanvasElement) { + targetCanvas = findTarget; + } + + else { + findTarget = document.querySelector(option.canvas); + + if (findTarget instanceof HTMLCanvasElement) { + targetCanvas = findTarget; + } + + else { + console.warn( + `[ray-lab Renderer] Unable to search any valid canvas through "${option.canvas}". \r\n` + + "Created internal canvas instead..." + ); + } + } + } + + if (option.context) { + + if (targetCanvas && targetCanvas !== option.context.canvas) { + console.warn( + "[ray-lab Renderer] The `canvas` element does not match the `context.canvas`: \r\n" + + "The `canvas` option will be ignored. \r\n" + + "Please do not use `canvas` and `context` at the same time!" + ); + } + + targetCanvas = option.context.canvas; + targetContext = option.context; + } + + if (targetCanvas) { + + if (targetCanvas instanceof HTMLCanvasElement) { + + if (option.isOffScreen) { + + if (OffscreenCanvas) { + targetCanvas = targetCanvas.transferControlToOffscreen(); + targetIsOffScreen = true; + } + + else { + targetIsOffScreen = false; + console.warn( + "[ray-lab Renderer] The target environment does not support OffscreenCanvas \r\n" + + "`isOffScreen` is ignored!" + ); + } + } + + else { + targetIsOffScreen = false; + } + } + + else if (targetCanvas instanceof OffscreenCanvas) { + targetIsOffScreen = true; + } + } + + else { + + if (option.isOffScreen) { + + if (OffscreenCanvas) { + targetIsOffScreen = true; + targetCanvas = new OffscreenCanvas(option.width ?? 300, option.height ?? 150); + } + + else { + targetIsOffScreen = false; + targetCanvas = document.createElement("canvas"); + console.warn( + "[ray-lab Renderer] The target environment does not support OffscreenCanvas \r\n" + + "`isOffScreen` is ignored!" + ); + } + } + + else { + targetIsOffScreen = false; + targetCanvas = document.createElement("canvas"); + } + } + + if (targetContext) { + + if (targetCanvas instanceof WebGL2RenderingContext) { + targetGLVersion = 2; + } + + else if (targetCanvas instanceof WebGLRenderingContext) { + targetGLVersion = 1; + } + } + + else { + let getContext: OffscreenRenderingContext | RenderingContext | null; + + getContext = targetCanvas.getContext("webgl2", option.contextAttributes); + + if (!getContext) { + getContext = targetCanvas.getContext("webgl", option.contextAttributes); + } + + if (WebGL2RenderingContext && (getContext instanceof WebGL2RenderingContext)) { + targetContext = getContext; + targetGLVersion = 2; + } + + else if (getContext instanceof WebGLRenderingContext) { + targetContext = getContext; + targetGLVersion = 1; + } + + else { + throw new Error("[ray-lab Renderer] The target environment does not support WebGL :("); + } + } + + this.canvas = targetCanvas; + this.context = targetContext; + this.glVersion = targetGLVersion; + this.isOffScreen = targetIsOffScreen; + + if (option.autoResize) { + this.enableAutoResize(option.container); + } + + else { + this.resize(option.width, option.height); + } + } + + /** + * Change the canvas size. + * @param width - canvas width. + * @param height - canvas height. + */ + public resize(width?: number, height?: number) { + + let hasResized = false; + + if (width !== void 0) { + this.canvas.width = width; + hasResized = true; + } + + if (height !== void 0) { + this.canvas.height = height; + hasResized = true; + } + + if (hasResized) { + this.emit("resize"); + } + } + + private resizeObserver: ResizeObserver | undefined; + + /** + * enable auto resize. + * @param container - Parent node of canvas. + */ + public enableAutoResize(container?: HTMLElement | string) { + let targetcontainer: HTMLElement | null = null; + + if (container instanceof HTMLElement) { + targetcontainer = container; + } + + else if (typeof container === "string") { + + targetcontainer = document.getElementById(container); + + if (targetcontainer === null) { + targetcontainer = document.querySelector(container); + + if (targetcontainer === null) { + console.warn( + `[ray-lab Renderer] Unable to search any valid container through "${container}".` + ); + } + } + } + + if (targetcontainer === null && this.canvas instanceof HTMLCanvasElement) { + targetcontainer = this.canvas.parentElement; + } + + if (targetcontainer === null) { + console.warn( + `[ray-lab Renderer] Unable to enable auto resize. \r\n` + + `Because a suitable container could not be found.` + ); + } + + else { + const resizeObserver = new ResizeObserver((entries) => { + + for (const entry of entries) { + if (entry.contentRect) { + this.resize(entry.contentRect.width, entry.contentRect.height); + } + } + }); + + if (this.resizeObserver) { + this.resizeObserver.disconnect(); + } + + this.resizeObserver = resizeObserver; + + if (this.canvas instanceof HTMLElement) { + this.canvas.style.width = "100%"; + this.canvas.style.height = "100%"; + this.canvas.style.boxSizing = "border-box"; + this.canvas.style.display = "block"; + } + + resizeObserver.observe(targetcontainer); + this.resize(targetcontainer.offsetWidth, targetcontainer.offsetHeight); + } + } + + /** + * disable auto resize. + */ + public disableAutoResize() { + if (this.resizeObserver) { + this.resizeObserver.disconnect(); + } + + this.resizeObserver = void 0; + } +} + +export { WebGLCanvas }; +export type { WebGLCanvasOption }; \ No newline at end of file diff --git a/packages/renderer-webgl/source/kernel/WebGLState.ts b/packages/renderer-webgl/source/kernel/WebGLState.ts new file mode 100644 index 0000000..e69de29 diff --git a/packages/renderer-webgl/source/renderer/WebGLRenderer.ts b/packages/renderer-webgl/source/renderer/WebGLRenderer.ts new file mode 100644 index 0000000..59b5d4c --- /dev/null +++ b/packages/renderer-webgl/source/renderer/WebGLRenderer.ts @@ -0,0 +1,7 @@ + +class WebGLRenderer { + + public constructor() {} +} + +export { WebGLRenderer }; \ No newline at end of file diff --git a/packages/renderer-webgl/source/webgl-renderer.ts b/packages/renderer-webgl/source/webgl-renderer.ts new file mode 100644 index 0000000..5b43b7b --- /dev/null +++ b/packages/renderer-webgl/source/webgl-renderer.ts @@ -0,0 +1,3 @@ +export * from "kernel/WebGLCanvas"; +export * from "kernel/EventEmitter"; +export * from "renderer/WebGLRenderer"; \ No newline at end of file diff --git a/packages/renderer-webgl/tsconfig.json b/packages/renderer-webgl/tsconfig.json new file mode 100644 index 0000000..3b3e1a9 --- /dev/null +++ b/packages/renderer-webgl/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "strict": true, + "baseUrl": "./", + "module": "ESNext", + "moduleResolution": "Node", + "target": "ESNext", + "declaration": true, + "lib": [ + "DOM", + "DOM.Iterable", + "ESNext" + ], + "paths": { + "kernel/*": ["./source/kernel/*"], + "renderer/*": ["./source/renderer/*"] + } + } +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..33582ef --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,792 @@ +lockfileVersion: 5.4 + +importers: + + .: + specifiers: {} + + packages/renderer-debugger: + specifiers: + '@ray-lab/renderer-virtual': workspace:* + '@ray-lab/renderer-webgl': workspace:* + '@types/node': ^18.11.18 + '@vitejs/plugin-vue': ^4.0.0 + '@vue/tsconfig': ^0.1.3 + typescript: ^4.9.4 + vite: ^4.0.4 + vite-plugin-vue-setup-extend: ^0.4.0 + vue: ^3.2.45 + dependencies: + '@ray-lab/renderer-virtual': link:../renderer-virtual + '@ray-lab/renderer-webgl': link:../renderer-webgl + vue: 3.2.45 + devDependencies: + '@types/node': 18.11.18 + '@vitejs/plugin-vue': 4.0.0_vite@4.0.4+vue@3.2.45 + '@vue/tsconfig': 0.1.3_@types+node@18.11.18 + typescript: 4.9.4 + vite: 4.0.4_@types+node@18.11.18 + vite-plugin-vue-setup-extend: 0.4.0_vite@4.0.4 + + packages/renderer-virtual: + specifiers: + rollup: ^3.9.1 + rollup-plugin-ts: ^3.0.2 + typescript: ^4.9.4 + devDependencies: + rollup: 3.9.1 + rollup-plugin-ts: 3.0.2_esmavzhadgk2idmxtiodxm33ma + typescript: 4.9.4 + + packages/renderer-webgl: + specifiers: + '@juggle/resize-observer': ^3.4.0 + '@ray-lab/renderer-virtual': workspace:* + rollup: ^3.9.1 + rollup-plugin-ts: ^3.0.2 + typescript: ^4.9.4 + dependencies: + '@juggle/resize-observer': 3.4.0 + '@ray-lab/renderer-virtual': link:../renderer-virtual + devDependencies: + rollup: 3.9.1 + rollup-plugin-ts: 3.0.2_esmavzhadgk2idmxtiodxm33ma + typescript: 4.9.4 + +packages: + + /@babel/helper-string-parser/7.19.4: + resolution: {integrity: sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==} + engines: {node: '>=6.9.0'} + + /@babel/helper-validator-identifier/7.19.1: + resolution: {integrity: sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==} + engines: {node: '>=6.9.0'} + + /@babel/parser/7.20.7: + resolution: {integrity: sha512-T3Z9oHybU+0vZlY9CiDSJQTD5ZapcW18ZctFMi0MOAl/4BjFF4ul7NVSARLdbGO5vDqy9eQiGTV0LtKfvCYvcg==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + '@babel/types': 7.20.7 + + /@babel/types/7.20.7: + resolution: {integrity: sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-string-parser': 7.19.4 + '@babel/helper-validator-identifier': 7.19.1 + to-fast-properties: 2.0.0 + + /@esbuild/android-arm/0.16.14: + resolution: {integrity: sha512-u0rITLxFIeYAvtJXBQNhNuV4YZe+MD1YvIWT7Nicj8hZAtRVZk2PgNH6KclcKDVHz1ChLKXRfX7d7tkbQBUfrg==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm64/0.16.14: + resolution: {integrity: sha512-hTqB6Iq13pW4xaydeqQrs8vPntUnMjbkq+PgGiBMi69eYk74naG2ftHWqKnxn874kNrt5Or3rQ0PJutx2doJuQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-x64/0.16.14: + resolution: {integrity: sha512-jir51K4J0K5Rt0KOcippjSNdOl7akKDVz5I6yrqdk4/m9y+rldGptQUF7qU4YpX8U61LtR+w2Tu2Ph+K/UaJOw==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-arm64/0.16.14: + resolution: {integrity: sha512-vrlaP81IuwPaw1fyX8fHCmivP3Gr73ojVEZy+oWJLAiZVcG8o8Phwun/XDnYIFUHxIoUnMFEpg9o38MIvlw8zw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-x64/0.16.14: + resolution: {integrity: sha512-KV1E01eC2hGYA2qzFDRCK4wdZCRUvMwCNcobgpiiOzp5QXpJBqFPdxI69j8vvzuU7oxFXDgANwEkXvpeQqyOyg==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-arm64/0.16.14: + resolution: {integrity: sha512-xRM1RQsazSvL42BNa5XC7ytD4ZDp0ZyJcH7aB0SlYUcHexJUKiDNKR7dlRVlpt6W0DvoRPU2nWK/9/QWS4u2fw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-x64/0.16.14: + resolution: {integrity: sha512-7ALTAn6YRRf1O6fw9jmn0rWmOx3XfwDo7njGtjy1LXhDGUjTY/vohEPM3ii5MQ411vJv1r498EEx2aBQTJcrEw==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm/0.16.14: + resolution: {integrity: sha512-X6xULug66ulrr4IzrW7qq+eq9n4MtEyagdWvj4o4cmWr+JXOT47atjpDF9j5M2zHY0UQBmqnHhwl+tXpkpIb2w==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm64/0.16.14: + resolution: {integrity: sha512-TLh2OcbBUQcMYRH4GbiDkDZfZ4t1A3GgmeXY27dHSI6xrU7IkO00MGBiJySmEV6sH3Wa6pAN6UtaVL0DwkGW4Q==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ia32/0.16.14: + resolution: {integrity: sha512-oBZkcZ56UZDFCAfE3Fd/Jgy10EoS7Td77NzNGenM+HSY8BkdQAcI9VF9qgwdOLZ+tuftWD7UqZ26SAhtvA3XhA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-loong64/0.16.14: + resolution: {integrity: sha512-udz/aEHTcuHP+xdWOJmZ5C9RQXHfZd/EhCnTi1Hfay37zH3lBxn/fNs85LA9HlsniFw2zccgcbrrTMKk7Cn1Qg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-mips64el/0.16.14: + resolution: {integrity: sha512-kJ2iEnikUOdC1SiTGbH0fJUgpZwa0ITDTvj9EHf9lm3I0hZ4Yugsb3M6XSl696jVxrEocLe519/8CbSpQWFSrg==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ppc64/0.16.14: + resolution: {integrity: sha512-kclKxvZvX5YhykwlJ/K9ljiY4THe5vXubXpWmr7q3Zu3WxKnUe1VOZmhkEZlqtnJx31GHPEV4SIG95IqTdfgfg==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-riscv64/0.16.14: + resolution: {integrity: sha512-fdwP9Dc+Kx/cZwp9T9kNqjAE/PQjfrxbio4rZ3XnC3cVvZBjuxpkiyu/tuCwt6SbAK5th6AYNjFdEV9kGC020A==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-s390x/0.16.14: + resolution: {integrity: sha512-++fw3P4fQk9nqvdzbANRqimKspL8pDCnSpXomyhV7V/ISha/BZIYvZwLBWVKp9CVWKwWPJ4ktsezuLIvlJRHqA==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-x64/0.16.14: + resolution: {integrity: sha512-TomtswAuzBf2NnddlrS4W01Tv85RM9YtATB3OugY6On0PLM4Ksz5qvQKVAjtzPKoLgL1FiZtfc8mkZc4IgoMEA==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/netbsd-x64/0.16.14: + resolution: {integrity: sha512-U06pfx8P5CqyoPNfqIJmnf+5/r4mJ1S62G4zE6eOjS59naQcxi6GnscUCPH3b+hRG0qdKoGX49RAyiqW+M9aSw==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/openbsd-x64/0.16.14: + resolution: {integrity: sha512-/Jl8XVaWEZNu9rZw+n792GIBupQwHo6GDoapHSb/2xp/Ku28eK6QpR2O9cPBkzHH4OOoMH0LB6zg/qczJ5TTGg==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/sunos-x64/0.16.14: + resolution: {integrity: sha512-2iI7D34uTbDn/TaSiUbEHz+fUa8KbN90vX5yYqo12QGpu6T8Jl+kxODsWuMCwoTVlqUpwfPV22nBbFPME9OPtw==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-arm64/0.16.14: + resolution: {integrity: sha512-SjlM7AHmQVTiGBJE/nqauY1aDh80UBsXZ94g4g60CDkrDMseatiqALVcIuElg4ZSYzJs8hsg5W6zS2zLpZTVgg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-ia32/0.16.14: + resolution: {integrity: sha512-z06t5zqk8ak0Xom5HG81z2iOQ1hNWYsFQp3sczVLVx+dctWdgl80tNRyTbwjaFfui2vFO12dfE3trCTvA+HO4g==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-x64/0.16.14: + resolution: {integrity: sha512-ED1UpWcM6lAbalbbQ9TrGqJh4Y9TaASUvu8bI/0mgJcxhSByJ6rbpgqRhxYMaQ682WfA71nxUreaTO7L275zrw==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@juggle/resize-observer/3.4.0: + resolution: {integrity: sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==} + dev: false + + /@mdn/browser-compat-data/4.2.1: + resolution: {integrity: sha512-EWUguj2kd7ldmrF9F+vI5hUOralPd+sdsUnYbRy33vZTuZkduC1shE9TtEMEjAQwyfyMb4ole5KtjF8MsnQOlA==} + dev: true + + /@rollup/pluginutils/4.2.1: + resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==} + engines: {node: '>= 8.0.0'} + dependencies: + estree-walker: 2.0.2 + picomatch: 2.3.1 + dev: true + + /@types/node/17.0.45: + resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==} + dev: true + + /@types/node/18.11.18: + resolution: {integrity: sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==} + dev: true + + /@types/object-path/0.11.1: + resolution: {integrity: sha512-219LSCO9HPcoXcRTC6DbCs0FRhZgBnEMzf16RRqkT40WbkKx3mOeQuz3e2XqbfhOz/AHfbru0kzB1n1RCAsIIg==} + dev: true + + /@types/semver/7.3.13: + resolution: {integrity: sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==} + dev: true + + /@types/ua-parser-js/0.7.36: + resolution: {integrity: sha512-N1rW+njavs70y2cApeIw1vLMYXRwfBy+7trgavGuuTfOd7j1Yh7QTRc/yqsPl6ncokt72ZXuxEU0PiCp9bSwNQ==} + dev: true + + /@vitejs/plugin-vue/4.0.0_vite@4.0.4+vue@3.2.45: + resolution: {integrity: sha512-e0X4jErIxAB5oLtDqbHvHpJe/uWNkdpYV83AOG2xo2tEVSzCzewgJMtREZM30wXnM5ls90hxiOtAuVU6H5JgbA==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + vite: ^4.0.0 + vue: ^3.2.25 + dependencies: + vite: 4.0.4_@types+node@18.11.18 + vue: 3.2.45 + dev: true + + /@vue/compiler-core/3.2.45: + resolution: {integrity: sha512-rcMj7H+PYe5wBV3iYeUgbCglC+pbpN8hBLTJvRiK2eKQiWqu+fG9F+8sW99JdL4LQi7Re178UOxn09puSXvn4A==} + dependencies: + '@babel/parser': 7.20.7 + '@vue/shared': 3.2.45 + estree-walker: 2.0.2 + source-map: 0.6.1 + + /@vue/compiler-dom/3.2.45: + resolution: {integrity: sha512-tyYeUEuKqqZO137WrZkpwfPCdiiIeXYCcJ8L4gWz9vqaxzIQRccTSwSWZ/Axx5YR2z+LvpUbmPNXxuBU45lyRw==} + dependencies: + '@vue/compiler-core': 3.2.45 + '@vue/shared': 3.2.45 + + /@vue/compiler-sfc/3.2.45: + resolution: {integrity: sha512-1jXDuWah1ggsnSAOGsec8cFjT/K6TMZ0sPL3o3d84Ft2AYZi2jWJgRMjw4iaK0rBfA89L5gw427H4n1RZQBu6Q==} + dependencies: + '@babel/parser': 7.20.7 + '@vue/compiler-core': 3.2.45 + '@vue/compiler-dom': 3.2.45 + '@vue/compiler-ssr': 3.2.45 + '@vue/reactivity-transform': 3.2.45 + '@vue/shared': 3.2.45 + estree-walker: 2.0.2 + magic-string: 0.25.9 + postcss: 8.4.20 + source-map: 0.6.1 + + /@vue/compiler-ssr/3.2.45: + resolution: {integrity: sha512-6BRaggEGqhWht3lt24CrIbQSRD5O07MTmd+LjAn5fJj568+R9eUD2F7wMQJjX859seSlrYog7sUtrZSd7feqrQ==} + dependencies: + '@vue/compiler-dom': 3.2.45 + '@vue/shared': 3.2.45 + + /@vue/reactivity-transform/3.2.45: + resolution: {integrity: sha512-BHVmzYAvM7vcU5WmuYqXpwaBHjsS8T63jlKGWVtHxAHIoMIlmaMyurUSEs1Zcg46M4AYT5MtB1U274/2aNzjJQ==} + dependencies: + '@babel/parser': 7.20.7 + '@vue/compiler-core': 3.2.45 + '@vue/shared': 3.2.45 + estree-walker: 2.0.2 + magic-string: 0.25.9 + + /@vue/reactivity/3.2.45: + resolution: {integrity: sha512-PRvhCcQcyEVohW0P8iQ7HDcIOXRjZfAsOds3N99X/Dzewy8TVhTCT4uXpAHfoKjVTJRA0O0K+6QNkDIZAxNi3A==} + dependencies: + '@vue/shared': 3.2.45 + + /@vue/runtime-core/3.2.45: + resolution: {integrity: sha512-gzJiTA3f74cgARptqzYswmoQx0fIA+gGYBfokYVhF8YSXjWTUA2SngRzZRku2HbGbjzB6LBYSbKGIaK8IW+s0A==} + dependencies: + '@vue/reactivity': 3.2.45 + '@vue/shared': 3.2.45 + + /@vue/runtime-dom/3.2.45: + resolution: {integrity: sha512-cy88YpfP5Ue2bDBbj75Cb4bIEZUMM/mAkDMfqDTpUYVgTf/kuQ2VQ8LebuZ8k6EudgH8pYhsGWHlY0lcxlvTwA==} + dependencies: + '@vue/runtime-core': 3.2.45 + '@vue/shared': 3.2.45 + csstype: 2.6.21 + + /@vue/server-renderer/3.2.45_vue@3.2.45: + resolution: {integrity: sha512-ebiMq7q24WBU1D6uhPK//2OTR1iRIyxjF5iVq/1a5I1SDMDyDu4Ts6fJaMnjrvD3MqnaiFkKQj+LKAgz5WIK3g==} + peerDependencies: + vue: 3.2.45 + dependencies: + '@vue/compiler-ssr': 3.2.45 + '@vue/shared': 3.2.45 + vue: 3.2.45 + + /@vue/shared/3.2.45: + resolution: {integrity: sha512-Ewzq5Yhimg7pSztDV+RH1UDKBzmtqieXQlpTVm2AwraoRL/Rks96mvd8Vgi7Lj+h+TH8dv7mXD3FRZR3TUvbSg==} + + /@vue/tsconfig/0.1.3_@types+node@18.11.18: + resolution: {integrity: sha512-kQVsh8yyWPvHpb8gIc9l/HIDiiVUy1amynLNpCy8p+FoCiZXCo6fQos5/097MmnNZc9AtseDsCrfkhqCrJ8Olg==} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + dependencies: + '@types/node': 18.11.18 + dev: true + + /@wessberg/stringutil/1.0.19: + resolution: {integrity: sha512-9AZHVXWlpN8Cn9k5BC/O0Dzb9E9xfEMXzYrNunwvkUTvuK7xgQPVRZpLo+jWCOZ5r8oBa8NIrHuPEu1hzbb6bg==} + engines: {node: '>=8.0.0'} + dev: true + + /ansi-colors/4.1.3: + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} + engines: {node: '>=6'} + dev: true + + /browserslist-generator/1.0.66: + resolution: {integrity: sha512-aFDax4Qzh29DdyhHQBD2Yu2L5OvaDnvYFMbmpLrLwwaNK4H6dHEhC/Nxv93/+mfAA+a/t94ln0P2JZvHO6LZDA==} + engines: {node: '>=8.0.0'} + dependencies: + '@mdn/browser-compat-data': 4.2.1 + '@types/object-path': 0.11.1 + '@types/semver': 7.3.13 + '@types/ua-parser-js': 0.7.36 + browserslist: 4.20.2 + caniuse-lite: 1.0.30001442 + isbot: 3.4.5 + object-path: 0.11.8 + semver: 7.3.8 + ua-parser-js: 1.0.32 + dev: true + + /browserslist/4.20.2: + resolution: {integrity: sha512-CQOBCqp/9pDvDbx3xfMi+86pr4KXIf2FDkTTdeuYw8OxS9t898LA1Khq57gtufFILXpfgsSx5woNgsBgvGjpsA==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + dependencies: + caniuse-lite: 1.0.30001442 + electron-to-chromium: 1.4.284 + escalade: 3.1.1 + node-releases: 2.0.8 + picocolors: 1.0.0 + dev: true + + /browserslist/4.21.4: + resolution: {integrity: sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + dependencies: + caniuse-lite: 1.0.30001442 + electron-to-chromium: 1.4.284 + node-releases: 2.0.8 + update-browserslist-db: 1.0.10_browserslist@4.21.4 + dev: true + + /caniuse-lite/1.0.30001442: + resolution: {integrity: sha512-239m03Pqy0hwxYPYR5JwOIxRJfLTWtle9FV8zosfV5pHg+/51uD4nxcUlM8+mWWGfwKtt8lJNHnD3cWw9VZ6ow==} + dev: true + + /compatfactory/1.0.1_typescript@4.9.4: + resolution: {integrity: sha512-hR9u0HSZTKDNNchPtMHg6myeNx0XO+av7UZIJPsi4rPALJBHi/W5Mbwi19hC/xm6y3JkYpxVYjTqnSGsU5X/iw==} + engines: {node: '>=14.9.0'} + peerDependencies: + typescript: '>=3.x || >= 4.x' + dependencies: + helpertypes: 0.0.18 + typescript: 4.9.4 + dev: true + + /crosspath/2.0.0: + resolution: {integrity: sha512-ju88BYCQ2uvjO2bR+SsgLSTwTSctU+6Vp2ePbKPgSCZyy4MWZxYsT738DlKVRE5utUjobjPRm1MkTYKJxCmpTA==} + engines: {node: '>=14.9.0'} + dependencies: + '@types/node': 17.0.45 + dev: true + + /csstype/2.6.21: + resolution: {integrity: sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==} + + /electron-to-chromium/1.4.284: + resolution: {integrity: sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==} + dev: true + + /esbuild/0.16.14: + resolution: {integrity: sha512-6xAn3O6ZZyoxZAEkwfI9hw4cEqSr/o1ViJtnkvImVkblmUN65Md04o0S/7H1WNu1XGf1Cjij/on7VO4psIYjkw==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/android-arm': 0.16.14 + '@esbuild/android-arm64': 0.16.14 + '@esbuild/android-x64': 0.16.14 + '@esbuild/darwin-arm64': 0.16.14 + '@esbuild/darwin-x64': 0.16.14 + '@esbuild/freebsd-arm64': 0.16.14 + '@esbuild/freebsd-x64': 0.16.14 + '@esbuild/linux-arm': 0.16.14 + '@esbuild/linux-arm64': 0.16.14 + '@esbuild/linux-ia32': 0.16.14 + '@esbuild/linux-loong64': 0.16.14 + '@esbuild/linux-mips64el': 0.16.14 + '@esbuild/linux-ppc64': 0.16.14 + '@esbuild/linux-riscv64': 0.16.14 + '@esbuild/linux-s390x': 0.16.14 + '@esbuild/linux-x64': 0.16.14 + '@esbuild/netbsd-x64': 0.16.14 + '@esbuild/openbsd-x64': 0.16.14 + '@esbuild/sunos-x64': 0.16.14 + '@esbuild/win32-arm64': 0.16.14 + '@esbuild/win32-ia32': 0.16.14 + '@esbuild/win32-x64': 0.16.14 + dev: true + + /escalade/3.1.1: + resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} + engines: {node: '>=6'} + dev: true + + /estree-walker/2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + + /fsevents/2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /function-bind/1.1.1: + resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} + dev: true + + /has/1.0.3: + resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} + engines: {node: '>= 0.4.0'} + dependencies: + function-bind: 1.1.1 + dev: true + + /helpertypes/0.0.18: + resolution: {integrity: sha512-XRhfbSEmR+poXUC5/8AbmYNJb2riOT6qPzjGJZr0S9YedHiaY+/tzPYzWMUclYMEdCYo/1l8PDYrQFCj02v97w==} + engines: {node: '>=10.0.0'} + dev: true + + /is-core-module/2.11.0: + resolution: {integrity: sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==} + dependencies: + has: 1.0.3 + dev: true + + /isbot/3.4.5: + resolution: {integrity: sha512-+KD6q1BBtw0iK9aGBGSfxJ31/ZgizKRjhm8ebgJUBMx0aeeQuIJ1I72beCoIrltIZGrSm4vmrxRxrG5n1aUTtw==} + engines: {node: '>=12'} + dev: true + + /lru-cache/6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + dependencies: + yallist: 4.0.0 + dev: true + + /magic-string/0.25.9: + resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} + dependencies: + sourcemap-codec: 1.4.8 + + /magic-string/0.26.7: + resolution: {integrity: sha512-hX9XH3ziStPoPhJxLq1syWuZMxbDvGNbVchfrdCtanC7D13888bMFow61x8axrx+GfHLtVeAx2kxL7tTGRl+Ow==} + engines: {node: '>=12'} + dependencies: + sourcemap-codec: 1.4.8 + dev: true + + /nanoid/3.3.4: + resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + /node-releases/2.0.8: + resolution: {integrity: sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A==} + dev: true + + /object-path/0.11.8: + resolution: {integrity: sha512-YJjNZrlXJFM42wTBn6zgOJVar9KFJvzx6sTWDte8sWZF//cnjl0BxHNpfZx+ZffXX63A9q0b1zsFiBX4g4X5KA==} + engines: {node: '>= 10.12.0'} + dev: true + + /path-parse/1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + dev: true + + /picocolors/1.0.0: + resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + + /picomatch/2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + dev: true + + /postcss/8.4.20: + resolution: {integrity: sha512-6Q04AXR1212bXr5fh03u8aAwbLxAQNGQ/Q1LNa0VfOI06ZAlhPHtQvE4OIdpj4kLThXilalPnmDSOD65DcHt+g==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.4 + picocolors: 1.0.0 + source-map-js: 1.0.2 + + /resolve/1.22.1: + resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==} + hasBin: true + dependencies: + is-core-module: 2.11.0 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: true + + /rollup-plugin-ts/3.0.2_esmavzhadgk2idmxtiodxm33ma: + resolution: {integrity: sha512-67qi2QTHewhLyKDG6fX3jpohWpmUPPIT/xJ7rsYK46X6MqmoWy64Ti0y8ygPfLv8mXDCdRZUofM3mTxDfCswRA==} + engines: {node: '>=14.9.0', npm: '>=7.0.0', pnpm: '>=3.2.0', yarn: '>=1.13'} + peerDependencies: + '@babel/core': '>=6.x || >=7.x' + '@babel/plugin-transform-runtime': '>=6.x || >=7.x' + '@babel/preset-env': '>=6.x || >=7.x' + '@babel/preset-typescript': '>=6.x || >=7.x' + '@babel/runtime': '>=6.x || >=7.x' + '@swc/core': '>=1.x' + '@swc/helpers': '>=0.2' + rollup: '>=1.x || >=2.x' + typescript: '>=3.2.x || >= 4.x' + peerDependenciesMeta: + '@babel/core': + optional: true + '@babel/plugin-transform-runtime': + optional: true + '@babel/preset-env': + optional: true + '@babel/preset-typescript': + optional: true + '@babel/runtime': + optional: true + '@swc/core': + optional: true + '@swc/helpers': + optional: true + dependencies: + '@rollup/pluginutils': 4.2.1 + '@wessberg/stringutil': 1.0.19 + ansi-colors: 4.1.3 + browserslist: 4.21.4 + browserslist-generator: 1.0.66 + compatfactory: 1.0.1_typescript@4.9.4 + crosspath: 2.0.0 + magic-string: 0.26.7 + rollup: 3.9.1 + ts-clone-node: 1.0.0_typescript@4.9.4 + tslib: 2.4.1 + typescript: 4.9.4 + dev: true + + /rollup/3.9.1: + resolution: {integrity: sha512-GswCYHXftN8ZKGVgQhTFUJB/NBXxrRGgO2NCy6E8s1rwEJ4Q9/VttNqcYfEvx4dTo4j58YqdC3OVztPzlKSX8w==} + engines: {node: '>=14.18.0', npm: '>=8.0.0'} + hasBin: true + optionalDependencies: + fsevents: 2.3.2 + dev: true + + /semver/7.3.8: + resolution: {integrity: sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: true + + /source-map-js/1.0.2: + resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} + engines: {node: '>=0.10.0'} + + /source-map/0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + /sourcemap-codec/1.4.8: + resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} + deprecated: Please use @jridgewell/sourcemap-codec instead + + /supports-preserve-symlinks-flag/1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + dev: true + + /to-fast-properties/2.0.0: + resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} + engines: {node: '>=4'} + + /ts-clone-node/1.0.0_typescript@4.9.4: + resolution: {integrity: sha512-/cDYbr2HAXxFNeTT41c/xs/2bhLJjqnYheHsmA3AoHSt+n4JA4t0FL9Lk5O8kWnJ6jeB3kPcUoXIFtwERNzv6Q==} + engines: {node: '>=14.9.0'} + peerDependencies: + typescript: ^3.x || ^4.x + dependencies: + compatfactory: 1.0.1_typescript@4.9.4 + typescript: 4.9.4 + dev: true + + /tslib/2.4.1: + resolution: {integrity: sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==} + dev: true + + /typescript/4.9.4: + resolution: {integrity: sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==} + engines: {node: '>=4.2.0'} + hasBin: true + dev: true + + /ua-parser-js/1.0.32: + resolution: {integrity: sha512-dXVsz3M4j+5tTiovFVyVqssXBu5HM47//YSOeZ9fQkdDKkfzv2v3PP1jmH6FUyPW+yCSn7aBVK1fGGKNhowdDA==} + dev: true + + /update-browserslist-db/1.0.10_browserslist@4.21.4: + resolution: {integrity: sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + dependencies: + browserslist: 4.21.4 + escalade: 3.1.1 + picocolors: 1.0.0 + dev: true + + /vite-plugin-vue-setup-extend/0.4.0_vite@4.0.4: + resolution: {integrity: sha512-WMbjPCui75fboFoUTHhdbXzu4Y/bJMv5N9QT9a7do3wNMNHHqrk+Tn2jrSJU0LS5fGl/EG+FEDBYVUeWIkDqXQ==} + peerDependencies: + vite: '>=2.0.0' + dependencies: + '@vue/compiler-sfc': 3.2.45 + magic-string: 0.25.9 + vite: 4.0.4_@types+node@18.11.18 + dev: true + + /vite/4.0.4_@types+node@18.11.18: + resolution: {integrity: sha512-xevPU7M8FU0i/80DMR+YhgrzR5KS2ORy1B4xcX/cXLsvnUWvfHuqMmVU6N0YiJ4JWGRJJsLCgjEzKjG9/GKoSw==} + engines: {node: ^14.18.0 || >=16.0.0} + hasBin: true + peerDependencies: + '@types/node': '>= 14' + less: '*' + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + dependencies: + '@types/node': 18.11.18 + esbuild: 0.16.14 + postcss: 8.4.20 + resolve: 1.22.1 + rollup: 3.9.1 + optionalDependencies: + fsevents: 2.3.2 + dev: true + + /vue/3.2.45: + resolution: {integrity: sha512-9Nx/Mg2b2xWlXykmCwiTUCWHbWIj53bnkizBxKai1g61f2Xit700A1ljowpTIM11e3uipOeiPcSqnmBg6gyiaA==} + dependencies: + '@vue/compiler-dom': 3.2.45 + '@vue/compiler-sfc': 3.2.45 + '@vue/runtime-dom': 3.2.45 + '@vue/server-renderer': 3.2.45_vue@3.2.45 + '@vue/shared': 3.2.45 + + /yallist/4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + dev: true diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..364efa1 --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,5 @@ + +packages: + + # all packages in direct subdirs of packages/ + - 'packages/*' \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..64d1b8a --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,43 @@ +{ + "compilerOptions": { + "strict": true, + "alwaysStrict": true, + "noFallthroughCasesInSwitch": true, + "noImplicitAny": true, + "noImplicitOverride": true, + "noImplicitReturns": true, + "noImplicitThis": true, + "strictBindCallApply": true, + "strictFunctionTypes": true, + "strictNullChecks": true, + "strictPropertyInitialization": true, + "allowSyntheticDefaultImports": true, + "experimentalDecorators": true, + "resolveJsonModule": true, + "baseUrl": "./", + "module": "commonjs", + "jsx": "react-jsx", + "target": "ES6", + "moduleSuffixes": [".ts", ".tsx", ".js", ".jsx", ".gl", ".vsh", ".fsh", ""], + "paths": { + "engine/*": ["./engine/*"], + "ray-lab": ["./engine/RayLab"], + "engine/math": ["./engine/math/Math"], + "engine/kernel": ["./engine/kernel/Kernel"], + "examples/*": ["./examples/*"], + "virtual-renderer": ["./engine/virtual-renderer/VirtualRenderer.ts"] + }, + "lib": [ + "ESNext", + "DOM" + ] + }, + "include": [ + "./engine/**/*", + "./examples/**/*" + ], + "exclude": [ + "node_modules", + "build" + ] +} \ No newline at end of file