commit 4fde9cf8f09eaf7f774ceb771f251d6efd2582f6 Author: Evert Prants Date: Sat Jun 3 20:49:26 2023 +0300 Initial code diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..63520da --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +node_modules +dist +build diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..937375d --- /dev/null +++ b/.prettierrc @@ -0,0 +1,4 @@ +{ + "semi": true, + "singleQuote": true +} diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..c0a6e5a --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..ad92582 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "editor.formatOnSave": true +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..a06edf2 --- /dev/null +++ b/package.json @@ -0,0 +1,20 @@ +{ + "name": "@freeblox/monorepo", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "workspaces": [ + "src/apps/**", + "src/packages/**" + ], + "engines": { + "node": ">16.0.0", + "pnpm": ">=6" + }, + "keywords": [], + "author": "", + "license": "ISC" +} diff --git a/packages/client/.gitignore b/packages/client/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/packages/client/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/packages/client/README.md b/packages/client/README.md new file mode 100644 index 0000000..ef72fd5 --- /dev/null +++ b/packages/client/README.md @@ -0,0 +1,18 @@ +# Vue 3 + TypeScript + Vite + +This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 ` + + diff --git a/packages/client/package.json b/packages/client/package.json new file mode 100644 index 0000000..b8c6fbe --- /dev/null +++ b/packages/client/package.json @@ -0,0 +1,35 @@ +{ + "name": "@freeblox/client", + "version": "0.0.1", + "type": "module", + "files": [ + "dist" + ], + "main": "./dist/client.umd.cjs", + "module": "./dist/client.js", + "exports": { + ".": { + "import": "./dist/client.js", + "require": "./dist/client.umd.cjs" + } + }, + "scripts": { + "dev": "vite", + "build": "vue-tsc && vite build", + "preview": "vite preview" + }, + "dependencies": { + "@freeblox/engine": "workspace:^", + "three": "^0.153.0", + "vite-plugin-dts": "^2.3.0", + "vue": "^3.2.47" + }, + "devDependencies": { + "@types/three": "^0.152.1", + "@vitejs/plugin-vue": "^4.1.0", + "tslib": "^2.5.3", + "typescript": "^5.0.2", + "vite": "^4.3.9", + "vue-tsc": "^1.4.2" + } +} diff --git a/packages/client/public/vite.svg b/packages/client/public/vite.svg new file mode 100644 index 0000000..e7b8dfb --- /dev/null +++ b/packages/client/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/client/src/App.vue b/packages/client/src/App.vue new file mode 100644 index 0000000..6948eec --- /dev/null +++ b/packages/client/src/App.vue @@ -0,0 +1,3 @@ + diff --git a/packages/client/src/components/GameWrapper.vue b/packages/client/src/components/GameWrapper.vue new file mode 100644 index 0000000..2414abd --- /dev/null +++ b/packages/client/src/components/GameWrapper.vue @@ -0,0 +1,3 @@ + diff --git a/packages/client/src/index.ts b/packages/client/src/index.ts new file mode 100644 index 0000000..de93b55 --- /dev/null +++ b/packages/client/src/index.ts @@ -0,0 +1 @@ +export * as GameWrapper from './components/GameWrapper.vue'; diff --git a/packages/client/src/main.css b/packages/client/src/main.css new file mode 100644 index 0000000..1c9f90e --- /dev/null +++ b/packages/client/src/main.css @@ -0,0 +1,8 @@ +* { + margin: 0; + padding: 0; +} + +*, *::before, *::after { + box-sizing: border-box; +} diff --git a/packages/client/src/main.ts b/packages/client/src/main.ts new file mode 100644 index 0000000..c80943b --- /dev/null +++ b/packages/client/src/main.ts @@ -0,0 +1,5 @@ +import { createApp } from 'vue'; +import App from './App.vue'; +import './main.css'; + +createApp(App).mount('#app'); diff --git a/packages/client/src/vite-env.d.ts b/packages/client/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/packages/client/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/packages/client/tsconfig.json b/packages/client/tsconfig.json new file mode 100644 index 0000000..ab9debb --- /dev/null +++ b/packages/client/tsconfig.json @@ -0,0 +1,29 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "useDefineForClassFields": true, + "lib": [ + "ES2020", + "DOM", + "DOM.Iterable" + ], + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "preserve", + }, + "include": [ + "src/**/*.ts", + "src/**/*.d.ts", + "src/**/*.tsx", + "src/**/*.vue" + ], + "references": [ + { + "path": "./tsconfig.node.json" + } + ] +} diff --git a/packages/client/tsconfig.node.json b/packages/client/tsconfig.node.json new file mode 100644 index 0000000..42872c5 --- /dev/null +++ b/packages/client/tsconfig.node.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/packages/client/vite.config.ts b/packages/client/vite.config.ts new file mode 100644 index 0000000..579a107 --- /dev/null +++ b/packages/client/vite.config.ts @@ -0,0 +1,24 @@ +import { defineConfig } from 'vite'; +import vue from '@vitejs/plugin-vue'; +import dts from 'vite-plugin-dts' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [vue(), dts()], + build: { + lib: { + entry: 'src/index.ts', + name: 'Client', + fileName: 'client', + formats: ['es', 'cjs', 'umd'] + }, + rollupOptions: { + external: ['vue'], + output: { + globals: { + vue: 'Vue', + }, + }, + }, + } +}); diff --git a/packages/editor/.gitignore b/packages/editor/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/packages/editor/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/packages/editor/README.md b/packages/editor/README.md new file mode 100644 index 0000000..ef72fd5 --- /dev/null +++ b/packages/editor/README.md @@ -0,0 +1,18 @@ +# Vue 3 + TypeScript + Vite + +This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 ` + + diff --git a/packages/editor/package.json b/packages/editor/package.json new file mode 100644 index 0000000..f9e2524 --- /dev/null +++ b/packages/editor/package.json @@ -0,0 +1,35 @@ +{ + "name": "@freeblox/editor", + "version": "0.0.1", + "type": "module", + "files": [ + "dist" + ], + "main": "./dist/editor.umd.cjs", + "module": "./dist/editor.js", + "exports": { + ".": { + "import": "./dist/editor.js", + "require": "./dist/editor.umd.cjs" + } + }, + "scripts": { + "dev": "vite", + "build": "vue-tsc && vite build", + "preview": "vite preview" + }, + "dependencies": { + "@freeblox/engine": "workspace:^", + "three": "^0.153.0", + "vite-plugin-dts": "^2.3.0", + "vue": "^3.2.47" + }, + "devDependencies": { + "@types/three": "^0.152.1", + "@vitejs/plugin-vue": "^4.1.0", + "tslib": "^2.5.3", + "typescript": "^5.0.2", + "vite": "^4.3.9", + "vue-tsc": "^1.4.2" + } +} diff --git a/packages/editor/public/vite.svg b/packages/editor/public/vite.svg new file mode 100644 index 0000000..e7b8dfb --- /dev/null +++ b/packages/editor/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/editor/src/App.vue b/packages/editor/src/App.vue new file mode 100644 index 0000000..21bc246 --- /dev/null +++ b/packages/editor/src/App.vue @@ -0,0 +1,6 @@ + + diff --git a/packages/editor/src/components/EditorWrapper.vue b/packages/editor/src/components/EditorWrapper.vue new file mode 100644 index 0000000..f45fca1 --- /dev/null +++ b/packages/editor/src/components/EditorWrapper.vue @@ -0,0 +1,23 @@ + + + diff --git a/packages/editor/src/editor/core/editor.ts b/packages/editor/src/editor/core/editor.ts new file mode 100644 index 0000000..083c63b --- /dev/null +++ b/packages/editor/src/editor/core/editor.ts @@ -0,0 +1,62 @@ +import { EventEmitter, GameRunner, Renderer } from '@freeblox/engine'; +import { EditorViewport } from './viewport'; +import { EditorEvents } from '../types/events'; +import { EditorWorkspace } from './workspace'; +import { EditorMouse } from './mouse'; +import { EditorEnvironment } from './environment'; + +export class Editor extends GameRunner { + public lastTick = performance.now(); + public events = new EventEmitter(); + public render!: Renderer; + public element!: HTMLElement; + public viewport!: EditorViewport; + public workspace!: EditorWorkspace; + public mouse!: EditorMouse; + public environment!: EditorEnvironment; + public running = false; + + override mount(element: HTMLElement) { + this.element = element; + this.render = new Renderer(element); + + this.viewport = new EditorViewport(this.render, this.events); + this.viewport.initialize(); + + this.workspace = new EditorWorkspace(this.render, this.events); + this.workspace.initialize(); + + this.mouse = new EditorMouse(this.render, this.events); + this.mouse.initialize(); + + this.environment = new EditorEnvironment(this.render, this.events); + this.environment.initialize(); + + this.start(); + } + + override loop(now: DOMHighResTimeStamp) { + const delta = now - this.lastTick; + this.lastTick = now; + + this.running && requestAnimationFrame((ts) => this.loop(ts)); + + this.viewport.update(delta); + this.workspace.update(delta); + this.mouse.update(delta); + + this.render.render(); + } + + override start() { + this.running = true; + this.loop(this.lastTick); + } + + override stop() { + this.running = false; + this.viewport.cleanUp(); + this.workspace.cleanUp(); + this.mouse.cleanUp(); + } +} diff --git a/packages/editor/src/editor/core/environment.ts b/packages/editor/src/editor/core/environment.ts new file mode 100644 index 0000000..0b3cf30 --- /dev/null +++ b/packages/editor/src/editor/core/environment.ts @@ -0,0 +1,28 @@ +import { EngineComponent, EventEmitter, Renderer } from '@freeblox/engine'; +import { EditorEvents } from '../types/events'; +import { AmbientLight, DirectionalLight } from 'three'; + +export class EditorEnvironment extends EngineComponent { + public ambient!: AmbientLight; + public directional!: DirectionalLight; + + constructor( + protected renderer: Renderer, + protected events: EventEmitter + ) { + super(renderer, events); + } + + initialize(): void { + this.ambient = new AmbientLight(0x8a8a8a, 1.0); + this.directional = new DirectionalLight(0xffffff, 1); + this.directional.position.set(1, 1, 1); + + this.renderer.scene.add(this.ambient); + this.renderer.scene.add(this.directional); + } + + update(delta: number): void {} + + cleanUp(): void {} +} diff --git a/packages/editor/src/editor/core/mouse.ts b/packages/editor/src/editor/core/mouse.ts new file mode 100644 index 0000000..9416e75 --- /dev/null +++ b/packages/editor/src/editor/core/mouse.ts @@ -0,0 +1,113 @@ +import { EngineComponent, EventEmitter, Renderer } from '@freeblox/engine'; +import { EditorEvents, SelectEvent } from '../types/events'; +import { Object3D, Raycaster, Vector2 } from 'three'; + +type MouseMap = [boolean, boolean, boolean]; +type EventMap = [string, Function]; + +export class EditorMouse extends EngineComponent { + private helpers!: Object3D; + private world!: Object3D; + + private mouseButtons: MouseMap = [false, false, false]; + private mouseButtonsLast: MouseMap = [false, false, false]; + + private mousePosition = new Vector2(0, 0); + private mousePositionGL = new Vector2(0, 0); + private mousePositionLast = new Vector2(0, 0); + private mousePositionGLLast = new Vector2(0, 0); + + private boundEvents: EventMap[] = []; + private ray = new Raycaster(); + + constructor( + protected renderer: Renderer, + protected events: EventEmitter + ) { + super(renderer, events); + } + + get canvas() { + return this.renderer.renderer.domElement; + } + + initialize(): void { + this.helpers = this.renderer.scene.getObjectByName('_helpers')!; + this.world = this.renderer.scene.getObjectByName('_world')!; + + const mouseDown = (ev: MouseEvent) => { + const [object] = this.ray.intersectObjects(this.world.children, true); + this.mouseButtons[ev.button] = true; + this.events.emit('mouseDown', { + position: this.mousePosition, + positionGL: this.mousePositionGL, + button: ev.button, + target: object, + shift: ev.shiftKey, + control: ev.ctrlKey, + alt: ev.altKey, + }); + }; + + const mouseUp = (ev: MouseEvent) => { + const [object] = this.ray.intersectObjects(this.world.children, true); + this.mouseButtons[ev.button] = false; + this.events.emit('mouseUp', { + position: this.mousePosition, + positionGL: this.mousePositionGL, + button: ev.button, + target: object, + }); + }; + + const mouseMove = (ev: MouseEvent) => { + this.mousePositionLast = this.mousePosition.clone(); + this.mousePositionGLLast = this.mousePositionGL.clone(); + + this.mousePosition.set(ev.clientX, ev.clientY); + this.mousePositionGL.set( + (this.mousePosition.x / this.renderer.resolution.x) * 2 - 1, + -(this.mousePosition.y / this.renderer.resolution.y) * 2 + 1 + ); + + this.events.emit('mouseMove', { + position: this.mousePosition, + positionGL: this.mousePositionGL, + offset: this.mousePositionLast.clone().sub(this.mousePosition), + offsetGL: this.mousePositionGLLast.clone().sub(this.mousePositionGL), + }); + }; + + const contextMenu = (ev: MouseEvent) => ev.preventDefault(); + + this.canvas.addEventListener('mousedown', mouseDown); + this.canvas.addEventListener('mousemove', mouseMove); + this.canvas.addEventListener('mouseup', mouseUp); + this.canvas.addEventListener('contextmenu', contextMenu); + + this.boundEvents.push( + ['mousedown', mouseDown], + ['mousemove', mouseMove], + ['mouseup', mouseUp], + ['contextmenu', contextMenu] + ); + } + + update(delta: number): void { + this.ray.setFromCamera(this.mousePositionGL, this.renderer.camera); + this.mouseButtonsLast = [...this.mouseButtons]; + } + + cleanUp(): void { + for (const [event, handler] of this.boundEvents) { + this.canvas.removeEventListener(event, handler as EventListener); + } + } + + // private realMousePos(vec: Vector2, x: number, y: number) { + // const rect = this.renderer.renderer.domElement.getBoundingClientRect(); + // const scaleX = this.renderer.renderer.domElement.width / rect.width; + // const scaleY = this.renderer.renderer.domElement.height / rect.height; + // vec.set((x - rect.left) * scaleX, (y - rect.top) * scaleY); + // } +} diff --git a/packages/editor/src/editor/core/viewport.ts b/packages/editor/src/editor/core/viewport.ts new file mode 100644 index 0000000..565a2e2 --- /dev/null +++ b/packages/editor/src/editor/core/viewport.ts @@ -0,0 +1,39 @@ +import { EngineComponent, EventEmitter, Renderer } from '@freeblox/engine'; +import { Object3D } from 'three'; +import { EditorEvents } from '../types/events'; + +export class EditorViewport extends EngineComponent { + constructor( + protected render: Renderer, + protected events: EventEmitter + ) { + super(render, events); + } + + get scene() { + return this.render.scene; + } + + get camera() { + return this.render.camera; + } + + initialize() { + this.setSizeFromWindow(); + this.camera.position.set(16, 8, 16); + } + + update(dt: number) {} + + cleanUp(): void {} + + setSize(width: number, height: number) { + this.render.viewport.style.width = `${width}px`; + this.render.viewport.style.height = `${height}px`; + this.render.setSize(width, height); + } + + setSizeFromWindow() { + this.setSize(window.innerWidth, window.innerHeight); + } +} diff --git a/packages/editor/src/editor/core/workspace.ts b/packages/editor/src/editor/core/workspace.ts new file mode 100644 index 0000000..69387c6 --- /dev/null +++ b/packages/editor/src/editor/core/workspace.ts @@ -0,0 +1,353 @@ +import { EngineComponent, EventEmitter, Renderer } from '@freeblox/engine'; +import { + AxesHelper, + BoxGeometry, + BoxHelper, + Color, + Euler, + GridHelper, + Material, + Mesh, + MeshPhongMaterial, + Object3D, + Vector3, +} from 'three'; +import { + EditorEvents, + MouseButtonEvent, + MouseMoveEvent, + SelectEvent, + TransformModeEvent, +} from '../types/events'; +import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'; +import { TransformControls } from 'three/examples/jsm/controls/TransformControls.js'; + +export class EditorWorkspace extends EngineComponent { + public background = new Object3D(); + public world = new Object3D(); + public helpers = new Object3D(); + + public orbitControls!: OrbitControls; + public transformControls!: TransformControls; + private grid!: GridHelper; + private box!: BoxHelper; + private axes!: AxesHelper; + + public transformPosition?: Vector3; + public transformRotation?: Euler; + public transformScale?: Vector3; + + public selection: Object3D[] = []; + public eventCleanUp?: Function; + + constructor( + protected renderer: Renderer, + protected events: EventEmitter + ) { + super(renderer, events); + } + + initialize() { + this.addToScene(this.renderer.scene); + this.initializeHelpers(); + this.initializeControls(); + this.eventCleanUp = this.initializeSelector(); + } + + update(dt: number) { + this.orbitControls?.update(); + this.box?.update(); + } + + cleanUp(): void { + this.removeFromScene(this.renderer.scene); + this.eventCleanUp?.call(this); + } + + private addToScene(scene: Object3D) { + this.background.name = '_background'; + this.world.name = '_world'; + this.helpers.name = '_helper'; + scene.add(this.background, this.world, this.helpers); + + const test = new Mesh(new BoxGeometry(), new MeshPhongMaterial()); + test.position.set(2, 2, 2); + this.world.add(test); + } + + private removeFromScene(scene: Object3D) { + scene.remove(this.background, this.world, this.helpers); + } + + private initializeSelector() { + let moved = false; + + const mouseDownEventHandler = () => { + moved = false; + }; + + const mouseMoveEventHandler = () => { + moved = true; + }; + + const mouseUpEventHandler = (event: MouseButtonEvent) => { + if (moved) return; + if (!event.target?.object) { + if (!this.selection.length) return; + const oldSelection = this.selection; + this.selection = []; + oldSelection.forEach((selection) => + this.events.emit('deselect', { + object: selection, + selection: [], + picker: true, + }) + ); + return; + } + + const object = event.target!.object; + if (this.selection.includes(object)) { + if (event.control) { + const index = this.selection.indexOf(object); + this.selection.splice(index, 1); + this.events.emit('deselect', { + object, + selection: this.selection, + picker: true, + }); + return; + } + } + + if (event.control) { + this.selection.push(object); + this.events.emit('select', { + object, + selection: this.selection, + multi: true, + picker: true, + }); + return; + } + + const notObject = this.selection.filter( + (entry) => entry.id !== object.id + ); + + const wasEmpty = !this.selection.length; + this.selection = [object]; + if (wasEmpty) { + this.events.emit('select', { + object: object, + selection: [object], + picker: true, + }); + } + + notObject.forEach((entry) => + this.events.emit('deselect', { + object: entry, + selection: this.selection, + picker: true, + }) + ); + }; + + const selectHandler = (select: SelectEvent) => { + if (!select.picker) { + if (select.multi) { + this.selection.push(select.object); + return; + } + this.selection = [select.object]; + } + + const attachTo = this.selection[this.selection.length - 1]; + this.transformControls?.attach(attachTo); + this.box.setFromObject(attachTo); + this.box.visible = true; + }; + + const deselectHandler = (select: SelectEvent) => { + if (!select.picker) { + const index = this.selection.indexOf(select.object); + this.selection.splice(index, 1); + } + + if (this.selection.length) { + const attachTo = this.selection[this.selection.length - 1]; + this.transformControls?.attach(attachTo); + this.box.setFromObject(attachTo); + this.box.visible = true; + return; + } + + this.transformControls?.detach(); + this.box.visible = false; + }; + + const transformMode = (mode: TransformModeEvent) => { + if (!this.transformControls) return; + if (!mode) { + this.transformControls.enabled = false; + return; + } + this.transformControls.setMode(mode); + }; + + const transformSnap = (value: number) => { + if (!this.transformControls) return; + this.transformControls.setTranslationSnap(value); + this.transformControls.setScaleSnap(value); + }; + + const transformRotationSnap = (value: number) => { + if (!this.transformControls) return; + this.transformControls.setRotationSnap(value); + }; + + this.events.addListener('mouseDown', mouseDownEventHandler); + this.events.addListener('mouseMove', mouseMoveEventHandler); + this.events.addListener('mouseUp', mouseUpEventHandler); + this.events.addListener('select', selectHandler); + this.events.addListener('deselect', deselectHandler); + this.events.addListener('transformMode', transformMode); + this.events.addListener('transformSnap', transformSnap); + this.events.addListener('transformRotationSnap', transformRotationSnap); + + return () => { + this.events.removeEventListener('mouseDown', mouseDownEventHandler); + this.events.removeEventListener('mouseMove', mouseMoveEventHandler); + this.events.removeEventListener('mouseUp', mouseUpEventHandler); + this.events.removeEventListener('select', selectHandler); + this.events.removeEventListener('deselect', deselectHandler); + this.events.removeEventListener('transformMode', transformMode); + this.events.removeEventListener('transformSnap', transformSnap); + this.events.removeEventListener( + 'transformRotationSnap', + transformRotationSnap + ); + }; + } + + private initializeHelpers() { + this.grid = new GridHelper(100, 100); + this.background.add(this.grid); + + this.box = new BoxHelper(this.world, 0x00a2ff); + (this.box.material as Material).depthTest = false; + (this.box.material as Material).transparent = true; + this.box.visible = false; + this.helpers.add(this.box); + + this.axes = new AxesHelper(50); + this.helpers.add(this.axes); + } + + private initializeControls() { + let translationSnap: number | null = 0.5; + let scaleSnap: number | null = 0.5; + let rotationSnap: number | null = null; + let mode: 'translate' | 'rotate' | 'scale' = 'translate'; + + if (this.orbitControls) this.orbitControls.dispose(); + if (this.transformControls) { + translationSnap = this.transformControls.translationSnap; + scaleSnap = (this.transformControls as any).scaleSnap; // FIXME: typedef bug + rotationSnap = this.transformControls.rotationSnap; + mode = this.transformControls.getMode(); + this.helpers.remove(this.transformControls); + this.transformControls.dispose(); + } + + this.orbitControls = new OrbitControls( + this.renderer.camera, + this.renderer.renderer.domElement + ); + this.transformControls = new TransformControls( + this.renderer.camera, + this.renderer.renderer.domElement + ); + this.transformControls.translationSnap = translationSnap; + (this.transformControls as any).scaleSnap = scaleSnap; + this.transformControls.rotationSnap = rotationSnap; + this.transformControls.setMode(mode); + this.helpers.add(this.transformControls); + + this.transformControls.addEventListener('mouseDown', () => { + this.orbitControls.enabled = false; + const target = this.transformControls.object; + if (!target) return; + this.transformPosition = target.position.clone(); + this.transformRotation = target.rotation.clone(); + this.transformScale = target.scale.clone(); + this.events.emit('transformStart', { + position: this.transformPosition!, + rotation: this.transformRotation!, + scale: this.transformScale!, + object: target, + }); + }); + + this.transformControls.addEventListener('mouseUp', () => { + this.orbitControls.enabled = true; + const target = this.transformControls.object; + if (!target) return; + this.events.emit('transformEnd', { + position: target.position.clone(), + rotation: target.rotation.clone(), + scale: target.scale.clone(), + object: target, + }); + }); + + this.transformControls.addEventListener('change', () => { + const target = this.transformControls.object; + if (!target) return; + + this.events.emit('transformChange', { + lastPosition: this.transformPosition!, + lastRotation: this.transformRotation!, + lastScale: this.transformScale!, + position: target.position.clone(), + rotation: target.rotation.clone(), + scale: target.scale.clone(), + object: target, + }); + + if ( + this.transformPosition && + !this.transformPosition.equals(target.position) + ) { + this.events.emit('change', { + object: target, + property: 'position', + value: target.position.clone(), + transformed: true, + }); + } + + if ( + this.transformRotation && + !this.transformRotation.equals(target.rotation) + ) { + this.events.emit('change', { + object: target, + property: 'rotation', + value: target.rotation.clone(), + transformed: true, + }); + } + + if (this.transformScale && !this.transformScale.equals(target.scale)) { + this.events.emit('change', { + object: target, + property: 'scale', + value: target.scale.clone(), + transformed: true, + }); + } + }); + } +} diff --git a/packages/editor/src/editor/index.ts b/packages/editor/src/editor/index.ts new file mode 100644 index 0000000..2307f78 --- /dev/null +++ b/packages/editor/src/editor/index.ts @@ -0,0 +1 @@ +export * from './core/editor'; diff --git a/packages/editor/src/editor/types/events.ts b/packages/editor/src/editor/types/events.ts new file mode 100644 index 0000000..dfcc6d1 --- /dev/null +++ b/packages/editor/src/editor/types/events.ts @@ -0,0 +1,70 @@ +import { EngineEvents } from '@freeblox/engine'; +import { Euler, Intersection, Object3D, Vector2, Vector3 } from 'three'; + +export interface MousePositionEvent { + position: Vector2; + positionGL: Vector2; +} + +export interface MouseMoveEvent extends MousePositionEvent { + offset: Vector2; + offsetGL: Vector2; + helper?: boolean; +} + +export interface MouseButtonEvent extends MousePositionEvent { + button: number; + helper?: boolean; + target?: Intersection; + shift?: boolean; + control?: boolean; + alt?: boolean; +} + +export interface TransformEvent { + object: Object3D; + position: Vector3; + rotation: Euler; + scale: Vector3; +} + +export type TransformModeEvent = 'translate' | 'rotate' | 'scale' | null; + +export interface TransformCompleteEvent extends TransformEvent { + lastPosition: Vector3; + lastRotation: Euler; + lastScale: Vector3; +} + +export interface ChangeEvent { + object: Object3D; + property: string; + value: any; + edited?: boolean; + transformed?: boolean; +} + +export interface SelectEvent { + object: Object3D; + selection: Object3D[]; + multi?: boolean; + picker?: boolean; +} + +export type Events = { + error: (error: Error) => void; + mouseDown: (event: MouseButtonEvent) => void; + mouseUp: (event: MouseButtonEvent) => void; + mouseMove: (event: MouseMoveEvent) => void; + transformStart: (event: TransformEvent) => void; + transformChange: (event: TransformCompleteEvent) => void; + transformEnd: (event: TransformEvent) => void; + transformMode: (event: TransformModeEvent) => void; + transformSnap: (event: number) => void; + transformRotationSnap: (event: number) => void; + change: (event: ChangeEvent) => void; + select: (event: SelectEvent) => void; + deselect: (event: SelectEvent) => void; +}; + +export type EditorEvents = Events & EngineEvents; diff --git a/packages/editor/src/index.ts b/packages/editor/src/index.ts new file mode 100644 index 0000000..e9114bf --- /dev/null +++ b/packages/editor/src/index.ts @@ -0,0 +1 @@ +export * as EditorWrapper from './components/EditorWrapper.vue'; diff --git a/packages/editor/src/main.css b/packages/editor/src/main.css new file mode 100644 index 0000000..1c9f90e --- /dev/null +++ b/packages/editor/src/main.css @@ -0,0 +1,8 @@ +* { + margin: 0; + padding: 0; +} + +*, *::before, *::after { + box-sizing: border-box; +} diff --git a/packages/editor/src/main.ts b/packages/editor/src/main.ts new file mode 100644 index 0000000..c80943b --- /dev/null +++ b/packages/editor/src/main.ts @@ -0,0 +1,5 @@ +import { createApp } from 'vue'; +import App from './App.vue'; +import './main.css'; + +createApp(App).mount('#app'); diff --git a/packages/editor/src/vite-env.d.ts b/packages/editor/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/packages/editor/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/packages/editor/tsconfig.json b/packages/editor/tsconfig.json new file mode 100644 index 0000000..ab9debb --- /dev/null +++ b/packages/editor/tsconfig.json @@ -0,0 +1,29 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "useDefineForClassFields": true, + "lib": [ + "ES2020", + "DOM", + "DOM.Iterable" + ], + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "preserve", + }, + "include": [ + "src/**/*.ts", + "src/**/*.d.ts", + "src/**/*.tsx", + "src/**/*.vue" + ], + "references": [ + { + "path": "./tsconfig.node.json" + } + ] +} diff --git a/packages/editor/tsconfig.node.json b/packages/editor/tsconfig.node.json new file mode 100644 index 0000000..42872c5 --- /dev/null +++ b/packages/editor/tsconfig.node.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/packages/editor/vite.config.ts b/packages/editor/vite.config.ts new file mode 100644 index 0000000..6c0602a --- /dev/null +++ b/packages/editor/vite.config.ts @@ -0,0 +1,24 @@ +import { defineConfig } from 'vite'; +import vue from '@vitejs/plugin-vue'; +import dts from 'vite-plugin-dts' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [vue(), dts()], + build: { + lib: { + entry: 'src/index.ts', + name: 'Editor', + fileName: 'editor', + formats: ['es', 'cjs', 'umd'] + }, + rollupOptions: { + external: ['vue'], + output: { + globals: { + vue: 'Vue', + }, + }, + }, + } +}); diff --git a/packages/engine/.gitignore b/packages/engine/.gitignore new file mode 100644 index 0000000..1eae0cf --- /dev/null +++ b/packages/engine/.gitignore @@ -0,0 +1,2 @@ +dist/ +node_modules/ diff --git a/packages/engine/package.json b/packages/engine/package.json new file mode 100644 index 0000000..f4f6d7c --- /dev/null +++ b/packages/engine/package.json @@ -0,0 +1,27 @@ +{ + "name": "@freeblox/engine", + "version": "0.0.1", + "description": "Freeblox Engine", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "build": "tsc", + "dev": "tsc --watch", + "prepare": "npm run build" + }, + "keywords": [ + "game", + "engine", + "three" + ], + "author": "Evert", + "license": "MIT", + "devDependencies": { + "@types/three": "^0.152.1", + "typescript": "^5.0.4" + }, + "dependencies": { + "three": "^0.153.0" + } +} diff --git a/packages/engine/src/core/engine.ts b/packages/engine/src/core/engine.ts new file mode 100644 index 0000000..78e6bc8 --- /dev/null +++ b/packages/engine/src/core/engine.ts @@ -0,0 +1,39 @@ +import { EngineComponent } from '..'; +import { EngineEvents } from '../types/events'; +import { GameRunner } from '../types/game-runner'; +import { EventEmitter, EventMap } from '../utils/events'; +import { Renderer } from './renderer'; + +export class Engine< + TEvents extends EventMap = EngineEvents +> extends GameRunner { + public lastTick = performance.now(); + public running = false; + public events = new EventEmitter(); + public render!: Renderer; + public element!: HTMLElement; + public components: EngineComponent[] = []; + + mount(element: HTMLElement): void { + this.element = element; + this.render = new Renderer(element); + + for (const component of this.components) { + component.initialize(); + } + + this.start(); + } + + loop(now: number): void { + throw new Error('Method not implemented.'); + } + + start(): void { + throw new Error('Method not implemented.'); + } + + stop(): void { + throw new Error('Method not implemented.'); + } +} diff --git a/packages/engine/src/core/index.ts b/packages/engine/src/core/index.ts new file mode 100644 index 0000000..d72f418 --- /dev/null +++ b/packages/engine/src/core/index.ts @@ -0,0 +1 @@ +export * from './renderer'; diff --git a/packages/engine/src/core/renderer.ts b/packages/engine/src/core/renderer.ts new file mode 100644 index 0000000..22dac26 --- /dev/null +++ b/packages/engine/src/core/renderer.ts @@ -0,0 +1,31 @@ +import { PerspectiveCamera, Scene, Vector2, WebGLRenderer } from 'three'; + +export class Renderer { + public renderer = new WebGLRenderer(); + public camera = new PerspectiveCamera( + 75, + this.resolution.x / this.resolution.y, + 0.1, + 10000 + ); + public scene = new Scene(); + + constructor( + public viewport: HTMLElement, + public resolution = new Vector2(1080, 720) + ) { + this.renderer.setSize(resolution.x, resolution.y); + viewport.appendChild(this.renderer.domElement); + } + + setSize(width: number, height: number) { + this.resolution.set(width, height); + this.camera.aspect = this.resolution.x / this.resolution.y; + this.renderer.setSize(this.resolution.x, this.resolution.y); + this.camera.updateProjectionMatrix(); + } + + render() { + this.renderer.render(this.scene, this.camera); + } +} diff --git a/packages/engine/src/index.ts b/packages/engine/src/index.ts new file mode 100644 index 0000000..9938162 --- /dev/null +++ b/packages/engine/src/index.ts @@ -0,0 +1,3 @@ +export * from './core'; +export * from './utils'; +export * from './types'; diff --git a/packages/engine/src/types/engine-component.ts b/packages/engine/src/types/engine-component.ts new file mode 100644 index 0000000..d38f7ee --- /dev/null +++ b/packages/engine/src/types/engine-component.ts @@ -0,0 +1,26 @@ +import { Renderer } from '../core/renderer'; +import { EventEmitter } from '../utils/events'; +import { EngineEvents } from './events'; + +export abstract class EngineComponent { + constructor( + protected renderer: Renderer, + protected events: EventEmitter + ) {} + + /** + * Initialize this component + */ + abstract initialize(): void; + + /** + * Update this component. Called on every frame. + * @param delta Delta time + */ + abstract update(delta: number): void; + + /** + * Clean up the component + */ + abstract cleanUp(): void; +} diff --git a/packages/engine/src/types/events.ts b/packages/engine/src/types/events.ts new file mode 100644 index 0000000..827a305 --- /dev/null +++ b/packages/engine/src/types/events.ts @@ -0,0 +1,3 @@ +export type EngineEvents = { + error: (error: Error) => void; +}; diff --git a/packages/engine/src/types/game-runner.ts b/packages/engine/src/types/game-runner.ts new file mode 100644 index 0000000..272e54c --- /dev/null +++ b/packages/engine/src/types/game-runner.ts @@ -0,0 +1,6 @@ +export abstract class GameRunner { + abstract mount(element: HTMLElement): void; + abstract loop(now: DOMHighResTimeStamp): void; + abstract start(): void; + abstract stop(): void; +} diff --git a/packages/engine/src/types/index.ts b/packages/engine/src/types/index.ts new file mode 100644 index 0000000..80ad71c --- /dev/null +++ b/packages/engine/src/types/index.ts @@ -0,0 +1,3 @@ +export * from './game-runner'; +export * from './events'; +export * from './engine-component'; diff --git a/packages/engine/src/utils/clamp.ts b/packages/engine/src/utils/clamp.ts new file mode 100644 index 0000000..d427d70 --- /dev/null +++ b/packages/engine/src/utils/clamp.ts @@ -0,0 +1,3 @@ +export function clamp(x: number, min: number, max: number): number { + return Math.min(Math.max(x, min), max); +} diff --git a/packages/engine/src/utils/debounce.ts b/packages/engine/src/utils/debounce.ts new file mode 100644 index 0000000..15bde86 --- /dev/null +++ b/packages/engine/src/utils/debounce.ts @@ -0,0 +1,9 @@ +export function debounce(func: Function, timeout = 300) { + let timer: any; + return (...args: any[]) => { + clearTimeout(timer); + timer = setTimeout(() => { + func.apply(null, args); + }, timeout); + }; +} diff --git a/packages/engine/src/utils/events.ts b/packages/engine/src/utils/events.ts new file mode 100644 index 0000000..b6997d3 --- /dev/null +++ b/packages/engine/src/utils/events.ts @@ -0,0 +1,65 @@ +export type EventMap = { + [key: string]: (...args: any) => void; +}; + +export class EventEmitter { + private _handlers: { + [x: string]: { fn: (...args: any) => void; once: boolean }[]; + } = {}; + + addListener(event: E, fn: Events[E], once = false) { + if (typeof fn !== 'function') { + return; + } + + if (!this._handlers[event as string]) { + this._handlers[event as string] = []; + } + + this._handlers[event as string].push({ fn, once }); + } + + on(event: E, fn: Events[E]) { + this.addListener(event, fn, false); + } + + once(event: E, fn: Events[E]) { + this.addListener(event, fn, true); + } + + emit(event: E, ...args: Parameters): void { + if (!this._handlers[event as string]) { + return; + } + + this._handlers[event as string] + .filter((handler) => handler && typeof handler.fn === 'function') + .forEach((handler) => { + handler.fn(...(args as [])); + if (handler.once) { + this.removeEventListener(event, handler.fn as Events[E]); + } + }); + } + + removeEventListener(event: E, fn: Events[E]): void { + if (!this._handlers[event as string] || typeof fn !== 'function') { + return; + } + + const indexOf = this._handlers[event as string].findIndex( + (entry) => entry.fn === fn + ); + if (indexOf > -1) { + this._handlers[event as string].splice(indexOf, 1); + } + } + + removeAllListeners(event: E): void { + if (!this._handlers[event as string]) { + return; + } + + delete this._handlers[event as string]; + } +} diff --git a/packages/engine/src/utils/index.ts b/packages/engine/src/utils/index.ts new file mode 100644 index 0000000..82ee93f --- /dev/null +++ b/packages/engine/src/utils/index.ts @@ -0,0 +1,3 @@ +export * from './clamp'; +export * from './debounce'; +export * from './events'; diff --git a/packages/engine/tsconfig.json b/packages/engine/tsconfig.json new file mode 100644 index 0000000..dfad0ae --- /dev/null +++ b/packages/engine/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "./dist", + }, + "include": [ + "src/**/*" + ] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..1529e6e --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,1219 @@ +lockfileVersion: '6.1' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: {} + + packages/client: + dependencies: + '@freeblox/engine': + specifier: workspace:^ + version: link:../engine + three: + specifier: ^0.153.0 + version: 0.153.0 + vite-plugin-dts: + specifier: ^2.3.0 + version: 2.3.0(vite@4.3.9) + vue: + specifier: ^3.2.47 + version: 3.2.47 + devDependencies: + '@types/three': + specifier: ^0.152.1 + version: 0.152.1 + '@vitejs/plugin-vue': + specifier: ^4.1.0 + version: 4.1.0(vite@4.3.9)(vue@3.2.47) + tslib: + specifier: ^2.5.3 + version: 2.5.3 + typescript: + specifier: ^5.0.2 + version: 5.0.4 + vite: + specifier: ^4.3.9 + version: 4.3.9 + vue-tsc: + specifier: ^1.4.2 + version: 1.4.2(typescript@5.0.4) + + packages/editor: + dependencies: + '@freeblox/engine': + specifier: workspace:^ + version: link:../engine + three: + specifier: ^0.153.0 + version: 0.153.0 + vite-plugin-dts: + specifier: ^2.3.0 + version: 2.3.0(vite@4.3.9) + vue: + specifier: ^3.2.47 + version: 3.2.47 + devDependencies: + '@types/three': + specifier: ^0.152.1 + version: 0.152.1 + '@vitejs/plugin-vue': + specifier: ^4.1.0 + version: 4.1.0(vite@4.3.9)(vue@3.2.47) + tslib: + specifier: ^2.5.3 + version: 2.5.3 + typescript: + specifier: ^5.0.2 + version: 5.0.4 + vite: + specifier: ^4.3.9 + version: 4.3.9 + vue-tsc: + specifier: ^1.4.2 + version: 1.4.2(typescript@5.0.4) + + packages/engine: + dependencies: + three: + specifier: ^0.153.0 + version: 0.153.0 + devDependencies: + '@types/three': + specifier: ^0.152.1 + version: 0.152.1 + typescript: + specifier: ^5.0.4 + version: 5.0.4 + +packages: + + /@babel/helper-string-parser@7.21.5: + resolution: {integrity: sha512-5pTUx3hAJaZIdW99sJ6ZUUgWq/Y+Hja7TowEnLNMm1VivRgZQL3vpBY3qUACVsvw+yQU6+YgfBVmcbLaZtrA1w==} + 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.22.4: + resolution: {integrity: sha512-VLLsx06XkEYqBtE5YGPwfSGwfrjnyPP5oiGty3S8pQLFDFLaS8VwWSIxkTXpcvr5zeYLE6+MBNl2npl/YnfofA==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + '@babel/types': 7.22.4 + + /@babel/types@7.22.4: + resolution: {integrity: sha512-Tx9x3UBHTTsMSW85WB2kphxYQVvrZ/t1FxD88IpSgIjiUJlCm9z+xWIDwyo1vffTwSqteqyznB8ZE9vYYk16zA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-string-parser': 7.21.5 + '@babel/helper-validator-identifier': 7.19.1 + to-fast-properties: 2.0.0 + + /@esbuild/android-arm64@0.17.19: + resolution: {integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + optional: true + + /@esbuild/android-arm@0.17.19: + resolution: {integrity: sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + optional: true + + /@esbuild/android-x64@0.17.19: + resolution: {integrity: sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + optional: true + + /@esbuild/darwin-arm64@0.17.19: + resolution: {integrity: sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + optional: true + + /@esbuild/darwin-x64@0.17.19: + resolution: {integrity: sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + optional: true + + /@esbuild/freebsd-arm64@0.17.19: + resolution: {integrity: sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + optional: true + + /@esbuild/freebsd-x64@0.17.19: + resolution: {integrity: sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + optional: true + + /@esbuild/linux-arm64@0.17.19: + resolution: {integrity: sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-arm@0.17.19: + resolution: {integrity: sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-ia32@0.17.19: + resolution: {integrity: sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-loong64@0.17.19: + resolution: {integrity: sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-mips64el@0.17.19: + resolution: {integrity: sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-ppc64@0.17.19: + resolution: {integrity: sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-riscv64@0.17.19: + resolution: {integrity: sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-s390x@0.17.19: + resolution: {integrity: sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-x64@0.17.19: + resolution: {integrity: sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/netbsd-x64@0.17.19: + resolution: {integrity: sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + optional: true + + /@esbuild/openbsd-x64@0.17.19: + resolution: {integrity: sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + optional: true + + /@esbuild/sunos-x64@0.17.19: + resolution: {integrity: sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + optional: true + + /@esbuild/win32-arm64@0.17.19: + resolution: {integrity: sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + optional: true + + /@esbuild/win32-ia32@0.17.19: + resolution: {integrity: sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + optional: true + + /@esbuild/win32-x64@0.17.19: + resolution: {integrity: sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + optional: true + + /@jridgewell/sourcemap-codec@1.4.15: + resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + + /@microsoft/api-extractor-model@7.27.1: + resolution: {integrity: sha512-WgmuQwElTuRLATQxCx+pqk5FtUeRX3FW8WDo7tSDmrN/7+XAggeVg5t8ItiJt688jEdbiPvagZlvjAcJMpXspg==} + dependencies: + '@microsoft/tsdoc': 0.14.2 + '@microsoft/tsdoc-config': 0.16.2 + '@rushstack/node-core-library': 3.59.2 + transitivePeerDependencies: + - '@types/node' + dev: false + + /@microsoft/api-extractor@7.35.1: + resolution: {integrity: sha512-xGVf1lKCYKEyJsspLzQjo4Oo6PGDPH95Z5/te75xQWpcRHcfemb6zTSPtiFeVDHkg9Tan5HW2QXGLwQRkW199w==} + hasBin: true + dependencies: + '@microsoft/api-extractor-model': 7.27.1 + '@microsoft/tsdoc': 0.14.2 + '@microsoft/tsdoc-config': 0.16.2 + '@rushstack/node-core-library': 3.59.2 + '@rushstack/rig-package': 0.3.19 + '@rushstack/ts-command-line': 4.13.3 + colors: 1.2.5 + lodash: 4.17.21 + resolve: 1.22.2 + semver: 7.3.8 + source-map: 0.6.1 + typescript: 5.0.4 + transitivePeerDependencies: + - '@types/node' + dev: false + + /@microsoft/tsdoc-config@0.16.2: + resolution: {integrity: sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==} + dependencies: + '@microsoft/tsdoc': 0.14.2 + ajv: 6.12.6 + jju: 1.4.0 + resolve: 1.19.0 + dev: false + + /@microsoft/tsdoc@0.14.2: + resolution: {integrity: sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==} + dev: false + + /@nodelib/fs.scandir@2.1.5: + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + dev: false + + /@nodelib/fs.stat@2.0.5: + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + dev: false + + /@nodelib/fs.walk@1.2.8: + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.15.0 + dev: false + + /@rollup/pluginutils@5.0.2: + resolution: {integrity: sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0 + peerDependenciesMeta: + rollup: + optional: true + dependencies: + '@types/estree': 1.0.1 + estree-walker: 2.0.2 + picomatch: 2.3.1 + dev: false + + /@rushstack/node-core-library@3.59.2: + resolution: {integrity: sha512-Od8i9ZXiRPHrnkuNOZ9IjEYRQ9JsBLNHlkWJr1wSQZrD2TVIc8APpIB/FnzEcjfpbJMT4XhtcCZaa0pVx+hTXw==} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + dependencies: + colors: 1.2.5 + fs-extra: 7.0.1 + import-lazy: 4.0.0 + jju: 1.4.0 + resolve: 1.22.2 + semver: 7.3.8 + z-schema: 5.0.5 + dev: false + + /@rushstack/rig-package@0.3.19: + resolution: {integrity: sha512-2d0/Gn+qjOYneZbiHjn4SjyDwq9I0WagV37z0F1V71G+yONgH7wlt3K/UoNiDkhA8gTHYPRo2jz3CvttybwSag==} + dependencies: + resolve: 1.22.2 + strip-json-comments: 3.1.1 + dev: false + + /@rushstack/ts-command-line@4.13.3: + resolution: {integrity: sha512-6aQIv/o1EgsC/+SpgUyRmzg2QIAL6sudEzw3sWzJKwWuQTc5XRsyZpyldfE7WAmIqMXDao9QG35/NYORjHm5Zw==} + dependencies: + '@types/argparse': 1.0.38 + argparse: 1.0.10 + colors: 1.2.5 + string-argv: 0.3.2 + dev: false + + /@ts-morph/common@0.19.0: + resolution: {integrity: sha512-Unz/WHmd4pGax91rdIKWi51wnVUW11QttMEPpBiBgIewnc9UQIX7UDLxr5vRlqeByXCwhkF6VabSsI0raWcyAQ==} + dependencies: + fast-glob: 3.2.12 + minimatch: 7.4.6 + mkdirp: 2.1.6 + path-browserify: 1.0.1 + dev: false + + /@tweenjs/tween.js@18.6.4: + resolution: {integrity: sha512-lB9lMjuqjtuJrx7/kOkqQBtllspPIN+96OvTCeJ2j5FEzinoAXTdAMFnDAQT1KVPRlnYfBrqxtqP66vDM40xxQ==} + dev: true + + /@types/argparse@1.0.38: + resolution: {integrity: sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==} + dev: false + + /@types/estree@1.0.1: + resolution: {integrity: sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==} + dev: false + + /@types/stats.js@0.17.0: + resolution: {integrity: sha512-9w+a7bR8PeB0dCT/HBULU2fMqf6BAzvKbxFboYhmDtDkKPiyXYbjoe2auwsXlEFI7CFNMF1dCv3dFH5Poy9R1w==} + dev: true + + /@types/three@0.152.1: + resolution: {integrity: sha512-PMOCQnx9JRmq+2OUGTPoY9h1hTWD2L7/nmuW/SyNq1Vbq3Lwt3MNdl3wYSa4DvLTGv62NmIXD9jYdAOwohwJyw==} + dependencies: + '@tweenjs/tween.js': 18.6.4 + '@types/stats.js': 0.17.0 + '@types/webxr': 0.5.2 + fflate: 0.6.10 + lil-gui: 0.17.0 + dev: true + + /@types/webxr@0.5.2: + resolution: {integrity: sha512-szL74BnIcok9m7QwYtVmQ+EdIKwbjPANudfuvDrAF8Cljg9MKUlIoc1w5tjj9PMpeSH3U1Xnx//czQybJ0EfSw==} + dev: true + + /@vitejs/plugin-vue@4.1.0(vite@4.3.9)(vue@3.2.47): + resolution: {integrity: sha512-++9JOAFdcXI3lyer9UKUV4rfoQ3T1RN8yDqoCLar86s0xQct5yblxAE+yWgRnU5/0FOlVCpTZpYSBV/bGWrSrQ==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + vite: ^4.0.0 + vue: ^3.2.25 + dependencies: + vite: 4.3.9 + vue: 3.2.47 + dev: true + + /@volar/language-core@1.4.0: + resolution: {integrity: sha512-zZg771L/v4MCPwM1KJxvnQ3q3QgbGJtEytivqf+PsxPr0kQ7XtwB1J30dd+YSGN869pXXZ0V6vWdHkDpWC8F3A==} + dependencies: + '@volar/source-map': 1.4.0 + dev: true + + /@volar/source-map@1.4.0: + resolution: {integrity: sha512-gkV8ol9qtP7aMdgijc8a5Yoxxoo90TT55YCi9bsMbKxEUDsOAnlciFNlijR9Ebe42d67GV3w15/RzjveTRNGBw==} + dependencies: + muggle-string: 0.2.2 + dev: true + + /@volar/typescript@1.4.0(typescript@5.0.4): + resolution: {integrity: sha512-r6OMHj/LeS86iQy3LEjjS+qpmHr9I7BiH8gAwp9WEJP76FHlMPi/EPDQxhf3VcMQ/w6Pi5aBczqI+I3akr9t4g==} + peerDependencies: + typescript: '*' + dependencies: + '@volar/language-core': 1.4.0 + typescript: 5.0.4 + dev: true + + /@volar/vue-language-core@1.4.2: + resolution: {integrity: sha512-bDdFowfnyHI7udELEgUWukOh4l9jVTaxb9jZtj0GxUp0Mjj0u81d9+jE2UC3fFJpbndQLGFR6F+ffguHgmrj6Q==} + dependencies: + '@volar/language-core': 1.4.0 + '@volar/source-map': 1.4.0 + '@vue/compiler-dom': 3.3.4 + '@vue/compiler-sfc': 3.3.4 + '@vue/reactivity': 3.3.4 + '@vue/shared': 3.3.4 + minimatch: 9.0.1 + muggle-string: 0.2.2 + vue-template-compiler: 2.7.14 + dev: true + + /@volar/vue-typescript@1.4.2(typescript@5.0.4): + resolution: {integrity: sha512-A1m1cSvS0Pf7Sm9q0S/1riV4RQQeH2h5gGo0vR9fGK2SrAStvh4HuuxPOX4N9uMDbRsNMhC0ILXwtlvjQ/IXJA==} + dependencies: + '@volar/typescript': 1.4.0(typescript@5.0.4) + '@volar/vue-language-core': 1.4.2 + transitivePeerDependencies: + - typescript + dev: true + + /@vue/compiler-core@3.2.47: + resolution: {integrity: sha512-p4D7FDnQb7+YJmO2iPEv0SQNeNzcbHdGByJDsT4lynf63AFkOTFN07HsiRSvjGo0QrxR/o3d0hUyNCUnBU2Tig==} + dependencies: + '@babel/parser': 7.22.4 + '@vue/shared': 3.2.47 + estree-walker: 2.0.2 + source-map: 0.6.1 + + /@vue/compiler-core@3.3.4: + resolution: {integrity: sha512-cquyDNvZ6jTbf/+x+AgM2Arrp6G4Dzbb0R64jiG804HRMfRiFXWI6kqUVqZ6ZR0bQhIoQjB4+2bhNtVwndW15g==} + dependencies: + '@babel/parser': 7.22.4 + '@vue/shared': 3.3.4 + estree-walker: 2.0.2 + source-map-js: 1.0.2 + dev: true + + /@vue/compiler-dom@3.2.47: + resolution: {integrity: sha512-dBBnEHEPoftUiS03a4ggEig74J2YBZ2UIeyfpcRM2tavgMWo4bsEfgCGsu+uJIL/vax9S+JztH8NmQerUo7shQ==} + dependencies: + '@vue/compiler-core': 3.2.47 + '@vue/shared': 3.2.47 + + /@vue/compiler-dom@3.3.4: + resolution: {integrity: sha512-wyM+OjOVpuUukIq6p5+nwHYtj9cFroz9cwkfmP9O1nzH68BenTTv0u7/ndggT8cIQlnBeOo6sUT/gvHcIkLA5w==} + dependencies: + '@vue/compiler-core': 3.3.4 + '@vue/shared': 3.3.4 + dev: true + + /@vue/compiler-sfc@3.2.47: + resolution: {integrity: sha512-rog05W+2IFfxjMcFw10tM9+f7i/+FFpZJJ5XHX72NP9eC2uRD+42M3pYcQqDXVYoj74kHMSEdQ/WmCjt8JFksQ==} + dependencies: + '@babel/parser': 7.22.4 + '@vue/compiler-core': 3.2.47 + '@vue/compiler-dom': 3.2.47 + '@vue/compiler-ssr': 3.2.47 + '@vue/reactivity-transform': 3.2.47 + '@vue/shared': 3.2.47 + estree-walker: 2.0.2 + magic-string: 0.25.9 + postcss: 8.4.24 + source-map: 0.6.1 + + /@vue/compiler-sfc@3.3.4: + resolution: {integrity: sha512-6y/d8uw+5TkCuzBkgLS0v3lSM3hJDntFEiUORM11pQ/hKvkhSKZrXW6i69UyXlJQisJxuUEJKAWEqWbWsLeNKQ==} + dependencies: + '@babel/parser': 7.22.4 + '@vue/compiler-core': 3.3.4 + '@vue/compiler-dom': 3.3.4 + '@vue/compiler-ssr': 3.3.4 + '@vue/reactivity-transform': 3.3.4 + '@vue/shared': 3.3.4 + estree-walker: 2.0.2 + magic-string: 0.30.0 + postcss: 8.4.24 + source-map-js: 1.0.2 + dev: true + + /@vue/compiler-ssr@3.2.47: + resolution: {integrity: sha512-wVXC+gszhulcMD8wpxMsqSOpvDZ6xKXSVWkf50Guf/S+28hTAXPDYRTbLQ3EDkOP5Xz/+SY37YiwDquKbJOgZw==} + dependencies: + '@vue/compiler-dom': 3.2.47 + '@vue/shared': 3.2.47 + + /@vue/compiler-ssr@3.3.4: + resolution: {integrity: sha512-m0v6oKpup2nMSehwA6Uuu+j+wEwcy7QmwMkVNVfrV9P2qE5KshC6RwOCq8fjGS/Eak/uNb8AaWekfiXxbBB6gQ==} + dependencies: + '@vue/compiler-dom': 3.3.4 + '@vue/shared': 3.3.4 + dev: true + + /@vue/reactivity-transform@3.2.47: + resolution: {integrity: sha512-m8lGXw8rdnPVVIdIFhf0LeQ/ixyHkH5plYuS83yop5n7ggVJU+z5v0zecwEnX7fa7HNLBhh2qngJJkxpwEEmYA==} + dependencies: + '@babel/parser': 7.22.4 + '@vue/compiler-core': 3.2.47 + '@vue/shared': 3.2.47 + estree-walker: 2.0.2 + magic-string: 0.25.9 + + /@vue/reactivity-transform@3.3.4: + resolution: {integrity: sha512-MXgwjako4nu5WFLAjpBnCj/ieqcjE2aJBINUNQzkZQfzIZA4xn+0fV1tIYBJvvva3N3OvKGofRLvQIwEQPpaXw==} + dependencies: + '@babel/parser': 7.22.4 + '@vue/compiler-core': 3.3.4 + '@vue/shared': 3.3.4 + estree-walker: 2.0.2 + magic-string: 0.30.0 + dev: true + + /@vue/reactivity@3.2.47: + resolution: {integrity: sha512-7khqQ/75oyyg+N/e+iwV6lpy1f5wq759NdlS1fpAhFXa8VeAIKGgk2E/C4VF59lx5b+Ezs5fpp/5WsRYXQiKxQ==} + dependencies: + '@vue/shared': 3.2.47 + + /@vue/reactivity@3.3.4: + resolution: {integrity: sha512-kLTDLwd0B1jG08NBF3R5rqULtv/f8x3rOFByTDz4J53ttIQEDmALqKqXY0J+XQeN0aV2FBxY8nJDf88yvOPAqQ==} + dependencies: + '@vue/shared': 3.3.4 + dev: true + + /@vue/runtime-core@3.2.47: + resolution: {integrity: sha512-RZxbLQIRB/K0ev0K9FXhNbBzT32H9iRtYbaXb0ZIz2usLms/D55dJR2t6cIEUn6vyhS3ALNvNthI+Q95C+NOpA==} + dependencies: + '@vue/reactivity': 3.2.47 + '@vue/shared': 3.2.47 + + /@vue/runtime-dom@3.2.47: + resolution: {integrity: sha512-ArXrFTjS6TsDei4qwNvgrdmHtD930KgSKGhS5M+j8QxXrDJYLqYw4RRcDy1bz1m1wMmb6j+zGLifdVHtkXA7gA==} + dependencies: + '@vue/runtime-core': 3.2.47 + '@vue/shared': 3.2.47 + csstype: 2.6.21 + + /@vue/server-renderer@3.2.47(vue@3.2.47): + resolution: {integrity: sha512-dN9gc1i8EvmP9RCzvneONXsKfBRgqFeFZLurmHOveL7oH6HiFXJw5OGu294n1nHc/HMgTy6LulU/tv5/A7f/LA==} + peerDependencies: + vue: 3.2.47 + dependencies: + '@vue/compiler-ssr': 3.2.47 + '@vue/shared': 3.2.47 + vue: 3.2.47 + + /@vue/shared@3.2.47: + resolution: {integrity: sha512-BHGyyGN3Q97EZx0taMQ+OLNuZcW3d37ZEVmEAyeoA9ERdGvm9Irc/0Fua8SNyOtV1w6BS4q25wbMzJujO9HIfQ==} + + /@vue/shared@3.3.4: + resolution: {integrity: sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ==} + dev: true + + /ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + dev: false + + /argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + dependencies: + sprintf-js: 1.0.3 + dev: false + + /balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + /brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + dependencies: + balanced-match: 1.0.2 + + /braces@3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.0.1 + dev: false + + /code-block-writer@12.0.0: + resolution: {integrity: sha512-q4dMFMlXtKR3XNBHyMHt/3pwYNA69EDk00lloMOaaUMKPUXBw6lpXtbu3MMVG6/uOihGnRDOlkyqsONEUj60+w==} + dev: false + + /colors@1.2.5: + resolution: {integrity: sha512-erNRLao/Y3Fv54qUa0LBB+//Uf3YwMUmdJinN20yMXm9zdKKqH9wt7R9IIVZ+K7ShzfpLV/Zg8+VyrBJYB4lpg==} + engines: {node: '>=0.1.90'} + dev: false + + /commander@9.5.0: + resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} + engines: {node: ^12.20.0 || >=14} + requiresBuild: true + dev: false + optional: true + + /csstype@2.6.21: + resolution: {integrity: sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==} + + /de-indent@1.0.2: + resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==} + dev: true + + /debug@4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + dev: false + + /esbuild@0.17.19: + resolution: {integrity: sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/android-arm': 0.17.19 + '@esbuild/android-arm64': 0.17.19 + '@esbuild/android-x64': 0.17.19 + '@esbuild/darwin-arm64': 0.17.19 + '@esbuild/darwin-x64': 0.17.19 + '@esbuild/freebsd-arm64': 0.17.19 + '@esbuild/freebsd-x64': 0.17.19 + '@esbuild/linux-arm': 0.17.19 + '@esbuild/linux-arm64': 0.17.19 + '@esbuild/linux-ia32': 0.17.19 + '@esbuild/linux-loong64': 0.17.19 + '@esbuild/linux-mips64el': 0.17.19 + '@esbuild/linux-ppc64': 0.17.19 + '@esbuild/linux-riscv64': 0.17.19 + '@esbuild/linux-s390x': 0.17.19 + '@esbuild/linux-x64': 0.17.19 + '@esbuild/netbsd-x64': 0.17.19 + '@esbuild/openbsd-x64': 0.17.19 + '@esbuild/sunos-x64': 0.17.19 + '@esbuild/win32-arm64': 0.17.19 + '@esbuild/win32-ia32': 0.17.19 + '@esbuild/win32-x64': 0.17.19 + + /estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + + /fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + dev: false + + /fast-glob@3.2.12: + resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + dev: false + + /fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + dev: false + + /fastq@1.15.0: + resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} + dependencies: + reusify: 1.0.4 + dev: false + + /fflate@0.6.10: + resolution: {integrity: sha512-IQrh3lEPM93wVCEczc9SaAOvkmcoQn/G8Bo1e8ZPlY3X3bnAxWaBdvTdvM1hP62iZp0BXWDy4vTAy4fF0+Dlpg==} + dev: true + + /fill-range@7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + dev: false + + /fs-extra@10.1.0: + resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} + engines: {node: '>=12'} + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.0 + dev: false + + /fs-extra@7.0.1: + resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} + engines: {node: '>=6 <7 || >=8'} + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + dev: false + + /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 + optional: true + + /function-bind@1.1.1: + resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} + dev: false + + /glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.3 + dev: false + + /graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + dev: false + + /has@1.0.3: + resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} + engines: {node: '>= 0.4.0'} + dependencies: + function-bind: 1.1.1 + dev: false + + /he@1.2.0: + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} + hasBin: true + dev: true + + /import-lazy@4.0.0: + resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} + engines: {node: '>=8'} + dev: false + + /is-core-module@2.12.1: + resolution: {integrity: sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==} + dependencies: + has: 1.0.3 + dev: false + + /is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + dev: false + + /is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + dev: false + + /is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + dev: false + + /jju@1.4.0: + resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} + dev: false + + /json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + dev: false + + /jsonfile@4.0.0: + resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + optionalDependencies: + graceful-fs: 4.2.11 + dev: false + + /jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + dependencies: + universalify: 2.0.0 + optionalDependencies: + graceful-fs: 4.2.11 + dev: false + + /kolorist@1.8.0: + resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} + dev: false + + /lil-gui@0.17.0: + resolution: {integrity: sha512-MVBHmgY+uEbmJNApAaPbtvNh1RCAeMnKym82SBjtp5rODTYKWtM+MXHCifLe2H2Ti1HuBGBtK/5SyG4ShQ3pUQ==} + dev: true + + /lodash.get@4.4.2: + resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} + dev: false + + /lodash.isequal@4.5.0: + resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} + dev: false + + /lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + dev: false + + /lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + dependencies: + yallist: 4.0.0 + + /magic-string@0.25.9: + resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} + dependencies: + sourcemap-codec: 1.4.8 + + /magic-string@0.29.0: + resolution: {integrity: sha512-WcfidHrDjMY+eLjlU+8OvwREqHwpgCeKVBUpQ3OhYYuvfaYCUgcbuBzappNzZvg/v8onU3oQj+BYpkOJe9Iw4Q==} + engines: {node: '>=12'} + dependencies: + '@jridgewell/sourcemap-codec': 1.4.15 + dev: false + + /magic-string@0.30.0: + resolution: {integrity: sha512-LA+31JYDJLs82r2ScLrlz1GjSgu66ZV518eyWT+S8VhyQn/JL0u9MeBOvQMGYiPk1DBiSN9DDMOcXvigJZaViQ==} + engines: {node: '>=12'} + dependencies: + '@jridgewell/sourcemap-codec': 1.4.15 + dev: true + + /merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + dev: false + + /micromatch@4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} + dependencies: + braces: 3.0.2 + picomatch: 2.3.1 + dev: false + + /minimatch@7.4.6: + resolution: {integrity: sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==} + engines: {node: '>=10'} + dependencies: + brace-expansion: 2.0.1 + dev: false + + /minimatch@9.0.1: + resolution: {integrity: sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + brace-expansion: 2.0.1 + dev: true + + /mkdirp@2.1.6: + resolution: {integrity: sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A==} + engines: {node: '>=10'} + hasBin: true + dev: false + + /ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + dev: false + + /muggle-string@0.2.2: + resolution: {integrity: sha512-YVE1mIJ4VpUMqZObFndk9CJu6DBJR/GB13p3tXuNbwD4XExaI5EOuRl6BHeIDxIqXZVxSfAC+y6U1Z/IxCfKUg==} + dev: true + + /nanoid@3.3.6: + resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + /path-browserify@1.0.1: + resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} + dev: false + + /path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + dev: false + + /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: false + + /postcss@8.4.24: + resolution: {integrity: sha512-M0RzbcI0sO/XJNucsGjvWU9ERWxb/ytp1w6dKtxTKgixdtQDq4rmx/g8W1hnaheq9jgwL/oyEdH5Bc4WwJKMqg==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.6 + picocolors: 1.0.0 + source-map-js: 1.0.2 + + /punycode@2.3.0: + resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} + engines: {node: '>=6'} + dev: false + + /queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + dev: false + + /resolve@1.19.0: + resolution: {integrity: sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==} + dependencies: + is-core-module: 2.12.1 + path-parse: 1.0.7 + dev: false + + /resolve@1.22.2: + resolution: {integrity: sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==} + hasBin: true + dependencies: + is-core-module: 2.12.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: false + + /reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + dev: false + + /rollup@3.23.0: + resolution: {integrity: sha512-h31UlwEi7FHihLe1zbk+3Q7z1k/84rb9BSwmBSr/XjOCEaBJ2YyedQDuM0t/kfOS0IxM+vk1/zI9XxYj9V+NJQ==} + engines: {node: '>=14.18.0', npm: '>=8.0.0'} + hasBin: true + optionalDependencies: + fsevents: 2.3.2 + + /run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + dependencies: + queue-microtask: 1.2.3 + dev: false + + /semver@7.3.8: + resolution: {integrity: sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: false + + /semver@7.5.1: + resolution: {integrity: sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==} + 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 + + /sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + dev: false + + /string-argv@0.3.2: + resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} + engines: {node: '>=0.6.19'} + dev: false + + /strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + dev: false + + /supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + dev: false + + /three@0.153.0: + resolution: {integrity: sha512-OCP2/uQR6GcDpSLnJt/3a4mdS0kNWcbfUXIwLoEMgLzEUIVIYsSDwskpmOii/AkDM+BBwrl6+CKgrjX9+E2aWg==} + dev: false + + /to-fast-properties@2.0.0: + resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} + engines: {node: '>=4'} + + /to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + dev: false + + /ts-morph@18.0.0: + resolution: {integrity: sha512-Kg5u0mk19PIIe4islUI/HWRvm9bC1lHejK4S0oh1zaZ77TMZAEmQC0sHQYiu2RgCQFZKXz1fMVi/7nOOeirznA==} + dependencies: + '@ts-morph/common': 0.19.0 + code-block-writer: 12.0.0 + dev: false + + /tslib@2.5.3: + resolution: {integrity: sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==} + dev: true + + /typescript@5.0.4: + resolution: {integrity: sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==} + engines: {node: '>=12.20'} + hasBin: true + + /universalify@0.1.2: + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} + engines: {node: '>= 4.0.0'} + dev: false + + /universalify@2.0.0: + resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==} + engines: {node: '>= 10.0.0'} + dev: false + + /uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + dependencies: + punycode: 2.3.0 + dev: false + + /validator@13.9.0: + resolution: {integrity: sha512-B+dGG8U3fdtM0/aNK4/X8CXq/EcxU2WPrPEkJGslb47qyHsxmbggTWK0yEA4qnYVNF+nxNlN88o14hIcPmSIEA==} + engines: {node: '>= 0.10'} + dev: false + + /vite-plugin-dts@2.3.0(vite@4.3.9): + resolution: {integrity: sha512-WbJgGtsStgQhdm3EosYmIdTGbag5YQpZ3HXWUAPCDyoXI5qN6EY0V7NXq0lAmnv9hVQsvh0htbYcg0Or5Db9JQ==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + vite: '>=2.9.0' + dependencies: + '@babel/parser': 7.22.4 + '@microsoft/api-extractor': 7.35.1 + '@rollup/pluginutils': 5.0.2 + '@rushstack/node-core-library': 3.59.2 + debug: 4.3.4 + fast-glob: 3.2.12 + fs-extra: 10.1.0 + kolorist: 1.8.0 + magic-string: 0.29.0 + ts-morph: 18.0.0 + vite: 4.3.9 + transitivePeerDependencies: + - '@types/node' + - rollup + - supports-color + dev: false + + /vite@4.3.9: + resolution: {integrity: sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==} + 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: + esbuild: 0.17.19 + postcss: 8.4.24 + rollup: 3.23.0 + optionalDependencies: + fsevents: 2.3.2 + + /vue-template-compiler@2.7.14: + resolution: {integrity: sha512-zyA5Y3ArvVG0NacJDkkzJuPQDF8RFeRlzV2vLeSnhSpieO6LK2OVbdLPi5MPPs09Ii+gMO8nY4S3iKQxBxDmWQ==} + dependencies: + de-indent: 1.0.2 + he: 1.2.0 + dev: true + + /vue-tsc@1.4.2(typescript@5.0.4): + resolution: {integrity: sha512-8VFjVekJuFtFG+N4rEimoR0OvNubhoTIMl2dlvbpyAD40LVPR1PN2SUc2qZPnWGGRsXZAVmFgiBHX0RB20HGyA==} + hasBin: true + peerDependencies: + typescript: '*' + dependencies: + '@volar/vue-language-core': 1.4.2 + '@volar/vue-typescript': 1.4.2(typescript@5.0.4) + semver: 7.5.1 + typescript: 5.0.4 + dev: true + + /vue@3.2.47: + resolution: {integrity: sha512-60188y/9Dc9WVrAZeUVSDxRQOZ+z+y5nO2ts9jWXSTkMvayiWxCWOWtBQoYjLeccfXkiiPZWAHcV+WTPhkqJHQ==} + dependencies: + '@vue/compiler-dom': 3.2.47 + '@vue/compiler-sfc': 3.2.47 + '@vue/runtime-dom': 3.2.47 + '@vue/server-renderer': 3.2.47(vue@3.2.47) + '@vue/shared': 3.2.47 + + /yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + + /z-schema@5.0.5: + resolution: {integrity: sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==} + engines: {node: '>=8.0.0'} + hasBin: true + dependencies: + lodash.get: 4.4.2 + lodash.isequal: 4.5.0 + validator: 13.9.0 + optionalDependencies: + commander: 9.5.0 + dev: false diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..44665b7 --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,3 @@ +packages: + - 'apps/**' + - 'packages/**' diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..e2451ff --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "ESNext", + "declaration": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + /* Linting */ + "strict": true, + "skipLibCheck": true, + "noFallthroughCasesInSwitch": true, + "moduleResolution": "bundler" + } +}