diff --git a/.env b/.env index 1237f78..fb13bf2 100644 --- a/.env +++ b/.env @@ -1,4 +1,4 @@ -PORT=3006 +PORT=5001 VITE_API_URL_DEV="http://localhost:3000" VITE_API_URL_PROD="localhost:3000" VITE_API_S3_PATH="https://s3.cloudfly.vn" \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 5147ef5..3cc68f6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "0.0.0", "dependencies": { "@preact/signals-react": "^1.3.7", + "@radix-ui/react-checkbox": "^1.0.4", "@radix-ui/react-dialog": "^1.0.5", "@radix-ui/react-label": "^2.0.2", "@radix-ui/react-select": "^2.0.0", @@ -36,9 +37,11 @@ "react-toastify": "^10.0.5", "tailwind-merge": "^2.3.0", "tailwindcss-animate": "^1.0.7", + "tailwindcss-animated": "^1.0.1", "three": "^0.163.0", "three-mesh-bvh": "^0.7.4", "three-stdlib": "^2.29.6", + "vaul": "^0.9.1", "web-ifc": "^0.0.54" }, "devDependencies": { @@ -57,7 +60,9 @@ "postcss": "^8.4.35", "tailwindcss": "^3.4.1", "typescript": "^5.0.2", - "vite": "^4.3.9" + "vite": "^4.3.9", + "vite-plugin-glsl": "^1.3.0", + "vite-plugin-svgr": "^3.3.0" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -1129,6 +1134,36 @@ } } }, + "node_modules/@radix-ui/react-checkbox": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.0.4.tgz", + "integrity": "sha512-CBuGQa52aAYnADZVt/KBQzXrwx6TqnlwtcIPGtVt5JkkzQwMOLJjPukimhfKEr4GQNd43C+djUh5Ikopj8pSLg==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-presence": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-controllable-state": "1.0.1", + "@radix-ui/react-use-previous": "1.0.1", + "@radix-ui/react-use-size": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-collection": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.0.3.tgz", @@ -1801,6 +1836,241 @@ "node": ">=14.0.0" } }, + "node_modules/@rollup/pluginutils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz", + "integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@svgr/babel-plugin-add-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", + "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", + "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-dynamic-title": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", + "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-em-dimensions": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", + "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-react-native-svg": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz", + "integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-svg-component": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", + "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-preset": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz", + "integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==", + "dev": true, + "dependencies": { + "@svgr/babel-plugin-add-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "8.0.0", + "@svgr/babel-plugin-replace-jsx-attribute-value": "8.0.0", + "@svgr/babel-plugin-svg-dynamic-title": "8.0.0", + "@svgr/babel-plugin-svg-em-dimensions": "8.0.0", + "@svgr/babel-plugin-transform-react-native-svg": "8.1.0", + "@svgr/babel-plugin-transform-svg-component": "8.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/core": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", + "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "camelcase": "^6.2.0", + "cosmiconfig": "^8.1.3", + "snake-case": "^3.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/hast-util-to-babel-ast": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", + "integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==", + "dev": true, + "dependencies": { + "@babel/types": "^7.21.3", + "entities": "^4.4.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/plugin-jsx": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz", + "integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "@svgr/hast-util-to-babel-ast": "8.0.0", + "svg-parser": "^2.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" + } + }, "node_modules/@tweenjs/tween.js": { "version": "23.1.1", "resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-23.1.1.tgz", @@ -1853,6 +2123,12 @@ "resolved": "https://registry.npmjs.org/@types/draco3d/-/draco3d-1.4.9.tgz", "integrity": "sha512-4MMUjMQb4yA5fJ4osXx+QxGHt0/ZSy4spT6jL1HM7Tn8OJEC35siqdnpOo+HxPhYjqEFumKfGVF9hJfdyKBIBA==" }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -2387,6 +2663,18 @@ "node": ">=6" } }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/camelcase-css": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", @@ -2544,6 +2832,32 @@ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true }, + "node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -2649,6 +2963,22 @@ "node": ">=6.0.0" } }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dev": true, + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/dot-case/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + }, "node_modules/draco3d": { "version": "1.5.7", "resolved": "https://registry.npmjs.org/draco3d/-/draco3d-1.5.7.tgz", @@ -2675,6 +3005,27 @@ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, "node_modules/esbuild": { "version": "0.18.20", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", @@ -3021,6 +3372,12 @@ "node": ">=4.0" } }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -3399,6 +3756,12 @@ "loose-envify": "^1.0.0" } }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -3530,6 +3893,12 @@ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -3621,6 +3990,21 @@ "loose-envify": "cli.js" } }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/lower-case/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -3762,6 +4146,22 @@ "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", "dev": true }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/no-case/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + }, "node_modules/node-releases": { "version": "2.0.14", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", @@ -3869,6 +4269,24 @@ "node": ">=6" } }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -4574,6 +4992,22 @@ "node": ">=8" } }, + "node_modules/snake-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", + "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "dev": true, + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/snake-case/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + }, "node_modules/source-map-js": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", @@ -4764,6 +5198,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/svg-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==", + "dev": true + }, "node_modules/tailwind-merge": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.3.0.tgz", @@ -4820,6 +5260,14 @@ "tailwindcss": ">=3.0.0 || insiders" } }, + "node_modules/tailwindcss-animated": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tailwindcss-animated/-/tailwindcss-animated-1.0.1.tgz", + "integrity": "sha512-u5wusj89ZwP8I+s8WZlaAd7aZTWBN/XEG6QgMKpkIKmAf3xP1A6WYf7oYIKmGaB10UAQaSqWopi/i1ozzZEs8Q==", + "peerDependencies": { + "tailwindcss": ">=3.1.0" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -5066,6 +5514,18 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, + "node_modules/vaul": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/vaul/-/vaul-0.9.1.tgz", + "integrity": "sha512-fAhd7i4RNMinx+WEm6pF3nOl78DFkAazcN04ElLPFF9BMCNGbY/kou8UMhIcicm0rJCNePJP0Yyza60gGOD0Jw==", + "dependencies": { + "@radix-ui/react-dialog": "^1.0.4" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + } + }, "node_modules/vite": { "version": "4.5.3", "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.3.tgz", @@ -5121,6 +5581,36 @@ } } }, + "node_modules/vite-plugin-glsl": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/vite-plugin-glsl/-/vite-plugin-glsl-1.3.0.tgz", + "integrity": "sha512-SzEoLet9Bp5VSozjrhUiSc3xX1+u7rCTjXAsq4qWM3u8UjilI76A9ucX/T+CRGQCe25j50GSY+9mKSGUVPET1w==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^5.1.0" + }, + "engines": { + "node": ">= 16.15.1", + "npm": ">= 8.11.0" + }, + "peerDependencies": { + "vite": "^3.0.0 || ^4.0.0 || ^5.0.0" + } + }, + "node_modules/vite-plugin-svgr": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/vite-plugin-svgr/-/vite-plugin-svgr-3.3.0.tgz", + "integrity": "sha512-vWZMCcGNdPqgziYFKQ3Y95XP0d0YGp28+MM3Dp9cTa/px5CKcHHrIoPl2Jw81rgVm6/ZUNONzjXbZQZ7Kw66og==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^5.0.4", + "@svgr/core": "^8.1.0", + "@svgr/plugin-jsx": "^8.1.0" + }, + "peerDependencies": { + "vite": "^2.6.0 || 3 || 4" + } + }, "node_modules/web-ifc": { "version": "0.0.54", "resolved": "https://registry.npmjs.org/web-ifc/-/web-ifc-0.0.54.tgz", diff --git a/package.json b/package.json index ee733da..8bd2ab5 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ }, "dependencies": { "@preact/signals-react": "^1.3.7", + "@radix-ui/react-checkbox": "^1.0.4", "@radix-ui/react-dialog": "^1.0.5", "@radix-ui/react-label": "^2.0.2", "@radix-ui/react-select": "^2.0.0", @@ -39,9 +40,11 @@ "react-toastify": "^10.0.5", "tailwind-merge": "^2.3.0", "tailwindcss-animate": "^1.0.7", + "tailwindcss-animated": "^1.0.1", "three": "^0.163.0", "three-mesh-bvh": "^0.7.4", "three-stdlib": "^2.29.6", + "vaul": "^0.9.1", "web-ifc": "^0.0.54" }, "devDependencies": { @@ -60,6 +63,8 @@ "postcss": "^8.4.35", "tailwindcss": "^3.4.1", "typescript": "^5.0.2", - "vite": "^4.3.9" + "vite": "^4.3.9", + "vite-plugin-glsl": "^1.3.0", + "vite-plugin-svgr": "^3.3.0" } } diff --git a/src/BimModel/index.ts b/src/BimModel/index.ts index 9b1b5d4..7f6dda5 100644 --- a/src/BimModel/index.ts +++ b/src/BimModel/index.ts @@ -6,6 +6,7 @@ import { ModelingComponent, PropertyComponent, RendererComponent, + RaycasterComponent, StructureComponent, ProjectComponent, SystemComponent, @@ -33,22 +34,41 @@ export class BimModel { private init() { this.components = new Components(this.container); + + /* =====MaterialComponent===== */ const materialManager = this.components.tools.get(MaterialComponent); materialManager.enabled = true; + + /* =====ProjectComponent===== */ const projectComponent = this.components.tools.get(ProjectComponent); projectComponent.enabled = true; + + /* =====RendererComponent===== */ const renderer = this.components.tools.get(RendererComponent); renderer.enabled = true; + + /* =====RaycasterComponent===== */ + const raycasterComponent = this.components.tools.get(RaycasterComponent); + raycasterComponent.enabled = true; + + /* =====CubeMapComponent===== */ const cubeMapComponent = this.components.tools.get(CubeMapComponent); cubeMapComponent.enabled = true; + + /* =====ModelingComponent===== */ const modelingComponent = this.components.tools.get(ModelingComponent); modelingComponent.enabled = true; modelingComponent.init(this.modeling, this.option); + + /* =====PropertyComponent===== */ const propertyComponent = this.components.tools.get(PropertyComponent); propertyComponent.enabled = true; + + /* =====StructureComponent===== */ const structureComponent = this.components.tools.get(StructureComponent); structureComponent.enabled = true; structureComponent.init(this.structure); + new SystemComponent(this.components); this.components.gameLoop(); } diff --git a/src/BimModel/src/Components/index.ts b/src/BimModel/src/Components/index.ts index 42a0cdb..3959ef9 100644 --- a/src/BimModel/src/Components/index.ts +++ b/src/BimModel/src/Components/index.ts @@ -8,7 +8,14 @@ import { } from "three-mesh-bvh"; import {effect} from "@preact/signals-react"; import {appTheme} from "@signals/theme"; -import {isModelingSignal, isOrthoSignal, keyboardSignal} from "../Signals"; +import { + isModelingSignal, + isOrthoSignal, + keyboardSignal, + visibilityStateSignal, +} from "../Signals"; +import {RendererComponent} from "../RendererComponent"; +import {SceneBuilder} from "./types"; /** * The entry point of Open BIM Components. * It contains the basic items to create a BIM 3D scene based on Three.js, as @@ -28,8 +35,21 @@ export class Components implements Disposable { enabled = true; public scene = new THREE.Scene(); + public modelScene = new SceneBuilder(); + public annotationScene = new SceneBuilder(); public canvas!: HTMLCanvasElement; private clock!: THREE.Clock; + get rect(): DOMRect { + if (!this.container) throw new Error("Not Initialized!"); + return this.container.getBoundingClientRect(); + } + + set ctrlKey(enabled: boolean) { + const mouseButtons = + this.tools.get(RendererComponent)!.camera.cameraControls.mouseButtons; + if (!mouseButtons) return; + mouseButtons.left = visibilityStateSignal.value === "3D" && enabled ? 1 : 0; + } set setupEvent(enabled: boolean) { if (enabled) { window.addEventListener("resize", this.onResize); @@ -41,16 +61,14 @@ export class Components implements Disposable { document.removeEventListener("keyup", this.onKeyUp); } } - get rect(): DOMRect { - if (!this.container) throw new Error("Not Initialized!"); - return this.container.getBoundingClientRect(); - } constructor(public container: HTMLDivElement) { this.init(); this.setupBVH(); this.tools = new ToolComponent(this); this.setupEvent = true; + this.scene.add(this.modelScene); + this.scene.add(this.annotationScene); effect(() => { this.scene.background = appTheme.value === "dark" ? null : sceneBG; }); @@ -60,6 +78,13 @@ export class Components implements Disposable { this.setupEvent = false; this.canvas?.remove(); (this.canvas as any) = null; + this.modelScene.dispose(); + this.modelScene.removeFromParent(); + (this.modelScene as any) = null; + this.annotationScene.dispose(); + this.annotationScene.removeFromParent(); + (this.annotationScene as any) = null; + (this.scene as any) = null; await this.tools.dispose(); } async init() { @@ -89,9 +114,11 @@ export class Components implements Disposable { isModelingSignal.value = false; if (e.key === "F8") isOrthoSignal.value = !isOrthoSignal.value; keyboardSignal.value = e.key; + this.ctrlKey = e.key === "Control"; }; private onKeyUp = (_e: KeyboardEvent) => { keyboardSignal.value = null; + this.ctrlKey = false; }; private initClock() { diff --git a/src/BimModel/src/Components/types.ts b/src/BimModel/src/Components/types.ts new file mode 100644 index 0000000..79738ea --- /dev/null +++ b/src/BimModel/src/Components/types.ts @@ -0,0 +1,18 @@ +/** + * @module Components + */ +import * as THREE from "three"; +import {Disposable} from "@BimModel/src/types"; + +export class SceneBuilder extends THREE.Scene implements Disposable { + get meshes() { + return this.children; + } + /** + * + */ + constructor() { + super(); + } + async dispose() {} +} diff --git a/src/BimModel/src/MaterialComponent/index.ts b/src/BimModel/src/MaterialComponent/index.ts index d7715d6..e7cc103 100644 --- a/src/BimModel/src/MaterialComponent/index.ts +++ b/src/BimModel/src/MaterialComponent/index.ts @@ -11,14 +11,17 @@ export class MaterialComponent implements Disposable, Updateable { static readonly uuid = UUID.MaterialComponent; - static readonly exclude = ["LocationMaterial"]; + static readonly exclude = ["LocationMaterial", "DimensionMaterial"]; enabled = false; listMaterial: Map< string, THREE.MeshLambertMaterial | THREE.MeshBasicMaterial | LineMaterial > = new Map(); - get LocationMaterial() { - return this.listMaterial.get("LocationMaterial"); + get LocationMaterial(): LineMaterial { + return this.listMaterial.get("LocationMaterial") as LineMaterial; + } + get DimensionMaterial(): LineMaterial { + return this.listMaterial.get("DimensionMaterial") as LineMaterial; } get() { return MaterialComponent.uuid; @@ -34,12 +37,18 @@ export class MaterialComponent new LineMaterial({ linewidth: 1, // in world units with size attenuation, pixels otherwise vertexColors: true, - color: 0xfcb603, + color: 0xeb1405, + alphaToCoverage: true, + depthTest: false, + }) + ); + this.addMaterial( + "DimensionMaterial", + new LineMaterial({ + linewidth: 0.5, // in world units with size attenuation, pixels otherwise + vertexColors: true, + color: 0x0303fc, alphaToCoverage: true, - dashed: false, - dashScale: 1, - dashSize: 1, - gapSize: 1, depthTest: false, }) ); @@ -51,12 +60,13 @@ export class MaterialComponent }); effect(() => { (this.LocationMaterial as LineMaterial).linewidth = - lineTypeSignal.value === "thin" ? 0.5 : 3; + lineTypeSignal.value === "thin" ? 2 : 6; }); } update(_delta?: number): void { const {width, height} = this.components.rect; (this.LocationMaterial as LineMaterial)?.resolution.set(width, height); + (this.DimensionMaterial as LineMaterial)?.resolution.set(width, height); } async dispose() { for (const [_, mat] of this.listMaterial) { diff --git a/src/BimModel/src/ModelingComponent/index.ts b/src/BimModel/src/ModelingComponent/index.ts index 3ec3454..6f664c5 100644 --- a/src/BimModel/src/ModelingComponent/index.ts +++ b/src/BimModel/src/ModelingComponent/index.ts @@ -1,8 +1,18 @@ +/** + * @module ModelingComponent + */ + import {Components} from "../Components"; import {ProjectComponent} from "../ProjectComponent"; import {ToolComponent} from "../Tool"; import {Component, Disposable, UUID} from "../types"; import {createModelingContainer, createOptionContainer} from "./src"; + +export {ModelingTools} from "./src/constants"; + +/** + * + */ export class ModelingComponent extends Component implements Disposable { static readonly uuid = UUID.ModelingComponent; enabled = false; @@ -21,8 +31,8 @@ export class ModelingComponent extends Component implements Disposable { } async dispose() { this.modelingContainer?.remove(); - this.optionContainer?.remove(); (this.modelingContainer as any) = null; + this.optionContainer?.remove(); (this.optionContainer as any) = null; } get() { diff --git a/src/BimModel/src/ModelingComponent/src/InitComponents.tsx b/src/BimModel/src/ModelingComponent/src/InitComponents.tsx index 27c2e97..d48f1b3 100644 --- a/src/BimModel/src/ModelingComponent/src/InitComponents.tsx +++ b/src/BimModel/src/ModelingComponent/src/InitComponents.tsx @@ -8,6 +8,7 @@ import Units from "./Units/Units"; import NewProject from "./Project/NewProject"; import VisibilityOption from "./VisibilityOption/VisibilityOption"; import LineOption from "./LineOption/LineOption"; +import WorkPlaneOption from "./WorkPlaneOption/WorkPlaneOption"; export function createModelingContainer(modeling: ModelingComponent) { const div = document.createElement("div"); @@ -29,6 +30,7 @@ export function createOptionContainer(_modeling: ModelingComponent) {
+
diff --git a/src/BimModel/src/ModelingComponent/src/ModelingOption/ModelingOption.tsx b/src/BimModel/src/ModelingComponent/src/ModelingOption/ModelingOption.tsx index 9fb36c0..acd2c21 100644 --- a/src/BimModel/src/ModelingComponent/src/ModelingOption/ModelingOption.tsx +++ b/src/BimModel/src/ModelingComponent/src/ModelingOption/ModelingOption.tsx @@ -1,10 +1,9 @@ -import React from "react"; +import React, {useState} from "react"; const ModelingOption = () => { + const [open, setOpen] = useState(false); return ( -
- ModelingOption -
+
); }; diff --git a/src/BimModel/src/ModelingComponent/src/Units/Units.tsx b/src/BimModel/src/ModelingComponent/src/Units/Units.tsx index 9123ad7..279e197 100644 --- a/src/BimModel/src/ModelingComponent/src/Units/Units.tsx +++ b/src/BimModel/src/ModelingComponent/src/Units/Units.tsx @@ -6,21 +6,21 @@ import { SelectTrigger, SelectValue, } from "@components/ui/select"; -import {ListUnits, unitSignal} from "@BimModel/src/Signals"; -import {IUnit} from "@BimModel/src/ProjectComponent/types"; +import {ListUnits, unitSymbolSignal} from "@BimModel/src/Signals"; +import {IUnitSymbol} from "@BimModel/src/ProjectComponent/types"; const Units = () => { return (