diff --git a/.eslintrc.json b/.eslintrc.json
index d66845bf..9bf56c59 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -12,7 +12,8 @@
"ecmaVersion": "latest"
},
"plugins": [
- "@typescript-eslint"
+ "@typescript-eslint",
+ "simple-import-sort"
],
"rules": {
"linebreak-style": "off",
@@ -31,6 +32,11 @@
"no-unused-vars": "warn",
"brace-style": [2, "1tbs", { "allowSingleLine": true }],
"block-spacing": [2, "always"],
- "semi": "error"
+ "semi": "error",
+ "spaced-comment": "off",
+ "keyword-spacing": "off",
+ "space-before-function-paren": "off",
+ "simple-import-sort/imports": "error",
+ "simple-import-sort/exports": "error"
}
}
diff --git a/.gitignore b/.gitignore
index 41a84202..aeb0decc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,5 +11,9 @@ ObjToSchematic-darwin-x64
/dev
/tools/blocks
/tools/models
+/tests/out
+/logs/
notes.txt
-*.DS_Store
\ No newline at end of file
+*.DS_Store
+.dependency-cruiser.js
+dependencygraph.svg
\ No newline at end of file
diff --git a/README.md b/README.md
index 92a20019..515b5054 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,6 @@
-
-
+
ObjToSchematic
@@ -19,8 +18,10 @@
-![Preview](https://i.imgur.com/HgQaEIO.png)
-"Homo erectus georgicus" (https://skfb.ly/6ADT8) by Geoffrey Marchal is licensed under Creative Commons Attribution-NonCommercial (http://creativecommons.org/licenses/by-nc/4.0/).
+
+
+ "Noodle Bowl - 3DDecember Day9" (https://skfb.ly/orI9z) by Batuhan13 is licensed under Creative Commons Attribution (http://creativecommons.org/licenses/by/4.0/).
+
## Usage
You can either download the [latest release](https://github.com/LucasDower/ObjToSchematic/releases) or if you want the latest features you can build it yourself by following the instructions below.
@@ -31,6 +32,11 @@ You can either download the [latest release](https://github.com/LucasDower/ObjTo
* Run `npm install`.
* Run `npm start`.
+
+
+ "Cut Fish" (https://skfb.ly/orWLC) by Suushimi is licensed under Creative Commons Attribution-NonCommercial (http://creativecommons.org/licenses/by-nc/4.0/).
+
+
### Advanced
#### Block Palettes
@@ -87,19 +93,20 @@ If you want to use the program without using the GUI, you can edit `/tools/headl
* 🟢 **Buffer refactor to support `OES_element_index_uint` WebGL extension (support for uint32 index buffers instead of uint16)**
0.6
+* 🟢 **Web workers**
+ * Processing UI animation
+ * Prevent UI hanging
* 🟢 **Options for handling falling blocks and overlapping voxels**
* 🟢 **Sponge schematics exporter (.schem)**
* 🟢 **Structure blocks exporter (.nbt)**
-* ⚪ Support for simplifying complex meshes
-* 🟡 Web workers (see [web-workers](https://github.com/LucasDower/ObjToSchematic/tree/web-workers))
- * Progress bar
- * Prevent UI hanging
-* 🟢 Alpha support
+* 🟢 **Alpha support**
* Alpha texture maps
* Transparent blocks
-* ⚪ Importers for .fbx and .gltf
+* 🟢 **Config file**
+* 🟢 **Log files**
0.7
+* ⚪ Support for simplifying complex meshes
* ⚪ Node.js C++ addons
* ⚪ Block painting
* ⚪ Building guides
@@ -114,9 +121,9 @@ This is an non-commercial **unofficial** tool that is neither approved, endorsed
![MinecraftPreview](https://i.imgur.com/LhTZ4G9.png)
## Contributing
-Any contributions are welcome, just fork and submit a PR! Just make sure the code style follows the rulings in the `.eslintrc.json` and pass the CI build task.
+Any contributions are welcome, just fork and submit a PR! Just make sure the code style follows the rulings in the `.eslintrc.json` by running `npm run lint` and the tests all pass by running `npm test`.
-Currently there's not much docs but if you're looking for where to get started, look at `app_context.ts` and follow `_import()`, `_simplify()`, `_voxelise()`, `_assign()`, and `_export()`. If you're looking to add elements to the UI, look at `ui/layout.ts`, I'm not using a UI framework because I'm a nutter. Adding more file formats to import from and export to would be nice. Adding new default block palettes would be great also.
+Currently there's not much docs but if you're looking for where to get started, look at `app_context.ts` and follow `_import()`, `_voxelise()`, `_assign()`, and `_export()`. If you're looking to add elements to the UI, look at `ui/layout.ts`, I'm not using a UI framework because I'm a nutter. Adding more file formats to import from and export to would be nice. Adding new default block palettes would be great also.
If you have any questions or need help getting started then feel free to join the [Discord](https://discord.gg/McS2VrBZPD) or message me **SinJi#4165**.
@@ -128,9 +135,6 @@ To allow for your favourite debugging tools like breakpoints and call stacks, I'
"Creepy Lady Bust Statue Scan" (https://skfb.ly/6B7pK) by alex.toporowicz is licensed under Creative Commons Attribution (http://creativecommons.org/licenses/by/4.0/).
-
- "Cut Fish" (https://skfb.ly/orWLC) by Suushimi is licensed under Creative Commons Attribution-NonCommercial (http://creativecommons.org/licenses/by-nc/4.0/).
-
"Pivot Demo: Journey" (https://skfb.ly/6WCIJ) by Sketchfab is licensed under Creative Commons Attribution (http://creativecommons.org/licenses/by/4.0/).
diff --git a/index.html b/index.html
index 24a8a8b8..1d785c03 100644
--- a/index.html
+++ b/index.html
@@ -7,6 +7,10 @@
+
+
diff --git a/jestconfig.full.json b/jestconfig.full.json
new file mode 100644
index 00000000..a7a636d9
--- /dev/null
+++ b/jestconfig.full.json
@@ -0,0 +1,7 @@
+{
+ "transform": {
+ "^.+\\.(t|j)sx?$": "ts-jest"
+ },
+ "testRegex": "(/test/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$",
+ "moduleFileExtensions": ["ts", "tsx", "js", "jsx", "json", "node"]
+ }
\ No newline at end of file
diff --git a/jestconfig.json b/jestconfig.json
index a7a636d9..508dc362 100644
--- a/jestconfig.json
+++ b/jestconfig.json
@@ -3,5 +3,6 @@
"^.+\\.(t|j)sx?$": "ts-jest"
},
"testRegex": "(/test/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$",
- "moduleFileExtensions": ["ts", "tsx", "js", "jsx", "json", "node"]
+ "moduleFileExtensions": ["ts", "tsx", "js", "jsx", "json", "node"],
+ "modulePathIgnorePatterns": ["/tests/full/"]
}
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 646db969..8279b9f2 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,17 +1,15 @@
{
"name": "objtoschematic",
- "version": "0.5.1",
+ "version": "0.6.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "objtoschematic",
- "version": "0.5.1",
+ "version": "0.6.0",
"license": "BSD-3-Clause",
"dependencies": {
- "bvh": "^0.5.0",
"bvh-tree": "^1.0.1",
- "color-convert": "^2.0.1",
"jpeg-js": "^0.4.4",
"pngjs": "^6.0.0",
"prismarine-nbt": "^1.6.0",
@@ -19,11 +17,14 @@
"varint-array": "^0.0.0"
},
"devDependencies": {
+ "@types/adm-zip": "^0.5.0",
"@types/jest": "^27.4.1",
"@types/jquery": "^3.5.6",
+ "@types/merge-images": "^1.2.1",
"@types/obj-file-parser": "^0.5.0",
"@types/pngjs": "^6.0.1",
"@types/prompt": "^1.1.2",
+ "@types/sharp": "^0.31.0",
"@types/varint": "^6.0.0",
"@typescript-eslint/eslint-plugin": "^5.9.1",
"@typescript-eslint/parser": "^5.9.1",
@@ -34,9 +35,11 @@
"electron-packager": "^15.2.0",
"eslint": "^8.7.0",
"eslint-config-google": "^0.14.0",
+ "eslint-plugin-simple-import-sort": "^8.0.0",
"images": "^3.2.3",
"jest": "^27.5.1",
"prompt": "^1.2.1",
+ "sharp": "^0.31.1",
"ts-jest": "^27.1.3",
"ts-node": "^10.1.0",
"typescript": "^4.3.5"
@@ -46,58 +49,59 @@
}
},
"node_modules/@ampproject/remapping": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz",
- "integrity": "sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg==",
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz",
+ "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==",
"dev": true,
"dependencies": {
- "@jridgewell/trace-mapping": "^0.3.0"
+ "@jridgewell/gen-mapping": "^0.1.0",
+ "@jridgewell/trace-mapping": "^0.3.9"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@babel/code-frame": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz",
- "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==",
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz",
+ "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==",
"dev": true,
"dependencies": {
- "@babel/highlight": "^7.16.7"
+ "@babel/highlight": "^7.18.6"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/compat-data": {
- "version": "7.17.7",
- "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.7.tgz",
- "integrity": "sha512-p8pdE6j0a29TNGebNm7NzYZWB3xVZJBZ7XGs42uAKzQo8VQ3F0By/cQCtUEABwIqw5zo6WA4NbmxsfzADzMKnQ==",
+ "version": "7.19.3",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.19.3.tgz",
+ "integrity": "sha512-prBHMK4JYYK+wDjJF1q99KK4JLL+egWS4nmNqdlMUgCExMZ+iZW0hGhyC3VEbsPjvaN0TBhW//VIFwBrk8sEiw==",
"dev": true,
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/core": {
- "version": "7.17.8",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.8.tgz",
- "integrity": "sha512-OdQDV/7cRBtJHLSOBqqbYNkOcydOgnX59TZx4puf41fzcVtN3e/4yqY8lMQsK+5X2lJtAdmA+6OHqsj1hBJ4IQ==",
+ "version": "7.19.3",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.3.tgz",
+ "integrity": "sha512-WneDJxdsjEvyKtXKsaBGbDeiyOjR5vYq4HcShxnIbG0qixpoHjI3MqeZM9NDvsojNCEBItQE4juOo/bU6e72gQ==",
"dev": true,
"dependencies": {
"@ampproject/remapping": "^2.1.0",
- "@babel/code-frame": "^7.16.7",
- "@babel/generator": "^7.17.7",
- "@babel/helper-compilation-targets": "^7.17.7",
- "@babel/helper-module-transforms": "^7.17.7",
- "@babel/helpers": "^7.17.8",
- "@babel/parser": "^7.17.8",
- "@babel/template": "^7.16.7",
- "@babel/traverse": "^7.17.3",
- "@babel/types": "^7.17.0",
+ "@babel/code-frame": "^7.18.6",
+ "@babel/generator": "^7.19.3",
+ "@babel/helper-compilation-targets": "^7.19.3",
+ "@babel/helper-module-transforms": "^7.19.0",
+ "@babel/helpers": "^7.19.0",
+ "@babel/parser": "^7.19.3",
+ "@babel/template": "^7.18.10",
+ "@babel/traverse": "^7.19.3",
+ "@babel/types": "^7.19.3",
"convert-source-map": "^1.7.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.2",
- "json5": "^2.1.2",
+ "json5": "^2.2.1",
"semver": "^6.3.0"
},
"engines": {
@@ -108,38 +112,52 @@
"url": "https://opencollective.com/babel"
}
},
+ "node_modules/@babel/core/node_modules/semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
"node_modules/@babel/generator": {
- "version": "7.17.7",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.7.tgz",
- "integrity": "sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w==",
+ "version": "7.19.3",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.19.3.tgz",
+ "integrity": "sha512-fqVZnmp1ncvZU757UzDheKZpfPgatqY59XtW2/j/18H7u76akb8xqvjw82f+i2UKd/ksYsSick/BCLQUUtJ/qQ==",
"dev": true,
"dependencies": {
- "@babel/types": "^7.17.0",
- "jsesc": "^2.5.1",
- "source-map": "^0.5.0"
+ "@babel/types": "^7.19.3",
+ "@jridgewell/gen-mapping": "^0.3.2",
+ "jsesc": "^2.5.1"
},
"engines": {
"node": ">=6.9.0"
}
},
- "node_modules/@babel/generator/node_modules/source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz",
+ "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==",
"dev": true,
+ "dependencies": {
+ "@jridgewell/set-array": "^1.0.1",
+ "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ },
"engines": {
- "node": ">=0.10.0"
+ "node": ">=6.0.0"
}
},
"node_modules/@babel/helper-compilation-targets": {
- "version": "7.17.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.17.7.tgz",
- "integrity": "sha512-UFzlz2jjd8kroj0hmCFV5zr+tQPi1dpC2cRsDV/3IEW8bJfCPrPpmcSN6ZS8RqIq4LXcmpipCQFPddyFA5Yc7w==",
+ "version": "7.19.3",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.3.tgz",
+ "integrity": "sha512-65ESqLGyGmLvgR0mst5AdW1FkNlj9rQsCKduzEoEPhBCDFGXvz2jW6bXFG6i0/MrV2s7hhXjjb2yAzcPuQlLwg==",
"dev": true,
"dependencies": {
- "@babel/compat-data": "^7.17.7",
- "@babel/helper-validator-option": "^7.16.7",
- "browserslist": "^4.17.5",
+ "@babel/compat-data": "^7.19.3",
+ "@babel/helper-validator-option": "^7.18.6",
+ "browserslist": "^4.21.3",
"semver": "^6.3.0"
},
"engines": {
@@ -149,159 +167,161 @@
"@babel/core": "^7.0.0"
}
},
- "node_modules/@babel/helper-environment-visitor": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz",
- "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==",
+ "node_modules/@babel/helper-compilation-targets/node_modules/semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"dev": true,
- "dependencies": {
- "@babel/types": "^7.16.7"
- },
- "engines": {
- "node": ">=6.9.0"
+ "bin": {
+ "semver": "bin/semver.js"
}
},
- "node_modules/@babel/helper-function-name": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz",
- "integrity": "sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA==",
+ "node_modules/@babel/helper-environment-visitor": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz",
+ "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==",
"dev": true,
- "dependencies": {
- "@babel/helper-get-function-arity": "^7.16.7",
- "@babel/template": "^7.16.7",
- "@babel/types": "^7.16.7"
- },
"engines": {
"node": ">=6.9.0"
}
},
- "node_modules/@babel/helper-get-function-arity": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz",
- "integrity": "sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==",
+ "node_modules/@babel/helper-function-name": {
+ "version": "7.19.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz",
+ "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==",
"dev": true,
"dependencies": {
- "@babel/types": "^7.16.7"
+ "@babel/template": "^7.18.10",
+ "@babel/types": "^7.19.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-hoist-variables": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz",
- "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==",
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz",
+ "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==",
"dev": true,
"dependencies": {
- "@babel/types": "^7.16.7"
+ "@babel/types": "^7.18.6"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-module-imports": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz",
- "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==",
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz",
+ "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==",
"dev": true,
"dependencies": {
- "@babel/types": "^7.16.7"
+ "@babel/types": "^7.18.6"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-module-transforms": {
- "version": "7.17.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.17.7.tgz",
- "integrity": "sha512-VmZD99F3gNTYB7fJRDTi+u6l/zxY0BE6OIxPSU7a50s6ZUQkHwSDmV92FfM+oCG0pZRVojGYhkR8I0OGeCVREw==",
+ "version": "7.19.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz",
+ "integrity": "sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==",
"dev": true,
"dependencies": {
- "@babel/helper-environment-visitor": "^7.16.7",
- "@babel/helper-module-imports": "^7.16.7",
- "@babel/helper-simple-access": "^7.17.7",
- "@babel/helper-split-export-declaration": "^7.16.7",
- "@babel/helper-validator-identifier": "^7.16.7",
- "@babel/template": "^7.16.7",
- "@babel/traverse": "^7.17.3",
- "@babel/types": "^7.17.0"
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-module-imports": "^7.18.6",
+ "@babel/helper-simple-access": "^7.18.6",
+ "@babel/helper-split-export-declaration": "^7.18.6",
+ "@babel/helper-validator-identifier": "^7.18.6",
+ "@babel/template": "^7.18.10",
+ "@babel/traverse": "^7.19.0",
+ "@babel/types": "^7.19.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-plugin-utils": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz",
- "integrity": "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==",
+ "version": "7.19.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz",
+ "integrity": "sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==",
"dev": true,
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-simple-access": {
- "version": "7.17.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.17.7.tgz",
- "integrity": "sha512-txyMCGroZ96i+Pxr3Je3lzEJjqwaRC9buMUgtomcrLe5Nd0+fk1h0LLA+ixUF5OW7AhHuQ7Es1WcQJZmZsz2XA==",
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz",
+ "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==",
"dev": true,
"dependencies": {
- "@babel/types": "^7.17.0"
+ "@babel/types": "^7.18.6"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-split-export-declaration": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz",
- "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==",
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz",
+ "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==",
"dev": true,
"dependencies": {
- "@babel/types": "^7.16.7"
+ "@babel/types": "^7.18.6"
},
"engines": {
"node": ">=6.9.0"
}
},
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.18.10",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz",
+ "integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
"node_modules/@babel/helper-validator-identifier": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz",
- "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==",
+ "version": "7.19.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz",
+ "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==",
"dev": true,
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-validator-option": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz",
- "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==",
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz",
+ "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==",
"dev": true,
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helpers": {
- "version": "7.17.8",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.8.tgz",
- "integrity": "sha512-QcL86FGxpfSJwGtAvv4iG93UL6bmqBdmoVY0CMCU2g+oD2ezQse3PT5Pa+jiD6LJndBQi0EDlpzOWNlLuhz5gw==",
+ "version": "7.19.0",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.0.tgz",
+ "integrity": "sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg==",
"dev": true,
"dependencies": {
- "@babel/template": "^7.16.7",
- "@babel/traverse": "^7.17.3",
- "@babel/types": "^7.17.0"
+ "@babel/template": "^7.18.10",
+ "@babel/traverse": "^7.19.0",
+ "@babel/types": "^7.19.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/highlight": {
- "version": "7.16.10",
- "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz",
- "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==",
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz",
+ "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==",
"dev": true,
"dependencies": {
- "@babel/helper-validator-identifier": "^7.16.7",
+ "@babel/helper-validator-identifier": "^7.18.6",
"chalk": "^2.0.0",
"js-tokens": "^4.0.0"
},
@@ -347,13 +367,13 @@
"node_modules/@babel/highlight/node_modules/color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
"dev": true
},
"node_modules/@babel/highlight/node_modules/escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
- "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
"dev": true,
"engines": {
"node": ">=0.8.0"
@@ -362,7 +382,7 @@
"node_modules/@babel/highlight/node_modules/has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
- "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
"dev": true,
"engines": {
"node": ">=4"
@@ -381,9 +401,9 @@
}
},
"node_modules/@babel/parser": {
- "version": "7.17.8",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.8.tgz",
- "integrity": "sha512-BoHhDJrJXqcg+ZL16Xv39H9n+AqJ4pcDrQBGZN+wHxIysrLZ3/ECwCBUch/1zUNhnsXULcONU3Ei5Hmkfk6kiQ==",
+ "version": "7.19.3",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.3.tgz",
+ "integrity": "sha512-pJ9xOlNWHiy9+FuFP09DEAFbAn4JskgRsVcc169w2xRBC3FRGuQEwjeIMMND9L2zc0iEhO/tGv4Zq+km+hxNpQ==",
"dev": true,
"bin": {
"parser": "bin/babel-parser.js"
@@ -540,12 +560,12 @@
}
},
"node_modules/@babel/plugin-syntax-typescript": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.7.tgz",
- "integrity": "sha512-YhUIJHHGkqPgEcMYkPCKTyGUdoGKWtopIycQyjJH8OjvRgOYsXsaKehLVPScKJWAULPxMa4N1vCe6szREFlZ7A==",
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz",
+ "integrity": "sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA==",
"dev": true,
"dependencies": {
- "@babel/helper-plugin-utils": "^7.16.7"
+ "@babel/helper-plugin-utils": "^7.18.6"
},
"engines": {
"node": ">=6.9.0"
@@ -555,33 +575,33 @@
}
},
"node_modules/@babel/template": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz",
- "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==",
+ "version": "7.18.10",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz",
+ "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==",
"dev": true,
"dependencies": {
- "@babel/code-frame": "^7.16.7",
- "@babel/parser": "^7.16.7",
- "@babel/types": "^7.16.7"
+ "@babel/code-frame": "^7.18.6",
+ "@babel/parser": "^7.18.10",
+ "@babel/types": "^7.18.10"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/traverse": {
- "version": "7.17.3",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.3.tgz",
- "integrity": "sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw==",
- "dev": true,
- "dependencies": {
- "@babel/code-frame": "^7.16.7",
- "@babel/generator": "^7.17.3",
- "@babel/helper-environment-visitor": "^7.16.7",
- "@babel/helper-function-name": "^7.16.7",
- "@babel/helper-hoist-variables": "^7.16.7",
- "@babel/helper-split-export-declaration": "^7.16.7",
- "@babel/parser": "^7.17.3",
- "@babel/types": "^7.17.0",
+ "version": "7.19.3",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.3.tgz",
+ "integrity": "sha512-qh5yf6149zhq2sgIXmwjnsvmnNQC2iw70UFjp4olxucKrWd/dvlUsBI88VSLUsnMNF7/vnOiA+nk1+yLoCqROQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.18.6",
+ "@babel/generator": "^7.19.3",
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-function-name": "^7.19.0",
+ "@babel/helper-hoist-variables": "^7.18.6",
+ "@babel/helper-split-export-declaration": "^7.18.6",
+ "@babel/parser": "^7.19.3",
+ "@babel/types": "^7.19.3",
"debug": "^4.1.0",
"globals": "^11.1.0"
},
@@ -599,12 +619,13 @@
}
},
"node_modules/@babel/types": {
- "version": "7.17.0",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz",
- "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==",
+ "version": "7.19.3",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.19.3.tgz",
+ "integrity": "sha512-hGCaQzIY22DJlDh9CH7NOxgKkFjBk0Cw9xDO1Xmh2151ti7wiGfQ3LauXzL4HP1fmFlTX6XjpRETTpUcv7wQLw==",
"dev": true,
"dependencies": {
- "@babel/helper-validator-identifier": "^7.16.7",
+ "@babel/helper-string-parser": "^7.18.10",
+ "@babel/helper-validator-identifier": "^7.19.1",
"to-fast-properties": "^2.0.0"
},
"engines": {
@@ -626,31 +647,32 @@
"node": ">=0.1.90"
}
},
- "node_modules/@cspotcode/source-map-consumer": {
- "version": "0.8.0",
- "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz",
- "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==",
- "dev": true,
- "engines": {
- "node": ">= 12"
- }
- },
"node_modules/@cspotcode/source-map-support": {
- "version": "0.7.0",
- "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz",
- "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==",
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
+ "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
"dev": true,
"dependencies": {
- "@cspotcode/source-map-consumer": "0.8.0"
+ "@jridgewell/trace-mapping": "0.3.9"
},
"engines": {
"node": ">=12"
}
},
+ "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.9",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
+ "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.0.3",
+ "@jridgewell/sourcemap-codec": "^1.4.10"
+ }
+ },
"node_modules/@electron/get": {
- "version": "1.12.4",
- "resolved": "https://registry.npmjs.org/@electron/get/-/get-1.12.4.tgz",
- "integrity": "sha512-6nr9DbJPUR9Xujw6zD3y+rS95TyItEVM0NVjt1EehY2vUWfIgPiIPVHxCvaTS0xr2B+DRxovYVKbuOWqC35kjg==",
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@electron/get/-/get-1.14.1.tgz",
+ "integrity": "sha512-BrZYyL/6m0ZXz/lDxy/nlVhQz+WF+iPS6qXolEU8atw7h6v1aYkjwJZ63m+bJMBTxDE66X+r2tPS4a/8C82sZw==",
"dev": true,
"dependencies": {
"debug": "^4.1.1",
@@ -665,34 +687,100 @@
"node": ">=8.6"
},
"optionalDependencies": {
- "global-agent": "^2.0.2",
+ "global-agent": "^3.0.0",
"global-tunnel-ng": "^2.7.1"
}
},
+ "node_modules/@electron/get/node_modules/semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@electron/universal": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-1.3.0.tgz",
+ "integrity": "sha512-6SAIlMZZRj1qpe3z3qhMWf3fmqhAdzferiQ5kpspCI9sH1GjkzRXY0RLaz0ktHtYonOj9XMpXNkhDy7QQagQEg==",
+ "dev": true,
+ "dependencies": {
+ "@malept/cross-spawn-promise": "^1.1.0",
+ "asar": "^3.1.0",
+ "debug": "^4.3.1",
+ "dir-compare": "^2.4.0",
+ "fs-extra": "^9.0.1",
+ "minimatch": "^3.0.4",
+ "plist": "^3.0.4"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/@electron/universal/node_modules/fs-extra": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
+ "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
+ "dev": true,
+ "dependencies": {
+ "at-least-node": "^1.0.0",
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@electron/universal/node_modules/jsonfile": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
+ "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
+ "dev": true,
+ "dependencies": {
+ "universalify": "^2.0.0"
+ },
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "node_modules/@electron/universal/node_modules/universalify": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
+ "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 10.0.0"
+ }
+ },
"node_modules/@eslint/eslintrc": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.1.tgz",
- "integrity": "sha512-bxvbYnBPN1Gibwyp6NrpnFzA3YtRL3BBAyEAFVIpNTm2Rn4Vy87GA5M4aSn3InRrlsbX5N0GW7XIx+U4SAEKdQ==",
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.2.tgz",
+ "integrity": "sha512-AXYd23w1S/bv3fTs3Lz0vjiYemS08jWkI3hYyS9I1ry+0f+Yjs1wm+sU0BS8qDOPrBIkp4qHYC16I8uVtpLajQ==",
"dev": true,
"dependencies": {
"ajv": "^6.12.4",
"debug": "^4.3.2",
- "espree": "^9.3.1",
- "globals": "^13.9.0",
+ "espree": "^9.4.0",
+ "globals": "^13.15.0",
"ignore": "^5.2.0",
"import-fresh": "^3.2.1",
"js-yaml": "^4.1.0",
- "minimatch": "^3.0.4",
+ "minimatch": "^3.1.2",
"strip-json-comments": "^3.1.1"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
}
},
"node_modules/@humanwhocodes/config-array": {
- "version": "0.9.5",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz",
- "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==",
+ "version": "0.10.7",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.7.tgz",
+ "integrity": "sha512-MDl6D6sBsaV452/QSdX+4CXIjZhIcI0PELsxUjk4U828yd58vk3bTIvk/6w5FY+4hIy9sLW0sfrV7K7Kc++j/w==",
"dev": true,
"dependencies": {
"@humanwhocodes/object-schema": "^1.2.1",
@@ -703,6 +791,29 @@
"node": ">=10.10.0"
}
},
+ "node_modules/@humanwhocodes/gitignore-to-minimatch": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz",
+ "integrity": "sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA==",
+ "dev": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
"node_modules/@humanwhocodes/object-schema": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz",
@@ -799,24 +910,6 @@
"node": ">=8"
}
},
- "node_modules/@istanbuljs/load-nyc-config/node_modules/p-try": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
- "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/@istanbuljs/load-nyc-config/node_modules/path-exists": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
- "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
@@ -829,7 +922,7 @@
"node_modules/@istanbuljs/load-nyc-config/node_modules/sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
- "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
+ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
"dev": true
},
"node_modules/@istanbuljs/schema": {
@@ -905,12 +998,6 @@
}
}
},
- "node_modules/@jest/core/node_modules/graceful-fs": {
- "version": "4.2.9",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
- "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
- "dev": true
- },
"node_modules/@jest/environment": {
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz",
@@ -1001,12 +1088,6 @@
}
}
},
- "node_modules/@jest/reporters/node_modules/graceful-fs": {
- "version": "4.2.9",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
- "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
- "dev": true
- },
"node_modules/@jest/source-map": {
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.5.1.tgz",
@@ -1021,12 +1102,6 @@
"node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
}
},
- "node_modules/@jest/source-map/node_modules/graceful-fs": {
- "version": "4.2.9",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
- "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
- "dev": true
- },
"node_modules/@jest/test-result": {
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.5.1.tgz",
@@ -1057,12 +1132,6 @@
"node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
}
},
- "node_modules/@jest/test-sequencer/node_modules/graceful-fs": {
- "version": "4.2.9",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
- "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
- "dev": true
- },
"node_modules/@jest/transform": {
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz",
@@ -1089,12 +1158,6 @@
"node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
}
},
- "node_modules/@jest/transform/node_modules/graceful-fs": {
- "version": "4.2.9",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
- "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
- "dev": true
- },
"node_modules/@jest/types": {
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz",
@@ -1111,25 +1174,47 @@
"node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
}
},
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz",
+ "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/set-array": "^1.0.0",
+ "@jridgewell/sourcemap-codec": "^1.4.10"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
"node_modules/@jridgewell/resolve-uri": {
- "version": "3.0.5",
- "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz",
- "integrity": "sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==",
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
+ "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/set-array": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
+ "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
"dev": true,
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/sourcemap-codec": {
- "version": "1.4.11",
- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz",
- "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==",
+ "version": "1.4.14",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
+ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
"dev": true
},
"node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.4",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz",
- "integrity": "sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ==",
+ "version": "0.3.15",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz",
+ "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==",
"dev": true,
"dependencies": {
"@jridgewell/resolve-uri": "^3.0.3",
@@ -1242,29 +1327,38 @@
}
},
"node_modules/@tsconfig/node10": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz",
- "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==",
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
+ "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==",
"dev": true
},
"node_modules/@tsconfig/node12": {
- "version": "1.0.9",
- "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz",
- "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==",
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
+ "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
"dev": true
},
"node_modules/@tsconfig/node14": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz",
- "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==",
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
+ "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
"dev": true
},
"node_modules/@tsconfig/node16": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz",
- "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==",
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz",
+ "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==",
"dev": true
},
+ "node_modules/@types/adm-zip": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/@types/adm-zip/-/adm-zip-0.5.0.tgz",
+ "integrity": "sha512-FCJBJq9ODsQZUNURo5ILAQueuA8WJhRvuihS3ke2iI25mJlfV2LK8jG2Qj2z2AWg8U0FtWWqBHVRetceLskSaw==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
"node_modules/@types/babel__core": {
"version": "7.1.19",
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.19.tgz",
@@ -1298,18 +1392,18 @@
}
},
"node_modules/@types/babel__traverse": {
- "version": "7.14.2",
- "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.14.2.tgz",
- "integrity": "sha512-K2waXdXBi2302XUdcHcR1jCeU0LL4TD9HRs/gk0N2Xvrht+G/BfJa4QObBQZfhMdxiCpV3COl5Nfq4uKTeTnJA==",
+ "version": "7.18.2",
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.2.tgz",
+ "integrity": "sha512-FcFaxOr2V5KZCviw1TnutEMVUVsGt4D2hP1TAfXZAMKuHYW3xQhe3jTxNPWutgCJ3/X1c5yX8ZoGVEItxKbwBg==",
"dev": true,
"dependencies": {
"@babel/types": "^7.3.0"
}
},
"node_modules/@types/glob": {
- "version": "7.1.4",
- "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.4.tgz",
- "integrity": "sha512-w+LsMxKyYQm347Otw+IfBXOv9UWVjpHpCDdbBMt8Kz/xbvCYNjP+0qPh91Km3iKfSRLBB0P7fAMf0KHrPu+MyA==",
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz",
+ "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==",
"dev": true,
"optional": true,
"dependencies": {
@@ -1351,9 +1445,9 @@
}
},
"node_modules/@types/jest": {
- "version": "27.4.1",
- "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.4.1.tgz",
- "integrity": "sha512-23iPJADSmicDVrWk+HT58LMJtzLAnB2AgIzplQuq/bSrGaxCrlvRFjGbXmamnnk/mAmCdLStiGqggu28ocUyiw==",
+ "version": "27.5.2",
+ "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.5.2.tgz",
+ "integrity": "sha512-mpT8LJJ4CMeeahobofYWIjFo0xonRS/HfxnVEPMPFSQdGUt1uHCnoPT7Zhb+sjDU2wz0oKV0OLUR0WzrHNgfeA==",
"dev": true,
"dependencies": {
"jest-matcher-utils": "^27.0.0",
@@ -1375,17 +1469,26 @@
"integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==",
"dev": true
},
+ "node_modules/@types/merge-images": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@types/merge-images/-/merge-images-1.2.1.tgz",
+ "integrity": "sha512-wXXXOXYvoHpa4QwQBDNOPH7QbGECTvQshThgytYhruIbwbF4/11EouhSnYtUgf0n52bGYdt2BQdZV2K6C2SrnA==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
"node_modules/@types/minimatch": {
- "version": "3.0.5",
- "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz",
- "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==",
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz",
+ "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==",
"dev": true,
"optional": true
},
"node_modules/@types/node": {
- "version": "16.6.1",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-16.6.1.tgz",
- "integrity": "sha512-Sr7BhXEAer9xyGuCN3Ek9eg9xPviCF2gfu9kTfuU2HkTVAMYSDeX40fvpmo72n5nansg3nsBjuQBrsS28r+NUw==",
+ "version": "18.7.23",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.23.tgz",
+ "integrity": "sha512-DWNcCHolDq0ZKGizjx2DZjR/PqsYwAcYUJmfMWqtVU2MBMG5Mo+xFZrhGId5r/O5HOuMPyQEcM6KUBp5lBZZBg==",
"dev": true
},
"node_modules/@types/obj-file-parser": {
@@ -1404,15 +1507,15 @@
}
},
"node_modules/@types/prettier": {
- "version": "2.4.4",
- "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.4.4.tgz",
- "integrity": "sha512-ReVR2rLTV1kvtlWFyuot+d1pkpG2Fw/XKE3PDAdj57rbM97ttSp9JZ2UsP+2EHTylra9cUf6JA7tGwW1INzUrA==",
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.1.tgz",
+ "integrity": "sha512-ri0UmynRRvZiiUJdiz38MmIblKK+oH30MztdBVR95dv/Ubw6neWSb8u1XpRb72L4qsZOhz+L+z9JD40SJmfWow==",
"dev": true
},
"node_modules/@types/prompt": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@types/prompt/-/prompt-1.1.2.tgz",
- "integrity": "sha512-Zc9YzOvjAWxxGY7qo0Q6yINMVVspAa4p68UCzucWMU+GaPujpjwbOwzI38s7Jq01k0GztzLxXlRiFcZf/aeIWA==",
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/@types/prompt/-/prompt-1.1.4.tgz",
+ "integrity": "sha512-FLMcf+ol+eUJALeIYWLjQl0hYw86G0PIg7D5+4jJHwr/wKI8p3R0u+oKLbyRkzCxb7e0pHixyCj7UgSv7I/TJQ==",
"dev": true,
"dependencies": {
"@types/node": "*",
@@ -1425,6 +1528,15 @@
"integrity": "sha512-q6KSi3PklLGQ0CesZ/XuLwly4DXXlnJuucYOG9lrBqrP8rKiuPZThav2h2+pFjaheNpnT0qKK3i304QWIePeJw==",
"dev": true
},
+ "node_modules/@types/sharp": {
+ "version": "0.31.0",
+ "resolved": "https://registry.npmjs.org/@types/sharp/-/sharp-0.31.0.tgz",
+ "integrity": "sha512-nwivOU101fYInCwdDcH/0/Ru6yIRXOpORx25ynEOc6/IakuCmjOAGpaO5VfUl4QkDtUC6hj+Z2eCQvgXOioknw==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
"node_modules/@types/sizzle": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz",
@@ -1462,9 +1574,9 @@
"dev": true
},
"node_modules/@types/yauzl": {
- "version": "2.9.2",
- "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.2.tgz",
- "integrity": "sha512-8uALY5LTvSuHgloDVUvWP3pIauILm+8/0pDMokuDYIoNsOkSwd5AiHBTSEJjKTDcZr5z8UpgOWZkxBF4iJftoA==",
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz",
+ "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==",
"dev": true,
"optional": true,
"dependencies": {
@@ -1472,19 +1584,18 @@
}
},
"node_modules/@typescript-eslint/eslint-plugin": {
- "version": "5.16.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.16.0.tgz",
- "integrity": "sha512-SJoba1edXvQRMmNI505Uo4XmGbxCK9ARQpkvOd00anxzri9RNQk0DDCxD+LIl+jYhkzOJiOMMKYEHnHEODjdCw==",
+ "version": "5.38.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.38.1.tgz",
+ "integrity": "sha512-ky7EFzPhqz3XlhS7vPOoMDaQnQMn+9o5ICR9CPr/6bw8HrFkzhMSxuA3gRfiJVvs7geYrSeawGJjZoZQKCOglQ==",
"dev": true,
"dependencies": {
- "@typescript-eslint/scope-manager": "5.16.0",
- "@typescript-eslint/type-utils": "5.16.0",
- "@typescript-eslint/utils": "5.16.0",
- "debug": "^4.3.2",
- "functional-red-black-tree": "^1.0.1",
- "ignore": "^5.1.8",
+ "@typescript-eslint/scope-manager": "5.38.1",
+ "@typescript-eslint/type-utils": "5.38.1",
+ "@typescript-eslint/utils": "5.38.1",
+ "debug": "^4.3.4",
+ "ignore": "^5.2.0",
"regexpp": "^3.2.0",
- "semver": "^7.3.5",
+ "semver": "^7.3.7",
"tsutils": "^3.21.0"
},
"engines": {
@@ -1504,31 +1615,16 @@
}
}
},
- "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": {
- "version": "7.3.5",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
- "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
- "dev": true,
- "dependencies": {
- "lru-cache": "^6.0.0"
- },
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/@typescript-eslint/parser": {
- "version": "5.16.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.16.0.tgz",
- "integrity": "sha512-fkDq86F0zl8FicnJtdXakFs4lnuebH6ZADDw6CYQv0UZeIjHvmEw87m9/29nk2Dv5Lmdp0zQ3zDQhiMWQf/GbA==",
+ "version": "5.38.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.38.1.tgz",
+ "integrity": "sha512-LDqxZBVFFQnQRz9rUZJhLmox+Ep5kdUmLatLQnCRR6523YV+XhRjfYzStQ4MheFA8kMAfUlclHSbu+RKdRwQKw==",
"dev": true,
"dependencies": {
- "@typescript-eslint/scope-manager": "5.16.0",
- "@typescript-eslint/types": "5.16.0",
- "@typescript-eslint/typescript-estree": "5.16.0",
- "debug": "^4.3.2"
+ "@typescript-eslint/scope-manager": "5.38.1",
+ "@typescript-eslint/types": "5.38.1",
+ "@typescript-eslint/typescript-estree": "5.38.1",
+ "debug": "^4.3.4"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -1547,13 +1643,13 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
- "version": "5.16.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.16.0.tgz",
- "integrity": "sha512-P+Yab2Hovg8NekLIR/mOElCDPyGgFZKhGoZA901Yax6WR6HVeGLbsqJkZ+Cvk5nts/dAlFKm8PfL43UZnWdpIQ==",
+ "version": "5.38.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.38.1.tgz",
+ "integrity": "sha512-BfRDq5RidVU3RbqApKmS7RFMtkyWMM50qWnDAkKgQiezRtLKsoyRKIvz1Ok5ilRWeD9IuHvaidaLxvGx/2eqTQ==",
"dev": true,
"dependencies": {
- "@typescript-eslint/types": "5.16.0",
- "@typescript-eslint/visitor-keys": "5.16.0"
+ "@typescript-eslint/types": "5.38.1",
+ "@typescript-eslint/visitor-keys": "5.38.1"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -1564,13 +1660,14 @@
}
},
"node_modules/@typescript-eslint/type-utils": {
- "version": "5.16.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.16.0.tgz",
- "integrity": "sha512-SKygICv54CCRl1Vq5ewwQUJV/8padIWvPgCxlWPGO/OgQLCijY9G7lDu6H+mqfQtbzDNlVjzVWQmeqbLMBLEwQ==",
+ "version": "5.38.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.38.1.tgz",
+ "integrity": "sha512-UU3j43TM66gYtzo15ivK2ZFoDFKKP0k03MItzLdq0zV92CeGCXRfXlfQX5ILdd4/DSpHkSjIgLLLh1NtkOJOAw==",
"dev": true,
"dependencies": {
- "@typescript-eslint/utils": "5.16.0",
- "debug": "^4.3.2",
+ "@typescript-eslint/typescript-estree": "5.38.1",
+ "@typescript-eslint/utils": "5.38.1",
+ "debug": "^4.3.4",
"tsutils": "^3.21.0"
},
"engines": {
@@ -1590,9 +1687,9 @@
}
},
"node_modules/@typescript-eslint/types": {
- "version": "5.16.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.16.0.tgz",
- "integrity": "sha512-oUorOwLj/3/3p/HFwrp6m/J2VfbLC8gjW5X3awpQJ/bSG+YRGFS4dpsvtQ8T2VNveV+LflQHjlLvB6v0R87z4g==",
+ "version": "5.38.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.38.1.tgz",
+ "integrity": "sha512-QTW1iHq1Tffp9lNfbfPm4WJabbvpyaehQ0SrvVK2yfV79SytD9XDVxqiPvdrv2LK7DGSFo91TB2FgWanbJAZXg==",
"dev": true,
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -1603,17 +1700,17 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
- "version": "5.16.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.16.0.tgz",
- "integrity": "sha512-SE4VfbLWUZl9MR+ngLSARptUv2E8brY0luCdgmUevU6arZRY/KxYoLI/3V/yxaURR8tLRN7bmZtJdgmzLHI6pQ==",
+ "version": "5.38.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.38.1.tgz",
+ "integrity": "sha512-99b5e/Enoe8fKMLdSuwrfH/C0EIbpUWmeEKHmQlGZb8msY33qn1KlkFww0z26o5Omx7EVjzVDCWEfrfCDHfE7g==",
"dev": true,
"dependencies": {
- "@typescript-eslint/types": "5.16.0",
- "@typescript-eslint/visitor-keys": "5.16.0",
- "debug": "^4.3.2",
- "globby": "^11.0.4",
+ "@typescript-eslint/types": "5.38.1",
+ "@typescript-eslint/visitor-keys": "5.38.1",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
"is-glob": "^4.0.3",
- "semver": "^7.3.5",
+ "semver": "^7.3.7",
"tsutils": "^3.21.0"
},
"engines": {
@@ -1629,31 +1726,16 @@
}
}
},
- "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": {
- "version": "7.3.5",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
- "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
- "dev": true,
- "dependencies": {
- "lru-cache": "^6.0.0"
- },
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/@typescript-eslint/utils": {
- "version": "5.16.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.16.0.tgz",
- "integrity": "sha512-iYej2ER6AwmejLWMWzJIHy3nPJeGDuCqf8Jnb+jAQVoPpmWzwQOfa9hWVB8GIQE5gsCv/rfN4T+AYb/V06WseQ==",
+ "version": "5.38.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.38.1.tgz",
+ "integrity": "sha512-oIuUiVxPBsndrN81oP8tXnFa/+EcZ03qLqPDfSZ5xIJVm7A9V0rlkQwwBOAGtrdN70ZKDlKv+l1BeT4eSFxwXA==",
"dev": true,
"dependencies": {
"@types/json-schema": "^7.0.9",
- "@typescript-eslint/scope-manager": "5.16.0",
- "@typescript-eslint/types": "5.16.0",
- "@typescript-eslint/typescript-estree": "5.16.0",
+ "@typescript-eslint/scope-manager": "5.38.1",
+ "@typescript-eslint/types": "5.38.1",
+ "@typescript-eslint/typescript-estree": "5.38.1",
"eslint-scope": "^5.1.1",
"eslint-utils": "^3.0.0"
},
@@ -1669,13 +1751,13 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
- "version": "5.16.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.16.0.tgz",
- "integrity": "sha512-jqxO8msp5vZDhikTwq9ubyMHqZ67UIvawohr4qF3KhlpL7gzSjOd+8471H3nh5LyABkaI85laEKKU8SnGUK5/g==",
+ "version": "5.38.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.38.1.tgz",
+ "integrity": "sha512-bSHr1rRxXt54+j2n4k54p4fj8AHJ49VDWtjpImOpzQj4qjAiOpPni+V1Tyajh19Api1i844F757cur8wH3YvOA==",
"dev": true,
"dependencies": {
- "@typescript-eslint/types": "5.16.0",
- "eslint-visitor-keys": "^3.0.0"
+ "@typescript-eslint/types": "5.38.1",
+ "eslint-visitor-keys": "^3.3.0"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -1686,15 +1768,15 @@
}
},
"node_modules/abab": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz",
- "integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==",
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz",
+ "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==",
"dev": true
},
"node_modules/acorn": {
- "version": "8.7.0",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz",
- "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==",
+ "version": "8.8.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz",
+ "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==",
"dev": true,
"bin": {
"acorn": "bin/acorn"
@@ -1865,9 +1947,9 @@
}
},
"node_modules/asar": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/asar/-/asar-3.0.3.tgz",
- "integrity": "sha512-k7zd+KoR+n8pl71PvgElcoKHrVNiSXtw7odKbyNpmgKe7EGRF9Pnu3uLOukD37EvavKwVFxOUpqXTIZC5B5Pmw==",
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/asar/-/asar-3.2.0.tgz",
+ "integrity": "sha512-COdw2ZQvKdFGFxXwX3oYh2/sOsJWJegrdJCGxnN4MZ7IULgRBp9P6665aqj9z1v9VwP4oP1hRBojRDQ//IGgAg==",
"dev": true,
"dependencies": {
"chromium-pickle-js": "^0.2.0",
@@ -1885,25 +1967,16 @@
"@types/glob": "^7.1.1"
}
},
- "node_modules/asar/node_modules/commander": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz",
- "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==",
- "dev": true,
- "engines": {
- "node": ">= 6"
- }
- },
"node_modules/async": {
- "version": "0.9.2",
- "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz",
- "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=",
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz",
+ "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==",
"dev": true
},
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
- "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
"dev": true
},
"node_modules/at-least-node": {
@@ -1918,7 +1991,7 @@
"node_modules/author-regex": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/author-regex/-/author-regex-1.0.0.tgz",
- "integrity": "sha1-0IiFvmubv5Q5/gh8dihyRfCoFFA=",
+ "integrity": "sha512-KbWgR8wOYRAPekEmMXrYYdc7BRyhn2Ftk7KWfMUnQ43hFdojWEFRxhhRUm3/OFEdPa1r0KAvTTg9YQK57xTe0g==",
"dev": true,
"engines": {
"node": ">=0.8"
@@ -1946,12 +2019,6 @@
"@babel/core": "^7.8.0"
}
},
- "node_modules/babel-jest/node_modules/graceful-fs": {
- "version": "4.2.9",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
- "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
- "dev": true
- },
"node_modules/babel-plugin-istanbul": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz",
@@ -2048,6 +2115,31 @@
}
]
},
+ "node_modules/bl": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
+ "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
+ "dev": true,
+ "dependencies": {
+ "buffer": "^5.5.0",
+ "inherits": "^2.0.4",
+ "readable-stream": "^3.4.0"
+ }
+ },
+ "node_modules/bl/node_modules/readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/bluebird": {
"version": "3.7.2",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
@@ -2055,9 +2147,9 @@
"dev": true
},
"node_modules/boolean": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.1.2.tgz",
- "integrity": "sha512-YN6UmV0FfLlBVvRvNPx3pz5W/mUoYB24J4WSXOKP/OOJpi+Oq6WYqPaNTHzjI0QzwWtnvEd5CGYyQPgp1jFxnw==",
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz",
+ "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==",
"dev": true,
"optional": true
},
@@ -2090,9 +2182,9 @@
"dev": true
},
"node_modules/browserslist": {
- "version": "4.20.2",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.2.tgz",
- "integrity": "sha512-CQOBCqp/9pDvDbx3xfMi+86pr4KXIf2FDkTTdeuYw8OxS9t898LA1Khq57gtufFILXpfgsSx5woNgsBgvGjpsA==",
+ "version": "4.21.4",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz",
+ "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==",
"dev": true,
"funding": [
{
@@ -2105,11 +2197,10 @@
}
],
"dependencies": {
- "caniuse-lite": "^1.0.30001317",
- "electron-to-chromium": "^1.4.84",
- "escalade": "^3.1.1",
- "node-releases": "^2.0.2",
- "picocolors": "^1.0.0"
+ "caniuse-lite": "^1.0.30001400",
+ "electron-to-chromium": "^1.4.251",
+ "node-releases": "^2.0.6",
+ "update-browserslist-db": "^1.0.9"
},
"bin": {
"browserslist": "cli.js"
@@ -2139,7 +2230,31 @@
"node-int64": "^0.4.0"
}
},
- "node_modules/buffer-alloc": {
+ "node_modules/buffer": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+ "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.1.13"
+ }
+ },
+ "node_modules/buffer-alloc": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz",
"integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==",
@@ -2158,16 +2273,25 @@
"node_modules/buffer-crc32": {
"version": "0.2.13",
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
- "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=",
+ "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
"dev": true,
"engines": {
"node": "*"
}
},
+ "node_modules/buffer-equal": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz",
+ "integrity": "sha512-tcBWO2Dl4e7Asr9hTGcpVrCe+F7DubpmqWCTbj4FHLmjqO2hIaC383acQubWtRJhdceqs5uBHs6Es+Sk//RKiQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
"node_modules/buffer-fill": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz",
- "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=",
+ "integrity": "sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==",
"dev": true
},
"node_modules/buffer-from": {
@@ -2176,15 +2300,10 @@
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
"dev": true
},
- "node_modules/bvh": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/bvh/-/bvh-0.5.0.tgz",
- "integrity": "sha512-AoqXrrBTaCCk+6pZWC33f4UR3jY3yyh7jahZ5pHUPqZ3KSyDfWqlryDrgxq+xsl60PYwZOWRoCFX4+RqN7T6gg=="
- },
"node_modules/bvh-tree": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/bvh-tree/-/bvh-tree-1.0.1.tgz",
- "integrity": "sha1-gIPgGIEokSmh5/kmirg5vl0LhZo="
+ "integrity": "sha512-oNi2ebOZnPVUjLP9QboCuthXnVpOCeCcIQBWWo+0W2Yvh5yaH6u2+dZCa515vj+7Yh+tcNJJDie/U8K0tEPPRQ=="
},
"node_modules/cacheable-request": {
"version": "6.1.0",
@@ -2247,9 +2366,9 @@
}
},
"node_modules/caniuse-lite": {
- "version": "1.0.30001320",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001320.tgz",
- "integrity": "sha512-MWPzG54AGdo3nWx7zHZTefseM5Y1ccM7hlQKHRqJkPozUaw3hNbBTMmLn16GG2FUzjR13Cr3NPfhIieX5PzXDA==",
+ "version": "1.0.30001414",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001414.tgz",
+ "integrity": "sha512-t55jfSaWjCdocnFdKQoO+d2ct9C59UZg4dY3OnUlSZ447r8pUtIKdp0hpAzrGFultmTC+Us+KpKi4GZl/LXlFg==",
"dev": true,
"funding": [
{
@@ -2287,16 +2406,22 @@
"node": ">=10"
}
},
+ "node_modules/chownr": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
+ "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
+ "dev": true
+ },
"node_modules/chromium-pickle-js": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz",
- "integrity": "sha1-BKEGZywYsIWrd02YPfo+oTjyIgU=",
+ "integrity": "sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw==",
"dev": true
},
"node_modules/ci-info": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz",
- "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==",
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.4.0.tgz",
+ "integrity": "sha512-t5QdPT5jq3o262DOQ8zA6E1tlH2upmUc4Hlvrbx1pGYJuiiHl7O7rvVNI+l8HTVhd/q3Qc9vqimkNk5yiXsAug==",
"dev": true
},
"node_modules/cjs-module-lexer": {
@@ -2317,18 +2442,21 @@
}
},
"node_modules/clone-response": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz",
- "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=",
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz",
+ "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==",
"dev": true,
"dependencies": {
"mimic-response": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/co": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
- "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
+ "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==",
"dev": true,
"engines": {
"iojs": ">= 1.0.0",
@@ -2341,10 +2469,24 @@
"integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==",
"dev": true
},
+ "node_modules/color": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
+ "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1",
+ "color-string": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=12.5.0"
+ }
+ },
"node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
"dependencies": {
"color-name": "~1.1.4"
},
@@ -2355,12 +2497,23 @@
"node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/color-string": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
+ "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "^1.0.0",
+ "simple-swizzle": "^0.2.2"
+ }
},
"node_modules/colors": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz",
- "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=",
+ "integrity": "sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==",
"dev": true,
"engines": {
"node": ">=0.1.90"
@@ -2378,10 +2531,19 @@
"node": ">= 0.8"
}
},
+ "node_modules/commander": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz",
+ "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/compare-version": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/compare-version/-/compare-version-0.1.2.tgz",
- "integrity": "sha1-AWLsLZNR9d3VmpICy6k1NmpyUIA=",
+ "integrity": "sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A==",
"dev": true,
"engines": {
"node": ">=0.10.0"
@@ -2390,7 +2552,7 @@
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
"dev": true
},
"node_modules/concat-stream": {
@@ -2408,36 +2570,6 @@
"typedarray": "^0.0.6"
}
},
- "node_modules/concat-stream/node_modules/readable-stream": {
- "version": "2.3.7",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
- "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
- "dev": true,
- "dependencies": {
- "core-util-is": "~1.0.0",
- "inherits": "~2.0.3",
- "isarray": "~1.0.0",
- "process-nextick-args": "~2.0.0",
- "safe-buffer": "~5.1.1",
- "string_decoder": "~1.1.1",
- "util-deprecate": "~1.0.1"
- }
- },
- "node_modules/concat-stream/node_modules/safe-buffer": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
- "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
- "dev": true
- },
- "node_modules/concat-stream/node_modules/string_decoder": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
- "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
- "dev": true,
- "dependencies": {
- "safe-buffer": "~5.1.0"
- }
- },
"node_modules/config-chain": {
"version": "1.1.13",
"resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz",
@@ -2458,30 +2590,12 @@
"safe-buffer": "~5.1.1"
}
},
- "node_modules/convert-source-map/node_modules/safe-buffer": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
- "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
- "dev": true
- },
"node_modules/copy-dir": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/copy-dir/-/copy-dir-1.3.0.tgz",
"integrity": "sha512-Q4+qBFnN4bwGwvtXXzbp4P/4iNk0MaiGAzvQ8OiMtlLjkIKjmNN689uVzShSM0908q7GoFHXIPx4zi75ocoaHw==",
"dev": true
},
- "node_modules/core-js": {
- "version": "3.16.1",
- "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.16.1.tgz",
- "integrity": "sha512-AAkP8i35EbefU+JddyWi12AWE9f2N/qr/pwnDtWz4nyUIBGMJPX99ANFFRSw6FefM374lDujdtLDyhN2A/btHw==",
- "dev": true,
- "hasInstallScript": true,
- "optional": true,
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/core-js"
- }
- },
"node_modules/core-util-is": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
@@ -2559,7 +2673,7 @@
"node_modules/cycle": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz",
- "integrity": "sha1-IegLK+hYD5i0aPN5QwZisEbDStI=",
+ "integrity": "sha512-TVF6svNzeQCOpjCqsy0/CSy8VgObG3wXusJ73xW2GbG5rGx7lC8zxDSURicsXI2UsGdi2L0QNRCi745/wUDvsA==",
"dev": true,
"engines": {
"node": ">=0.4.0"
@@ -2597,15 +2711,15 @@
}
},
"node_modules/decimal.js": {
- "version": "10.3.1",
- "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz",
- "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==",
+ "version": "10.4.1",
+ "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.1.tgz",
+ "integrity": "sha512-F29o+vci4DodHYT9UrR5IEbfBw9pE5eSapIJdTqXK5+6hq+t8VRxwQyKlW2i+KDKFkkJQRvFyI/QXD83h8LyQw==",
"dev": true
},
"node_modules/decompress-response": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz",
- "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=",
+ "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==",
"dev": true,
"dependencies": {
"mimic-response": "^1.0.0"
@@ -2617,9 +2731,18 @@
"node_modules/dedent": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz",
- "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=",
+ "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==",
"dev": true
},
+ "node_modules/deep-extend": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
+ "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
"node_modules/deep-is": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
@@ -2642,27 +2765,40 @@
"dev": true
},
"node_modules/define-properties": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
- "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz",
+ "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==",
"dev": true,
"optional": true,
"dependencies": {
- "object-keys": "^1.0.12"
+ "has-property-descriptors": "^1.0.0",
+ "object-keys": "^1.1.1"
},
"engines": {
"node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
- "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
"dev": true,
"engines": {
"node": ">=0.4.0"
}
},
+ "node_modules/detect-libc": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz",
+ "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/detect-newline": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz",
@@ -2697,6 +2833,45 @@
"node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
}
},
+ "node_modules/dir-compare": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-2.4.0.tgz",
+ "integrity": "sha512-l9hmu8x/rjVC9Z2zmGzkhOEowZvW7pmYws5CWHutg8u1JgvsKWMx7Q/UODeu4djLZ4FgW5besw5yvMQnBHzuCA==",
+ "dev": true,
+ "dependencies": {
+ "buffer-equal": "1.0.0",
+ "colors": "1.0.3",
+ "commander": "2.9.0",
+ "minimatch": "3.0.4"
+ },
+ "bin": {
+ "dircompare": "src/cli/dircompare.js"
+ }
+ },
+ "node_modules/dir-compare/node_modules/commander": {
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz",
+ "integrity": "sha512-bmkUukX8wAOjHdN26xj5c4ctEV22TQ7dQYhSmuckKhToXrkUn0iIaolHdIxYYqD55nhpSPA9zPQ1yP57GdXP2A==",
+ "dev": true,
+ "dependencies": {
+ "graceful-readlink": ">= 1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.6.x"
+ }
+ },
+ "node_modules/dir-compare/node_modules/minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/dir-glob": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
@@ -2709,15 +2884,6 @@
"node": ">=8"
}
},
- "node_modules/dir-glob/node_modules/path-type": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
- "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/doctrine": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
@@ -2752,15 +2918,15 @@
}
},
"node_modules/duplexer3": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
- "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=",
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.5.tgz",
+ "integrity": "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==",
"dev": true
},
"node_modules/electron": {
- "version": "13.6.6",
- "resolved": "https://registry.npmjs.org/electron/-/electron-13.6.6.tgz",
- "integrity": "sha512-TP2Bl1nTxaH1yRmlYiF7imzvKE/NASE0cl6wOYA3AaP/UrBGc4L3NwJfn5Z55o+1t4TH8vCRxENufESyb32HhA==",
+ "version": "13.6.9",
+ "resolved": "https://registry.npmjs.org/electron/-/electron-13.6.9.tgz",
+ "integrity": "sha512-Es/sBy85NIuqsO9MW41PUCpwIkeinlTQ7g0ainfnmRAM2rmog3GBxVCaoV5dzEjwTF7TKG1Yr/E7Z3qHmlfWAg==",
"dev": true,
"hasInstallScript": true,
"dependencies": {
@@ -2776,9 +2942,9 @@
}
},
"node_modules/electron-notarize": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/electron-notarize/-/electron-notarize-1.1.0.tgz",
- "integrity": "sha512-Dmp/jm2y3PTcjmjVe+jCT0sjsbBfbNuk7GOPtduZce2iae1hgAPnlNErk6x70TalsGIL5Ip3liSryqde/6eB5w==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/electron-notarize/-/electron-notarize-1.2.1.tgz",
+ "integrity": "sha512-u/ECWhIrhkSQpZM4cJzVZ5TsmkaqrRo5LDC/KMbGF0sPkm53Ng59+M0zp8QVaql0obfJy9vlVT+4iOkAi2UDlA==",
"dev": true,
"dependencies": {
"debug": "^4.1.1",
@@ -2828,6 +2994,7 @@
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/electron-osx-sign/-/electron-osx-sign-0.5.0.tgz",
"integrity": "sha512-icoRLHzFz/qxzDh/N4Pi2z4yVHurlsCAYQvsCSG7fCedJ4UJXBS6PoQyGH71IfcqKupcKeK7HX/NkyfG+v6vlQ==",
+ "deprecated": "Please use @electron/osx-sign moving forward. Be aware the API is slightly different",
"dev": true,
"dependencies": {
"bluebird": "^3.5.0",
@@ -2857,24 +3024,25 @@
"node_modules/electron-osx-sign/node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"dev": true
},
"node_modules/electron-packager": {
- "version": "15.3.0",
- "resolved": "https://registry.npmjs.org/electron-packager/-/electron-packager-15.3.0.tgz",
- "integrity": "sha512-PHcykXinmjPyJcYoNGbOWNsOU25nIbMLHBAfg4caazWzYELFL14FshDZEqqrvVOMEUnqjx/Ktc1NmMIN5ZRomQ==",
+ "version": "15.5.2",
+ "resolved": "https://registry.npmjs.org/electron-packager/-/electron-packager-15.5.2.tgz",
+ "integrity": "sha512-8zUdkSONn0jomu/efqoxApGzgqIb56ooMs671HeB/BXTPnWcWvqpEY08g16PL6ok2ymA5zPj8vmUszLrq99F0Q==",
"dev": true,
"dependencies": {
"@electron/get": "^1.6.0",
- "asar": "^3.0.0",
+ "@electron/universal": "^1.2.1",
+ "asar": "^3.1.0",
"cross-spawn-windows-exe": "^1.2.0",
"debug": "^4.0.1",
- "electron-notarize": "^1.0.0",
+ "electron-notarize": "^1.1.1",
"electron-osx-sign": "^0.5.0",
"extract-zip": "^2.0.0",
"filenamify": "^4.1.0",
- "fs-extra": "^9.0.0",
+ "fs-extra": "^10.1.0",
"galactus": "^0.2.1",
"get-package-info": "^1.0.0",
"junk": "^3.1.0",
@@ -2883,7 +3051,7 @@
"rcedit": "^3.0.1",
"resolve": "^1.1.6",
"semver": "^7.1.3",
- "yargs-parser": "^20.0.0"
+ "yargs-parser": "^20.2.9"
},
"bin": {
"electron-packager": "bin/electron-packager.js"
@@ -2916,18 +3084,17 @@
}
},
"node_modules/electron-packager/node_modules/fs-extra": {
- "version": "9.1.0",
- "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
- "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
+ "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
"dev": true,
"dependencies": {
- "at-least-node": "^1.0.0",
"graceful-fs": "^4.2.0",
"jsonfile": "^6.0.1",
"universalify": "^2.0.0"
},
"engines": {
- "node": ">=10"
+ "node": ">=12"
}
},
"node_modules/electron-packager/node_modules/get-stream": {
@@ -2957,21 +3124,6 @@
"graceful-fs": "^4.1.6"
}
},
- "node_modules/electron-packager/node_modules/semver": {
- "version": "7.3.5",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
- "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
- "dev": true,
- "dependencies": {
- "lru-cache": "^6.0.0"
- },
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/electron-packager/node_modules/universalify": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
@@ -2982,15 +3134,15 @@
}
},
"node_modules/electron-to-chromium": {
- "version": "1.4.96",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.96.tgz",
- "integrity": "sha512-DPNjvNGPabv6FcyjzLAN4C0psN/GgD9rSGvMTuv81SeXG/EX3mCz0wiw9N1tUEnfQXYCJi3H8M0oFPRziZh7rw==",
+ "version": "1.4.270",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.270.tgz",
+ "integrity": "sha512-KNhIzgLiJmDDC444dj9vEOpZEgsV96ult9Iff98Vanumn+ShJHd5se8aX6KeVxdc0YQeqdrezBZv89rleDbvSg==",
"dev": true
},
"node_modules/electron/node_modules/@types/node": {
- "version": "14.18.12",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.12.tgz",
- "integrity": "sha512-q4jlIR71hUpWTnGhXWcakgkZeHa3CCjcQcnuzU8M891BAWA2jHiziiWEPEkdS5pFsz7H9HJiy8BrK7tBRNrY7A==",
+ "version": "14.18.31",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.31.tgz",
+ "integrity": "sha512-vQAnaReSQkEDa8uwAyQby8bYGKu84R/deEc6mg5T8fX6gzCn8QW6rziSgsti1fNvsrswKUKPnVTi7uoB+u62Mw==",
"dev": true
},
"node_modules/emittery": {
@@ -3014,7 +3166,7 @@
"node_modules/encodeurl": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
- "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
+ "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
"dev": true,
"optional": true,
"engines": {
@@ -3110,7 +3262,7 @@
"node_modules/escodegen/node_modules/levn": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
- "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
+ "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==",
"dev": true,
"dependencies": {
"prelude-ls": "~1.1.2",
@@ -3140,7 +3292,7 @@
"node_modules/escodegen/node_modules/prelude-ls": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
- "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
+ "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==",
"dev": true,
"engines": {
"node": ">= 0.8.0"
@@ -3149,7 +3301,7 @@
"node_modules/escodegen/node_modules/type-check": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
- "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
+ "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==",
"dev": true,
"dependencies": {
"prelude-ls": "~1.1.2"
@@ -3159,13 +3311,15 @@
}
},
"node_modules/eslint": {
- "version": "8.12.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.12.0.tgz",
- "integrity": "sha512-it1oBL9alZg1S8UycLm5YDMAkIhtH6FtAzuZs6YvoGVldWjbS08BkAdb/ymP9LlAyq8koANu32U7Ib/w+UNh8Q==",
+ "version": "8.24.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.24.0.tgz",
+ "integrity": "sha512-dWFaPhGhTAiPcCgm3f6LI2MBWbogMnTJzFBbhXVRQDJPkr9pGZvVjlVfXd+vyDcWPA2Ic9L2AXPIQM0+vk/cSQ==",
"dev": true,
"dependencies": {
- "@eslint/eslintrc": "^1.2.1",
- "@humanwhocodes/config-array": "^0.9.2",
+ "@eslint/eslintrc": "^1.3.2",
+ "@humanwhocodes/config-array": "^0.10.5",
+ "@humanwhocodes/gitignore-to-minimatch": "^1.0.2",
+ "@humanwhocodes/module-importer": "^1.0.1",
"ajv": "^6.10.0",
"chalk": "^4.0.0",
"cross-spawn": "^7.0.2",
@@ -3175,30 +3329,32 @@
"eslint-scope": "^7.1.1",
"eslint-utils": "^3.0.0",
"eslint-visitor-keys": "^3.3.0",
- "espree": "^9.3.1",
+ "espree": "^9.4.0",
"esquery": "^1.4.0",
"esutils": "^2.0.2",
"fast-deep-equal": "^3.1.3",
"file-entry-cache": "^6.0.1",
- "functional-red-black-tree": "^1.0.1",
+ "find-up": "^5.0.0",
"glob-parent": "^6.0.1",
- "globals": "^13.6.0",
+ "globals": "^13.15.0",
+ "globby": "^11.1.0",
+ "grapheme-splitter": "^1.0.4",
"ignore": "^5.2.0",
"import-fresh": "^3.0.0",
"imurmurhash": "^0.1.4",
"is-glob": "^4.0.0",
+ "js-sdsl": "^4.1.4",
"js-yaml": "^4.1.0",
"json-stable-stringify-without-jsonify": "^1.0.1",
"levn": "^0.4.1",
"lodash.merge": "^4.6.2",
- "minimatch": "^3.0.4",
+ "minimatch": "^3.1.2",
"natural-compare": "^1.4.0",
"optionator": "^0.9.1",
"regexpp": "^3.2.0",
"strip-ansi": "^6.0.1",
"strip-json-comments": "^3.1.0",
- "text-table": "^0.2.0",
- "v8-compile-cache": "^2.0.3"
+ "text-table": "^0.2.0"
},
"bin": {
"eslint": "bin/eslint.js"
@@ -3222,6 +3378,15 @@
"eslint": ">=5.16.0"
}
},
+ "node_modules/eslint-plugin-simple-import-sort": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-8.0.0.tgz",
+ "integrity": "sha512-bXgJQ+lqhtQBCuWY/FUWdB27j4+lqcvXv5rUARkzbeWLwea+S5eBZEQrhnO+WgX3ZoJHVj0cn943iyXwByHHQw==",
+ "dev": true,
+ "peerDependencies": {
+ "eslint": ">=5.0.0"
+ }
+ },
"node_modules/eslint-scope": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
@@ -3293,30 +3458,21 @@
"node": ">=4.0"
}
},
- "node_modules/eslint/node_modules/glob-parent": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
- "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
- "dev": true,
- "dependencies": {
- "is-glob": "^4.0.3"
- },
- "engines": {
- "node": ">=10.13.0"
- }
- },
"node_modules/espree": {
- "version": "9.3.1",
- "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.1.tgz",
- "integrity": "sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==",
+ "version": "9.4.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.0.tgz",
+ "integrity": "sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==",
"dev": true,
"dependencies": {
- "acorn": "^8.7.0",
- "acorn-jsx": "^5.3.1",
+ "acorn": "^8.8.0",
+ "acorn-jsx": "^5.3.2",
"eslint-visitor-keys": "^3.3.0"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
}
},
"node_modules/esprima": {
@@ -3430,12 +3586,21 @@
"node_modules/exit": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
- "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=",
+ "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==",
"dev": true,
"engines": {
"node": ">= 0.8.0"
}
},
+ "node_modules/expand-template": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
+ "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/expect": {
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz",
@@ -3478,13 +3643,13 @@
"node_modules/extract-zip/node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"dev": true
},
"node_modules/eyes": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz",
- "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=",
+ "integrity": "sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==",
"dev": true,
"engines": {
"node": "> 0.1.90"
@@ -3496,9 +3661,9 @@
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
},
"node_modules/fast-glob": {
- "version": "3.2.11",
- "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz",
- "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==",
+ "version": "3.2.12",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz",
+ "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==",
"dev": true,
"dependencies": {
"@nodelib/fs.stat": "^2.0.2",
@@ -3511,6 +3676,18 @@
"node": ">=8.6.0"
}
},
+ "node_modules/fast-glob/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/fast-json-stable-stringify": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
@@ -3519,7 +3696,7 @@
"node_modules/fast-levenshtein": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
- "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
"dev": true
},
"node_modules/fastq": {
@@ -3532,9 +3709,9 @@
}
},
"node_modules/fb-watchman": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz",
- "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==",
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz",
+ "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==",
"dev": true,
"dependencies": {
"bser": "2.1.1"
@@ -3543,7 +3720,7 @@
"node_modules/fd-slicer": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
- "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=",
+ "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==",
"dev": true,
"dependencies": {
"pend": "~1.2.0"
@@ -3564,7 +3741,7 @@
"node_modules/filename-reserved-regex": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz",
- "integrity": "sha1-q/c9+rc10EVECr/qLZHzieu/oik=",
+ "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==",
"dev": true,
"engines": {
"node": ">=4"
@@ -3600,15 +3777,19 @@
}
},
"node_modules/find-up": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
- "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
"dev": true,
"dependencies": {
- "locate-path": "^2.0.0"
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
},
"engines": {
- "node": ">=4"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/flat-cache": {
@@ -3625,9 +3806,9 @@
}
},
"node_modules/flatted": {
- "version": "3.2.5",
- "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz",
- "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==",
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz",
+ "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==",
"dev": true
},
"node_modules/flora-colossus": {
@@ -3671,6 +3852,12 @@
"node": ">= 6"
}
},
+ "node_modules/fs-constants": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
+ "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
+ "dev": true
+ },
"node_modules/fs-extra": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
@@ -3688,7 +3875,7 @@
"node_modules/fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
"dev": true
},
"node_modules/fsevents": {
@@ -3711,16 +3898,10 @@
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
"dev": true
},
- "node_modules/functional-red-black-tree": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
- "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
- "dev": true
- },
"node_modules/galactus": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/galactus/-/galactus-0.2.1.tgz",
- "integrity": "sha1-y+0tIKQMH1Z5o1kI4rlBVzPnjbk=",
+ "integrity": "sha512-mDc8EQJKtxjp9PMYS3PbpjjbX3oXhBTxoGaPahw620XZBIHJ4+nvw5KN/tRtmmSDR9dypstGNvqQ3C29QGoGHQ==",
"dev": true,
"dependencies": {
"debug": "^3.1.0",
@@ -3766,10 +3947,25 @@
"node": "6.* || 8.* || >= 10.*"
}
},
+ "node_modules/get-intrinsic": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz",
+ "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/get-package-info": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/get-package-info/-/get-package-info-1.0.0.tgz",
- "integrity": "sha1-ZDJ5ZWPigRPNlHTbvQAFKYWkmZw=",
+ "integrity": "sha512-SCbprXGAPdIhKAXiG+Mk6yeoFH61JlYunqdFQFHDtLjJlDjFf6x07dsS8acO+xWt52jpdVo49AlVDnUVK1sDNw==",
"dev": true,
"dependencies": {
"bluebird": "^3.1.1",
@@ -3793,7 +3989,7 @@
"node_modules/get-package-info/node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"dev": true
},
"node_modules/get-package-type": {
@@ -3817,16 +4013,22 @@
"node": ">=6"
}
},
+ "node_modules/github-from-package": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
+ "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==",
+ "dev": true
+ },
"node_modules/glob": {
- "version": "7.1.7",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
- "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
"dev": true,
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
- "minimatch": "^3.0.4",
+ "minimatch": "^3.1.1",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
},
@@ -3838,26 +4040,25 @@
}
},
"node_modules/glob-parent": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
- "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
"dev": true,
"dependencies": {
- "is-glob": "^4.0.1"
+ "is-glob": "^4.0.3"
},
"engines": {
- "node": ">= 6"
+ "node": ">=10.13.0"
}
},
"node_modules/global-agent": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-2.2.0.tgz",
- "integrity": "sha512-+20KpaW6DDLqhG7JDiJpD1JvNvb8ts+TNl7BPOYcURqCrXqnN1Vf+XVOrkKJAFPqfX+oEhsdzOj1hLWkBTdNJg==",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz",
+ "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==",
"dev": true,
"optional": true,
"dependencies": {
"boolean": "^3.0.1",
- "core-js": "^3.6.5",
"es6-error": "^4.1.1",
"matcher": "^3.0.0",
"roarr": "^2.15.3",
@@ -3868,42 +4069,26 @@
"node": ">=10.0"
}
},
- "node_modules/global-agent/node_modules/semver": {
- "version": "7.3.5",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
- "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
+ "node_modules/global-tunnel-ng": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/global-tunnel-ng/-/global-tunnel-ng-2.7.1.tgz",
+ "integrity": "sha512-4s+DyciWBV0eK148wqXxcmVAbFVPqtc3sEtUE/GTQfuU80rySLcMhUmHKSHI7/LDj8q0gDYI1lIhRRB7ieRAqg==",
"dev": true,
"optional": true,
"dependencies": {
- "lru-cache": "^6.0.0"
- },
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/global-tunnel-ng": {
- "version": "2.7.1",
- "resolved": "https://registry.npmjs.org/global-tunnel-ng/-/global-tunnel-ng-2.7.1.tgz",
- "integrity": "sha512-4s+DyciWBV0eK148wqXxcmVAbFVPqtc3sEtUE/GTQfuU80rySLcMhUmHKSHI7/LDj8q0gDYI1lIhRRB7ieRAqg==",
- "dev": true,
- "optional": true,
- "dependencies": {
- "encodeurl": "^1.0.2",
- "lodash": "^4.17.10",
- "npm-conf": "^1.1.3",
- "tunnel": "^0.0.6"
+ "encodeurl": "^1.0.2",
+ "lodash": "^4.17.10",
+ "npm-conf": "^1.1.3",
+ "tunnel": "^0.0.6"
},
"engines": {
"node": ">=0.10"
}
},
"node_modules/globals": {
- "version": "13.13.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-13.13.0.tgz",
- "integrity": "sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A==",
+ "version": "13.17.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz",
+ "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==",
"dev": true,
"dependencies": {
"type-fest": "^0.20.2"
@@ -3915,22 +4100,10 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/globals/node_modules/type-fest": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
- "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
- "dev": true,
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/globalthis": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.2.tgz",
- "integrity": "sha512-ZQnSFO1la8P7auIOQECnm0sSuoMeaSq0EEdXMBFF2QJO4uNcwbyhSgG3MruWNbFTqCLmxVwGOl7LZ9kASvHdeQ==",
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz",
+ "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==",
"dev": true,
"optional": true,
"dependencies": {
@@ -3986,9 +4159,21 @@
}
},
"node_modules/graceful-fs": {
- "version": "4.2.8",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz",
- "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==",
+ "version": "4.2.10",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
+ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
+ "dev": true
+ },
+ "node_modules/graceful-readlink": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz",
+ "integrity": "sha512-8tLu60LgxF6XpdbK8OW3FA+IfTNBn1ZHGHKF4KQbEeSkajYw5PlYJcKluntgegDPTg8UkHjpet1T82vk6TQ68w==",
+ "dev": true
+ },
+ "node_modules/grapheme-splitter": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz",
+ "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==",
"dev": true
},
"node_modules/has": {
@@ -4012,6 +4197,32 @@
"node": ">=8"
}
},
+ "node_modules/has-property-descriptors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz",
+ "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "get-intrinsic": "^1.1.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
+ "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
+ "dev": true,
+ "optional": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/hosted-git-info": {
"version": "2.8.9",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
@@ -4057,9 +4268,9 @@
}
},
"node_modules/https-proxy-agent": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz",
- "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==",
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
+ "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
"dev": true,
"dependencies": {
"agent-base": "6",
@@ -4090,6 +4301,26 @@
"node": ">=0.10.0"
}
},
+ "node_modules/ieee754": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
"node_modules/ignore": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
@@ -4144,7 +4375,7 @@
"node_modules/imurmurhash": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
- "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
"dev": true,
"engines": {
"node": ">=0.8.19"
@@ -4153,7 +4384,7 @@
"node_modules/inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
- "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
"dev": true,
"dependencies": {
"once": "^1.3.0",
@@ -4169,19 +4400,18 @@
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
- "dev": true,
- "optional": true
+ "dev": true
},
"node_modules/is-arrayish": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
- "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
+ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
"dev": true
},
"node_modules/is-core-module": {
- "version": "2.9.0",
- "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz",
- "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==",
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz",
+ "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==",
"dev": true,
"dependencies": {
"has": "^1.0.3"
@@ -4208,7 +4438,7 @@
"node_modules/is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
- "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
"dev": true,
"engines": {
"node": ">=0.10.0"
@@ -4274,7 +4504,7 @@
"node_modules/is-typedarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
- "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
+ "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==",
"dev": true
},
"node_modules/is-wsl": {
@@ -4292,7 +4522,7 @@
"node_modules/isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
- "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
"dev": true
},
"node_modules/isbinaryfile": {
@@ -4310,13 +4540,13 @@
"node_modules/isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
- "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
"dev": true
},
"node_modules/isstream": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
- "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
+ "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==",
"dev": true
},
"node_modules/istanbul-lib-coverage": {
@@ -4329,9 +4559,9 @@
}
},
"node_modules/istanbul-lib-instrument": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.1.0.tgz",
- "integrity": "sha512-czwUz525rkOFDJxfKK6mYfIs9zBKILyrZQxjz3ABhjQXhbhFsSbo1HW/BFcsDnfJYJWA6thRR5/TUY2qs5W99Q==",
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.0.tgz",
+ "integrity": "sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A==",
"dev": true,
"dependencies": {
"@babel/core": "^7.12.3",
@@ -4344,6 +4574,15 @@
"node": ">=8"
}
},
+ "node_modules/istanbul-lib-instrument/node_modules/semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
"node_modules/istanbul-lib-report": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz",
@@ -4373,9 +4612,9 @@
}
},
"node_modules/istanbul-reports": {
- "version": "3.1.4",
- "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.4.tgz",
- "integrity": "sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw==",
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz",
+ "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==",
"dev": true,
"dependencies": {
"html-escaper": "^2.0.0",
@@ -4454,6 +4693,40 @@
"node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
}
},
+ "node_modules/jest-cli": {
+ "version": "27.5.1",
+ "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.5.1.tgz",
+ "integrity": "sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==",
+ "dev": true,
+ "dependencies": {
+ "@jest/core": "^27.5.1",
+ "@jest/test-result": "^27.5.1",
+ "@jest/types": "^27.5.1",
+ "chalk": "^4.0.0",
+ "exit": "^0.1.2",
+ "graceful-fs": "^4.2.9",
+ "import-local": "^3.0.2",
+ "jest-config": "^27.5.1",
+ "jest-util": "^27.5.1",
+ "jest-validate": "^27.5.1",
+ "prompts": "^2.0.1",
+ "yargs": "^16.2.0"
+ },
+ "bin": {
+ "jest": "bin/jest.js"
+ },
+ "engines": {
+ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
"node_modules/jest-config": {
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.5.1.tgz",
@@ -4497,30 +4770,6 @@
}
}
},
- "node_modules/jest-config/node_modules/graceful-fs": {
- "version": "4.2.9",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
- "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
- "dev": true
- },
- "node_modules/jest-config/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/jest-diff": {
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz",
@@ -4634,12 +4883,6 @@
"fsevents": "^2.3.2"
}
},
- "node_modules/jest-haste-map/node_modules/graceful-fs": {
- "version": "4.2.9",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
- "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
- "dev": true
- },
"node_modules/jest-jasmine2": {
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz",
@@ -4716,12 +4959,6 @@
"node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
}
},
- "node_modules/jest-message-util/node_modules/graceful-fs": {
- "version": "4.2.9",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
- "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
- "dev": true
- },
"node_modules/jest-mock": {
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz",
@@ -4796,12 +5033,6 @@
"node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
}
},
- "node_modules/jest-resolve/node_modules/graceful-fs": {
- "version": "4.2.9",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
- "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
- "dev": true
- },
"node_modules/jest-runner": {
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.5.1.tgz",
@@ -4834,12 +5065,6 @@
"node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
}
},
- "node_modules/jest-runner/node_modules/graceful-fs": {
- "version": "4.2.9",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
- "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
- "dev": true
- },
"node_modules/jest-runtime": {
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.5.1.tgz",
@@ -4873,21 +5098,6 @@
"node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
}
},
- "node_modules/jest-runtime/node_modules/graceful-fs": {
- "version": "4.2.9",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
- "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
- "dev": true
- },
- "node_modules/jest-runtime/node_modules/strip-bom": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
- "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/jest-serializer": {
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz",
@@ -4901,12 +5111,6 @@
"node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
}
},
- "node_modules/jest-serializer/node_modules/graceful-fs": {
- "version": "4.2.9",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
- "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
- "dev": true
- },
"node_modules/jest-snapshot": {
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.5.1.tgz",
@@ -4940,27 +5144,6 @@
"node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
}
},
- "node_modules/jest-snapshot/node_modules/graceful-fs": {
- "version": "4.2.9",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
- "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
- "dev": true
- },
- "node_modules/jest-snapshot/node_modules/semver": {
- "version": "7.3.5",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
- "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
- "dev": true,
- "dependencies": {
- "lru-cache": "^6.0.0"
- },
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/jest-util": {
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz",
@@ -4978,12 +5161,6 @@
"node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
}
},
- "node_modules/jest-util/node_modules/graceful-fs": {
- "version": "4.2.9",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
- "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
- "dev": true
- },
"node_modules/jest-validate": {
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.5.1.tgz",
@@ -5060,51 +5237,17 @@
"url": "https://github.com/chalk/supports-color?sponsor=1"
}
},
- "node_modules/jest/node_modules/graceful-fs": {
- "version": "4.2.9",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
- "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
- "dev": true
- },
- "node_modules/jest/node_modules/jest-cli": {
- "version": "27.5.1",
- "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.5.1.tgz",
- "integrity": "sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==",
- "dev": true,
- "dependencies": {
- "@jest/core": "^27.5.1",
- "@jest/test-result": "^27.5.1",
- "@jest/types": "^27.5.1",
- "chalk": "^4.0.0",
- "exit": "^0.1.2",
- "graceful-fs": "^4.2.9",
- "import-local": "^3.0.2",
- "jest-config": "^27.5.1",
- "jest-util": "^27.5.1",
- "jest-validate": "^27.5.1",
- "prompts": "^2.0.1",
- "yargs": "^16.2.0"
- },
- "bin": {
- "jest": "bin/jest.js"
- },
- "engines": {
- "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
- },
- "peerDependencies": {
- "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
- },
- "peerDependenciesMeta": {
- "node-notifier": {
- "optional": true
- }
- }
- },
"node_modules/jpeg-js": {
"version": "0.4.4",
"resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz",
"integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg=="
},
+ "node_modules/js-sdsl": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz",
+ "integrity": "sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==",
+ "dev": true
+ },
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -5184,7 +5327,7 @@
"node_modules/json-buffer": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz",
- "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=",
+ "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==",
"dev": true
},
"node_modules/json-parse-even-better-errors": {
@@ -5201,13 +5344,13 @@
"node_modules/json-stable-stringify-without-jsonify": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
- "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
"dev": true
},
"node_modules/json-stringify-safe": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
- "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
+ "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==",
"dev": true,
"optional": true
},
@@ -5226,7 +5369,7 @@
"node_modules/jsonfile": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
- "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
+ "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
"dev": true,
"optionalDependencies": {
"graceful-fs": "^4.1.6"
@@ -5290,7 +5433,7 @@
"node_modules/load-json-file": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
- "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=",
+ "integrity": "sha512-3p6ZOGNbiX4CdvEd1VcE6yi78UrGNpjHO33noGwHCnT/o2fyllJDepsm8+mFFv/DvtwFHht5HIHSyOy5a+ChVQ==",
"dev": true,
"dependencies": {
"graceful-fs": "^4.1.2",
@@ -5302,26 +5445,49 @@
"node": ">=4"
}
},
+ "node_modules/load-json-file/node_modules/parse-json": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
+ "integrity": "sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==",
+ "dev": true,
+ "dependencies": {
+ "error-ex": "^1.2.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/load-json-file/node_modules/pify": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
- "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
+ "node_modules/load-json-file/node_modules/strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/locate-path": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
- "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
"dev": true,
"dependencies": {
- "p-locate": "^2.0.0",
- "path-exists": "^3.0.0"
+ "p-locate": "^5.0.0"
},
"engines": {
- "node": ">=4"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/lodash": {
@@ -5333,12 +5499,12 @@
"node_modules/lodash.get": {
"version": "4.4.2",
"resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
- "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk="
+ "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ=="
},
"node_modules/lodash.memoize": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
- "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=",
+ "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==",
"dev": true
},
"node_modules/lodash.merge": {
@@ -5350,7 +5516,7 @@
"node_modules/lodash.reduce": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz",
- "integrity": "sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs="
+ "integrity": "sha512-6raRe2vxCYBhpBu+B+TtNGUzah+hQjVdu3E17wfusjyrXBka2nBS8OH/gjVZ5PvHOhWmIZTYri09Z6n/QfnNMw=="
},
"node_modules/lowercase-keys": {
"version": "1.0.1",
@@ -5388,6 +5554,15 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/make-dir/node_modules/semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
"node_modules/make-error": {
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
@@ -5484,9 +5659,9 @@
}
},
"node_modules/minimatch": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
- "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"dev": true,
"dependencies": {
"brace-expansion": "^1.1.7"
@@ -5513,6 +5688,12 @@
"mkdirp": "bin/cmd.js"
}
},
+ "node_modules/mkdirp-classic": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
+ "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
+ "dev": true
+ },
"node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@@ -5525,22 +5706,46 @@
"integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
"dev": true
},
+ "node_modules/napi-build-utils": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz",
+ "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==",
+ "dev": true
+ },
"node_modules/natural-compare": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
- "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true
+ },
+ "node_modules/node-abi": {
+ "version": "3.25.0",
+ "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.25.0.tgz",
+ "integrity": "sha512-p+0xx5ruIQ+8X57CRIMxbTZRT7tU0Tjn2C/aAK68AEMrbGsCo6IjnDdPNhEyyjWCT4bRtzomXchYd3sSgk3BJQ==",
+ "dev": true,
+ "dependencies": {
+ "semver": "^7.3.5"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/node-addon-api": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.0.0.tgz",
+ "integrity": "sha512-CvkDw2OEnme7ybCykJpVcKH+uAOLV2qLqiyla128dN9TkEWfrYmxG6C2boDe5KcNQqZF3orkqzGgOMvZ/JNekA==",
"dev": true
},
"node_modules/node-int64": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
- "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=",
+ "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==",
"dev": true
},
"node_modules/node-releases": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz",
- "integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==",
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz",
+ "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==",
"dev": true
},
"node_modules/normalize-package-data": {
@@ -5609,9 +5814,9 @@
}
},
"node_modules/nwsapi": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz",
- "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==",
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.2.tgz",
+ "integrity": "sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw==",
"dev": true
},
"node_modules/object-keys": {
@@ -5627,7 +5832,7 @@
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
- "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"dev": true,
"dependencies": {
"wrappy": "1"
@@ -5675,36 +5880,42 @@
}
},
"node_modules/p-limit": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
- "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
"dev": true,
"dependencies": {
- "p-try": "^1.0.0"
+ "yocto-queue": "^0.1.0"
},
"engines": {
- "node": ">=4"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/p-locate": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
- "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
"dev": true,
"dependencies": {
- "p-limit": "^1.1.0"
+ "p-limit": "^3.0.2"
},
"engines": {
- "node": ">=4"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/p-try": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
- "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
"dev": true,
"engines": {
- "node": ">=4"
+ "node": ">=6"
}
},
"node_modules/parent-module": {
@@ -5722,7 +5933,7 @@
"node_modules/parse-author": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/parse-author/-/parse-author-2.0.0.tgz",
- "integrity": "sha1-00YL8d3Q367tQtp1QkLmX7aEqB8=",
+ "integrity": "sha512-yx5DfvkN8JsHL2xk2Os9oTia467qnvRgey4ahSm2X8epehBLx/gWLcy5KI+Y36ful5DzGbCS6RazqZGgy1gHNw==",
"dev": true,
"dependencies": {
"author-regex": "^1.0.0"
@@ -5732,15 +5943,21 @@
}
},
"node_modules/parse-json": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
- "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
+ "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": {
- "error-ex": "^1.2.0"
+ "@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": ">=0.10.0"
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/parse5": {
@@ -5750,18 +5967,18 @@
"dev": true
},
"node_modules/path-exists": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
- "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
"dev": true,
"engines": {
- "node": ">=4"
+ "node": ">=8"
}
},
"node_modules/path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
- "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
"dev": true,
"engines": {
"node": ">=0.10.0"
@@ -5783,30 +6000,18 @@
"dev": true
},
"node_modules/path-type": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz",
- "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=",
- "dev": true,
- "dependencies": {
- "pify": "^2.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/path-type/node_modules/pify": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
- "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
"dev": true,
"engines": {
- "node": ">=0.10.0"
+ "node": ">=8"
}
},
"node_modules/pend": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
- "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=",
+ "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==",
"dev": true
},
"node_modules/picocolors": {
@@ -5830,7 +6035,7 @@
"node_modules/pify": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
- "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+ "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
"dev": true,
"optional": true,
"engines": {
@@ -5910,32 +6115,14 @@
"node": ">=8"
}
},
- "node_modules/pkg-dir/node_modules/p-try": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
- "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/pkg-dir/node_modules/path-exists": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
- "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/plist": {
- "version": "3.0.5",
- "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.5.tgz",
- "integrity": "sha512-83vX4eYdQp3vP9SxuYgEM/G/pJQqLUz/V/xzPrzruLs7fz7jxGQ1msZ/mg1nwZxUSuOp4sb+/bEIbRrbzZRxDA==",
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.6.tgz",
+ "integrity": "sha512-WiIVYyrp8TD4w8yCvyeIr+lkmrGRd5u0VbRnU+tP/aRLxP/YadJUYOMZJ/6hIa3oUyVCsycXvtNRgd5XBJIbiA==",
"dev": true,
"dependencies": {
"base64-js": "^1.5.1",
- "xmlbuilder": "^9.0.7"
+ "xmlbuilder": "^15.1.1"
},
"engines": {
"node": ">=6"
@@ -5949,6 +6136,32 @@
"node": ">=12.13.0"
}
},
+ "node_modules/prebuild-install": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz",
+ "integrity": "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==",
+ "dev": true,
+ "dependencies": {
+ "detect-libc": "^2.0.0",
+ "expand-template": "^2.0.3",
+ "github-from-package": "0.0.0",
+ "minimist": "^1.2.3",
+ "mkdirp-classic": "^0.5.3",
+ "napi-build-utils": "^1.0.1",
+ "node-abi": "^3.3.0",
+ "pump": "^3.0.0",
+ "rc": "^1.2.7",
+ "simple-get": "^4.0.0",
+ "tar-fs": "^2.0.0",
+ "tunnel-agent": "^0.6.0"
+ },
+ "bin": {
+ "prebuild-install": "bin.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/prelude-ls": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
@@ -5961,7 +6174,7 @@
"node_modules/prepend-http": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz",
- "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=",
+ "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==",
"dev": true,
"engines": {
"node": ">=4"
@@ -6017,19 +6230,19 @@
}
},
"node_modules/prompt": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/prompt/-/prompt-1.2.2.tgz",
- "integrity": "sha512-XNXhNv3PUHJDcDkISpCwSJxtw9Bor4FZnlMUDW64N/KCPdxhfVlpD5+YUXI/Z8a9QWmOhs9KSiVtR8nzPS0BYA==",
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/prompt/-/prompt-1.3.0.tgz",
+ "integrity": "sha512-ZkaRWtaLBZl7KKAKndKYUL8WqNT+cQHKRZnT4RYYms48jQkFw3rrBL+/N5K/KtdEveHkxs982MX2BkDKub2ZMg==",
"dev": true,
"dependencies": {
"@colors/colors": "1.5.0",
- "async": "~0.9.0",
+ "async": "3.2.3",
"read": "1.0.x",
"revalidator": "0.1.x",
"winston": "2.x"
},
"engines": {
- "node": ">= 0.6.6"
+ "node": ">= 6.0.0"
}
},
"node_modules/prompts": {
@@ -6048,14 +6261,14 @@
"node_modules/proto-list": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
- "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=",
+ "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==",
"dev": true,
"optional": true
},
"node_modules/protodef": {
- "version": "1.14.0",
- "resolved": "https://registry.npmjs.org/protodef/-/protodef-1.14.0.tgz",
- "integrity": "sha512-rL1WRlBC8LbAgBTa401eHMqnkX6zy1pHgS4kTSJVJ8rwP/AgVuWijGE3S3XHRkRjB/+4U1jMTqRdmtGdIqVOKQ==",
+ "version": "1.15.0",
+ "resolved": "https://registry.npmjs.org/protodef/-/protodef-1.15.0.tgz",
+ "integrity": "sha512-bZ2Omw8dT+DACjJHLrBWZlqN4MlT9g9oSpJDdkUAJOStUzgJp+Zn42FJfPUdwutUxjaxA0PftN0PDlNa2XbneA==",
"dependencies": {
"lodash.get": "^4.4.2",
"lodash.reduce": "^4.6.0",
@@ -6077,10 +6290,23 @@
"protodef-validator": "cli.js"
}
},
+ "node_modules/protodef/node_modules/readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/psl": {
- "version": "1.8.0",
- "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
- "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==",
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
+ "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==",
"dev": true
},
"node_modules/pump": {
@@ -6101,6 +6327,12 @@
"node": ">=6"
}
},
+ "node_modules/querystringify": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
+ "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
+ "dev": true
+ },
"node_modules/queue-microtask": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
@@ -6121,6 +6353,30 @@
}
]
},
+ "node_modules/rc": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
+ "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
+ "dev": true,
+ "dependencies": {
+ "deep-extend": "^0.6.0",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
+ },
+ "bin": {
+ "rc": "cli.js"
+ }
+ },
+ "node_modules/rc/node_modules/strip-json-comments": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+ "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/rcedit": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/rcedit/-/rcedit-3.0.1.tgz",
@@ -6142,7 +6398,7 @@
"node_modules/read": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz",
- "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=",
+ "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==",
"dev": true,
"dependencies": {
"mute-stream": "~0.0.4"
@@ -6154,7 +6410,7 @@
"node_modules/read-pkg": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz",
- "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=",
+ "integrity": "sha512-eFIBOPW7FGjzBuk3hdXEuNSiTZS/xEMlH49HxMyzb0hyPfu4EhVjT2DH32K1hSSmVq4sebAWnZuuY5auISUTGA==",
"dev": true,
"dependencies": {
"load-json-file": "^2.0.0",
@@ -6168,7 +6424,7 @@
"node_modules/read-pkg-up": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz",
- "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=",
+ "integrity": "sha512-1orxQfbWGUiTn9XsPlChs6rLie/AV9jwZTGmu2NZw/CUDJQchXJFYE0Fq5j7+n558T1JhDWLdhyd1Zj+wLY//w==",
"dev": true,
"dependencies": {
"find-up": "^2.0.0",
@@ -6178,17 +6434,107 @@
"node": ">=4"
}
},
- "node_modules/readable-stream": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
- "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "node_modules/read-pkg-up/node_modules/find-up": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
+ "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==",
+ "dev": true,
"dependencies": {
- "inherits": "^2.0.3",
- "string_decoder": "^1.1.1",
- "util-deprecate": "^1.0.1"
+ "locate-path": "^2.0.0"
},
"engines": {
- "node": ">= 6"
+ "node": ">=4"
+ }
+ },
+ "node_modules/read-pkg-up/node_modules/locate-path": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
+ "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^2.0.0",
+ "path-exists": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/read-pkg-up/node_modules/p-limit": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
+ "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
+ "dev": true,
+ "dependencies": {
+ "p-try": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/read-pkg-up/node_modules/p-locate": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
+ "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/read-pkg-up/node_modules/p-try": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
+ "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/read-pkg-up/node_modules/path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/read-pkg/node_modules/path-type": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz",
+ "integrity": "sha512-dUnb5dXUf+kzhC/W/F4e5/SkluXIFf5VUHolW1Eg1irn1hGWjPGdsRcvYJ1nD6lhk8Ir7VM0bHJKsYTx8Jx9OQ==",
+ "dev": true,
+ "dependencies": {
+ "pify": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/read-pkg/node_modules/pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/readable-stream": {
+ "version": "2.3.7",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
+ "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
+ "dev": true,
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
}
},
"node_modules/regexpp": {
@@ -6206,19 +6552,25 @@
"node_modules/require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
- "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
+ "node_modules/requires-port": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
+ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
+ "dev": true
+ },
"node_modules/resolve": {
- "version": "1.22.0",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz",
- "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==",
+ "version": "1.22.1",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
+ "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
"dev": true,
"dependencies": {
- "is-core-module": "^2.8.1",
+ "is-core-module": "^2.9.0",
"path-parse": "^1.0.7",
"supports-preserve-symlinks-flag": "^1.0.0"
},
@@ -6271,7 +6623,7 @@
"node_modules/responselike": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz",
- "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=",
+ "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==",
"dev": true,
"dependencies": {
"lowercase-keys": "^1.0.0"
@@ -6290,7 +6642,7 @@
"node_modules/revalidator": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/revalidator/-/revalidator-0.1.8.tgz",
- "integrity": "sha1-/s5hv6DBtSoga9axgZgYS91SOjs=",
+ "integrity": "sha512-xcBILK2pA9oh4SiinPEZfhP8HfrB/ha+a2fTMyl7Om2WjlDVrOQy99N2MXXlUHqGJz4qEu2duXxHJjDWuK/0xg==",
"dev": true,
"engines": {
"node": ">= 0.4.0"
@@ -6352,10 +6704,155 @@
"queue-microtask": "^1.2.2"
}
},
- "node_modules/safe-buffer": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
- "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "node_modules/safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+ },
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "dev": true
+ },
+ "node_modules/saxes": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz",
+ "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==",
+ "dev": true,
+ "dependencies": {
+ "xmlchars": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/semver": {
+ "version": "7.3.7",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
+ "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/semver-compare": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz",
+ "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==",
+ "dev": true,
+ "optional": true
+ },
+ "node_modules/serialize-error": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz",
+ "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "type-fest": "^0.13.1"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/serialize-error/node_modules/type-fest": {
+ "version": "0.13.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz",
+ "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==",
+ "dev": true,
+ "optional": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/sharp": {
+ "version": "0.31.1",
+ "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.31.1.tgz",
+ "integrity": "sha512-GR8M1wBwOiFKLkm9JPun27OQnNRZdHfSf9VwcdZX6UrRmM1/XnOrLFTF0GAil+y/YK4E6qcM/ugxs80QirsHxg==",
+ "dev": true,
+ "hasInstallScript": true,
+ "dependencies": {
+ "color": "^4.2.3",
+ "detect-libc": "^2.0.1",
+ "node-addon-api": "^5.0.0",
+ "prebuild-install": "^7.1.1",
+ "semver": "^7.3.7",
+ "simple-get": "^4.0.1",
+ "tar-fs": "^2.1.1",
+ "tunnel-agent": "^0.6.0"
+ },
+ "engines": {
+ "node": ">=14.15.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "dev": true
+ },
+ "node_modules/simple-concat": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
+ "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/simple-get": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz",
+ "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==",
+ "dev": true,
"funding": [
{
"type": "github",
@@ -6369,50 +6866,20 @@
"type": "consulting",
"url": "https://feross.org/support"
}
- ]
- },
- "node_modules/safer-buffer": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
- "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
- "dev": true
- },
- "node_modules/saxes": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz",
- "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==",
- "dev": true,
+ ],
"dependencies": {
- "xmlchars": "^2.2.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/semver": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
- "dev": true,
- "bin": {
- "semver": "bin/semver.js"
+ "decompress-response": "^6.0.0",
+ "once": "^1.3.1",
+ "simple-concat": "^1.0.0"
}
},
- "node_modules/semver-compare": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz",
- "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=",
- "dev": true,
- "optional": true
- },
- "node_modules/serialize-error": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz",
- "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==",
+ "node_modules/simple-get/node_modules/decompress-response": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
+ "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
"dev": true,
- "optional": true,
"dependencies": {
- "type-fest": "^0.13.1"
+ "mimic-response": "^3.1.0"
},
"engines": {
"node": ">=10"
@@ -6421,31 +6888,31 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/shebang-command": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
- "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "node_modules/simple-get/node_modules/mimic-response": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
+ "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
"dev": true,
- "dependencies": {
- "shebang-regex": "^3.0.0"
- },
"engines": {
- "node": ">=8"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/shebang-regex": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
- "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "node_modules/simple-swizzle": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
+ "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
"dev": true,
- "engines": {
- "node": ">=8"
+ "dependencies": {
+ "is-arrayish": "^0.3.1"
}
},
- "node_modules/signal-exit": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
- "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "node_modules/simple-swizzle/node_modules/is-arrayish": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
+ "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==",
"dev": true
},
"node_modules/sisteransi": {
@@ -6509,9 +6976,9 @@
}
},
"node_modules/spdx-license-ids": {
- "version": "3.0.10",
- "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz",
- "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==",
+ "version": "3.0.12",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz",
+ "integrity": "sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==",
"dev": true
},
"node_modules/sprintf-js": {
@@ -6524,7 +6991,7 @@
"node_modules/stack-trace": {
"version": "0.0.10",
"resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
- "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=",
+ "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==",
"dev": true,
"engines": {
"node": "*"
@@ -6552,11 +7019,11 @@
}
},
"node_modules/string_decoder": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
- "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"dependencies": {
- "safe-buffer": "~5.2.0"
+ "safe-buffer": "~5.1.0"
}
},
"node_modules/string-length": {
@@ -6599,12 +7066,12 @@
}
},
"node_modules/strip-bom": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
- "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
+ "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==",
"dev": true,
"engines": {
- "node": ">=4"
+ "node": ">=8"
}
},
"node_modules/strip-final-newline": {
@@ -6643,7 +7110,7 @@
"node_modules/strip-outer/node_modules/escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
- "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
"dev": true,
"engines": {
"node": ">=0.8.0"
@@ -6682,9 +7149,9 @@
}
},
"node_modules/supports-hyperlinks": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz",
- "integrity": "sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==",
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz",
+ "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==",
"dev": true,
"dependencies": {
"has-flag": "^4.0.0",
@@ -6712,6 +7179,48 @@
"integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
"dev": true
},
+ "node_modules/tar-fs": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz",
+ "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==",
+ "dev": true,
+ "dependencies": {
+ "chownr": "^1.1.1",
+ "mkdirp-classic": "^0.5.2",
+ "pump": "^3.0.0",
+ "tar-stream": "^2.1.4"
+ }
+ },
+ "node_modules/tar-stream": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
+ "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
+ "dev": true,
+ "dependencies": {
+ "bl": "^4.0.3",
+ "end-of-stream": "^1.4.1",
+ "fs-constants": "^1.0.0",
+ "inherits": "^2.0.3",
+ "readable-stream": "^3.1.1"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/tar-stream/node_modules/readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/terminal-link": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz",
@@ -6745,7 +7254,7 @@
"node_modules/text-table": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
- "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
"dev": true
},
"node_modules/throat": {
@@ -6763,7 +7272,7 @@
"node_modules/to-fast-properties": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
- "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
+ "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==",
"dev": true,
"engines": {
"node": ">=4"
@@ -6791,19 +7300,29 @@
}
},
"node_modules/tough-cookie": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz",
- "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==",
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.2.tgz",
+ "integrity": "sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==",
"dev": true,
"dependencies": {
"psl": "^1.1.33",
"punycode": "^2.1.1",
- "universalify": "^0.1.2"
+ "universalify": "^0.2.0",
+ "url-parse": "^1.5.3"
},
"engines": {
"node": ">=6"
}
},
+ "node_modules/tough-cookie/node_modules/universalify": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz",
+ "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4.0.0"
+ }
+ },
"node_modules/tr46": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz",
@@ -6819,7 +7338,7 @@
"node_modules/trim-repeated": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz",
- "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=",
+ "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==",
"dev": true,
"dependencies": {
"escape-string-regexp": "^1.0.2"
@@ -6831,16 +7350,16 @@
"node_modules/trim-repeated/node_modules/escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
- "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
"dev": true,
"engines": {
"node": ">=0.8.0"
}
},
"node_modules/ts-jest": {
- "version": "27.1.4",
- "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-27.1.4.tgz",
- "integrity": "sha512-qjkZlVPWVctAezwsOD1OPzbZ+k7zA5z3oxII4dGdZo5ggX/PL7kvwTM0pXTr10fAtbiVpJaL3bWd502zAhpgSQ==",
+ "version": "27.1.5",
+ "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-27.1.5.tgz",
+ "integrity": "sha512-Xv6jBQPoBEvBq/5i2TeSG9tt/nqkbpcurrEG1b+2yfBrcJelOZF9Ml6dmyMh7bcW9JyFbRYpR5rxROSlBLTZHA==",
"dev": true,
"dependencies": {
"bs-logger": "0.x",
@@ -6880,28 +7399,13 @@
}
}
},
- "node_modules/ts-jest/node_modules/semver": {
- "version": "7.3.5",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
- "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
- "dev": true,
- "dependencies": {
- "lru-cache": "^6.0.0"
- },
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/ts-node": {
- "version": "10.7.0",
- "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.7.0.tgz",
- "integrity": "sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A==",
+ "version": "10.9.1",
+ "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz",
+ "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==",
"dev": true,
"dependencies": {
- "@cspotcode/source-map-support": "0.7.0",
+ "@cspotcode/source-map-support": "^0.8.0",
"@tsconfig/node10": "^1.0.7",
"@tsconfig/node12": "^1.0.7",
"@tsconfig/node14": "^1.0.0",
@@ -6912,7 +7416,7 @@
"create-require": "^1.1.0",
"diff": "^4.0.1",
"make-error": "^1.1.1",
- "v8-compile-cache-lib": "^3.0.0",
+ "v8-compile-cache-lib": "^3.0.1",
"yn": "3.1.1"
},
"bin": {
@@ -6978,10 +7482,22 @@
"node": ">=0.6.11 <=0.7.0 || >=0.7.3"
}
},
+ "node_modules/tunnel-agent": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+ "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "^5.0.1"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/twgl.js": {
- "version": "4.19.2",
- "resolved": "https://registry.npmjs.org/twgl.js/-/twgl.js-4.19.2.tgz",
- "integrity": "sha512-dK58dWDJyDyfJVTywpkb2cgqenFiMYqXXMQAp9AOO7Ed0zQ6K6HOjg9mjoWvk01sdSbd6O2Y6FG/M1SW25X+iQ=="
+ "version": "4.24.0",
+ "resolved": "https://registry.npmjs.org/twgl.js/-/twgl.js-4.24.0.tgz",
+ "integrity": "sha512-JGVTxuV9dqaBmajXyvuZIlhCHrTbIaoNjQvtdoLHyK74OtbmNwZUj6rfdp+pz9htitI/tVxiVQ2nuw+KmD29vg=="
},
"node_modules/type-check": {
"version": "0.4.0",
@@ -7005,11 +7521,10 @@
}
},
"node_modules/type-fest": {
- "version": "0.13.1",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz",
- "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==",
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
"dev": true,
- "optional": true,
"engines": {
"node": ">=10"
},
@@ -7020,7 +7535,7 @@
"node_modules/typedarray": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
- "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
+ "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==",
"dev": true
},
"node_modules/typedarray-to-buffer": {
@@ -7033,9 +7548,9 @@
}
},
"node_modules/typescript": {
- "version": "4.6.3",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz",
- "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==",
+ "version": "4.8.4",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz",
+ "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==",
"dev": true,
"bin": {
"tsc": "bin/tsc",
@@ -7054,6 +7569,32 @@
"node": ">= 4.0.0"
}
},
+ "node_modules/update-browserslist-db": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.9.tgz",
+ "integrity": "sha512-/xsqn21EGVdXI3EXSum1Yckj3ZVZugqyOZQ/CxYPBD/R+ko9NSUScf8tFF4dOKY+2pvSSJA/S+5B8s4Zr4kyvg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ }
+ ],
+ "dependencies": {
+ "escalade": "^3.1.1",
+ "picocolors": "^1.0.0"
+ },
+ "bin": {
+ "browserslist-lint": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
"node_modules/uri-js": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
@@ -7062,10 +7603,20 @@
"punycode": "^2.1.0"
}
},
+ "node_modules/url-parse": {
+ "version": "1.5.10",
+ "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
+ "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
+ "dev": true,
+ "dependencies": {
+ "querystringify": "^2.1.1",
+ "requires-port": "^1.0.0"
+ }
+ },
"node_modules/url-parse-lax": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz",
- "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=",
+ "integrity": "sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==",
"dev": true,
"dependencies": {
"prepend-http": "^2.0.0"
@@ -7077,18 +7628,12 @@
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
- },
- "node_modules/v8-compile-cache": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz",
- "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==",
- "dev": true
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
},
"node_modules/v8-compile-cache-lib": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz",
- "integrity": "sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA==",
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
+ "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
"dev": true
},
"node_modules/v8-to-istanbul": {
@@ -7106,9 +7651,9 @@
}
},
"node_modules/v8-to-istanbul/node_modules/source-map": {
- "version": "0.7.3",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
- "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
+ "version": "0.7.4",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz",
+ "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==",
"dev": true,
"engines": {
"node": ">= 8"
@@ -7124,6 +7669,11 @@
"spdx-expression-parse": "^3.0.0"
}
},
+ "node_modules/varint": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/varint/-/varint-5.0.2.tgz",
+ "integrity": "sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow=="
+ },
"node_modules/varint-array": {
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/varint-array/-/varint-array-0.0.0.tgz",
@@ -7133,11 +7683,6 @@
"varint": "^5.0.0"
}
},
- "node_modules/varint-array/node_modules/varint": {
- "version": "5.0.2",
- "resolved": "https://registry.npmjs.org/varint/-/varint-5.0.2.tgz",
- "integrity": "sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow=="
- },
"node_modules/w3c-hr-time": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz",
@@ -7222,12 +7767,12 @@
}
},
"node_modules/winston": {
- "version": "2.4.5",
- "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.5.tgz",
- "integrity": "sha512-TWoamHt5yYvsMarGlGEQE59SbJHqGsZV8/lwC+iCcGeAe0vUaOh+Lv6SYM17ouzC/a/LB1/hz/7sxFBtlu1l4A==",
+ "version": "2.4.6",
+ "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.6.tgz",
+ "integrity": "sha512-J5Zu4p0tojLde8mIOyDSsmLmcP8I3Z6wtwpTDHx1+hGcdhxcJaAmG4CFtagkb+NiN1M9Ek4b42pzMWqfc9jm8w==",
"dev": true,
"dependencies": {
- "async": "~1.0.0",
+ "async": "^3.2.3",
"colors": "1.0.x",
"cycle": "1.0.x",
"eyes": "0.1.x",
@@ -7238,12 +7783,6 @@
"node": ">= 0.10.0"
}
},
- "node_modules/winston/node_modules/async": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/async/-/async-1.0.0.tgz",
- "integrity": "sha1-+PwEyjoTeErenhZBr5hXjPvWR6k=",
- "dev": true
- },
"node_modules/word-wrap": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
@@ -7273,7 +7812,7 @@
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
"dev": true
},
"node_modules/write-file-atomic": {
@@ -7289,9 +7828,9 @@
}
},
"node_modules/ws": {
- "version": "7.5.7",
- "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz",
- "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==",
+ "version": "7.5.9",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
+ "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
"dev": true,
"engines": {
"node": ">=8.3.0"
@@ -7316,12 +7855,12 @@
"dev": true
},
"node_modules/xmlbuilder": {
- "version": "9.0.7",
- "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz",
- "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=",
+ "version": "15.1.1",
+ "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz",
+ "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==",
"dev": true,
"engines": {
- "node": ">=4.0"
+ "node": ">=8.0"
}
},
"node_modules/xmlchars": {
@@ -7375,7 +7914,7 @@
"node_modules/yauzl": {
"version": "2.10.0",
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
- "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=",
+ "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==",
"dev": true,
"dependencies": {
"buffer-crc32": "~0.2.3",
@@ -7390,204 +7929,231 @@
"engines": {
"node": ">=6"
}
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
}
},
"dependencies": {
"@ampproject/remapping": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz",
- "integrity": "sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg==",
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz",
+ "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==",
"dev": true,
"requires": {
- "@jridgewell/trace-mapping": "^0.3.0"
+ "@jridgewell/gen-mapping": "^0.1.0",
+ "@jridgewell/trace-mapping": "^0.3.9"
}
},
"@babel/code-frame": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz",
- "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==",
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz",
+ "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==",
"dev": true,
"requires": {
- "@babel/highlight": "^7.16.7"
+ "@babel/highlight": "^7.18.6"
}
},
"@babel/compat-data": {
- "version": "7.17.7",
- "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.7.tgz",
- "integrity": "sha512-p8pdE6j0a29TNGebNm7NzYZWB3xVZJBZ7XGs42uAKzQo8VQ3F0By/cQCtUEABwIqw5zo6WA4NbmxsfzADzMKnQ==",
+ "version": "7.19.3",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.19.3.tgz",
+ "integrity": "sha512-prBHMK4JYYK+wDjJF1q99KK4JLL+egWS4nmNqdlMUgCExMZ+iZW0hGhyC3VEbsPjvaN0TBhW//VIFwBrk8sEiw==",
"dev": true
},
"@babel/core": {
- "version": "7.17.8",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.8.tgz",
- "integrity": "sha512-OdQDV/7cRBtJHLSOBqqbYNkOcydOgnX59TZx4puf41fzcVtN3e/4yqY8lMQsK+5X2lJtAdmA+6OHqsj1hBJ4IQ==",
+ "version": "7.19.3",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.3.tgz",
+ "integrity": "sha512-WneDJxdsjEvyKtXKsaBGbDeiyOjR5vYq4HcShxnIbG0qixpoHjI3MqeZM9NDvsojNCEBItQE4juOo/bU6e72gQ==",
"dev": true,
"requires": {
"@ampproject/remapping": "^2.1.0",
- "@babel/code-frame": "^7.16.7",
- "@babel/generator": "^7.17.7",
- "@babel/helper-compilation-targets": "^7.17.7",
- "@babel/helper-module-transforms": "^7.17.7",
- "@babel/helpers": "^7.17.8",
- "@babel/parser": "^7.17.8",
- "@babel/template": "^7.16.7",
- "@babel/traverse": "^7.17.3",
- "@babel/types": "^7.17.0",
+ "@babel/code-frame": "^7.18.6",
+ "@babel/generator": "^7.19.3",
+ "@babel/helper-compilation-targets": "^7.19.3",
+ "@babel/helper-module-transforms": "^7.19.0",
+ "@babel/helpers": "^7.19.0",
+ "@babel/parser": "^7.19.3",
+ "@babel/template": "^7.18.10",
+ "@babel/traverse": "^7.19.3",
+ "@babel/types": "^7.19.3",
"convert-source-map": "^1.7.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.2",
- "json5": "^2.1.2",
+ "json5": "^2.2.1",
"semver": "^6.3.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
}
},
"@babel/generator": {
- "version": "7.17.7",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.7.tgz",
- "integrity": "sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w==",
+ "version": "7.19.3",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.19.3.tgz",
+ "integrity": "sha512-fqVZnmp1ncvZU757UzDheKZpfPgatqY59XtW2/j/18H7u76akb8xqvjw82f+i2UKd/ksYsSick/BCLQUUtJ/qQ==",
"dev": true,
"requires": {
- "@babel/types": "^7.17.0",
- "jsesc": "^2.5.1",
- "source-map": "^0.5.0"
+ "@babel/types": "^7.19.3",
+ "@jridgewell/gen-mapping": "^0.3.2",
+ "jsesc": "^2.5.1"
},
"dependencies": {
- "source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
- "dev": true
+ "@jridgewell/gen-mapping": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz",
+ "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==",
+ "dev": true,
+ "requires": {
+ "@jridgewell/set-array": "^1.0.1",
+ "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ }
}
}
},
"@babel/helper-compilation-targets": {
- "version": "7.17.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.17.7.tgz",
- "integrity": "sha512-UFzlz2jjd8kroj0hmCFV5zr+tQPi1dpC2cRsDV/3IEW8bJfCPrPpmcSN6ZS8RqIq4LXcmpipCQFPddyFA5Yc7w==",
+ "version": "7.19.3",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.3.tgz",
+ "integrity": "sha512-65ESqLGyGmLvgR0mst5AdW1FkNlj9rQsCKduzEoEPhBCDFGXvz2jW6bXFG6i0/MrV2s7hhXjjb2yAzcPuQlLwg==",
"dev": true,
"requires": {
- "@babel/compat-data": "^7.17.7",
- "@babel/helper-validator-option": "^7.16.7",
- "browserslist": "^4.17.5",
+ "@babel/compat-data": "^7.19.3",
+ "@babel/helper-validator-option": "^7.18.6",
+ "browserslist": "^4.21.3",
"semver": "^6.3.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
}
},
"@babel/helper-environment-visitor": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz",
- "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==",
- "dev": true,
- "requires": {
- "@babel/types": "^7.16.7"
- }
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz",
+ "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==",
+ "dev": true
},
"@babel/helper-function-name": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz",
- "integrity": "sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA==",
- "dev": true,
- "requires": {
- "@babel/helper-get-function-arity": "^7.16.7",
- "@babel/template": "^7.16.7",
- "@babel/types": "^7.16.7"
- }
- },
- "@babel/helper-get-function-arity": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz",
- "integrity": "sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==",
+ "version": "7.19.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz",
+ "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==",
"dev": true,
"requires": {
- "@babel/types": "^7.16.7"
+ "@babel/template": "^7.18.10",
+ "@babel/types": "^7.19.0"
}
},
"@babel/helper-hoist-variables": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz",
- "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==",
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz",
+ "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==",
"dev": true,
"requires": {
- "@babel/types": "^7.16.7"
+ "@babel/types": "^7.18.6"
}
},
"@babel/helper-module-imports": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz",
- "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==",
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz",
+ "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==",
"dev": true,
"requires": {
- "@babel/types": "^7.16.7"
+ "@babel/types": "^7.18.6"
}
},
"@babel/helper-module-transforms": {
- "version": "7.17.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.17.7.tgz",
- "integrity": "sha512-VmZD99F3gNTYB7fJRDTi+u6l/zxY0BE6OIxPSU7a50s6ZUQkHwSDmV92FfM+oCG0pZRVojGYhkR8I0OGeCVREw==",
+ "version": "7.19.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz",
+ "integrity": "sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==",
"dev": true,
"requires": {
- "@babel/helper-environment-visitor": "^7.16.7",
- "@babel/helper-module-imports": "^7.16.7",
- "@babel/helper-simple-access": "^7.17.7",
- "@babel/helper-split-export-declaration": "^7.16.7",
- "@babel/helper-validator-identifier": "^7.16.7",
- "@babel/template": "^7.16.7",
- "@babel/traverse": "^7.17.3",
- "@babel/types": "^7.17.0"
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-module-imports": "^7.18.6",
+ "@babel/helper-simple-access": "^7.18.6",
+ "@babel/helper-split-export-declaration": "^7.18.6",
+ "@babel/helper-validator-identifier": "^7.18.6",
+ "@babel/template": "^7.18.10",
+ "@babel/traverse": "^7.19.0",
+ "@babel/types": "^7.19.0"
}
},
"@babel/helper-plugin-utils": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz",
- "integrity": "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==",
+ "version": "7.19.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz",
+ "integrity": "sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==",
"dev": true
},
"@babel/helper-simple-access": {
- "version": "7.17.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.17.7.tgz",
- "integrity": "sha512-txyMCGroZ96i+Pxr3Je3lzEJjqwaRC9buMUgtomcrLe5Nd0+fk1h0LLA+ixUF5OW7AhHuQ7Es1WcQJZmZsz2XA==",
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz",
+ "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==",
"dev": true,
"requires": {
- "@babel/types": "^7.17.0"
+ "@babel/types": "^7.18.6"
}
},
"@babel/helper-split-export-declaration": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz",
- "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==",
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz",
+ "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==",
"dev": true,
"requires": {
- "@babel/types": "^7.16.7"
+ "@babel/types": "^7.18.6"
}
},
+ "@babel/helper-string-parser": {
+ "version": "7.18.10",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz",
+ "integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==",
+ "dev": true
+ },
"@babel/helper-validator-identifier": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz",
- "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==",
+ "version": "7.19.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz",
+ "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==",
"dev": true
},
"@babel/helper-validator-option": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz",
- "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==",
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz",
+ "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==",
"dev": true
},
"@babel/helpers": {
- "version": "7.17.8",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.8.tgz",
- "integrity": "sha512-QcL86FGxpfSJwGtAvv4iG93UL6bmqBdmoVY0CMCU2g+oD2ezQse3PT5Pa+jiD6LJndBQi0EDlpzOWNlLuhz5gw==",
+ "version": "7.19.0",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.0.tgz",
+ "integrity": "sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg==",
"dev": true,
"requires": {
- "@babel/template": "^7.16.7",
- "@babel/traverse": "^7.17.3",
- "@babel/types": "^7.17.0"
+ "@babel/template": "^7.18.10",
+ "@babel/traverse": "^7.19.0",
+ "@babel/types": "^7.19.0"
}
},
"@babel/highlight": {
- "version": "7.16.10",
- "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz",
- "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==",
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz",
+ "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==",
"dev": true,
"requires": {
- "@babel/helper-validator-identifier": "^7.16.7",
+ "@babel/helper-validator-identifier": "^7.18.6",
"chalk": "^2.0.0",
"js-tokens": "^4.0.0"
},
@@ -7624,19 +8190,19 @@
"color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
"dev": true
},
"escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
- "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
"dev": true
},
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
- "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
"dev": true
},
"supports-color": {
@@ -7651,9 +8217,9 @@
}
},
"@babel/parser": {
- "version": "7.17.8",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.8.tgz",
- "integrity": "sha512-BoHhDJrJXqcg+ZL16Xv39H9n+AqJ4pcDrQBGZN+wHxIysrLZ3/ECwCBUch/1zUNhnsXULcONU3Ei5Hmkfk6kiQ==",
+ "version": "7.19.3",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.3.tgz",
+ "integrity": "sha512-pJ9xOlNWHiy9+FuFP09DEAFbAn4JskgRsVcc169w2xRBC3FRGuQEwjeIMMND9L2zc0iEhO/tGv4Zq+km+hxNpQ==",
"dev": true
},
"@babel/plugin-syntax-async-generators": {
@@ -7765,39 +8331,39 @@
}
},
"@babel/plugin-syntax-typescript": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.7.tgz",
- "integrity": "sha512-YhUIJHHGkqPgEcMYkPCKTyGUdoGKWtopIycQyjJH8OjvRgOYsXsaKehLVPScKJWAULPxMa4N1vCe6szREFlZ7A==",
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz",
+ "integrity": "sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.16.7"
+ "@babel/helper-plugin-utils": "^7.18.6"
}
},
"@babel/template": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz",
- "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==",
+ "version": "7.18.10",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz",
+ "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==",
"dev": true,
"requires": {
- "@babel/code-frame": "^7.16.7",
- "@babel/parser": "^7.16.7",
- "@babel/types": "^7.16.7"
+ "@babel/code-frame": "^7.18.6",
+ "@babel/parser": "^7.18.10",
+ "@babel/types": "^7.18.10"
}
},
"@babel/traverse": {
- "version": "7.17.3",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.3.tgz",
- "integrity": "sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw==",
- "dev": true,
- "requires": {
- "@babel/code-frame": "^7.16.7",
- "@babel/generator": "^7.17.3",
- "@babel/helper-environment-visitor": "^7.16.7",
- "@babel/helper-function-name": "^7.16.7",
- "@babel/helper-hoist-variables": "^7.16.7",
- "@babel/helper-split-export-declaration": "^7.16.7",
- "@babel/parser": "^7.17.3",
- "@babel/types": "^7.17.0",
+ "version": "7.19.3",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.3.tgz",
+ "integrity": "sha512-qh5yf6149zhq2sgIXmwjnsvmnNQC2iw70UFjp4olxucKrWd/dvlUsBI88VSLUsnMNF7/vnOiA+nk1+yLoCqROQ==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.18.6",
+ "@babel/generator": "^7.19.3",
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-function-name": "^7.19.0",
+ "@babel/helper-hoist-variables": "^7.18.6",
+ "@babel/helper-split-export-declaration": "^7.18.6",
+ "@babel/parser": "^7.19.3",
+ "@babel/types": "^7.19.3",
"debug": "^4.1.0",
"globals": "^11.1.0"
},
@@ -7811,12 +8377,13 @@
}
},
"@babel/types": {
- "version": "7.17.0",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz",
- "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==",
+ "version": "7.19.3",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.19.3.tgz",
+ "integrity": "sha512-hGCaQzIY22DJlDh9CH7NOxgKkFjBk0Cw9xDO1Xmh2151ti7wiGfQ3LauXzL4HP1fmFlTX6XjpRETTpUcv7wQLw==",
"dev": true,
"requires": {
- "@babel/helper-validator-identifier": "^7.16.7",
+ "@babel/helper-string-parser": "^7.18.10",
+ "@babel/helper-validator-identifier": "^7.19.1",
"to-fast-properties": "^2.0.0"
}
},
@@ -7832,59 +8399,118 @@
"integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==",
"dev": true
},
- "@cspotcode/source-map-consumer": {
- "version": "0.8.0",
- "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz",
- "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==",
- "dev": true
- },
"@cspotcode/source-map-support": {
- "version": "0.7.0",
- "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz",
- "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==",
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
+ "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
+ "dev": true,
+ "requires": {
+ "@jridgewell/trace-mapping": "0.3.9"
+ },
+ "dependencies": {
+ "@jridgewell/trace-mapping": {
+ "version": "0.3.9",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
+ "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
+ "dev": true,
+ "requires": {
+ "@jridgewell/resolve-uri": "^3.0.3",
+ "@jridgewell/sourcemap-codec": "^1.4.10"
+ }
+ }
+ }
+ },
+ "@electron/get": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@electron/get/-/get-1.14.1.tgz",
+ "integrity": "sha512-BrZYyL/6m0ZXz/lDxy/nlVhQz+WF+iPS6qXolEU8atw7h6v1aYkjwJZ63m+bJMBTxDE66X+r2tPS4a/8C82sZw==",
"dev": true,
"requires": {
- "@cspotcode/source-map-consumer": "0.8.0"
+ "debug": "^4.1.1",
+ "env-paths": "^2.2.0",
+ "fs-extra": "^8.1.0",
+ "global-agent": "^3.0.0",
+ "global-tunnel-ng": "^2.7.1",
+ "got": "^9.6.0",
+ "progress": "^2.0.3",
+ "semver": "^6.2.0",
+ "sumchecker": "^3.0.1"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
}
},
- "@electron/get": {
- "version": "1.12.4",
- "resolved": "https://registry.npmjs.org/@electron/get/-/get-1.12.4.tgz",
- "integrity": "sha512-6nr9DbJPUR9Xujw6zD3y+rS95TyItEVM0NVjt1EehY2vUWfIgPiIPVHxCvaTS0xr2B+DRxovYVKbuOWqC35kjg==",
+ "@electron/universal": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-1.3.0.tgz",
+ "integrity": "sha512-6SAIlMZZRj1qpe3z3qhMWf3fmqhAdzferiQ5kpspCI9sH1GjkzRXY0RLaz0ktHtYonOj9XMpXNkhDy7QQagQEg==",
"dev": true,
"requires": {
- "debug": "^4.1.1",
- "env-paths": "^2.2.0",
- "fs-extra": "^8.1.0",
- "global-agent": "^2.0.2",
- "global-tunnel-ng": "^2.7.1",
- "got": "^9.6.0",
- "progress": "^2.0.3",
- "semver": "^6.2.0",
- "sumchecker": "^3.0.1"
+ "@malept/cross-spawn-promise": "^1.1.0",
+ "asar": "^3.1.0",
+ "debug": "^4.3.1",
+ "dir-compare": "^2.4.0",
+ "fs-extra": "^9.0.1",
+ "minimatch": "^3.0.4",
+ "plist": "^3.0.4"
+ },
+ "dependencies": {
+ "fs-extra": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
+ "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
+ "dev": true,
+ "requires": {
+ "at-least-node": "^1.0.0",
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ }
+ },
+ "jsonfile": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
+ "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.6",
+ "universalify": "^2.0.0"
+ }
+ },
+ "universalify": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
+ "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
+ "dev": true
+ }
}
},
"@eslint/eslintrc": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.1.tgz",
- "integrity": "sha512-bxvbYnBPN1Gibwyp6NrpnFzA3YtRL3BBAyEAFVIpNTm2Rn4Vy87GA5M4aSn3InRrlsbX5N0GW7XIx+U4SAEKdQ==",
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.2.tgz",
+ "integrity": "sha512-AXYd23w1S/bv3fTs3Lz0vjiYemS08jWkI3hYyS9I1ry+0f+Yjs1wm+sU0BS8qDOPrBIkp4qHYC16I8uVtpLajQ==",
"dev": true,
"requires": {
"ajv": "^6.12.4",
"debug": "^4.3.2",
- "espree": "^9.3.1",
- "globals": "^13.9.0",
+ "espree": "^9.4.0",
+ "globals": "^13.15.0",
"ignore": "^5.2.0",
"import-fresh": "^3.2.1",
"js-yaml": "^4.1.0",
- "minimatch": "^3.0.4",
+ "minimatch": "^3.1.2",
"strip-json-comments": "^3.1.1"
}
},
"@humanwhocodes/config-array": {
- "version": "0.9.5",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz",
- "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==",
+ "version": "0.10.7",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.7.tgz",
+ "integrity": "sha512-MDl6D6sBsaV452/QSdX+4CXIjZhIcI0PELsxUjk4U828yd58vk3bTIvk/6w5FY+4hIy9sLW0sfrV7K7Kc++j/w==",
"dev": true,
"requires": {
"@humanwhocodes/object-schema": "^1.2.1",
@@ -7892,6 +8518,18 @@
"minimatch": "^3.0.4"
}
},
+ "@humanwhocodes/gitignore-to-minimatch": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz",
+ "integrity": "sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA==",
+ "dev": true
+ },
+ "@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true
+ },
"@humanwhocodes/object-schema": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz",
@@ -7967,18 +8605,6 @@
"p-limit": "^2.2.0"
}
},
- "p-try": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
- "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
- "dev": true
- },
- "path-exists": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
- "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
- "dev": true
- },
"resolve-from": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
@@ -7988,7 +8614,7 @@
"sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
- "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
+ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
"dev": true
}
}
@@ -8047,14 +8673,6 @@
"rimraf": "^3.0.0",
"slash": "^3.0.0",
"strip-ansi": "^6.0.0"
- },
- "dependencies": {
- "graceful-fs": {
- "version": "4.2.9",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
- "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
- "dev": true
- }
}
},
"@jest/environment": {
@@ -8125,14 +8743,6 @@
"string-length": "^4.0.1",
"terminal-link": "^2.0.0",
"v8-to-istanbul": "^8.1.0"
- },
- "dependencies": {
- "graceful-fs": {
- "version": "4.2.9",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
- "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
- "dev": true
- }
}
},
"@jest/source-map": {
@@ -8144,14 +8754,6 @@
"callsites": "^3.0.0",
"graceful-fs": "^4.2.9",
"source-map": "^0.6.0"
- },
- "dependencies": {
- "graceful-fs": {
- "version": "4.2.9",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
- "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
- "dev": true
- }
}
},
"@jest/test-result": {
@@ -8176,14 +8778,6 @@
"graceful-fs": "^4.2.9",
"jest-haste-map": "^27.5.1",
"jest-runtime": "^27.5.1"
- },
- "dependencies": {
- "graceful-fs": {
- "version": "4.2.9",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
- "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
- "dev": true
- }
}
},
"@jest/transform": {
@@ -8207,14 +8801,6 @@
"slash": "^3.0.0",
"source-map": "^0.6.1",
"write-file-atomic": "^3.0.0"
- },
- "dependencies": {
- "graceful-fs": {
- "version": "4.2.9",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
- "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
- "dev": true
- }
}
},
"@jest/types": {
@@ -8230,22 +8816,38 @@
"chalk": "^4.0.0"
}
},
+ "@jridgewell/gen-mapping": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz",
+ "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==",
+ "dev": true,
+ "requires": {
+ "@jridgewell/set-array": "^1.0.0",
+ "@jridgewell/sourcemap-codec": "^1.4.10"
+ }
+ },
"@jridgewell/resolve-uri": {
- "version": "3.0.5",
- "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz",
- "integrity": "sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==",
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
+ "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
+ "dev": true
+ },
+ "@jridgewell/set-array": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
+ "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
"dev": true
},
"@jridgewell/sourcemap-codec": {
- "version": "1.4.11",
- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz",
- "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==",
+ "version": "1.4.14",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
+ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
"dev": true
},
"@jridgewell/trace-mapping": {
- "version": "0.3.4",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz",
- "integrity": "sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ==",
+ "version": "0.3.15",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz",
+ "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==",
"dev": true,
"requires": {
"@jridgewell/resolve-uri": "^3.0.3",
@@ -8327,29 +8929,38 @@
"dev": true
},
"@tsconfig/node10": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz",
- "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==",
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
+ "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==",
"dev": true
},
"@tsconfig/node12": {
- "version": "1.0.9",
- "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz",
- "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==",
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
+ "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
"dev": true
},
"@tsconfig/node14": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz",
- "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==",
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
+ "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
"dev": true
},
"@tsconfig/node16": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz",
- "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==",
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz",
+ "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==",
"dev": true
},
+ "@types/adm-zip": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/@types/adm-zip/-/adm-zip-0.5.0.tgz",
+ "integrity": "sha512-FCJBJq9ODsQZUNURo5ILAQueuA8WJhRvuihS3ke2iI25mJlfV2LK8jG2Qj2z2AWg8U0FtWWqBHVRetceLskSaw==",
+ "dev": true,
+ "requires": {
+ "@types/node": "*"
+ }
+ },
"@types/babel__core": {
"version": "7.1.19",
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.19.tgz",
@@ -8383,18 +8994,18 @@
}
},
"@types/babel__traverse": {
- "version": "7.14.2",
- "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.14.2.tgz",
- "integrity": "sha512-K2waXdXBi2302XUdcHcR1jCeU0LL4TD9HRs/gk0N2Xvrht+G/BfJa4QObBQZfhMdxiCpV3COl5Nfq4uKTeTnJA==",
+ "version": "7.18.2",
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.2.tgz",
+ "integrity": "sha512-FcFaxOr2V5KZCviw1TnutEMVUVsGt4D2hP1TAfXZAMKuHYW3xQhe3jTxNPWutgCJ3/X1c5yX8ZoGVEItxKbwBg==",
"dev": true,
"requires": {
"@babel/types": "^7.3.0"
}
},
"@types/glob": {
- "version": "7.1.4",
- "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.4.tgz",
- "integrity": "sha512-w+LsMxKyYQm347Otw+IfBXOv9UWVjpHpCDdbBMt8Kz/xbvCYNjP+0qPh91Km3iKfSRLBB0P7fAMf0KHrPu+MyA==",
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz",
+ "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==",
"dev": true,
"optional": true,
"requires": {
@@ -8436,9 +9047,9 @@
}
},
"@types/jest": {
- "version": "27.4.1",
- "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.4.1.tgz",
- "integrity": "sha512-23iPJADSmicDVrWk+HT58LMJtzLAnB2AgIzplQuq/bSrGaxCrlvRFjGbXmamnnk/mAmCdLStiGqggu28ocUyiw==",
+ "version": "27.5.2",
+ "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.5.2.tgz",
+ "integrity": "sha512-mpT8LJJ4CMeeahobofYWIjFo0xonRS/HfxnVEPMPFSQdGUt1uHCnoPT7Zhb+sjDU2wz0oKV0OLUR0WzrHNgfeA==",
"dev": true,
"requires": {
"jest-matcher-utils": "^27.0.0",
@@ -8460,17 +9071,26 @@
"integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==",
"dev": true
},
+ "@types/merge-images": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@types/merge-images/-/merge-images-1.2.1.tgz",
+ "integrity": "sha512-wXXXOXYvoHpa4QwQBDNOPH7QbGECTvQshThgytYhruIbwbF4/11EouhSnYtUgf0n52bGYdt2BQdZV2K6C2SrnA==",
+ "dev": true,
+ "requires": {
+ "@types/node": "*"
+ }
+ },
"@types/minimatch": {
- "version": "3.0.5",
- "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz",
- "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==",
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz",
+ "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==",
"dev": true,
"optional": true
},
"@types/node": {
- "version": "16.6.1",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-16.6.1.tgz",
- "integrity": "sha512-Sr7BhXEAer9xyGuCN3Ek9eg9xPviCF2gfu9kTfuU2HkTVAMYSDeX40fvpmo72n5nansg3nsBjuQBrsS28r+NUw==",
+ "version": "18.7.23",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.23.tgz",
+ "integrity": "sha512-DWNcCHolDq0ZKGizjx2DZjR/PqsYwAcYUJmfMWqtVU2MBMG5Mo+xFZrhGId5r/O5HOuMPyQEcM6KUBp5lBZZBg==",
"dev": true
},
"@types/obj-file-parser": {
@@ -8489,15 +9109,15 @@
}
},
"@types/prettier": {
- "version": "2.4.4",
- "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.4.4.tgz",
- "integrity": "sha512-ReVR2rLTV1kvtlWFyuot+d1pkpG2Fw/XKE3PDAdj57rbM97ttSp9JZ2UsP+2EHTylra9cUf6JA7tGwW1INzUrA==",
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.1.tgz",
+ "integrity": "sha512-ri0UmynRRvZiiUJdiz38MmIblKK+oH30MztdBVR95dv/Ubw6neWSb8u1XpRb72L4qsZOhz+L+z9JD40SJmfWow==",
"dev": true
},
"@types/prompt": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@types/prompt/-/prompt-1.1.2.tgz",
- "integrity": "sha512-Zc9YzOvjAWxxGY7qo0Q6yINMVVspAa4p68UCzucWMU+GaPujpjwbOwzI38s7Jq01k0GztzLxXlRiFcZf/aeIWA==",
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/@types/prompt/-/prompt-1.1.4.tgz",
+ "integrity": "sha512-FLMcf+ol+eUJALeIYWLjQl0hYw86G0PIg7D5+4jJHwr/wKI8p3R0u+oKLbyRkzCxb7e0pHixyCj7UgSv7I/TJQ==",
"dev": true,
"requires": {
"@types/node": "*",
@@ -8510,6 +9130,15 @@
"integrity": "sha512-q6KSi3PklLGQ0CesZ/XuLwly4DXXlnJuucYOG9lrBqrP8rKiuPZThav2h2+pFjaheNpnT0qKK3i304QWIePeJw==",
"dev": true
},
+ "@types/sharp": {
+ "version": "0.31.0",
+ "resolved": "https://registry.npmjs.org/@types/sharp/-/sharp-0.31.0.tgz",
+ "integrity": "sha512-nwivOU101fYInCwdDcH/0/Ru6yIRXOpORx25ynEOc6/IakuCmjOAGpaO5VfUl4QkDtUC6hj+Z2eCQvgXOioknw==",
+ "dev": true,
+ "requires": {
+ "@types/node": "*"
+ }
+ },
"@types/sizzle": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz",
@@ -8547,9 +9176,9 @@
"dev": true
},
"@types/yauzl": {
- "version": "2.9.2",
- "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.2.tgz",
- "integrity": "sha512-8uALY5LTvSuHgloDVUvWP3pIauILm+8/0pDMokuDYIoNsOkSwd5AiHBTSEJjKTDcZr5z8UpgOWZkxBF4iJftoA==",
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz",
+ "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==",
"dev": true,
"optional": true,
"requires": {
@@ -8557,132 +9186,110 @@
}
},
"@typescript-eslint/eslint-plugin": {
- "version": "5.16.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.16.0.tgz",
- "integrity": "sha512-SJoba1edXvQRMmNI505Uo4XmGbxCK9ARQpkvOd00anxzri9RNQk0DDCxD+LIl+jYhkzOJiOMMKYEHnHEODjdCw==",
+ "version": "5.38.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.38.1.tgz",
+ "integrity": "sha512-ky7EFzPhqz3XlhS7vPOoMDaQnQMn+9o5ICR9CPr/6bw8HrFkzhMSxuA3gRfiJVvs7geYrSeawGJjZoZQKCOglQ==",
"dev": true,
"requires": {
- "@typescript-eslint/scope-manager": "5.16.0",
- "@typescript-eslint/type-utils": "5.16.0",
- "@typescript-eslint/utils": "5.16.0",
- "debug": "^4.3.2",
- "functional-red-black-tree": "^1.0.1",
- "ignore": "^5.1.8",
+ "@typescript-eslint/scope-manager": "5.38.1",
+ "@typescript-eslint/type-utils": "5.38.1",
+ "@typescript-eslint/utils": "5.38.1",
+ "debug": "^4.3.4",
+ "ignore": "^5.2.0",
"regexpp": "^3.2.0",
- "semver": "^7.3.5",
+ "semver": "^7.3.7",
"tsutils": "^3.21.0"
- },
- "dependencies": {
- "semver": {
- "version": "7.3.5",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
- "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
- "dev": true,
- "requires": {
- "lru-cache": "^6.0.0"
- }
- }
}
},
"@typescript-eslint/parser": {
- "version": "5.16.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.16.0.tgz",
- "integrity": "sha512-fkDq86F0zl8FicnJtdXakFs4lnuebH6ZADDw6CYQv0UZeIjHvmEw87m9/29nk2Dv5Lmdp0zQ3zDQhiMWQf/GbA==",
+ "version": "5.38.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.38.1.tgz",
+ "integrity": "sha512-LDqxZBVFFQnQRz9rUZJhLmox+Ep5kdUmLatLQnCRR6523YV+XhRjfYzStQ4MheFA8kMAfUlclHSbu+RKdRwQKw==",
"dev": true,
"requires": {
- "@typescript-eslint/scope-manager": "5.16.0",
- "@typescript-eslint/types": "5.16.0",
- "@typescript-eslint/typescript-estree": "5.16.0",
- "debug": "^4.3.2"
+ "@typescript-eslint/scope-manager": "5.38.1",
+ "@typescript-eslint/types": "5.38.1",
+ "@typescript-eslint/typescript-estree": "5.38.1",
+ "debug": "^4.3.4"
}
},
"@typescript-eslint/scope-manager": {
- "version": "5.16.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.16.0.tgz",
- "integrity": "sha512-P+Yab2Hovg8NekLIR/mOElCDPyGgFZKhGoZA901Yax6WR6HVeGLbsqJkZ+Cvk5nts/dAlFKm8PfL43UZnWdpIQ==",
+ "version": "5.38.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.38.1.tgz",
+ "integrity": "sha512-BfRDq5RidVU3RbqApKmS7RFMtkyWMM50qWnDAkKgQiezRtLKsoyRKIvz1Ok5ilRWeD9IuHvaidaLxvGx/2eqTQ==",
"dev": true,
"requires": {
- "@typescript-eslint/types": "5.16.0",
- "@typescript-eslint/visitor-keys": "5.16.0"
+ "@typescript-eslint/types": "5.38.1",
+ "@typescript-eslint/visitor-keys": "5.38.1"
}
},
"@typescript-eslint/type-utils": {
- "version": "5.16.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.16.0.tgz",
- "integrity": "sha512-SKygICv54CCRl1Vq5ewwQUJV/8padIWvPgCxlWPGO/OgQLCijY9G7lDu6H+mqfQtbzDNlVjzVWQmeqbLMBLEwQ==",
+ "version": "5.38.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.38.1.tgz",
+ "integrity": "sha512-UU3j43TM66gYtzo15ivK2ZFoDFKKP0k03MItzLdq0zV92CeGCXRfXlfQX5ILdd4/DSpHkSjIgLLLh1NtkOJOAw==",
"dev": true,
"requires": {
- "@typescript-eslint/utils": "5.16.0",
- "debug": "^4.3.2",
+ "@typescript-eslint/typescript-estree": "5.38.1",
+ "@typescript-eslint/utils": "5.38.1",
+ "debug": "^4.3.4",
"tsutils": "^3.21.0"
}
},
"@typescript-eslint/types": {
- "version": "5.16.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.16.0.tgz",
- "integrity": "sha512-oUorOwLj/3/3p/HFwrp6m/J2VfbLC8gjW5X3awpQJ/bSG+YRGFS4dpsvtQ8T2VNveV+LflQHjlLvB6v0R87z4g==",
+ "version": "5.38.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.38.1.tgz",
+ "integrity": "sha512-QTW1iHq1Tffp9lNfbfPm4WJabbvpyaehQ0SrvVK2yfV79SytD9XDVxqiPvdrv2LK7DGSFo91TB2FgWanbJAZXg==",
"dev": true
},
"@typescript-eslint/typescript-estree": {
- "version": "5.16.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.16.0.tgz",
- "integrity": "sha512-SE4VfbLWUZl9MR+ngLSARptUv2E8brY0luCdgmUevU6arZRY/KxYoLI/3V/yxaURR8tLRN7bmZtJdgmzLHI6pQ==",
+ "version": "5.38.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.38.1.tgz",
+ "integrity": "sha512-99b5e/Enoe8fKMLdSuwrfH/C0EIbpUWmeEKHmQlGZb8msY33qn1KlkFww0z26o5Omx7EVjzVDCWEfrfCDHfE7g==",
"dev": true,
"requires": {
- "@typescript-eslint/types": "5.16.0",
- "@typescript-eslint/visitor-keys": "5.16.0",
- "debug": "^4.3.2",
- "globby": "^11.0.4",
+ "@typescript-eslint/types": "5.38.1",
+ "@typescript-eslint/visitor-keys": "5.38.1",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
"is-glob": "^4.0.3",
- "semver": "^7.3.5",
+ "semver": "^7.3.7",
"tsutils": "^3.21.0"
- },
- "dependencies": {
- "semver": {
- "version": "7.3.5",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
- "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
- "dev": true,
- "requires": {
- "lru-cache": "^6.0.0"
- }
- }
}
},
"@typescript-eslint/utils": {
- "version": "5.16.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.16.0.tgz",
- "integrity": "sha512-iYej2ER6AwmejLWMWzJIHy3nPJeGDuCqf8Jnb+jAQVoPpmWzwQOfa9hWVB8GIQE5gsCv/rfN4T+AYb/V06WseQ==",
+ "version": "5.38.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.38.1.tgz",
+ "integrity": "sha512-oIuUiVxPBsndrN81oP8tXnFa/+EcZ03qLqPDfSZ5xIJVm7A9V0rlkQwwBOAGtrdN70ZKDlKv+l1BeT4eSFxwXA==",
"dev": true,
"requires": {
"@types/json-schema": "^7.0.9",
- "@typescript-eslint/scope-manager": "5.16.0",
- "@typescript-eslint/types": "5.16.0",
- "@typescript-eslint/typescript-estree": "5.16.0",
+ "@typescript-eslint/scope-manager": "5.38.1",
+ "@typescript-eslint/types": "5.38.1",
+ "@typescript-eslint/typescript-estree": "5.38.1",
"eslint-scope": "^5.1.1",
"eslint-utils": "^3.0.0"
}
},
"@typescript-eslint/visitor-keys": {
- "version": "5.16.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.16.0.tgz",
- "integrity": "sha512-jqxO8msp5vZDhikTwq9ubyMHqZ67UIvawohr4qF3KhlpL7gzSjOd+8471H3nh5LyABkaI85laEKKU8SnGUK5/g==",
+ "version": "5.38.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.38.1.tgz",
+ "integrity": "sha512-bSHr1rRxXt54+j2n4k54p4fj8AHJ49VDWtjpImOpzQj4qjAiOpPni+V1Tyajh19Api1i844F757cur8wH3YvOA==",
"dev": true,
"requires": {
- "@typescript-eslint/types": "5.16.0",
- "eslint-visitor-keys": "^3.0.0"
+ "@typescript-eslint/types": "5.38.1",
+ "eslint-visitor-keys": "^3.3.0"
}
},
"abab": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz",
- "integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==",
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz",
+ "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==",
"dev": true
},
"acorn": {
- "version": "8.7.0",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz",
- "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==",
+ "version": "8.8.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz",
+ "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==",
"dev": true
},
"acorn-globals": {
@@ -8803,9 +9410,9 @@
"dev": true
},
"asar": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/asar/-/asar-3.0.3.tgz",
- "integrity": "sha512-k7zd+KoR+n8pl71PvgElcoKHrVNiSXtw7odKbyNpmgKe7EGRF9Pnu3uLOukD37EvavKwVFxOUpqXTIZC5B5Pmw==",
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/asar/-/asar-3.2.0.tgz",
+ "integrity": "sha512-COdw2ZQvKdFGFxXwX3oYh2/sOsJWJegrdJCGxnN4MZ7IULgRBp9P6665aqj9z1v9VwP4oP1hRBojRDQ//IGgAg==",
"dev": true,
"requires": {
"@types/glob": "^7.1.1",
@@ -8813,26 +9420,18 @@
"commander": "^5.0.0",
"glob": "^7.1.6",
"minimatch": "^3.0.4"
- },
- "dependencies": {
- "commander": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz",
- "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==",
- "dev": true
- }
}
},
"async": {
- "version": "0.9.2",
- "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz",
- "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=",
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz",
+ "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==",
"dev": true
},
"asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
- "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
"dev": true
},
"at-least-node": {
@@ -8844,7 +9443,7 @@
"author-regex": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/author-regex/-/author-regex-1.0.0.tgz",
- "integrity": "sha1-0IiFvmubv5Q5/gh8dihyRfCoFFA=",
+ "integrity": "sha512-KbWgR8wOYRAPekEmMXrYYdc7BRyhn2Ftk7KWfMUnQ43hFdojWEFRxhhRUm3/OFEdPa1r0KAvTTg9YQK57xTe0g==",
"dev": true
},
"babel-jest": {
@@ -8861,14 +9460,6 @@
"chalk": "^4.0.0",
"graceful-fs": "^4.2.9",
"slash": "^3.0.0"
- },
- "dependencies": {
- "graceful-fs": {
- "version": "4.2.9",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
- "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
- "dev": true
- }
}
},
"babel-plugin-istanbul": {
@@ -8938,6 +9529,30 @@
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
"dev": true
},
+ "bl": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
+ "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
+ "dev": true,
+ "requires": {
+ "buffer": "^5.5.0",
+ "inherits": "^2.0.4",
+ "readable-stream": "^3.4.0"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ }
+ }
+ },
"bluebird": {
"version": "3.7.2",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
@@ -8945,9 +9560,9 @@
"dev": true
},
"boolean": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.1.2.tgz",
- "integrity": "sha512-YN6UmV0FfLlBVvRvNPx3pz5W/mUoYB24J4WSXOKP/OOJpi+Oq6WYqPaNTHzjI0QzwWtnvEd5CGYyQPgp1jFxnw==",
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz",
+ "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==",
"dev": true,
"optional": true
},
@@ -8977,16 +9592,15 @@
"dev": true
},
"browserslist": {
- "version": "4.20.2",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.2.tgz",
- "integrity": "sha512-CQOBCqp/9pDvDbx3xfMi+86pr4KXIf2FDkTTdeuYw8OxS9t898LA1Khq57gtufFILXpfgsSx5woNgsBgvGjpsA==",
+ "version": "4.21.4",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz",
+ "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==",
"dev": true,
"requires": {
- "caniuse-lite": "^1.0.30001317",
- "electron-to-chromium": "^1.4.84",
- "escalade": "^3.1.1",
- "node-releases": "^2.0.2",
- "picocolors": "^1.0.0"
+ "caniuse-lite": "^1.0.30001400",
+ "electron-to-chromium": "^1.4.251",
+ "node-releases": "^2.0.6",
+ "update-browserslist-db": "^1.0.9"
}
},
"bs-logger": {
@@ -9007,6 +9621,16 @@
"node-int64": "^0.4.0"
}
},
+ "buffer": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+ "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+ "dev": true,
+ "requires": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.1.13"
+ }
+ },
"buffer-alloc": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz",
@@ -9026,13 +9650,19 @@
"buffer-crc32": {
"version": "0.2.13",
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
- "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=",
+ "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
+ "dev": true
+ },
+ "buffer-equal": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz",
+ "integrity": "sha512-tcBWO2Dl4e7Asr9hTGcpVrCe+F7DubpmqWCTbj4FHLmjqO2hIaC383acQubWtRJhdceqs5uBHs6Es+Sk//RKiQ==",
"dev": true
},
"buffer-fill": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz",
- "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=",
+ "integrity": "sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==",
"dev": true
},
"buffer-from": {
@@ -9041,15 +9671,10 @@
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
"dev": true
},
- "bvh": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/bvh/-/bvh-0.5.0.tgz",
- "integrity": "sha512-AoqXrrBTaCCk+6pZWC33f4UR3jY3yyh7jahZ5pHUPqZ3KSyDfWqlryDrgxq+xsl60PYwZOWRoCFX4+RqN7T6gg=="
- },
"bvh-tree": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/bvh-tree/-/bvh-tree-1.0.1.tgz",
- "integrity": "sha1-gIPgGIEokSmh5/kmirg5vl0LhZo="
+ "integrity": "sha512-oNi2ebOZnPVUjLP9QboCuthXnVpOCeCcIQBWWo+0W2Yvh5yaH6u2+dZCa515vj+7Yh+tcNJJDie/U8K0tEPPRQ=="
},
"cacheable-request": {
"version": "6.1.0",
@@ -9096,9 +9721,9 @@
"dev": true
},
"caniuse-lite": {
- "version": "1.0.30001320",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001320.tgz",
- "integrity": "sha512-MWPzG54AGdo3nWx7zHZTefseM5Y1ccM7hlQKHRqJkPozUaw3hNbBTMmLn16GG2FUzjR13Cr3NPfhIieX5PzXDA==",
+ "version": "1.0.30001414",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001414.tgz",
+ "integrity": "sha512-t55jfSaWjCdocnFdKQoO+d2ct9C59UZg4dY3OnUlSZ447r8pUtIKdp0hpAzrGFultmTC+Us+KpKi4GZl/LXlFg==",
"dev": true
},
"chalk": {
@@ -9117,16 +9742,22 @@
"integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==",
"dev": true
},
+ "chownr": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
+ "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
+ "dev": true
+ },
"chromium-pickle-js": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz",
- "integrity": "sha1-BKEGZywYsIWrd02YPfo+oTjyIgU=",
+ "integrity": "sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw==",
"dev": true
},
"ci-info": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz",
- "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==",
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.4.0.tgz",
+ "integrity": "sha512-t5QdPT5jq3o262DOQ8zA6E1tlH2upmUc4Hlvrbx1pGYJuiiHl7O7rvVNI+l8HTVhd/q3Qc9vqimkNk5yiXsAug==",
"dev": true
},
"cjs-module-lexer": {
@@ -9147,9 +9778,9 @@
}
},
"clone-response": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz",
- "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=",
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz",
+ "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==",
"dev": true,
"requires": {
"mimic-response": "^1.0.0"
@@ -9158,7 +9789,7 @@
"co": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
- "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
+ "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==",
"dev": true
},
"collect-v8-coverage": {
@@ -9167,10 +9798,21 @@
"integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==",
"dev": true
},
+ "color": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
+ "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^2.0.1",
+ "color-string": "^1.9.0"
+ }
+ },
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
"requires": {
"color-name": "~1.1.4"
}
@@ -9178,12 +9820,23 @@
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "color-string": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
+ "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
+ "dev": true,
+ "requires": {
+ "color-name": "^1.0.0",
+ "simple-swizzle": "^0.2.2"
+ }
},
"colors": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz",
- "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=",
+ "integrity": "sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==",
"dev": true
},
"combined-stream": {
@@ -9195,16 +9848,22 @@
"delayed-stream": "~1.0.0"
}
},
+ "commander": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz",
+ "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==",
+ "dev": true
+ },
"compare-version": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/compare-version/-/compare-version-0.1.2.tgz",
- "integrity": "sha1-AWLsLZNR9d3VmpICy6k1NmpyUIA=",
+ "integrity": "sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A==",
"dev": true
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
"dev": true
},
"concat-stream": {
@@ -9217,38 +9876,6 @@
"inherits": "^2.0.3",
"readable-stream": "^2.2.2",
"typedarray": "^0.0.6"
- },
- "dependencies": {
- "readable-stream": {
- "version": "2.3.7",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
- "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
- "dev": true,
- "requires": {
- "core-util-is": "~1.0.0",
- "inherits": "~2.0.3",
- "isarray": "~1.0.0",
- "process-nextick-args": "~2.0.0",
- "safe-buffer": "~5.1.1",
- "string_decoder": "~1.1.1",
- "util-deprecate": "~1.0.1"
- }
- },
- "safe-buffer": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
- "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
- "dev": true
- },
- "string_decoder": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
- "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
- "dev": true,
- "requires": {
- "safe-buffer": "~5.1.0"
- }
- }
}
},
"config-chain": {
@@ -9269,14 +9896,6 @@
"dev": true,
"requires": {
"safe-buffer": "~5.1.1"
- },
- "dependencies": {
- "safe-buffer": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
- "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
- "dev": true
- }
}
},
"copy-dir": {
@@ -9285,13 +9904,6 @@
"integrity": "sha512-Q4+qBFnN4bwGwvtXXzbp4P/4iNk0MaiGAzvQ8OiMtlLjkIKjmNN689uVzShSM0908q7GoFHXIPx4zi75ocoaHw==",
"dev": true
},
- "core-js": {
- "version": "3.16.1",
- "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.16.1.tgz",
- "integrity": "sha512-AAkP8i35EbefU+JddyWi12AWE9f2N/qr/pwnDtWz4nyUIBGMJPX99ANFFRSw6FefM374lDujdtLDyhN2A/btHw==",
- "dev": true,
- "optional": true
- },
"core-util-is": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
@@ -9352,7 +9964,7 @@
"cycle": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz",
- "integrity": "sha1-IegLK+hYD5i0aPN5QwZisEbDStI=",
+ "integrity": "sha512-TVF6svNzeQCOpjCqsy0/CSy8VgObG3wXusJ73xW2GbG5rGx7lC8zxDSURicsXI2UsGdi2L0QNRCi745/wUDvsA==",
"dev": true
},
"data-urls": {
@@ -9376,15 +9988,15 @@
}
},
"decimal.js": {
- "version": "10.3.1",
- "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz",
- "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==",
+ "version": "10.4.1",
+ "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.1.tgz",
+ "integrity": "sha512-F29o+vci4DodHYT9UrR5IEbfBw9pE5eSapIJdTqXK5+6hq+t8VRxwQyKlW2i+KDKFkkJQRvFyI/QXD83h8LyQw==",
"dev": true
},
"decompress-response": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz",
- "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=",
+ "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==",
"dev": true,
"requires": {
"mimic-response": "^1.0.0"
@@ -9393,7 +10005,13 @@
"dedent": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz",
- "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=",
+ "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==",
+ "dev": true
+ },
+ "deep-extend": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
+ "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
"dev": true
},
"deep-is": {
@@ -9415,19 +10033,26 @@
"dev": true
},
"define-properties": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
- "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz",
+ "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==",
"dev": true,
"optional": true,
"requires": {
- "object-keys": "^1.0.12"
+ "has-property-descriptors": "^1.0.0",
+ "object-keys": "^1.1.1"
}
},
"delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
- "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "dev": true
+ },
+ "detect-libc": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz",
+ "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==",
"dev": true
},
"detect-newline": {
@@ -9455,6 +10080,38 @@
"integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==",
"dev": true
},
+ "dir-compare": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-2.4.0.tgz",
+ "integrity": "sha512-l9hmu8x/rjVC9Z2zmGzkhOEowZvW7pmYws5CWHutg8u1JgvsKWMx7Q/UODeu4djLZ4FgW5besw5yvMQnBHzuCA==",
+ "dev": true,
+ "requires": {
+ "buffer-equal": "1.0.0",
+ "colors": "1.0.3",
+ "commander": "2.9.0",
+ "minimatch": "3.0.4"
+ },
+ "dependencies": {
+ "commander": {
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz",
+ "integrity": "sha512-bmkUukX8wAOjHdN26xj5c4ctEV22TQ7dQYhSmuckKhToXrkUn0iIaolHdIxYYqD55nhpSPA9zPQ1yP57GdXP2A==",
+ "dev": true,
+ "requires": {
+ "graceful-readlink": ">= 1.0.0"
+ }
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ }
+ }
+ },
"dir-glob": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
@@ -9462,14 +10119,6 @@
"dev": true,
"requires": {
"path-type": "^4.0.0"
- },
- "dependencies": {
- "path-type": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
- "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
- "dev": true
- }
}
},
"doctrine": {
@@ -9499,15 +10148,15 @@
}
},
"duplexer3": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
- "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=",
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.5.tgz",
+ "integrity": "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==",
"dev": true
},
"electron": {
- "version": "13.6.6",
- "resolved": "https://registry.npmjs.org/electron/-/electron-13.6.6.tgz",
- "integrity": "sha512-TP2Bl1nTxaH1yRmlYiF7imzvKE/NASE0cl6wOYA3AaP/UrBGc4L3NwJfn5Z55o+1t4TH8vCRxENufESyb32HhA==",
+ "version": "13.6.9",
+ "resolved": "https://registry.npmjs.org/electron/-/electron-13.6.9.tgz",
+ "integrity": "sha512-Es/sBy85NIuqsO9MW41PUCpwIkeinlTQ7g0ainfnmRAM2rmog3GBxVCaoV5dzEjwTF7TKG1Yr/E7Z3qHmlfWAg==",
"dev": true,
"requires": {
"@electron/get": "^1.0.1",
@@ -9516,17 +10165,17 @@
},
"dependencies": {
"@types/node": {
- "version": "14.18.12",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.12.tgz",
- "integrity": "sha512-q4jlIR71hUpWTnGhXWcakgkZeHa3CCjcQcnuzU8M891BAWA2jHiziiWEPEkdS5pFsz7H9HJiy8BrK7tBRNrY7A==",
+ "version": "14.18.31",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.31.tgz",
+ "integrity": "sha512-vQAnaReSQkEDa8uwAyQby8bYGKu84R/deEc6mg5T8fX6gzCn8QW6rziSgsti1fNvsrswKUKPnVTi7uoB+u62Mw==",
"dev": true
}
}
},
"electron-notarize": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/electron-notarize/-/electron-notarize-1.1.0.tgz",
- "integrity": "sha512-Dmp/jm2y3PTcjmjVe+jCT0sjsbBfbNuk7GOPtduZce2iae1hgAPnlNErk6x70TalsGIL5Ip3liSryqde/6eB5w==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/electron-notarize/-/electron-notarize-1.2.1.tgz",
+ "integrity": "sha512-u/ECWhIrhkSQpZM4cJzVZ5TsmkaqrRo5LDC/KMbGF0sPkm53Ng59+M0zp8QVaql0obfJy9vlVT+4iOkAi2UDlA==",
"dev": true,
"requires": {
"debug": "^4.1.1",
@@ -9589,26 +10238,27 @@
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"dev": true
}
}
},
"electron-packager": {
- "version": "15.3.0",
- "resolved": "https://registry.npmjs.org/electron-packager/-/electron-packager-15.3.0.tgz",
- "integrity": "sha512-PHcykXinmjPyJcYoNGbOWNsOU25nIbMLHBAfg4caazWzYELFL14FshDZEqqrvVOMEUnqjx/Ktc1NmMIN5ZRomQ==",
+ "version": "15.5.2",
+ "resolved": "https://registry.npmjs.org/electron-packager/-/electron-packager-15.5.2.tgz",
+ "integrity": "sha512-8zUdkSONn0jomu/efqoxApGzgqIb56ooMs671HeB/BXTPnWcWvqpEY08g16PL6ok2ymA5zPj8vmUszLrq99F0Q==",
"dev": true,
"requires": {
"@electron/get": "^1.6.0",
- "asar": "^3.0.0",
+ "@electron/universal": "^1.2.1",
+ "asar": "^3.1.0",
"cross-spawn-windows-exe": "^1.2.0",
"debug": "^4.0.1",
- "electron-notarize": "^1.0.0",
+ "electron-notarize": "^1.1.1",
"electron-osx-sign": "^0.5.0",
"extract-zip": "^2.0.0",
"filenamify": "^4.1.0",
- "fs-extra": "^9.0.0",
+ "fs-extra": "^10.1.0",
"galactus": "^0.2.1",
"get-package-info": "^1.0.0",
"junk": "^3.1.0",
@@ -9617,7 +10267,7 @@
"rcedit": "^3.0.1",
"resolve": "^1.1.6",
"semver": "^7.1.3",
- "yargs-parser": "^20.0.0"
+ "yargs-parser": "^20.2.9"
},
"dependencies": {
"extract-zip": {
@@ -9631,14 +10281,13 @@
"get-stream": "^5.1.0",
"yauzl": "^2.10.0"
}
- },
- "fs-extra": {
- "version": "9.1.0",
- "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
- "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
+ },
+ "fs-extra": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
+ "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
"dev": true,
"requires": {
- "at-least-node": "^1.0.0",
"graceful-fs": "^4.2.0",
"jsonfile": "^6.0.1",
"universalify": "^2.0.0"
@@ -9663,15 +10312,6 @@
"universalify": "^2.0.0"
}
},
- "semver": {
- "version": "7.3.5",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
- "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
- "dev": true,
- "requires": {
- "lru-cache": "^6.0.0"
- }
- },
"universalify": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
@@ -9681,9 +10321,9 @@
}
},
"electron-to-chromium": {
- "version": "1.4.96",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.96.tgz",
- "integrity": "sha512-DPNjvNGPabv6FcyjzLAN4C0psN/GgD9rSGvMTuv81SeXG/EX3mCz0wiw9N1tUEnfQXYCJi3H8M0oFPRziZh7rw==",
+ "version": "1.4.270",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.270.tgz",
+ "integrity": "sha512-KNhIzgLiJmDDC444dj9vEOpZEgsV96ult9Iff98Vanumn+ShJHd5se8aX6KeVxdc0YQeqdrezBZv89rleDbvSg==",
"dev": true
},
"emittery": {
@@ -9701,7 +10341,7 @@
"encodeurl": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
- "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
+ "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
"dev": true,
"optional": true
},
@@ -9770,7 +10410,7 @@
"levn": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
- "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
+ "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==",
"dev": true,
"requires": {
"prelude-ls": "~1.1.2",
@@ -9794,13 +10434,13 @@
"prelude-ls": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
- "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
+ "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==",
"dev": true
},
"type-check": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
- "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
+ "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==",
"dev": true,
"requires": {
"prelude-ls": "~1.1.2"
@@ -9809,13 +10449,15 @@
}
},
"eslint": {
- "version": "8.12.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.12.0.tgz",
- "integrity": "sha512-it1oBL9alZg1S8UycLm5YDMAkIhtH6FtAzuZs6YvoGVldWjbS08BkAdb/ymP9LlAyq8koANu32U7Ib/w+UNh8Q==",
+ "version": "8.24.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.24.0.tgz",
+ "integrity": "sha512-dWFaPhGhTAiPcCgm3f6LI2MBWbogMnTJzFBbhXVRQDJPkr9pGZvVjlVfXd+vyDcWPA2Ic9L2AXPIQM0+vk/cSQ==",
"dev": true,
"requires": {
- "@eslint/eslintrc": "^1.2.1",
- "@humanwhocodes/config-array": "^0.9.2",
+ "@eslint/eslintrc": "^1.3.2",
+ "@humanwhocodes/config-array": "^0.10.5",
+ "@humanwhocodes/gitignore-to-minimatch": "^1.0.2",
+ "@humanwhocodes/module-importer": "^1.0.1",
"ajv": "^6.10.0",
"chalk": "^4.0.0",
"cross-spawn": "^7.0.2",
@@ -9825,30 +10467,32 @@
"eslint-scope": "^7.1.1",
"eslint-utils": "^3.0.0",
"eslint-visitor-keys": "^3.3.0",
- "espree": "^9.3.1",
+ "espree": "^9.4.0",
"esquery": "^1.4.0",
"esutils": "^2.0.2",
"fast-deep-equal": "^3.1.3",
"file-entry-cache": "^6.0.1",
- "functional-red-black-tree": "^1.0.1",
+ "find-up": "^5.0.0",
"glob-parent": "^6.0.1",
- "globals": "^13.6.0",
+ "globals": "^13.15.0",
+ "globby": "^11.1.0",
+ "grapheme-splitter": "^1.0.4",
"ignore": "^5.2.0",
"import-fresh": "^3.0.0",
"imurmurhash": "^0.1.4",
"is-glob": "^4.0.0",
+ "js-sdsl": "^4.1.4",
"js-yaml": "^4.1.0",
"json-stable-stringify-without-jsonify": "^1.0.1",
"levn": "^0.4.1",
"lodash.merge": "^4.6.2",
- "minimatch": "^3.0.4",
+ "minimatch": "^3.1.2",
"natural-compare": "^1.4.0",
"optionator": "^0.9.1",
"regexpp": "^3.2.0",
"strip-ansi": "^6.0.1",
"strip-json-comments": "^3.1.0",
- "text-table": "^0.2.0",
- "v8-compile-cache": "^2.0.3"
+ "text-table": "^0.2.0"
},
"dependencies": {
"eslint-scope": {
@@ -9866,15 +10510,6 @@
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
"dev": true
- },
- "glob-parent": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
- "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
- "dev": true,
- "requires": {
- "is-glob": "^4.0.3"
- }
}
}
},
@@ -9885,6 +10520,13 @@
"dev": true,
"requires": {}
},
+ "eslint-plugin-simple-import-sort": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-8.0.0.tgz",
+ "integrity": "sha512-bXgJQ+lqhtQBCuWY/FUWdB27j4+lqcvXv5rUARkzbeWLwea+S5eBZEQrhnO+WgX3ZoJHVj0cn943iyXwByHHQw==",
+ "dev": true,
+ "requires": {}
+ },
"eslint-scope": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
@@ -9919,13 +10561,13 @@
"dev": true
},
"espree": {
- "version": "9.3.1",
- "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.1.tgz",
- "integrity": "sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==",
+ "version": "9.4.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.0.tgz",
+ "integrity": "sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==",
"dev": true,
"requires": {
- "acorn": "^8.7.0",
- "acorn-jsx": "^5.3.1",
+ "acorn": "^8.8.0",
+ "acorn-jsx": "^5.3.2",
"eslint-visitor-keys": "^3.3.0"
}
},
@@ -10009,7 +10651,13 @@
"exit": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
- "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=",
+ "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==",
+ "dev": true
+ },
+ "expand-template": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
+ "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
"dev": true
},
"expect": {
@@ -10048,7 +10696,7 @@
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"dev": true
}
}
@@ -10056,7 +10704,7 @@
"eyes": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz",
- "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=",
+ "integrity": "sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==",
"dev": true
},
"fast-deep-equal": {
@@ -10065,9 +10713,9 @@
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
},
"fast-glob": {
- "version": "3.2.11",
- "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz",
- "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==",
+ "version": "3.2.12",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz",
+ "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==",
"dev": true,
"requires": {
"@nodelib/fs.stat": "^2.0.2",
@@ -10075,6 +10723,17 @@
"glob-parent": "^5.1.2",
"merge2": "^1.3.0",
"micromatch": "^4.0.4"
+ },
+ "dependencies": {
+ "glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "requires": {
+ "is-glob": "^4.0.1"
+ }
+ }
}
},
"fast-json-stable-stringify": {
@@ -10085,7 +10744,7 @@
"fast-levenshtein": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
- "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
"dev": true
},
"fastq": {
@@ -10098,9 +10757,9 @@
}
},
"fb-watchman": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz",
- "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==",
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz",
+ "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==",
"dev": true,
"requires": {
"bser": "2.1.1"
@@ -10109,7 +10768,7 @@
"fd-slicer": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
- "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=",
+ "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==",
"dev": true,
"requires": {
"pend": "~1.2.0"
@@ -10127,7 +10786,7 @@
"filename-reserved-regex": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz",
- "integrity": "sha1-q/c9+rc10EVECr/qLZHzieu/oik=",
+ "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==",
"dev": true
},
"filenamify": {
@@ -10151,12 +10810,13 @@
}
},
"find-up": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
- "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
"dev": true,
"requires": {
- "locate-path": "^2.0.0"
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
}
},
"flat-cache": {
@@ -10170,9 +10830,9 @@
}
},
"flatted": {
- "version": "3.2.5",
- "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz",
- "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==",
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz",
+ "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==",
"dev": true
},
"flora-colossus": {
@@ -10209,6 +10869,12 @@
"mime-types": "^2.1.12"
}
},
+ "fs-constants": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
+ "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
+ "dev": true
+ },
"fs-extra": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
@@ -10223,7 +10889,7 @@
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
"dev": true
},
"fsevents": {
@@ -10239,16 +10905,10 @@
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
"dev": true
},
- "functional-red-black-tree": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
- "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
- "dev": true
- },
"galactus": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/galactus/-/galactus-0.2.1.tgz",
- "integrity": "sha1-y+0tIKQMH1Z5o1kI4rlBVzPnjbk=",
+ "integrity": "sha512-mDc8EQJKtxjp9PMYS3PbpjjbX3oXhBTxoGaPahw620XZBIHJ4+nvw5KN/tRtmmSDR9dypstGNvqQ3C29QGoGHQ==",
"dev": true,
"requires": {
"debug": "^3.1.0",
@@ -10290,10 +10950,22 @@
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
"dev": true
},
+ "get-intrinsic": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz",
+ "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.3"
+ }
+ },
"get-package-info": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/get-package-info/-/get-package-info-1.0.0.tgz",
- "integrity": "sha1-ZDJ5ZWPigRPNlHTbvQAFKYWkmZw=",
+ "integrity": "sha512-SCbprXGAPdIhKAXiG+Mk6yeoFH61JlYunqdFQFHDtLjJlDjFf6x07dsS8acO+xWt52jpdVo49AlVDnUVK1sDNw==",
"dev": true,
"requires": {
"bluebird": "^3.1.1",
@@ -10314,7 +10986,7 @@
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"dev": true
}
}
@@ -10334,55 +11006,48 @@
"pump": "^3.0.0"
}
},
+ "github-from-package": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
+ "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==",
+ "dev": true
+ },
"glob": {
- "version": "7.1.7",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
- "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
"dev": true,
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
- "minimatch": "^3.0.4",
+ "minimatch": "^3.1.1",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
}
},
"glob-parent": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
- "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
"dev": true,
"requires": {
- "is-glob": "^4.0.1"
+ "is-glob": "^4.0.3"
}
},
"global-agent": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-2.2.0.tgz",
- "integrity": "sha512-+20KpaW6DDLqhG7JDiJpD1JvNvb8ts+TNl7BPOYcURqCrXqnN1Vf+XVOrkKJAFPqfX+oEhsdzOj1hLWkBTdNJg==",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz",
+ "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==",
"dev": true,
"optional": true,
"requires": {
"boolean": "^3.0.1",
- "core-js": "^3.6.5",
"es6-error": "^4.1.1",
"matcher": "^3.0.0",
"roarr": "^2.15.3",
"semver": "^7.3.2",
"serialize-error": "^7.0.1"
- },
- "dependencies": {
- "semver": {
- "version": "7.3.5",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
- "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
- "dev": true,
- "optional": true,
- "requires": {
- "lru-cache": "^6.0.0"
- }
- }
}
},
"global-tunnel-ng": {
@@ -10399,26 +11064,18 @@
}
},
"globals": {
- "version": "13.13.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-13.13.0.tgz",
- "integrity": "sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A==",
+ "version": "13.17.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz",
+ "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==",
"dev": true,
"requires": {
"type-fest": "^0.20.2"
- },
- "dependencies": {
- "type-fest": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
- "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
- "dev": true
- }
}
},
"globalthis": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.2.tgz",
- "integrity": "sha512-ZQnSFO1la8P7auIOQECnm0sSuoMeaSq0EEdXMBFF2QJO4uNcwbyhSgG3MruWNbFTqCLmxVwGOl7LZ9kASvHdeQ==",
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz",
+ "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==",
"dev": true,
"optional": true,
"requires": {
@@ -10459,9 +11116,21 @@
}
},
"graceful-fs": {
- "version": "4.2.8",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz",
- "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==",
+ "version": "4.2.10",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
+ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
+ "dev": true
+ },
+ "graceful-readlink": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz",
+ "integrity": "sha512-8tLu60LgxF6XpdbK8OW3FA+IfTNBn1ZHGHKF4KQbEeSkajYw5PlYJcKluntgegDPTg8UkHjpet1T82vk6TQ68w==",
+ "dev": true
+ },
+ "grapheme-splitter": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz",
+ "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==",
"dev": true
},
"has": {
@@ -10479,6 +11148,23 @@
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true
},
+ "has-property-descriptors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz",
+ "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "get-intrinsic": "^1.1.1"
+ }
+ },
+ "has-symbols": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
+ "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
+ "dev": true,
+ "optional": true
+ },
"hosted-git-info": {
"version": "2.8.9",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
@@ -10518,9 +11204,9 @@
}
},
"https-proxy-agent": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz",
- "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==",
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
+ "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
"dev": true,
"requires": {
"agent-base": "6",
@@ -10542,6 +11228,12 @@
"safer-buffer": ">= 2.1.2 < 3"
}
},
+ "ieee754": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+ "dev": true
+ },
"ignore": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
@@ -10577,13 +11269,13 @@
"imurmurhash": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
- "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
"dev": true
},
"inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
- "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
"dev": true,
"requires": {
"once": "^1.3.0",
@@ -10599,19 +11291,18 @@
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
- "dev": true,
- "optional": true
+ "dev": true
},
"is-arrayish": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
- "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
+ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
"dev": true
},
"is-core-module": {
- "version": "2.9.0",
- "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz",
- "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==",
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz",
+ "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==",
"dev": true,
"requires": {
"has": "^1.0.3"
@@ -10626,7 +11317,7 @@
"is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
- "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
"dev": true
},
"is-fullwidth-code-point": {
@@ -10671,7 +11362,7 @@
"is-typedarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
- "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
+ "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==",
"dev": true
},
"is-wsl": {
@@ -10686,7 +11377,7 @@
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
- "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
"dev": true
},
"isbinaryfile": {
@@ -10701,13 +11392,13 @@
"isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
- "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
"dev": true
},
"isstream": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
- "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
+ "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==",
"dev": true
},
"istanbul-lib-coverage": {
@@ -10717,9 +11408,9 @@
"dev": true
},
"istanbul-lib-instrument": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.1.0.tgz",
- "integrity": "sha512-czwUz525rkOFDJxfKK6mYfIs9zBKILyrZQxjz3ABhjQXhbhFsSbo1HW/BFcsDnfJYJWA6thRR5/TUY2qs5W99Q==",
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.0.tgz",
+ "integrity": "sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A==",
"dev": true,
"requires": {
"@babel/core": "^7.12.3",
@@ -10727,6 +11418,14 @@
"@istanbuljs/schema": "^0.1.2",
"istanbul-lib-coverage": "^3.2.0",
"semver": "^6.3.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
}
},
"istanbul-lib-report": {
@@ -10752,9 +11451,9 @@
}
},
"istanbul-reports": {
- "version": "3.1.4",
- "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.4.tgz",
- "integrity": "sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw==",
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz",
+ "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==",
"dev": true,
"requires": {
"html-escaper": "^2.0.0",
@@ -10770,34 +11469,6 @@
"@jest/core": "^27.5.1",
"import-local": "^3.0.2",
"jest-cli": "^27.5.1"
- },
- "dependencies": {
- "graceful-fs": {
- "version": "4.2.9",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
- "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
- "dev": true
- },
- "jest-cli": {
- "version": "27.5.1",
- "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.5.1.tgz",
- "integrity": "sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==",
- "dev": true,
- "requires": {
- "@jest/core": "^27.5.1",
- "@jest/test-result": "^27.5.1",
- "@jest/types": "^27.5.1",
- "chalk": "^4.0.0",
- "exit": "^0.1.2",
- "graceful-fs": "^4.2.9",
- "import-local": "^3.0.2",
- "jest-config": "^27.5.1",
- "jest-util": "^27.5.1",
- "jest-validate": "^27.5.1",
- "prompts": "^2.0.1",
- "yargs": "^16.2.0"
- }
- }
}
},
"jest-changed-files": {
@@ -10838,6 +11509,26 @@
"throat": "^6.0.1"
}
},
+ "jest-cli": {
+ "version": "27.5.1",
+ "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.5.1.tgz",
+ "integrity": "sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==",
+ "dev": true,
+ "requires": {
+ "@jest/core": "^27.5.1",
+ "@jest/test-result": "^27.5.1",
+ "@jest/types": "^27.5.1",
+ "chalk": "^4.0.0",
+ "exit": "^0.1.2",
+ "graceful-fs": "^4.2.9",
+ "import-local": "^3.0.2",
+ "jest-config": "^27.5.1",
+ "jest-util": "^27.5.1",
+ "jest-validate": "^27.5.1",
+ "prompts": "^2.0.1",
+ "yargs": "^16.2.0"
+ }
+ },
"jest-config": {
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.5.1.tgz",
@@ -10868,26 +11559,6 @@
"pretty-format": "^27.5.1",
"slash": "^3.0.0",
"strip-json-comments": "^3.1.1"
- },
- "dependencies": {
- "graceful-fs": {
- "version": "4.2.9",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
- "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
- "dev": true
- },
- "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,
- "requires": {
- "@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"
- }
- }
}
},
"jest-diff": {
@@ -10978,14 +11649,6 @@
"jest-worker": "^27.5.1",
"micromatch": "^4.0.4",
"walker": "^1.0.7"
- },
- "dependencies": {
- "graceful-fs": {
- "version": "4.2.9",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
- "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
- "dev": true
- }
}
},
"jest-jasmine2": {
@@ -11050,14 +11713,6 @@
"pretty-format": "^27.5.1",
"slash": "^3.0.0",
"stack-utils": "^2.0.3"
- },
- "dependencies": {
- "graceful-fs": {
- "version": "4.2.9",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
- "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
- "dev": true
- }
}
},
"jest-mock": {
@@ -11099,14 +11754,6 @@
"resolve": "^1.20.0",
"resolve.exports": "^1.1.0",
"slash": "^3.0.0"
- },
- "dependencies": {
- "graceful-fs": {
- "version": "4.2.9",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
- "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
- "dev": true
- }
}
},
"jest-resolve-dependencies": {
@@ -11147,14 +11794,6 @@
"jest-worker": "^27.5.1",
"source-map-support": "^0.5.6",
"throat": "^6.0.1"
- },
- "dependencies": {
- "graceful-fs": {
- "version": "4.2.9",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
- "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
- "dev": true
- }
}
},
"jest-runtime": {
@@ -11185,20 +11824,6 @@
"jest-util": "^27.5.1",
"slash": "^3.0.0",
"strip-bom": "^4.0.0"
- },
- "dependencies": {
- "graceful-fs": {
- "version": "4.2.9",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
- "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
- "dev": true
- },
- "strip-bom": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
- "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==",
- "dev": true
- }
}
},
"jest-serializer": {
@@ -11209,14 +11834,6 @@
"requires": {
"@types/node": "*",
"graceful-fs": "^4.2.9"
- },
- "dependencies": {
- "graceful-fs": {
- "version": "4.2.9",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
- "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
- "dev": true
- }
}
},
"jest-snapshot": {
@@ -11247,23 +11864,6 @@
"natural-compare": "^1.4.0",
"pretty-format": "^27.5.1",
"semver": "^7.3.2"
- },
- "dependencies": {
- "graceful-fs": {
- "version": "4.2.9",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
- "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
- "dev": true
- },
- "semver": {
- "version": "7.3.5",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
- "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
- "dev": true,
- "requires": {
- "lru-cache": "^6.0.0"
- }
- }
}
},
"jest-util": {
@@ -11278,14 +11878,6 @@
"ci-info": "^3.2.0",
"graceful-fs": "^4.2.9",
"picomatch": "^2.2.3"
- },
- "dependencies": {
- "graceful-fs": {
- "version": "4.2.9",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
- "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
- "dev": true
- }
}
},
"jest-validate": {
@@ -11352,6 +11944,12 @@
"resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz",
"integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg=="
},
+ "js-sdsl": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz",
+ "integrity": "sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==",
+ "dev": true
+ },
"js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -11411,7 +12009,7 @@
"json-buffer": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz",
- "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=",
+ "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==",
"dev": true
},
"json-parse-even-better-errors": {
@@ -11428,13 +12026,13 @@
"json-stable-stringify-without-jsonify": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
- "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
"dev": true
},
"json-stringify-safe": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
- "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
+ "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==",
"dev": true,
"optional": true
},
@@ -11447,7 +12045,7 @@
"jsonfile": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
- "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
+ "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
"dev": true,
"requires": {
"graceful-fs": "^4.1.6"
@@ -11499,7 +12097,7 @@
"load-json-file": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
- "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=",
+ "integrity": "sha512-3p6ZOGNbiX4CdvEd1VcE6yi78UrGNpjHO33noGwHCnT/o2fyllJDepsm8+mFFv/DvtwFHht5HIHSyOy5a+ChVQ==",
"dev": true,
"requires": {
"graceful-fs": "^4.1.2",
@@ -11508,22 +12106,36 @@
"strip-bom": "^3.0.0"
},
"dependencies": {
+ "parse-json": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
+ "integrity": "sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==",
+ "dev": true,
+ "requires": {
+ "error-ex": "^1.2.0"
+ }
+ },
"pify": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
- "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
+ "dev": true
+ },
+ "strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
"dev": true
}
}
},
"locate-path": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
- "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
"dev": true,
"requires": {
- "p-locate": "^2.0.0",
- "path-exists": "^3.0.0"
+ "p-locate": "^5.0.0"
}
},
"lodash": {
@@ -11535,12 +12147,12 @@
"lodash.get": {
"version": "4.4.2",
"resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
- "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk="
+ "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ=="
},
"lodash.memoize": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
- "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=",
+ "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==",
"dev": true
},
"lodash.merge": {
@@ -11552,7 +12164,7 @@
"lodash.reduce": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz",
- "integrity": "sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs="
+ "integrity": "sha512-6raRe2vxCYBhpBu+B+TtNGUzah+hQjVdu3E17wfusjyrXBka2nBS8OH/gjVZ5PvHOhWmIZTYri09Z6n/QfnNMw=="
},
"lowercase-keys": {
"version": "1.0.1",
@@ -11576,6 +12188,14 @@
"dev": true,
"requires": {
"semver": "^6.0.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
}
},
"make-error": {
@@ -11653,9 +12273,9 @@
"dev": true
},
"minimatch": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
- "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"dev": true,
"requires": {
"brace-expansion": "^1.1.7"
@@ -11676,6 +12296,12 @@
"minimist": "^1.2.6"
}
},
+ "mkdirp-classic": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
+ "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
+ "dev": true
+ },
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@@ -11688,22 +12314,43 @@
"integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
"dev": true
},
+ "napi-build-utils": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz",
+ "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==",
+ "dev": true
+ },
"natural-compare": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
- "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true
+ },
+ "node-abi": {
+ "version": "3.25.0",
+ "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.25.0.tgz",
+ "integrity": "sha512-p+0xx5ruIQ+8X57CRIMxbTZRT7tU0Tjn2C/aAK68AEMrbGsCo6IjnDdPNhEyyjWCT4bRtzomXchYd3sSgk3BJQ==",
+ "dev": true,
+ "requires": {
+ "semver": "^7.3.5"
+ }
+ },
+ "node-addon-api": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.0.0.tgz",
+ "integrity": "sha512-CvkDw2OEnme7ybCykJpVcKH+uAOLV2qLqiyla128dN9TkEWfrYmxG6C2boDe5KcNQqZF3orkqzGgOMvZ/JNekA==",
"dev": true
},
"node-int64": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
- "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=",
+ "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==",
"dev": true
},
"node-releases": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz",
- "integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==",
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz",
+ "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==",
"dev": true
},
"normalize-package-data": {
@@ -11759,9 +12406,9 @@
}
},
"nwsapi": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz",
- "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==",
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.2.tgz",
+ "integrity": "sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw==",
"dev": true
},
"object-keys": {
@@ -11774,7 +12421,7 @@
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
- "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"dev": true,
"requires": {
"wrappy": "1"
@@ -11810,27 +12457,27 @@
"dev": true
},
"p-limit": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
- "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
"dev": true,
"requires": {
- "p-try": "^1.0.0"
+ "yocto-queue": "^0.1.0"
}
},
"p-locate": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
- "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
"dev": true,
"requires": {
- "p-limit": "^1.1.0"
+ "p-limit": "^3.0.2"
}
},
"p-try": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
- "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
"dev": true
},
"parent-module": {
@@ -11845,19 +12492,22 @@
"parse-author": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/parse-author/-/parse-author-2.0.0.tgz",
- "integrity": "sha1-00YL8d3Q367tQtp1QkLmX7aEqB8=",
+ "integrity": "sha512-yx5DfvkN8JsHL2xk2Os9oTia467qnvRgey4ahSm2X8epehBLx/gWLcy5KI+Y36ful5DzGbCS6RazqZGgy1gHNw==",
"dev": true,
"requires": {
"author-regex": "^1.0.0"
}
},
"parse-json": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
- "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
+ "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,
"requires": {
- "error-ex": "^1.2.0"
+ "@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"
}
},
"parse5": {
@@ -11867,15 +12517,15 @@
"dev": true
},
"path-exists": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
- "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
"dev": true
},
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
- "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
"dev": true
},
"path-key": {
@@ -11891,26 +12541,15 @@
"dev": true
},
"path-type": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz",
- "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=",
- "dev": true,
- "requires": {
- "pify": "^2.0.0"
- },
- "dependencies": {
- "pify": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
- "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
- "dev": true
- }
- }
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+ "dev": true
},
"pend": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
- "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=",
+ "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==",
"dev": true
},
"picocolors": {
@@ -11928,7 +12567,7 @@
"pify": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
- "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+ "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
"dev": true,
"optional": true
},
@@ -11983,29 +12622,17 @@
"requires": {
"p-limit": "^2.2.0"
}
- },
- "p-try": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
- "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
- "dev": true
- },
- "path-exists": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
- "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
- "dev": true
}
}
},
"plist": {
- "version": "3.0.5",
- "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.5.tgz",
- "integrity": "sha512-83vX4eYdQp3vP9SxuYgEM/G/pJQqLUz/V/xzPrzruLs7fz7jxGQ1msZ/mg1nwZxUSuOp4sb+/bEIbRrbzZRxDA==",
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.6.tgz",
+ "integrity": "sha512-WiIVYyrp8TD4w8yCvyeIr+lkmrGRd5u0VbRnU+tP/aRLxP/YadJUYOMZJ/6hIa3oUyVCsycXvtNRgd5XBJIbiA==",
"dev": true,
"requires": {
"base64-js": "^1.5.1",
- "xmlbuilder": "^9.0.7"
+ "xmlbuilder": "^15.1.1"
}
},
"pngjs": {
@@ -12013,6 +12640,26 @@
"resolved": "https://registry.npmjs.org/pngjs/-/pngjs-6.0.0.tgz",
"integrity": "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg=="
},
+ "prebuild-install": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz",
+ "integrity": "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==",
+ "dev": true,
+ "requires": {
+ "detect-libc": "^2.0.0",
+ "expand-template": "^2.0.3",
+ "github-from-package": "0.0.0",
+ "minimist": "^1.2.3",
+ "mkdirp-classic": "^0.5.3",
+ "napi-build-utils": "^1.0.1",
+ "node-abi": "^3.3.0",
+ "pump": "^3.0.0",
+ "rc": "^1.2.7",
+ "simple-get": "^4.0.0",
+ "tar-fs": "^2.0.0",
+ "tunnel-agent": "^0.6.0"
+ }
+ },
"prelude-ls": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
@@ -12022,7 +12669,7 @@
"prepend-http": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz",
- "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=",
+ "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==",
"dev": true
},
"pretty-format": {
@@ -12065,13 +12712,13 @@
"dev": true
},
"prompt": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/prompt/-/prompt-1.2.2.tgz",
- "integrity": "sha512-XNXhNv3PUHJDcDkISpCwSJxtw9Bor4FZnlMUDW64N/KCPdxhfVlpD5+YUXI/Z8a9QWmOhs9KSiVtR8nzPS0BYA==",
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/prompt/-/prompt-1.3.0.tgz",
+ "integrity": "sha512-ZkaRWtaLBZl7KKAKndKYUL8WqNT+cQHKRZnT4RYYms48jQkFw3rrBL+/N5K/KtdEveHkxs982MX2BkDKub2ZMg==",
"dev": true,
"requires": {
"@colors/colors": "1.5.0",
- "async": "~0.9.0",
+ "async": "3.2.3",
"read": "1.0.x",
"revalidator": "0.1.x",
"winston": "2.x"
@@ -12090,19 +12737,31 @@
"proto-list": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
- "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=",
+ "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==",
"dev": true,
"optional": true
},
"protodef": {
- "version": "1.14.0",
- "resolved": "https://registry.npmjs.org/protodef/-/protodef-1.14.0.tgz",
- "integrity": "sha512-rL1WRlBC8LbAgBTa401eHMqnkX6zy1pHgS4kTSJVJ8rwP/AgVuWijGE3S3XHRkRjB/+4U1jMTqRdmtGdIqVOKQ==",
+ "version": "1.15.0",
+ "resolved": "https://registry.npmjs.org/protodef/-/protodef-1.15.0.tgz",
+ "integrity": "sha512-bZ2Omw8dT+DACjJHLrBWZlqN4MlT9g9oSpJDdkUAJOStUzgJp+Zn42FJfPUdwutUxjaxA0PftN0PDlNa2XbneA==",
"requires": {
"lodash.get": "^4.4.2",
"lodash.reduce": "^4.6.0",
"protodef-validator": "^1.3.0",
"readable-stream": "^3.0.3"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ }
}
},
"protodef-validator": {
@@ -12114,9 +12773,9 @@
}
},
"psl": {
- "version": "1.8.0",
- "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
- "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==",
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
+ "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==",
"dev": true
},
"pump": {
@@ -12134,12 +12793,38 @@
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
},
+ "querystringify": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
+ "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
+ "dev": true
+ },
"queue-microtask": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
"dev": true
},
+ "rc": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
+ "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
+ "dev": true,
+ "requires": {
+ "deep-extend": "^0.6.0",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
+ },
+ "dependencies": {
+ "strip-json-comments": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+ "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
+ "dev": true
+ }
+ }
+ },
"rcedit": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/rcedit/-/rcedit-3.0.1.tgz",
@@ -12158,7 +12843,7 @@
"read": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz",
- "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=",
+ "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==",
"dev": true,
"requires": {
"mute-stream": "~0.0.4"
@@ -12167,32 +12852,105 @@
"read-pkg": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz",
- "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=",
+ "integrity": "sha512-eFIBOPW7FGjzBuk3hdXEuNSiTZS/xEMlH49HxMyzb0hyPfu4EhVjT2DH32K1hSSmVq4sebAWnZuuY5auISUTGA==",
"dev": true,
"requires": {
"load-json-file": "^2.0.0",
"normalize-package-data": "^2.3.2",
"path-type": "^2.0.0"
+ },
+ "dependencies": {
+ "path-type": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz",
+ "integrity": "sha512-dUnb5dXUf+kzhC/W/F4e5/SkluXIFf5VUHolW1Eg1irn1hGWjPGdsRcvYJ1nD6lhk8Ir7VM0bHJKsYTx8Jx9OQ==",
+ "dev": true,
+ "requires": {
+ "pify": "^2.0.0"
+ }
+ },
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
+ "dev": true
+ }
}
},
"read-pkg-up": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz",
- "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=",
+ "integrity": "sha512-1orxQfbWGUiTn9XsPlChs6rLie/AV9jwZTGmu2NZw/CUDJQchXJFYE0Fq5j7+n558T1JhDWLdhyd1Zj+wLY//w==",
"dev": true,
"requires": {
"find-up": "^2.0.0",
"read-pkg": "^2.0.0"
+ },
+ "dependencies": {
+ "find-up": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
+ "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^2.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
+ "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^2.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "p-limit": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
+ "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
+ "dev": true,
+ "requires": {
+ "p-try": "^1.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
+ "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^1.1.0"
+ }
+ },
+ "p-try": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
+ "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==",
+ "dev": true
+ },
+ "path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==",
+ "dev": true
+ }
}
},
"readable-stream": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
- "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "version": "2.3.7",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
+ "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
+ "dev": true,
"requires": {
- "inherits": "^2.0.3",
- "string_decoder": "^1.1.1",
- "util-deprecate": "^1.0.1"
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
}
},
"regexpp": {
@@ -12204,16 +12962,22 @@
"require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
- "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "dev": true
+ },
+ "requires-port": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
+ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
"dev": true
},
"resolve": {
- "version": "1.22.0",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz",
- "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==",
+ "version": "1.22.1",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
+ "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
"dev": true,
"requires": {
- "is-core-module": "^2.8.1",
+ "is-core-module": "^2.9.0",
"path-parse": "^1.0.7",
"supports-preserve-symlinks-flag": "^1.0.0"
}
@@ -12250,7 +13014,7 @@
"responselike": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz",
- "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=",
+ "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==",
"dev": true,
"requires": {
"lowercase-keys": "^1.0.0"
@@ -12265,7 +13029,7 @@
"revalidator": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/revalidator/-/revalidator-0.1.8.tgz",
- "integrity": "sha1-/s5hv6DBtSoga9axgZgYS91SOjs=",
+ "integrity": "sha512-xcBILK2pA9oh4SiinPEZfhP8HfrB/ha+a2fTMyl7Om2WjlDVrOQy99N2MXXlUHqGJz4qEu2duXxHJjDWuK/0xg==",
"dev": true
},
"rimraf": {
@@ -12302,9 +13066,9 @@
}
},
"safe-buffer": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
- "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"safer-buffer": {
"version": "2.1.2",
@@ -12322,15 +13086,18 @@
}
},
"semver": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
- "dev": true
+ "version": "7.3.7",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
+ "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
},
"semver-compare": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz",
- "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=",
+ "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==",
"dev": true,
"optional": true
},
@@ -12342,6 +13109,31 @@
"optional": true,
"requires": {
"type-fest": "^0.13.1"
+ },
+ "dependencies": {
+ "type-fest": {
+ "version": "0.13.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz",
+ "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==",
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "sharp": {
+ "version": "0.31.1",
+ "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.31.1.tgz",
+ "integrity": "sha512-GR8M1wBwOiFKLkm9JPun27OQnNRZdHfSf9VwcdZX6UrRmM1/XnOrLFTF0GAil+y/YK4E6qcM/ugxs80QirsHxg==",
+ "dev": true,
+ "requires": {
+ "color": "^4.2.3",
+ "detect-libc": "^2.0.1",
+ "node-addon-api": "^5.0.0",
+ "prebuild-install": "^7.1.1",
+ "semver": "^7.3.7",
+ "simple-get": "^4.0.1",
+ "tar-fs": "^2.1.1",
+ "tunnel-agent": "^0.6.0"
}
},
"shebang-command": {
@@ -12365,6 +13157,57 @@
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
"dev": true
},
+ "simple-concat": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
+ "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
+ "dev": true
+ },
+ "simple-get": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz",
+ "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==",
+ "dev": true,
+ "requires": {
+ "decompress-response": "^6.0.0",
+ "once": "^1.3.1",
+ "simple-concat": "^1.0.0"
+ },
+ "dependencies": {
+ "decompress-response": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
+ "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
+ "dev": true,
+ "requires": {
+ "mimic-response": "^3.1.0"
+ }
+ },
+ "mimic-response": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
+ "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
+ "dev": true
+ }
+ }
+ },
+ "simple-swizzle": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
+ "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
+ "dev": true,
+ "requires": {
+ "is-arrayish": "^0.3.1"
+ },
+ "dependencies": {
+ "is-arrayish": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
+ "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==",
+ "dev": true
+ }
+ }
+ },
"sisteransi": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
@@ -12420,9 +13263,9 @@
}
},
"spdx-license-ids": {
- "version": "3.0.10",
- "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz",
- "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==",
+ "version": "3.0.12",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz",
+ "integrity": "sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==",
"dev": true
},
"sprintf-js": {
@@ -12435,7 +13278,7 @@
"stack-trace": {
"version": "0.0.10",
"resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
- "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=",
+ "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==",
"dev": true
},
"stack-utils": {
@@ -12456,11 +13299,11 @@
}
},
"string_decoder": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
- "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"requires": {
- "safe-buffer": "~5.2.0"
+ "safe-buffer": "~5.1.0"
}
},
"string-length": {
@@ -12494,9 +13337,9 @@
}
},
"strip-bom": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
- "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
+ "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==",
"dev": true
},
"strip-final-newline": {
@@ -12523,7 +13366,7 @@
"escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
- "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
"dev": true
}
}
@@ -12552,9 +13395,9 @@
}
},
"supports-hyperlinks": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz",
- "integrity": "sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==",
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz",
+ "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==",
"dev": true,
"requires": {
"has-flag": "^4.0.0",
@@ -12573,6 +13416,44 @@
"integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
"dev": true
},
+ "tar-fs": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz",
+ "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==",
+ "dev": true,
+ "requires": {
+ "chownr": "^1.1.1",
+ "mkdirp-classic": "^0.5.2",
+ "pump": "^3.0.0",
+ "tar-stream": "^2.1.4"
+ }
+ },
+ "tar-stream": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
+ "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
+ "dev": true,
+ "requires": {
+ "bl": "^4.0.3",
+ "end-of-stream": "^1.4.1",
+ "fs-constants": "^1.0.0",
+ "inherits": "^2.0.3",
+ "readable-stream": "^3.1.1"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ }
+ }
+ },
"terminal-link": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz",
@@ -12597,7 +13478,7 @@
"text-table": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
- "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
"dev": true
},
"throat": {
@@ -12615,7 +13496,7 @@
"to-fast-properties": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
- "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
+ "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==",
"dev": true
},
"to-readable-stream": {
@@ -12634,14 +13515,23 @@
}
},
"tough-cookie": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz",
- "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==",
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.2.tgz",
+ "integrity": "sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==",
"dev": true,
"requires": {
"psl": "^1.1.33",
"punycode": "^2.1.1",
- "universalify": "^0.1.2"
+ "universalify": "^0.2.0",
+ "url-parse": "^1.5.3"
+ },
+ "dependencies": {
+ "universalify": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz",
+ "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==",
+ "dev": true
+ }
}
},
"tr46": {
@@ -12656,7 +13546,7 @@
"trim-repeated": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz",
- "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=",
+ "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==",
"dev": true,
"requires": {
"escape-string-regexp": "^1.0.2"
@@ -12665,15 +13555,15 @@
"escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
- "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
"dev": true
}
}
},
"ts-jest": {
- "version": "27.1.4",
- "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-27.1.4.tgz",
- "integrity": "sha512-qjkZlVPWVctAezwsOD1OPzbZ+k7zA5z3oxII4dGdZo5ggX/PL7kvwTM0pXTr10fAtbiVpJaL3bWd502zAhpgSQ==",
+ "version": "27.1.5",
+ "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-27.1.5.tgz",
+ "integrity": "sha512-Xv6jBQPoBEvBq/5i2TeSG9tt/nqkbpcurrEG1b+2yfBrcJelOZF9Ml6dmyMh7bcW9JyFbRYpR5rxROSlBLTZHA==",
"dev": true,
"requires": {
"bs-logger": "0.x",
@@ -12684,26 +13574,15 @@
"make-error": "1.x",
"semver": "7.x",
"yargs-parser": "20.x"
- },
- "dependencies": {
- "semver": {
- "version": "7.3.5",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
- "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
- "dev": true,
- "requires": {
- "lru-cache": "^6.0.0"
- }
- }
}
},
"ts-node": {
- "version": "10.7.0",
- "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.7.0.tgz",
- "integrity": "sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A==",
+ "version": "10.9.1",
+ "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz",
+ "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==",
"dev": true,
"requires": {
- "@cspotcode/source-map-support": "0.7.0",
+ "@cspotcode/source-map-support": "^0.8.0",
"@tsconfig/node10": "^1.0.7",
"@tsconfig/node12": "^1.0.7",
"@tsconfig/node14": "^1.0.0",
@@ -12714,7 +13593,7 @@
"create-require": "^1.1.0",
"diff": "^4.0.1",
"make-error": "^1.1.1",
- "v8-compile-cache-lib": "^3.0.0",
+ "v8-compile-cache-lib": "^3.0.1",
"yn": "3.1.1"
},
"dependencies": {
@@ -12748,10 +13627,19 @@
"dev": true,
"optional": true
},
+ "tunnel-agent": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+ "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "^5.0.1"
+ }
+ },
"twgl.js": {
- "version": "4.19.2",
- "resolved": "https://registry.npmjs.org/twgl.js/-/twgl.js-4.19.2.tgz",
- "integrity": "sha512-dK58dWDJyDyfJVTywpkb2cgqenFiMYqXXMQAp9AOO7Ed0zQ6K6HOjg9mjoWvk01sdSbd6O2Y6FG/M1SW25X+iQ=="
+ "version": "4.24.0",
+ "resolved": "https://registry.npmjs.org/twgl.js/-/twgl.js-4.24.0.tgz",
+ "integrity": "sha512-JGVTxuV9dqaBmajXyvuZIlhCHrTbIaoNjQvtdoLHyK74OtbmNwZUj6rfdp+pz9htitI/tVxiVQ2nuw+KmD29vg=="
},
"type-check": {
"version": "0.4.0",
@@ -12769,16 +13657,15 @@
"dev": true
},
"type-fest": {
- "version": "0.13.1",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz",
- "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==",
- "dev": true,
- "optional": true
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "dev": true
},
"typedarray": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
- "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
+ "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==",
"dev": true
},
"typedarray-to-buffer": {
@@ -12791,9 +13678,9 @@
}
},
"typescript": {
- "version": "4.6.3",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz",
- "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==",
+ "version": "4.8.4",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz",
+ "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==",
"dev": true
},
"universalify": {
@@ -12802,6 +13689,16 @@
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
"dev": true
},
+ "update-browserslist-db": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.9.tgz",
+ "integrity": "sha512-/xsqn21EGVdXI3EXSum1Yckj3ZVZugqyOZQ/CxYPBD/R+ko9NSUScf8tFF4dOKY+2pvSSJA/S+5B8s4Zr4kyvg==",
+ "dev": true,
+ "requires": {
+ "escalade": "^3.1.1",
+ "picocolors": "^1.0.0"
+ }
+ },
"uri-js": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
@@ -12810,10 +13707,20 @@
"punycode": "^2.1.0"
}
},
+ "url-parse": {
+ "version": "1.5.10",
+ "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
+ "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
+ "dev": true,
+ "requires": {
+ "querystringify": "^2.1.1",
+ "requires-port": "^1.0.0"
+ }
+ },
"url-parse-lax": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz",
- "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=",
+ "integrity": "sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==",
"dev": true,
"requires": {
"prepend-http": "^2.0.0"
@@ -12822,18 +13729,12 @@
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
- },
- "v8-compile-cache": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz",
- "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==",
- "dev": true
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
},
"v8-compile-cache-lib": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz",
- "integrity": "sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA==",
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
+ "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
"dev": true
},
"v8-to-istanbul": {
@@ -12848,9 +13749,9 @@
},
"dependencies": {
"source-map": {
- "version": "0.7.3",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
- "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
+ "version": "0.7.4",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz",
+ "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==",
"dev": true
}
}
@@ -12865,6 +13766,11 @@
"spdx-expression-parse": "^3.0.0"
}
},
+ "varint": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/varint/-/varint-5.0.2.tgz",
+ "integrity": "sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow=="
+ },
"varint-array": {
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/varint-array/-/varint-array-0.0.0.tgz",
@@ -12872,13 +13778,6 @@
"requires": {
"struct": "0.0.11",
"varint": "^5.0.0"
- },
- "dependencies": {
- "varint": {
- "version": "5.0.2",
- "resolved": "https://registry.npmjs.org/varint/-/varint-5.0.2.tgz",
- "integrity": "sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow=="
- }
}
},
"w3c-hr-time": {
@@ -12950,25 +13849,17 @@
}
},
"winston": {
- "version": "2.4.5",
- "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.5.tgz",
- "integrity": "sha512-TWoamHt5yYvsMarGlGEQE59SbJHqGsZV8/lwC+iCcGeAe0vUaOh+Lv6SYM17ouzC/a/LB1/hz/7sxFBtlu1l4A==",
+ "version": "2.4.6",
+ "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.6.tgz",
+ "integrity": "sha512-J5Zu4p0tojLde8mIOyDSsmLmcP8I3Z6wtwpTDHx1+hGcdhxcJaAmG4CFtagkb+NiN1M9Ek4b42pzMWqfc9jm8w==",
"dev": true,
"requires": {
- "async": "~1.0.0",
+ "async": "^3.2.3",
"colors": "1.0.x",
"cycle": "1.0.x",
"eyes": "0.1.x",
"isstream": "0.1.x",
"stack-trace": "0.0.x"
- },
- "dependencies": {
- "async": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/async/-/async-1.0.0.tgz",
- "integrity": "sha1-+PwEyjoTeErenhZBr5hXjPvWR6k=",
- "dev": true
- }
}
},
"word-wrap": {
@@ -12991,7 +13882,7 @@
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
"dev": true
},
"write-file-atomic": {
@@ -13007,9 +13898,9 @@
}
},
"ws": {
- "version": "7.5.7",
- "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz",
- "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==",
+ "version": "7.5.9",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
+ "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
"dev": true,
"requires": {}
},
@@ -13020,9 +13911,9 @@
"dev": true
},
"xmlbuilder": {
- "version": "9.0.7",
- "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz",
- "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=",
+ "version": "15.1.1",
+ "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz",
+ "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==",
"dev": true
},
"xmlchars": {
@@ -13067,7 +13958,7 @@
"yauzl": {
"version": "2.10.0",
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
- "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=",
+ "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==",
"dev": true,
"requires": {
"buffer-crc32": "~0.2.3",
@@ -13079,6 +13970,12 @@
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
"dev": true
+ },
+ "yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true
}
}
}
diff --git a/package.json b/package.json
index e137ba91..853e0ca9 100644
--- a/package.json
+++ b/package.json
@@ -1,24 +1,23 @@
{
"name": "objtoschematic",
- "version": "0.5.1",
+ "private": true,
+ "version": "0.6.0",
"description": "A tool to convert .obj files into voxels and then into Minecraft Schematic files",
"main": "./dist/src/main.js",
"engines": {
"node": ">=14.0.0"
},
"scripts": {
- "lint": "eslint --fix ./src/**/*.ts && eslint --fix ./tools/**/*.ts",
- "debug": "tsc && electron ./dist/src/main.js --enable-logging",
- "build": "npm run lint && tsc",
- "fast-build": "tsc",
+ "lint": "eslint --fix src tools tests --ext .ts",
+ "build": "tsc",
"test": "jest --config jestconfig.json",
- "start": "npm run build && electron ./dist/src/main.js --enable-logging",
+ "start": "npm run build && electron ./dist/src/main.js --enable-logging --remote-debugging-port=9222",
"atlas": "node ./dist/tools/build-atlas.js",
"palette": "node ./dist/tools/build-palette.js",
- "headless": "node ./dist/tools/headless.js",
- "package:win": "electron-packager . ObjToSchematic --overwrite --platform=win32 --arch=x64 --app-version=0.5.1 --prune=true",
- "package:linux": "electron-packager . ObjToSchematic --overwrite --platform=linux --arch=x64 --icon=res/static/icon.png --app-version=0.5.1 --prune=true",
- "package:macos": "electron-packager . ObjToSchematic --overwrite --platform=darwin --arch=x64 --icon=res/static/icon.icns --app-version=0.5.1 --prune=true"
+ "headless": "tsc && node ./dist/tools/run-headless.js",
+ "package:win": "electron-packager . ObjToSchematic --overwrite --platform=win32 --arch=x64 --app-version=0.6.0 --prune=true",
+ "package:linux": "electron-packager . ObjToSchematic --overwrite --platform=linux --arch=x64 --icon=res/static/icon.png --app-version=0.6.0 --prune=true",
+ "package:macos": "electron-packager . ObjToSchematic --overwrite --platform=darwin --arch=x64 --icon=res/static/icon.icns --app-version=0.6.0 --prune=true"
},
"repository": {
"type": "git",
@@ -31,11 +30,14 @@
},
"homepage": "https://github.com/LucasDower/ObjToSchematic#readme",
"devDependencies": {
+ "@types/adm-zip": "^0.5.0",
"@types/jest": "^27.4.1",
"@types/jquery": "^3.5.6",
+ "@types/merge-images": "^1.2.1",
"@types/obj-file-parser": "^0.5.0",
"@types/pngjs": "^6.0.1",
"@types/prompt": "^1.1.2",
+ "@types/sharp": "^0.31.0",
"@types/varint": "^6.0.0",
"@typescript-eslint/eslint-plugin": "^5.9.1",
"@typescript-eslint/parser": "^5.9.1",
@@ -46,17 +48,17 @@
"electron-packager": "^15.2.0",
"eslint": "^8.7.0",
"eslint-config-google": "^0.14.0",
+ "eslint-plugin-simple-import-sort": "^8.0.0",
"images": "^3.2.3",
"jest": "^27.5.1",
"prompt": "^1.2.1",
+ "sharp": "^0.31.1",
"ts-jest": "^27.1.3",
"ts-node": "^10.1.0",
"typescript": "^4.3.5"
},
"dependencies": {
- "bvh": "^0.5.0",
"bvh-tree": "^1.0.1",
- "color-convert": "^2.0.1",
"jpeg-js": "^0.4.4",
"pngjs": "^6.0.0",
"prismarine-nbt": "^1.6.0",
diff --git a/res/atlases/vanilla.atlas b/res/atlases/vanilla.atlas
index be5aeb3b..9551b4c3 100644
--- a/res/atlases/vanilla.atlas
+++ b/res/atlases/vanilla.atlas
@@ -13781,59 +13781,6 @@
"a": 1
}
},
- {
- "name": "smooth_stone_slab_double",
- "faces": {
- "up": {
- "name": "minecraft:block/smooth_stone",
- "texcoord": {
- "u": 0.49122807017543857,
- "v": 0.8070175438596491
- }
- },
- "down": {
- "name": "minecraft:block/smooth_stone",
- "texcoord": {
- "u": 0.49122807017543857,
- "v": 0.8070175438596491
- }
- },
- "north": {
- "name": "minecraft:block/smooth_stone_slab_side",
- "texcoord": {
- "u": 0.543859649122807,
- "v": 0.8070175438596491
- }
- },
- "south": {
- "name": "minecraft:block/smooth_stone_slab_side",
- "texcoord": {
- "u": 0.543859649122807,
- "v": 0.8070175438596491
- }
- },
- "east": {
- "name": "minecraft:block/smooth_stone_slab_side",
- "texcoord": {
- "u": 0.543859649122807,
- "v": 0.8070175438596491
- }
- },
- "west": {
- "name": "minecraft:block/smooth_stone_slab_side",
- "texcoord": {
- "u": 0.543859649122807,
- "v": 0.8070175438596491
- }
- }
- },
- "colour": {
- "r": 0.645455473856208,
- "g": 0.645455473856208,
- "b": 0.645455473856208,
- "a": 1
- }
- },
{
"name": "snow_block",
"faces": {
@@ -16905,7 +16852,6 @@
"smooth_red_sandstone",
"smooth_sandstone",
"smooth_stone",
- "smooth_stone_slab_double",
"snow_block",
"soul_sand",
"soul_soil",
diff --git a/res/block_ids.json b/res/block_ids.json
index 52d42823..34fd6368 100644
--- a/res/block_ids.json
+++ b/res/block_ids.json
@@ -1,1400 +1,1400 @@
{
- "air": {
+ "minecraft:air": {
"id": 0,
"meta": 0,
"name": "Air"
},
- "stone": {
+ "minecraft:stone": {
"id": 1,
"meta": 0,
"name": "Stone"
},
- "granite": {
+ "minecraft:granite": {
"id": 1,
"meta": 1,
"name": "Granite"
},
- "polished_granite": {
+ "minecraft:polished_granite": {
"id": 1,
"meta": 2,
"name": "Polished Granite"
},
- "diorite": {
+ "minecraft:diorite": {
"id": 1,
"meta": 3,
"name": "Diorite"
},
- "polished_diorite": {
+ "minecraft:polished_diorite": {
"id": 1,
"meta": 4,
"name": "Polished Diorite"
},
- "andesite": {
+ "minecraft:andesite": {
"id": 1,
"meta": 5,
"name": "Andesite"
},
- "polished_andesite": {
+ "minecraft:polished_andesite": {
"id": 1,
"meta": 6,
"name": "Polished Andesite"
},
- "grass_block": {
+ "minecraft:grass_block": {
"id": 31,
"meta": 1,
"name": "Grass"
},
- "dirt": {
+ "minecraft:dirt": {
"id": 3,
"meta": 0,
"name": "Dirt"
},
- "coarse_dirt": {
+ "minecraft:coarse_dirt": {
"id": 3,
"meta": 1,
"name": "Coarse Dirt"
},
- "podzol": {
+ "minecraft:podzol": {
"id": 3,
"meta": 2,
"name": "Podzol"
},
- "cobblestone": {
+ "minecraft:cobblestone": {
"id": 4,
"meta": 0,
"name": "Cobblestone"
},
- "oak_planks": {
+ "minecraft:oak_planks": {
"id": 5,
"meta": 0,
"name": "Oak Wood Plank"
},
- "spruce_planks": {
+ "minecraft:spruce_planks": {
"id": 5,
"meta": 1,
"name": "Spruce Wood Plank"
},
- "birch_planks": {
+ "minecraft:birch_planks": {
"id": 5,
"meta": 2,
"name": "Birch Wood Plank"
},
- "jungle_planks": {
+ "minecraft:jungle_planks": {
"id": 5,
"meta": 3,
"name": "Jungle Wood Plank"
},
- "acacia_planks": {
+ "minecraft:acacia_planks": {
"id": 5,
"meta": 4,
"name": "Acacia Wood Plank"
},
- "dark_oak_planks": {
+ "minecraft:dark_oak_planks": {
"id": 5,
"meta": 5,
"name": "Dark Oak Wood Plank"
},
- "bedrock": {
+ "minecraft:bedrock": {
"id": 7,
"meta": 0,
"name": "Bedrock"
},
- "sand": {
+ "minecraft:sand": {
"id": 12,
"meta": 0,
"name": "Sand"
},
- "red_sand": {
+ "minecraft:red_sand": {
"id": 12,
"meta": 1,
"name": "Red Sand"
},
- "gravel": {
+ "minecraft:gravel": {
"id": 13,
"meta": 0,
"name": "Gravel"
},
- "gold_ore": {
+ "minecraft:gold_ore": {
"id": 14,
"meta": 0,
"name": "Gold Ore"
},
- "iron_ore": {
+ "minecraft:iron_ore": {
"id": 15,
"meta": 0,
"name": "Iron Ore"
},
- "coal_ore": {
+ "minecraft:coal_ore": {
"id": 16,
"meta": 0,
"name": "Coal Ore"
},
- "oak_log": {
+ "minecraft:oak_log": {
"id": 17,
"meta": 0,
"name": "Oak Wood"
},
- "spruce_log": {
+ "minecraft:spruce_log": {
"id": 17,
"meta": 1,
"name": "Spruce Wood"
},
- "birch_log": {
+ "minecraft:birch_log": {
"id": 17,
"meta": 2,
"name": "Birch Wood"
},
- "jungle_log": {
+ "minecraft:jungle_log": {
"id": 17,
"meta": 3,
"name": "Jungle Wood"
},
- "oak_leaves": {
+ "minecraft:oak_leaves": {
"id": 18,
"meta": 0,
"name": "Oak Leaves"
},
- "spruce_leaves": {
+ "minecraft:spruce_leaves": {
"id": 18,
"meta": 1,
"name": "Spruce Leaves"
},
- "birch_leaves": {
+ "minecraft:birch_leaves": {
"id": 18,
"meta": 2,
"name": "Birch Leaves"
},
- "jungle_leaves": {
+ "minecraft:jungle_leaves": {
"id": 18,
"meta": 3,
"name": "Jungle Leaves"
},
- "sponge": {
+ "minecraft:sponge": {
"id": 19,
"meta": 0,
"name": "Sponge"
},
- "wet_sponge": {
+ "minecraft:wet_sponge": {
"id": 19,
"meta": 1,
"name": "Wet Sponge"
},
- "glass": {
+ "minecraft:glass": {
"id": 20,
"meta": 0,
"name": "Glass"
},
- "lapis_ore": {
+ "minecraft:lapis_ore": {
"id": 21,
"meta": 0,
"name": "Lapis Lazuli Ore"
},
- "lapis_block": {
+ "minecraft:lapis_block": {
"id": 22,
"meta": 0,
"name": "Lapis Lazuli Block"
},
- "dispenser": {
+ "minecraft:dispenser": {
"id": 23,
"meta": 0,
"name": "Dispenser"
},
- "sandstone": {
+ "minecraft:sandstone": {
"id": 24,
"meta": 0,
"name": "Sandstone"
},
- "chiseled_sandstone": {
+ "minecraft:chiseled_sandstone": {
"id": 24,
"meta": 1,
"name": "Chiseled Sandstone"
},
- "cut_sandstone": {
+ "minecraft:cut_sandstone": {
"id": 24,
"meta": 2,
"name": "Smooth Sandstone"
},
- "note_block": {
+ "minecraft:note_block": {
"id": 25,
"meta": 0,
"name": "Note Block"
},
- "powered_rail": {
+ "minecraft:powered_rail": {
"id": 27,
"meta": 0,
"name": "Powered Rail"
},
- "detector_rail": {
+ "minecraft:detector_rail": {
"id": 28,
"meta": 0,
"name": "Detector Rail"
},
- "sticky_piston": {
+ "minecraft:sticky_piston": {
"id": 29,
"meta": 0,
"name": "Sticky Piston"
},
- "cobweb": {
+ "minecraft:cobweb": {
"id": 30,
"meta": 0,
"name": "Cobweb"
},
- "fern": {
+ "minecraft:fern": {
"id": 31,
"meta": 2,
"name": "Fern"
},
- "dead_bush": {
+ "minecraft:dead_bush": {
"id": 32,
"meta": 0,
"name": "Dead Bush"
},
- "piston": {
+ "minecraft:piston": {
"id": 33,
"meta": 0,
"name": "Piston"
},
- "white_wool": {
+ "minecraft:white_wool": {
"id": 35,
"meta": 0,
"name": "White Wool"
},
- "orange_wool": {
+ "minecraft:orange_wool": {
"id": 35,
"meta": 1,
"name": "Orange Wool"
},
- "magenta_wool": {
+ "minecraft:magenta_wool": {
"id": 35,
"meta": 2,
"name": "Magenta Wool"
},
- "light_blue_wool": {
+ "minecraft:light_blue_wool": {
"id": 35,
"meta": 3,
"name": "Light Blue Wool"
},
- "yellow_wool": {
+ "minecraft:yellow_wool": {
"id": 35,
"meta": 4,
"name": "Yellow Wool"
},
- "lime_wool": {
+ "minecraft:lime_wool": {
"id": 35,
"meta": 5,
"name": "Lime Wool"
},
- "pink_wool": {
+ "minecraft:pink_wool": {
"id": 35,
"meta": 6,
"name": "Pink Wool"
},
- "gray_wool": {
+ "minecraft:gray_wool": {
"id": 35,
"meta": 7,
"name": "Gray Wool"
},
- "light_gray_wool": {
+ "minecraft:light_gray_wool": {
"id": 35,
"meta": 8,
"name": "Light Gray Wool"
},
- "cyan_wool": {
+ "minecraft:cyan_wool": {
"id": 35,
"meta": 9,
"name": "Cyan Wool"
},
- "purple_wool": {
+ "minecraft:purple_wool": {
"id": 35,
"meta": 10,
"name": "Purple Wool"
},
- "blue_wool": {
+ "minecraft:blue_wool": {
"id": 35,
"meta": 11,
"name": "Blue Wool"
},
- "brown_wool": {
+ "minecraft:brown_wool": {
"id": 35,
"meta": 12,
"name": "Brown Wool"
},
- "green_wool": {
+ "minecraft:green_wool": {
"id": 35,
"meta": 13,
"name": "Green Wool"
},
- "red_wool": {
+ "minecraft:red_wool": {
"id": 35,
"meta": 14,
"name": "Red Wool"
},
- "black_wool": {
+ "minecraft:black_wool": {
"id": 35,
"meta": 15,
"name": "Black Wool"
},
- "gold_block": {
+ "minecraft:gold_block": {
"id": 41,
"meta": 0,
"name": "Gold Block"
},
- "iron_block": {
+ "minecraft:iron_block": {
"id": 42,
"meta": 0,
"name": "Iron Block"
},
- "smooth_stone": {
+ "minecraft:smooth_stone": {
"id": 43,
"meta": 8,
"name": "Iron Block"
},
- "stone_slab": {
+ "minecraft:stone_slab": {
"id": 44,
"meta": 0,
"name": "Stone Slab"
},
- "sandstone_slab": {
+ "minecraft:sandstone_slab": {
"id": 44,
"meta": 1,
"name": "Sandstone Slab"
},
- "cobblestone_slab": {
+ "minecraft:cobblestone_slab": {
"id": 44,
"meta": 3,
"name": "Cobblestone Slab"
},
- "brick_slab": {
+ "minecraft:brick_slab": {
"id": 44,
"meta": 4,
"name": "Brick Slab"
},
- "stone_brick_slab": {
+ "minecraft:stone_brick_slab": {
"id": 44,
"meta": 5,
"name": "Stone Brick Slab"
},
- "nether_brick_slab": {
+ "minecraft:nether_brick_slab": {
"id": 44,
"meta": 6,
"name": "Nether Brick Slab"
},
- "quartz_slab": {
+ "minecraft:quartz_slab": {
"id": 44,
"meta": 7,
"name": "Quartz Slab"
},
- "bricks": {
+ "minecraft:bricks": {
"id": 45,
"meta": 0,
"name": "Bricks"
},
- "tnt": {
+ "minecraft:tnt": {
"id": 46,
"meta": 0,
"name": "TNT"
},
- "bookshelf": {
+ "minecraft:bookshelf": {
"id": 47,
"meta": 0,
"name": "Bookshelf"
},
- "mossy_cobblestone": {
+ "minecraft:mossy_cobblestone": {
"id": 48,
"meta": 0,
"name": "Moss Stone"
},
- "obsidian": {
+ "minecraft:obsidian": {
"id": 49,
"meta": 0,
"name": "Obsidian"
},
- "monster_spawner": {
+ "minecraft:monster_spawner": {
"id": 52,
"meta": 0,
"name": "Monster Spawner"
},
- "oak_stairs": {
+ "minecraft:oak_stairs": {
"id": 53,
"meta": 0,
"name": "Oak Wood Stairs"
},
- "diamond_ore": {
+ "minecraft:diamond_ore": {
"id": 56,
"meta": 0,
"name": "Diamond Ore"
},
- "diamond_block": {
+ "minecraft:diamond_block": {
"id": 57,
"meta": 0,
"name": "Diamond Block"
},
- "crafting_table": {
+ "minecraft:crafting_table": {
"id": 58,
"meta": 0,
"name": "Crafting Table"
},
- "farmland": {
+ "minecraft:farmland": {
"id": 60,
"meta": 0,
"name": "Farmland"
},
- "furnace": {
+ "minecraft:furnace": {
"id": 61,
"meta": 0,
"name": "Furnace"
},
- "cobblestone_stairs": {
+ "minecraft:cobblestone_stairs": {
"id": 67,
"meta": 0,
"name": "Cobblestone Stairs"
},
- "redstone_ore": {
+ "minecraft:redstone_ore": {
"id": 73,
"meta": 0,
"name": "Redstone Ore"
},
- "ice": {
+ "minecraft:ice": {
"id": 79,
"meta": 0,
"name": "Ice"
},
- "snow_block": {
+ "minecraft:snow_block": {
"id": 80,
"meta": 0,
"name": "Snow Block"
},
- "clay": {
- "id": 337,
+ "minecraft:clay": {
+ "id": 82,
"meta": 0,
"name": "Clay"
},
- "jukebox": {
+ "minecraft:jukebox": {
"id": 84,
"meta": 0,
"name": "Jukebox"
},
- "pumpkin": {
+ "minecraft:pumpkin": {
"id": 86,
"meta": 0,
"name": "Pumpkin"
},
- "netherrack": {
+ "minecraft:netherrack": {
"id": 87,
"meta": 0,
"name": "Netherrack"
},
- "soul_sand": {
+ "minecraft:soul_sand": {
"id": 88,
"meta": 0,
"name": "Soul Sand"
},
- "glowstone": {
+ "minecraft:glowstone": {
"id": 89,
"meta": 0,
"name": "Glowstone"
},
- "jack_o_lantern": {
+ "minecraft:jack_o_lantern": {
"id": 91,
"meta": 0,
"name": "Jack o'Lantern"
},
- "white_stained_glass": {
+ "minecraft:white_stained_glass": {
"id": 95,
"meta": 0,
"name": "White Stained Glass"
},
- "orange_stained_glass": {
+ "minecraft:orange_stained_glass": {
"id": 95,
"meta": 1,
"name": "Orange Stained Glass"
},
- "magenta_stained_glass": {
+ "minecraft:magenta_stained_glass": {
"id": 95,
"meta": 2,
"name": "Magenta Stained Glass"
},
- "light_blue stained_glass": {
+ "minecraft:light_blue stained_glass": {
"id": 95,
"meta": 3,
"name": "Light Blue Stained Glass"
},
- "yellow_stained_glass": {
+ "minecraft:yellow_stained_glass": {
"id": 95,
"meta": 4,
"name": "Yellow Stained Glass"
},
- "lime_stained_glass": {
+ "minecraft:lime_stained_glass": {
"id": 95,
"meta": 5,
"name": "Lime Stained Glass"
},
- "pink_stained_glass": {
+ "minecraft:pink_stained_glass": {
"id": 95,
"meta": 6,
"name": "Pink Stained Glass"
},
- "gray_stained_glass": {
+ "minecraft:gray_stained_glass": {
"id": 95,
"meta": 7,
"name": "Gray Stained Glass"
},
- "light_gray stained_glass": {
+ "minecraft:light_gray stained_glass": {
"id": 95,
"meta": 8,
"name": "Light Gray Stained Glass"
},
- "cyan_stained_glass": {
+ "minecraft:cyan_stained_glass": {
"id": 95,
"meta": 9,
"name": "Cyan Stained Glass"
},
- "purple_stained_glass": {
+ "minecraft:purple_stained_glass": {
"id": 95,
"meta": 10,
"name": "Purple Stained Glass"
},
- "blue_stained_glass": {
+ "minecraft:blue_stained_glass": {
"id": 95,
"meta": 11,
"name": "Blue Stained Glass"
},
- "brown_stained_glass": {
+ "minecraft:brown_stained_glass": {
"id": 95,
"meta": 12,
"name": "Brown Stained Glass"
},
- "green_stained_glass": {
+ "minecraft:green_stained_glass": {
"id": 95,
"meta": 13,
"name": "Green Stained Glass"
},
- "red_stained_glass": {
+ "minecraft:red_stained_glass": {
"id": 95,
"meta": 14,
"name": "Red Stained Glass"
},
- "black_stained_glass": {
+ "minecraft:black_stained_glass": {
"id": 95,
"meta": 15,
"name": "Black Stained Glass"
},
- "stone_bricks": {
+ "minecraft:stone_bricks": {
"id": 98,
"meta": 0,
"name": "Stone Bricks"
},
- "mossy_stone_bricks": {
+ "minecraft:mossy_stone_bricks": {
"id": 98,
"meta": 1,
"name": "Mossy Stone Bricks"
},
- "cracked_stone_bricks": {
+ "minecraft:cracked_stone_bricks": {
"id": 98,
"meta": 2,
"name": "Cracked Stone Bricks"
},
- "chiseled_stone_bricks": {
+ "minecraft:chiseled_stone_bricks": {
"id": 98,
"meta": 3,
"name": "Chiseled Stone Bricks"
},
- "brown_mushroom_block": {
+ "minecraft:brown_mushroom_block": {
"id": 99,
"meta": 0,
"name": "Brown Mushroom Block"
},
- "red_mushroom_block": {
+ "minecraft:red_mushroom_block": {
"id": 100,
"meta": 0,
"name": "Red Mushroom Block"
},
- "iron_bars": {
+ "minecraft:iron_bars": {
"id": 101,
"meta": 0,
"name": "Iron Bars"
},
- "glass_pane": {
+ "minecraft:glass_pane": {
"id": 102,
"meta": 0,
"name": "Glass Pane"
},
- "melon_block": {
+ "minecraft:melon_block": {
"id": 103,
"meta": 0,
"name": "Melon Block"
},
- "brick_stairs": {
+ "minecraft:brick_stairs": {
"id": 108,
"meta": 0,
"name": "Brick Stairs"
},
- "stone_brick_stairs": {
+ "minecraft:stone_brick_stairs": {
"id": 109,
"meta": 0,
"name": "Stone Brick Stairs"
},
- "mycelium": {
+ "minecraft:mycelium": {
"id": 110,
"meta": 0,
"name": "Mycelium"
},
- "nether_bricks": {
+ "minecraft:nether_bricks": {
"id": 112,
"meta": 0,
"name": "Nether Bricks"
},
- "nether_brick_stairs": {
+ "minecraft:nether_brick_stairs": {
"id": 114,
"meta": 0,
"name": "Nether Brick Stairs"
},
- "end_stone": {
+ "minecraft:end_stone": {
"id": 121,
"meta": 0,
"name": "End Stone"
},
- "redstone_lamp": {
+ "minecraft:redstone_lamp": {
"id": 123,
"meta": 0,
"name": "Redstone Lamp (inactive)"
},
- "oak_slab": {
+ "minecraft:oak_slab": {
"id": 126,
"meta": 0,
"name": "Oak Wood Slab"
},
- "spruce_slab": {
+ "minecraft:spruce_slab": {
"id": 126,
"meta": 1,
"name": "Spruce Wood Slab"
},
- "birch_slab": {
+ "minecraft:birch_slab": {
"id": 126,
"meta": 2,
"name": "Birch Wood Slab"
},
- "jungle_slab": {
+ "minecraft:jungle_slab": {
"id": 126,
"meta": 3,
"name": "Jungle Wood Slab"
},
- "acacia_slab": {
+ "minecraft:acacia_slab": {
"id": 126,
"meta": 4,
"name": "Acacia Wood Slab"
},
- "dark_oak_slab": {
+ "minecraft:dark_oak_slab": {
"id": 126,
"meta": 5,
"name": "Dark Oak Wood Slab"
},
- "sandstone_stairs": {
+ "minecraft:sandstone_stairs": {
"id": 128,
"meta": 0,
"name": "Sandstone Stairs"
},
- "emerald_ore": {
+ "minecraft:emerald_ore": {
"id": 129,
"meta": 0,
"name": "Emerald Ore"
},
- "emerald_block": {
+ "minecraft:emerald_block": {
"id": 133,
"meta": 0,
"name": "Emerald Block"
},
- "spruce_stairs": {
+ "minecraft:spruce_stairs": {
"id": 134,
"meta": 0,
"name": "Spruce Wood Stairs"
},
- "birch_stairs": {
+ "minecraft:birch_stairs": {
"id": 135,
"meta": 0,
"name": "Birch Wood Stairs"
},
- "jungle_stairs": {
+ "minecraft:jungle_stairs": {
"id": 136,
"meta": 0,
"name": "Jungle Wood Stairs"
},
- "redstone_block": {
+ "minecraft:redstone_block": {
"id": 152,
"meta": 0,
"name": "Redstone Block"
},
- "nether_quartz_ore": {
+ "minecraft:nether_quartz_ore": {
"id": 153,
"meta": 0,
"name": "Nether Quartz Ore"
},
- "quartz_block": {
+ "minecraft:quartz_block": {
"id": 155,
"meta": 0,
"name": "Quartz Block"
},
- "chiseled_quartz_block": {
+ "minecraft:chiseled_quartz_block": {
"id": 155,
"meta": 1,
"name": "Chiseled Quartz Block"
},
- "pillar_quartz_block": {
+ "minecraft:pillar_quartz_block": {
"id": 155,
"meta": 2,
"name": "Pillar Quartz Block"
},
- "quartz_stairs": {
+ "minecraft:quartz_stairs": {
"id": 156,
"meta": 0,
"name": "Quartz Stairs"
},
- "dropper": {
+ "minecraft:dropper": {
"id": 158,
"meta": 0,
"name": "Dropper"
},
- "white_terracotta": {
+ "minecraft:white_terracotta": {
"id": 159,
"meta": 0,
"name": "White Hardened Clay"
},
- "orange_terracotta": {
+ "minecraft:orange_terracotta": {
"id": 159,
"meta": 1,
"name": "Orange Hardened Clay"
},
- "magenta_terracotta": {
+ "minecraft:magenta_terracotta": {
"id": 159,
"meta": 2,
"name": "Magenta Hardened Clay"
},
- "light_blue_terracotta": {
+ "minecraft:light_blue_terracotta": {
"id": 159,
"meta": 3,
"name": "Light Blue Hardened Clay"
},
- "yellow_terracotta": {
+ "minecraft:yellow_terracotta": {
"id": 159,
"meta": 4,
"name": "Yellow Hardened Clay"
},
- "lime_terracotta": {
+ "minecraft:lime_terracotta": {
"id": 159,
"meta": 5,
"name": "Lime Hardened Clay"
},
- "pink_terracotta": {
+ "minecraft:pink_terracotta": {
"id": 159,
"meta": 6,
"name": "Pink Hardened Clay"
},
- "gray_terracotta": {
+ "minecraft:gray_terracotta": {
"id": 159,
"meta": 7,
"name": "Gray Hardened Clay"
},
- "light_gray_terracotta": {
+ "minecraft:light_gray_terracotta": {
"id": 159,
"meta": 8,
"name": "Light Gray Hardened Clay"
},
- "cyan_terracotta": {
+ "minecraft:cyan_terracotta": {
"id": 159,
"meta": 9,
"name": "Cyan Hardened Clay"
},
- "purple_terracotta": {
+ "minecraft:purple_terracotta": {
"id": 159,
"meta": 10,
"name": "Purple Hardened Clay"
},
- "blue_terracotta": {
+ "minecraft:blue_terracotta": {
"id": 159,
"meta": 11,
"name": "Blue Hardened Clay"
},
- "brown_terracotta": {
+ "minecraft:brown_terracotta": {
"id": 159,
"meta": 12,
"name": "Brown Hardened Clay"
},
- "green_terracotta": {
+ "minecraft:green_terracotta": {
"id": 159,
"meta": 13,
"name": "Green Hardened Clay"
},
- "red_terracotta": {
+ "minecraft:red_terracotta": {
"id": 159,
"meta": 14,
"name": "Red Hardened Clay"
},
- "black_terracotta": {
+ "minecraft:black_terracotta": {
"id": 159,
"meta": 15,
"name": "Black Hardened Clay"
},
- "white_stained_glass_pane": {
+ "minecraft:white_stained_glass_pane": {
"id": 160,
"meta": 0,
"name": "White Stained Glass Pane"
},
- "orange_stained_glass_pane": {
+ "minecraft:orange_stained_glass_pane": {
"id": 160,
"meta": 1,
"name": "Orange Stained Glass Pane"
},
- "magenta_stained_glass_pane": {
+ "minecraft:magenta_stained_glass_pane": {
"id": 160,
"meta": 2,
"name": "Magenta Stained Glass Pane"
},
- "light_blue_stained_glass_pane": {
+ "minecraft:light_blue_stained_glass_pane": {
"id": 160,
"meta": 3,
"name": "Light Blue Stained Glass Pane"
},
- "yellow_stained_glass_pane": {
+ "minecraft:yellow_stained_glass_pane": {
"id": 160,
"meta": 4,
"name": "Yellow Stained Glass Pane"
},
- "lime_stained_glass_pane": {
+ "minecraft:lime_stained_glass_pane": {
"id": 160,
"meta": 5,
"name": "Lime Stained Glass Pane"
},
- "pink_stained_glass_pane": {
+ "minecraft:pink_stained_glass_pane": {
"id": 160,
"meta": 6,
"name": "Pink Stained Glass Pane"
},
- "gray_stained_glass_pane": {
+ "minecraft:gray_stained_glass_pane": {
"id": 160,
"meta": 7,
"name": "Gray Stained Glass Pane"
},
- "light_gray_stained_glass_pane": {
+ "minecraft:light_gray_stained_glass_pane": {
"id": 160,
"meta": 8,
"name": "Light Gray Stained Glass Pane"
},
- "cyan_stained_glass_pane": {
+ "minecraft:cyan_stained_glass_pane": {
"id": 160,
"meta": 9,
"name": "Cyan Stained Glass Pane"
},
- "purple_stained_glass_pane": {
+ "minecraft:purple_stained_glass_pane": {
"id": 160,
"meta": 10,
"name": "Purple Stained Glass Pane"
},
- "blue_stained_glass_pane": {
+ "minecraft:blue_stained_glass_pane": {
"id": 160,
"meta": 11,
"name": "Blue Stained Glass Pane"
},
- "brown_stained_glass_pane": {
+ "minecraft:brown_stained_glass_pane": {
"id": 160,
"meta": 12,
"name": "Brown Stained Glass Pane"
},
- "green_stained_glass_pane": {
+ "minecraft:green_stained_glass_pane": {
"id": 160,
"meta": 13,
"name": "Green Stained Glass Pane"
},
- "red_stained_glass_pane": {
+ "minecraft:red_stained_glass_pane": {
"id": 160,
"meta": 14,
"name": "Red Stained Glass Pane"
},
- "black_stained_glass_pane": {
+ "minecraft:black_stained_glass_pane": {
"id": 160,
"meta": 15,
"name": "Black Stained Glass Pane"
},
- "acacia_leaves": {
+ "minecraft:acacia_leaves": {
"id": 161,
"meta": 0,
"name": "Acacia Leaves"
},
- "dark_oak_leaves": {
+ "minecraft:dark_oak_leaves": {
"id": 161,
"meta": 1,
"name": "Dark Oak Leaves"
},
- "acacia_log": {
+ "minecraft:acacia_log": {
"id": 162,
"meta": 0,
"name": "Acacia Wood"
},
- "dark_oak_log": {
+ "minecraft:dark_oak_log": {
"id": 162,
"meta": 1,
"name": "Dark Oak Wood"
},
- "acacia_stairs": {
+ "minecraft:acacia_stairs": {
"id": 163,
"meta": 0,
"name": "Acacia Wood Stairs"
},
- "dark_oak_stairs": {
+ "minecraft:dark_oak_stairs": {
"id": 164,
"meta": 0,
"name": "Dark Oak Wood Stairs"
},
- "slime_block": {
+ "minecraft:slime_block": {
"id": 165,
"meta": 0,
"name": "Slime Block"
},
- "prismarine": {
+ "minecraft:prismarine": {
"id": 168,
"meta": 0,
"name": "Prismarine"
},
- "prismarine_bricks": {
+ "minecraft:prismarine_bricks": {
"id": 168,
"meta": 1,
"name": "Prismarine Bricks"
},
- "dark_prismarine": {
+ "minecraft:dark_prismarine": {
"id": 168,
"meta": 2,
"name": "Dark Prismarine"
},
- "sea_lantern": {
+ "minecraft:sea_lantern": {
"id": 169,
"meta": 0,
"name": "Sea Lantern"
},
- "hay_block": {
+ "minecraft:hay_block": {
"id": 170,
"meta": 0,
"name": "Hay Bale"
},
- "terracotta": {
+ "minecraft:terracotta": {
"id": 172,
"meta": 0,
"name": "Hardened Clay"
},
- "coal_block": {
+ "minecraft:coal_block": {
"id": 173,
"meta": 0,
"name": "Block of Coal"
},
- "packed_ice": {
+ "minecraft:packed_ice": {
"id": 174,
"meta": 0,
"name": "Packed Ice"
},
- "red_sandstone": {
+ "minecraft:red_sandstone": {
"id": 179,
"meta": 0,
"name": "Red Sandstone"
},
- "chiseled_red_sandstone": {
+ "minecraft:chiseled_red_sandstone": {
"id": 179,
"meta": 1,
"name": "Chiseled Red Sandstone"
},
- "smooth_red_sandstone": {
+ "minecraft:smooth_red_sandstone": {
"id": 179,
"meta": 2,
"name": "Smooth Red Sandstone"
},
- "red_sandstone_stairs": {
+ "minecraft:red_sandstone_stairs": {
"id": 180,
"meta": 0,
"name": "Red Sandstone Stairs"
},
- "red_sandstone_slab": {
+ "minecraft:red_sandstone_slab": {
"id": 182,
"meta": 0,
"name": "Red Sandstone Slab"
},
- "purpur_block": {
+ "minecraft:purpur_block": {
"id": 201,
"meta": 0,
"name": "Purpur Block"
},
- "purpur_pillar": {
+ "minecraft:purpur_pillar": {
"id": 202,
"meta": 0,
"name": "Purpur Pillar"
},
- "purpur_stairs": {
+ "minecraft:purpur_stairs": {
"id": 203,
"meta": 0,
"name": "Purpur Stairs"
},
- "purpur_slab": {
+ "minecraft:purpur_slab": {
"id": 205,
"meta": 0,
"name": "Purpur Slab"
},
- "end_stone_bricks": {
+ "minecraft:end_stone_bricks": {
"id": 206,
"meta": 0,
"name": "End Stone Bricks"
},
- "grass_path": {
+ "minecraft:grass_path": {
"id": 208,
"meta": 0,
"name": "Grass Path"
},
- "frosted_ice": {
+ "minecraft:frosted_ice": {
"id": 212,
"meta": 0,
"name": "Frosted Ice"
},
- "magma_block": {
+ "minecraft:magma_block": {
"id": 213,
"meta": 0,
"name": "Magma Block"
},
- "nether_wart_block": {
+ "minecraft:nether_wart_block": {
"id": 214,
"meta": 0,
"name": "Nether Wart Block"
},
- "red_nether_bricks": {
+ "minecraft:red_nether_bricks": {
"id": 215,
"meta": 0,
"name": "Red Nether Brick"
},
- "bone_block": {
+ "minecraft:bone_block": {
"id": 216,
"meta": 0,
"name": "Bone Block"
},
- "structure_void": {
+ "minecraft:structure_void": {
"id": 217,
"meta": 0,
"name": "Structure Void"
},
- "observer": {
+ "minecraft:observer": {
"id": 218,
"meta": 0,
"name": "Observer"
},
- "white_shulker_box": {
+ "minecraft:white_shulker_box": {
"id": 219,
"meta": 0,
"name": "White Shulker Box"
},
- "orange_shulker_box": {
+ "minecraft:orange_shulker_box": {
"id": 220,
"meta": 0,
"name": "Orange Shulker Box"
},
- "magenta_shulker_box": {
+ "minecraft:magenta_shulker_box": {
"id": 221,
"meta": 0,
"name": "Magenta Shulker Box"
},
- "light_blue_shulker_box": {
+ "minecraft:light_blue_shulker_box": {
"id": 222,
"meta": 0,
"name": "Light Blue Shulker Box"
},
- "yellow_shulker_box": {
+ "minecraft:yellow_shulker_box": {
"id": 223,
"meta": 0,
"name": "Yellow Shulker Box"
},
- "lime_shulker_box": {
+ "minecraft:lime_shulker_box": {
"id": 224,
"meta": 0,
"name": "Lime Shulker Box"
},
- "pink_shulker_box": {
+ "minecraft:pink_shulker_box": {
"id": 225,
"meta": 0,
"name": "Pink Shulker Box"
},
- "gray_shulker_box": {
+ "minecraft:gray_shulker_box": {
"id": 226,
"meta": 0,
"name": "Gray Shulker Box"
},
- "light_gray_shulker_box": {
+ "minecraft:light_gray_shulker_box": {
"id": 227,
"meta": 0,
"name": "Light Gray Shulker Box"
},
- "cyan_shulker_box": {
+ "minecraft:cyan_shulker_box": {
"id": 228,
"meta": 0,
"name": "Cyan Shulker Box"
},
- "purple_shulker_box": {
+ "minecraft:purple_shulker_box": {
"id": 229,
"meta": 0,
"name": "Purple Shulker Box"
},
- "blue_shulker_box": {
+ "minecraft:blue_shulker_box": {
"id": 230,
"meta": 0,
"name": "Blue Shulker Box"
},
- "brown_shulker_box": {
+ "minecraft:brown_shulker_box": {
"id": 231,
"meta": 0,
"name": "Brown Shulker Box"
},
- "green_shulker_box": {
+ "minecraft:green_shulker_box": {
"id": 232,
"meta": 0,
"name": "Green Shulker Box"
},
- "red_shulker_box": {
+ "minecraft:red_shulker_box": {
"id": 233,
"meta": 0,
"name": "Red Shulker Box"
},
- "black_shulker_box": {
+ "minecraft:black_shulker_box": {
"id": 234,
"meta": 0,
"name": "Black Shulker Box"
},
- "white_glazed_terracotta": {
+ "minecraft:white_glazed_terracotta": {
"id": 235,
"meta": 0,
"name": "White Glazed Terracotta"
},
- "orange_glazed_terracotta": {
+ "minecraft:orange_glazed_terracotta": {
"id": 236,
"meta": 0,
"name": "Orange Glazed Terracotta"
},
- "magenta_glazed_terracotta": {
+ "minecraft:magenta_glazed_terracotta": {
"id": 237,
"meta": 0,
"name": "Magenta Glazed Terracotta"
},
- "light_blue_glazed_terracotta": {
+ "minecraft:light_blue_glazed_terracotta": {
"id": 238,
"meta": 0,
"name": "Light Blue Glazed Terracotta"
},
- "yellow_glazed_terracotta": {
+ "minecraft:yellow_glazed_terracotta": {
"id": 239,
"meta": 0,
"name": "Yellow Glazed Terracotta"
},
- "lime_glazed_terracotta": {
+ "minecraft:lime_glazed_terracotta": {
"id": 240,
"meta": 0,
"name": "Lime Glazed Terracotta"
},
- "pink_glazed_terracotta": {
+ "minecraft:pink_glazed_terracotta": {
"id": 241,
"meta": 0,
"name": "Pink Glazed Terracotta"
},
- "gray_glazed_terracotta": {
+ "minecraft:gray_glazed_terracotta": {
"id": 242,
"meta": 0,
"name": "Gray Glazed Terracotta"
},
- "light_gray glazed_terracotta": {
+ "minecraft:light_gray glazed_terracotta": {
"id": 243,
"meta": 0,
"name": "Light Gray Glazed Terracotta"
},
- "cyan_glazed_terracotta": {
+ "minecraft:cyan_glazed_terracotta": {
"id": 244,
"meta": 0,
"name": "Cyan Glazed Terracotta"
},
- "purple_glazed_terracotta": {
+ "minecraft:purple_glazed_terracotta": {
"id": 245,
"meta": 0,
"name": "Purple Glazed Terracotta"
},
- "blue_glazed_terracotta": {
+ "minecraft:blue_glazed_terracotta": {
"id": 246,
"meta": 0,
"name": "Blue Glazed Terracotta"
},
- "brown_glazed_terracotta": {
+ "minecraft:brown_glazed_terracotta": {
"id": 247,
"meta": 0,
"name": "Brown Glazed Terracotta"
},
- "green_glazed_terracotta": {
+ "minecraft:green_glazed_terracotta": {
"id": 248,
"meta": 0,
"name": "Green Glazed Terracotta"
},
- "red_glazed_terracotta": {
+ "minecraft:red_glazed_terracotta": {
"id": 249,
"meta": 0,
"name": "Red Glazed Terracotta"
},
- "black_glazed_terracotta": {
+ "minecraft:black_glazed_terracotta": {
"id": 250,
"meta": 0,
"name": "Black Glazed Terracotta"
},
- "white_concrete": {
+ "minecraft:white_concrete": {
"id": 251,
"meta": 0,
"name": "White Concrete"
},
- "orange_concrete": {
+ "minecraft:orange_concrete": {
"id": 251,
"meta": 1,
"name": "Orange Concrete"
},
- "magenta_concrete": {
+ "minecraft:magenta_concrete": {
"id": 251,
"meta": 2,
"name": "Magenta Concrete"
},
- "light_blue_concrete": {
+ "minecraft:light_blue_concrete": {
"id": 251,
"meta": 3,
"name": "Light Blue Concrete"
},
- "yellow_concrete": {
+ "minecraft:yellow_concrete": {
"id": 251,
"meta": 4,
"name": "Yellow Concrete"
},
- "lime_concrete": {
+ "minecraft:lime_concrete": {
"id": 251,
"meta": 5,
"name": "Lime Concrete"
},
- "pink_concrete": {
+ "minecraft:pink_concrete": {
"id": 251,
"meta": 6,
"name": "Pink Concrete"
},
- "gray_concrete": {
+ "minecraft:gray_concrete": {
"id": 251,
"meta": 7,
"name": "Gray Concrete"
},
- "light_gray_concrete": {
+ "minecraft:light_gray_concrete": {
"id": 251,
"meta": 8,
"name": "Light Gray Concrete"
},
- "cyan_concrete": {
+ "minecraft:cyan_concrete": {
"id": 251,
"meta": 9,
"name": "Cyan Concrete"
},
- "purple_concrete": {
+ "minecraft:purple_concrete": {
"id": 251,
"meta": 10,
"name": "Purple Concrete"
},
- "blue_concrete": {
+ "minecraft:blue_concrete": {
"id": 251,
"meta": 11,
"name": "Blue Concrete"
},
- "brown_concrete": {
+ "minecraft:brown_concrete": {
"id": 251,
"meta": 12,
"name": "Brown Concrete"
},
- "green_concrete": {
+ "minecraft:green_concrete": {
"id": 251,
"meta": 13,
"name": "Green Concrete"
},
- "red_concrete": {
+ "minecraft:red_concrete": {
"id": 251,
"meta": 14,
"name": "Red Concrete"
},
- "black_concrete": {
+ "minecraft:black_concrete": {
"id": 251,
"meta": 15,
"name": "Black Concrete"
},
- "white_concrete_powder": {
+ "minecraft:white_concrete_powder": {
"id": 252,
"meta": 0,
"name": "White Concrete Powder"
},
- "orange_concrete_powder": {
+ "minecraft:orange_concrete_powder": {
"id": 252,
"meta": 1,
"name": "Orange Concrete Powder"
},
- "magenta_concrete_powder": {
+ "minecraft:magenta_concrete_powder": {
"id": 252,
"meta": 2,
"name": "Magenta Concrete Powder"
},
- "light_blue_concrete_powder": {
+ "minecraft:light_blue_concrete_powder": {
"id": 252,
"meta": 3,
"name": "Light Blue Concrete Powder"
},
- "yellow_concrete_powder": {
+ "minecraft:yellow_concrete_powder": {
"id": 252,
"meta": 4,
"name": "Yellow Concrete Powder"
},
- "lime_concrete_powder": {
+ "minecraft:lime_concrete_powder": {
"id": 252,
"meta": 5,
"name": "Lime Concrete Powder"
},
- "pink_concrete_powder": {
+ "minecraft:pink_concrete_powder": {
"id": 252,
"meta": 6,
"name": "Pink Concrete Powder"
},
- "gray_concrete_powder": {
+ "minecraft:gray_concrete_powder": {
"id": 252,
"meta": 7,
"name": "Gray Concrete Powder"
},
- "light_gray_concrete_powder": {
+ "minecraft:light_gray_concrete_powder": {
"id": 252,
"meta": 8,
"name": "Light Gray Concrete Powder"
},
- "cyan_concrete_powder": {
+ "minecraft:cyan_concrete_powder": {
"id": 252,
"meta": 9,
"name": "Cyan Concrete Powder"
},
- "purple_concrete_powder": {
+ "minecraft:purple_concrete_powder": {
"id": 252,
"meta": 10,
"name": "Purple Concrete Powder"
},
- "blue_concrete_powder": {
+ "minecraft:blue_concrete_powder": {
"id": 252,
"meta": 11,
"name": "Blue Concrete Powder"
},
- "brown_concrete_powder": {
+ "minecraft:brown_concrete_powder": {
"id": 252,
"meta": 12,
"name": "Brown Concrete Powder"
},
- "green_concrete_powder": {
+ "minecraft:green_concrete_powder": {
"id": 252,
"meta": 13,
"name": "Green Concrete Powder"
},
- "red_concrete_powder": {
+ "minecraft:red_concrete_powder": {
"id": 252,
"meta": 14,
"name": "Red Concrete Powder"
},
- "black_concrete_powder": {
+ "minecraft:black_concrete_powder": {
"id": 252,
"meta": 15,
"name": "Black Concrete Powder"
diff --git a/res/config.json b/res/config.json
new file mode 100644
index 00000000..2ef4c183
--- /dev/null
+++ b/res/config.json
@@ -0,0 +1,17 @@
+{
+ "AMBIENT_OCCLUSION_OVERRIDE_CORNER": true,
+ "LOG_TO_FILE": true,
+ "USE_WORKER_THREAD": true,
+ "MULTISAMPLE_COUNT": 16,
+ "OLD_SPACE_SIZE_MB": 8192,
+ "ALPHA_BIAS": 1.0,
+ "ANGLE_SNAP_RADIUS_DEGREES": 10.0,
+ "RENDER_TRIANGLE_THRESHOLD": 1000000,
+ "MAXIMUM_IMAGE_MEM_ALLOC": 2048,
+ "CAMERA_FOV_DEGREES": 30.0,
+ "CAMERA_DEFAULT_DISTANCE_UNITS": 18.0,
+ "CAMERA_DEFAULT_AZIMUTH_RADIANS": -1.0,
+ "CAMERA_DEFAULT_ELEVATION_RADIANS": 1.3,
+ "CAMERA_SENSITIVITY_ROTATION": 0.005,
+ "CAMERA_SENSITIVITY_ZOOM": 0.005
+}
\ No newline at end of file
diff --git a/res/fallable_blocks.json b/res/fallable_blocks.json
index 4f10e809..feeff907 100644
--- a/res/fallable_blocks.json
+++ b/res/fallable_blocks.json
@@ -1,27 +1,27 @@
{
"fallable_blocks": [
- "anvil",
- "lime_concrete_powder",
- "orange_concrete_powder",
- "black_concrete_powder",
- "brown_concrete_powder",
- "cyan_concrete_powder",
- "light_gray_concrete_powder",
- "purple_concrete_powder",
- "magenta_concrete_powder",
- "light_blue_concrete_powder",
- "yellow_concrete_powder",
- "white_concrete_powder",
- "blue_concrete_powder",
- "red_concrete_powder",
- "gray_concrete_powder",
- "pink_concrete_powder",
- "green_concrete_powder",
- "dragon_egg",
- "gravel",
- "pointed_dripstone",
- "red_sand",
- "sand",
- "scaffolding"
+ "minecraft:anvil",
+ "minecraft:lime_concrete_powder",
+ "minecraft:orange_concrete_powder",
+ "minecraft:black_concrete_powder",
+ "minecraft:brown_concrete_powder",
+ "minecraft:cyan_concrete_powder",
+ "minecraft:light_gray_concrete_powder",
+ "minecraft:purple_concrete_powder",
+ "minecraft:magenta_concrete_powder",
+ "minecraft:light_blue_concrete_powder",
+ "minecraft:yellow_concrete_powder",
+ "minecraft:white_concrete_powder",
+ "minecraft:blue_concrete_powder",
+ "minecraft:red_concrete_powder",
+ "minecraft:gray_concrete_powder",
+ "minecraft:pink_concrete_powder",
+ "minecraft:green_concrete_powder",
+ "minecraft:dragon_egg",
+ "minecraft:gravel",
+ "minecraft:pointed_dripstone",
+ "minecraft:red_sand",
+ "minecraft:sand",
+ "minecraft:scaffolding"
]
}
\ No newline at end of file
diff --git a/res/palettes/all-release.palette b/res/palettes/all-release.palette
index d0f116ee..09cd2239 100644
--- a/res/palettes/all-release.palette
+++ b/res/palettes/all-release.palette
@@ -260,7 +260,6 @@
"smooth_red_sandstone",
"smooth_sandstone",
"smooth_stone",
- "smooth_stone_slab_double",
"snow_block",
"soul_sand",
"soul_soil",
diff --git a/res/palettes/all-snapshot.palette b/res/palettes/all-snapshot.palette
index b4bdecbf..17b2d2fb 100644
--- a/res/palettes/all-snapshot.palette
+++ b/res/palettes/all-snapshot.palette
@@ -245,7 +245,6 @@
"smooth_red_sandstone",
"smooth_sandstone",
"smooth_stone",
- "smooth_stone_slab_double",
"snow_block",
"soul_sand",
"soul_soil",
diff --git a/res/palettes/greyscale.palette b/res/palettes/greyscale.palette
index a399efe4..8a4d7687 100644
--- a/res/palettes/greyscale.palette
+++ b/res/palettes/greyscale.palette
@@ -43,7 +43,6 @@
"quartz_pillar",
"smooth_quartz",
"smooth_stone",
- "smooth_stone_slab_double",
"snow_block",
"stone",
"stone_bricks",
diff --git a/res/palettes/test-palette.palette b/res/palettes/test-palette.palette
new file mode 100644
index 00000000..66ed9fd5
--- /dev/null
+++ b/res/palettes/test-palette.palette
@@ -0,0 +1,85 @@
+{
+ "version": 1,
+ "blocks": [
+ "minecraft:black_concrete",
+ "minecraft:black_concrete_powder",
+ "minecraft:black_glazed_terracotta",
+ "minecraft:black_terracotta",
+ "minecraft:black_wool",
+ "minecraft:blue_concrete",
+ "minecraft:blue_concrete_powder",
+ "minecraft:blue_glazed_terracotta",
+ "minecraft:blue_terracotta",
+ "minecraft:blue_wool",
+ "minecraft:brown_concrete",
+ "minecraft:brown_concrete_powder",
+ "minecraft:brown_glazed_terracotta",
+ "minecraft:brown_terracotta",
+ "minecraft:brown_wool",
+ "minecraft:cyan_concrete",
+ "minecraft:cyan_concrete_powder",
+ "minecraft:cyan_glazed_terracotta",
+ "minecraft:cyan_terracotta",
+ "minecraft:cyan_wool",
+ "minecraft:gray_concrete",
+ "minecraft:gray_concrete_powder",
+ "minecraft:gray_glazed_terracotta",
+ "minecraft:gray_terracotta",
+ "minecraft:gray_wool",
+ "minecraft:green_concrete",
+ "minecraft:green_concrete_powder",
+ "minecraft:green_glazed_terracotta",
+ "minecraft:green_terracotta",
+ "minecraft:green_wool",
+ "minecraft:light_blue_concrete",
+ "minecraft:light_blue_concrete_powder",
+ "minecraft:light_blue_glazed_terracotta",
+ "minecraft:light_blue_terracotta",
+ "minecraft:light_blue_wool",
+ "minecraft:light_gray_concrete",
+ "minecraft:light_gray_concrete_powder",
+ "minecraft:light_gray_glazed_terracotta",
+ "minecraft:light_gray_terracotta",
+ "minecraft:light_gray_wool",
+ "minecraft:lime_concrete",
+ "minecraft:lime_concrete_powder",
+ "minecraft:lime_glazed_terracotta",
+ "minecraft:lime_terracotta",
+ "minecraft:lime_wool",
+ "minecraft:magenta_concrete",
+ "minecraft:magenta_concrete_powder",
+ "minecraft:magenta_glazed_terracotta",
+ "minecraft:magenta_terracotta",
+ "minecraft:magenta_wool",
+ "minecraft:orange_concrete",
+ "minecraft:orange_concrete_powder",
+ "minecraft:orange_glazed_terracotta",
+ "minecraft:orange_terracotta",
+ "minecraft:orange_wool",
+ "minecraft:pink_concrete",
+ "minecraft:pink_concrete_powder",
+ "minecraft:pink_glazed_terracotta",
+ "minecraft:pink_terracotta",
+ "minecraft:pink_wool",
+ "minecraft:purple_concrete",
+ "minecraft:purple_concrete_powder",
+ "minecraft:purple_glazed_terracotta",
+ "minecraft:purple_terracotta",
+ "minecraft:purple_wool",
+ "minecraft:red_concrete",
+ "minecraft:red_concrete_powder",
+ "minecraft:red_glazed_terracotta",
+ "minecraft:red_terracotta",
+ "minecraft:red_wool",
+ "minecraft:white_concrete",
+ "minecraft:white_concrete_powder",
+ "minecraft:white_glazed_terracotta",
+ "minecraft:white_terracotta",
+ "minecraft:white_wool",
+ "minecraft:yellow_concrete",
+ "minecraft:yellow_concrete_powder",
+ "minecraft:yellow_glazed_terracotta",
+ "minecraft:yellow_terracotta",
+ "minecraft:yellow_wool"
+ ]
+}
\ No newline at end of file
diff --git a/res/samples/editor.png b/res/samples/editor.png
new file mode 100644
index 00000000..cfaab9c8
Binary files /dev/null and b/res/samples/editor.png differ
diff --git a/res/samples/noodles.png b/res/samples/noodles.png
new file mode 100644
index 00000000..4ccd02c7
Binary files /dev/null and b/res/samples/noodles.png differ
diff --git a/res/shaders/voxel_fragment.fs b/res/shaders/voxel_fragment.fs
index a69ab32d..a0e48fce 100644
--- a/res/shaders/voxel_fragment.fs
+++ b/res/shaders/voxel_fragment.fs
@@ -1,5 +1,8 @@
precision mediump float;
+uniform bool u_ambientOcclusion;
+uniform float u_globalAlpha;
+
varying float v_lighting;
varying vec4 v_occlusion;
varying vec2 v_texcoord;
@@ -85,11 +88,15 @@ void main() {
float u = v_texcoord.x;
float v = v_texcoord.y;
- float a = v_occlusion.x;
- float b = v_occlusion.y;
- float c = v_occlusion.z;
- float d = v_occlusion.w;
- float g = v*(u*b + (1.0-u)*d) + (1.0-v)*(u*a + (1.0-u)*c);
+ float g = 1.0;
+ if (u_ambientOcclusion)
+ {
+ float a = v_occlusion.x;
+ float b = v_occlusion.y;
+ float c = v_occlusion.z;
+ float d = v_occlusion.w;
+ g = v*(u*b + (1.0-u)*d) + (1.0-v)*(u*a + (1.0-u)*c);
+ }
float alpha = dither8x8(gl_FragCoord.xy, v_colour.a);
if (alpha < 0.5)
diff --git a/res/shaders/voxel_vertex.vs b/res/shaders/voxel_vertex.vs
index 8096f256..3bc78b58 100644
--- a/res/shaders/voxel_vertex.vs
+++ b/res/shaders/voxel_vertex.vs
@@ -3,6 +3,7 @@ precision mediump float;
uniform mat4 u_worldViewProjection;
uniform float u_voxelSize;
uniform vec3 u_gridOffset;
+uniform bool u_ambientOcclusion;
attribute vec3 position;
attribute vec3 normal;
diff --git a/res/static/magnet.svg b/res/static/magnet.svg
new file mode 100644
index 00000000..5d1abd72
--- /dev/null
+++ b/res/static/magnet.svg
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/static/orthographic.svg b/res/static/orthographic.svg
new file mode 100644
index 00000000..71cc3eb6
--- /dev/null
+++ b/res/static/orthographic.svg
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/res/static/perspective.svg b/res/static/perspective.svg
new file mode 100644
index 00000000..15c45091
--- /dev/null
+++ b/res/static/perspective.svg
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/src/app_context.ts b/src/app_context.ts
index ef2944aa..ff0ce291 100644
--- a/src/app_context.ts
+++ b/src/app_context.ts
@@ -1,232 +1,441 @@
-import { UI } from './ui/layout';
-import { Renderer } from './renderer';
-import { Mesh } from './mesh';
-import { ObjImporter } from './importers/obj_importer';
-import { ASSERT, ColourSpace, AppError, LOG, LOG_ERROR, TIME_START, TIME_END } from './util';
-
-import { remote } from 'electron';
-import { VoxelMesh } from './voxel_mesh';
-import { BlockMesh, BlockMeshParams, FallableBehaviour } from './block_mesh';
-import { TextureFiltering } from './texture';
-import { IVoxeliser } from './voxelisers/base-voxeliser';
-import { StatusHandler } from './status';
-import { UIMessageBuilder } from './ui/misc';
-import { OutputStyle } from './ui/elements/output';
-import { IExporter } from './exporters/base_exporter';
-import { TVoxelisers, VoxeliseParams, VoxeliserFactory } from './voxelisers/voxelisers';
-import { ExporterFactory, TExporters } from './exporters/exporters';
-
-/* eslint-disable */
-export enum EAction {
- Import = 0,
- Simplify = 1,
- Voxelise = 2,
- Assign = 3,
- Export = 4,
- MAX = 5,
-}
-/* eslint-enable */
-
-export class AppContext {
- private _loadedMesh?: Mesh;
- private _loadedVoxelMesh?: VoxelMesh;
- private _loadedBlockMesh?: BlockMesh;
- private _ui: UI;
-
- private _actionMap = new Map void;
- onFailure?: () => void
- }>();
-
- public constructor() {
- const gl = (document.getElementById('canvas')).getContext('webgl');
- if (!gl) {
- throw Error('Could not load WebGL context');
- }
-
- this._actionMap = new Map([
- [
- EAction.Import, {
- action: () => { return this._import(); },
- onFailure: () => { this._loadedMesh = undefined; },
- },
- ],
- [
- EAction.Simplify, {
- action: () => { return this._simplify(); },
- },
- ],
- [
- EAction.Voxelise, {
- action: () => { return this._voxelise(); },
- onFailure: () => { this._loadedVoxelMesh = undefined; },
- },
- ],
- [
- EAction.Assign, {
- action: () => { return this._assign(); },
- onFailure: () => { this._loadedBlockMesh = undefined; },
- },
- ],
- [
- EAction.Export, {
- action: () => { return this._export(); },
- },
- ],
- ]);
-
- this._ui = new UI(this);
- this._ui.build();
- this._ui.registerEvents();
-
- this._ui.disable(EAction.Simplify);
-
- Renderer.Get.toggleIsGridEnabled();
- Renderer.Get.toggleIsAxesEnabled();
- }
-
- public do(action: EAction) {
- LOG(`Doing ${action}`);
- const groupName = this._ui.uiOrder[action];
- this._ui.disable(action + 1);
- this._ui.cacheValues(action);
- StatusHandler.Get.clear();
-
- const delegate = this._actionMap.get(action)!;
- try {
- delegate.action();
- } catch (error: any) {
- // On failure...
- LOG_ERROR(error);
- const message = new UIMessageBuilder();
- if (error instanceof AppError) {
- message.addHeading(StatusHandler.Get.getDefaultFailureMessage(action));
- message.add(error.message);
- } else {
- message.addBold(StatusHandler.Get.getDefaultFailureMessage(action));
- }
- this._ui.layoutDull[groupName].output.setMessage(message, 'error');
- delegate.onFailure?.();
- return;
- }
-
- // On success...
- const message = new UIMessageBuilder();
- if (StatusHandler.Get.hasStatusMessages('info')) {
- message.addHeading(StatusHandler.Get.getDefaultSuccessMessage(action));
- message.add(...StatusHandler.Get.getStatusMessages('info'));
- } else {
- message.addBold(StatusHandler.Get.getDefaultSuccessMessage(action));
- }
-
- let returnStyle: OutputStyle = 'success';
- if (StatusHandler.Get.hasStatusMessages('warning')) {
- message.addHeading('There were some warnings');
- message.add(...StatusHandler.Get.getStatusMessages('warning'));
- returnStyle = 'warning';
- }
-
- this._ui.layoutDull[groupName].output.setMessage(message, returnStyle);
-
- this._ui.enable(action + 1);
- LOG(`Finished ${action}`);
- }
-
- private _import() {
- const uiElements = this._ui.layout.import.elements;
- const filePath = uiElements.input.getCachedValue();
-
- TIME_START('Load Mesh');
- {
- const importer = new ObjImporter();
- importer.parseFile(filePath);
- this._loadedMesh = importer.toMesh();
- this._loadedMesh.processMesh();
- }
- TIME_END('Load Mesh');
-
- TIME_START('Render Mesh');
- {
- Renderer.Get.useMesh(this._loadedMesh);
- }
- TIME_END('Render Mesh');
- }
-
- private _simplify() {
- ASSERT(false);
- }
-
- private _voxelise() {
- ASSERT(this._loadedMesh);
-
- const uiElements = this._ui.layout.build.elements;
- const voxeliseParams: VoxeliseParams = {
- desiredHeight: uiElements.height.getDisplayValue(),
- useMultisampleColouring: uiElements.multisampleColouring.getCachedValue() === 'on',
- textureFiltering: uiElements.textureFiltering.getCachedValue() === 'linear' ? TextureFiltering.Linear : TextureFiltering.Nearest,
- enableAmbientOcclusion: uiElements.ambientOcclusion.getCachedValue() === 'on',
- voxelOverlapRule: uiElements.voxelOverlapRule.getCachedValue(),
- calculateNeighbours: uiElements.ambientOcclusion.getCachedValue() === 'on',
- };
-
- const voxeliserID: TVoxelisers = uiElements.voxeliser.getCachedValue();
- const voxeliser: IVoxeliser = VoxeliserFactory.GetVoxeliser(voxeliserID);
-
- TIME_START('Voxelising');
- {
- this._loadedVoxelMesh = voxeliser.voxelise(this._loadedMesh, voxeliseParams);
- }
- TIME_END('Voxelising');
- TIME_START('Render Voxel Mesh');
- {
- const voxelSize = 8.0 / voxeliseParams.desiredHeight;
- Renderer.Get.useVoxelMesh(this._loadedVoxelMesh, voxelSize, voxeliseParams.enableAmbientOcclusion);
- }
- TIME_END('Render Voxel Mesh');
- }
-
- private _assign() {
- ASSERT(this._loadedVoxelMesh);
-
- const uiElements = this._ui.layout.assign.elements;
- const blockMeshParams: BlockMeshParams = {
- textureAtlas: uiElements.textureAtlas.getCachedValue(),
- blockPalette: uiElements.blockPalette.getCachedValue(),
- blockAssigner: uiElements.dithering.getCachedValue(),
- colourSpace: uiElements.colourSpace.getCachedValue() === 'rgb' ? ColourSpace.RGB : ColourSpace.LAB,
- fallable: uiElements.fallable.getCachedValue() as FallableBehaviour,
- };
-
- this._loadedBlockMesh = BlockMesh.createFromVoxelMesh(this._loadedVoxelMesh, blockMeshParams);
- Renderer.Get.useBlockMesh(this._loadedBlockMesh);
- }
-
- private _export() {
- const exporterID: TExporters = this._ui.layout.export.elements.export.getCachedValue();
- const exporter: IExporter = ExporterFactory.GetExporter(exporterID);
-
- let filePath = remote.dialog.showSaveDialogSync({
- title: 'Save structure',
- buttonLabel: 'Save',
- filters: [exporter.getFormatFilter()],
- });
-
- ASSERT(this._loadedBlockMesh);
- if (filePath) {
- const fileExtension = '.' + exporter.getFileExtension();
- if (!filePath.endsWith(fileExtension)) {
- filePath += fileExtension;
- }
- exporter.export(this._loadedBlockMesh, filePath);
- }
- }
-
- public draw() {
- Renderer.Get.update();
- Renderer.Get.draw();
- }
-
- public getLoadedMesh() {
- return this._loadedMesh;
- }
-}
+import { remote } from 'electron';
+import path from 'path';
+
+import { FallableBehaviour } from './block_mesh';
+import { ArcballCamera } from './camera';
+import { AppConfig } from './config';
+import { EAppEvent, EventManager } from './event';
+import { IExporter } from './exporters/base_exporter';
+import { ExporterFactory, TExporters } from './exporters/exporters';
+import { Renderer } from './renderer';
+import { StatusHandler, StatusMessage } from './status';
+import { TextureFiltering } from './texture';
+import { OutputStyle } from './ui/elements/output';
+import { UI } from './ui/layout';
+import { UIMessageBuilder } from './ui/misc';
+import { ColourSpace, EAction } from './util';
+import { ASSERT } from './util/error_util';
+import { LOG_ERROR, Logger } from './util/log_util';
+import { TWorkerJob, WorkerController } from './worker_controller';
+import { TFromWorkerMessage, TToWorkerMessage } from './worker_types';
+
+export class AppContext {
+ private _ui: UI;
+ private _workerController: WorkerController;
+ private _lastAction?: EAction;
+
+ public constructor() {
+ Logger.Get.enableLogToFile();
+ Logger.Get.initLogFile('client');
+ Logger.Get.enableLOG();
+ Logger.Get.enableLOGMAJOR();
+ Logger.Get.enableLOGWARN();
+
+ AppConfig.Get.dumpConfig();
+
+ const gl = (document.getElementById('canvas')).getContext('webgl');
+ if (!gl) {
+ throw Error('Could not load WebGL context');
+ }
+
+ this._ui = new UI(this);
+ this._ui.build();
+ this._ui.registerEvents();
+ this._ui.disable(EAction.Voxelise);
+
+ this._workerController = new WorkerController(path.resolve(__dirname, 'worker_interface.js'));
+ this._workerController.addJob({ id: 'init', payload: { action: 'Init', params: {} } });
+
+ Renderer.Get.toggleIsAxesEnabled();
+ ArcballCamera.Get.setCameraMode('perspective');
+ ArcballCamera.Get.toggleAngleSnap();
+
+ EventManager.Get.add(EAppEvent.onTaskStart, (...data) => {
+ if (this._lastAction) {
+ this._ui.getActionButton(this._lastAction)
+ .startLoading()
+ .setProgress(0.0);
+ }
+ });
+
+ EventManager.Get.add(EAppEvent.onTaskProgress, (...data) => {
+ if (this._lastAction) {
+ this._ui.getActionButton(this._lastAction)
+ .setProgress(data[0][1]);
+ }
+ });
+
+ EventManager.Get.add(EAppEvent.onTaskEnd, (...data) => {
+ if (this._lastAction) {
+ this._ui.getActionButton(this._lastAction)
+ .stopLoading()
+ .setProgress(0.0);
+ }
+ });
+ }
+
+ public do(action: EAction) {
+ this._ui.cacheValues(action);
+ this._ui.disable(action);
+ this._ui.disableAll();
+
+ const workerJob = this._getWorkerJob(action);
+ if (workerJob === undefined) {
+ this._ui.enableTo(action);
+ return;
+ }
+
+ const uiOutput = this._ui.getActionOutput(action);
+
+ const jobCallback = (payload: TFromWorkerMessage) => {
+ //this._ui.enableTo(action);
+ switch (payload.action) {
+ case 'KnownError':
+ case 'UnknownError': {
+ uiOutput.setTaskComplete(
+ 'action',
+ StatusHandler.Get.getDefaultFailureMessage(action),
+ [payload.action === 'KnownError' ? payload.error.message : 'Something unexpectedly went wrong'],
+ 'error',
+ );
+ LOG_ERROR(payload.error);
+
+ this._ui.getActionButton(action)
+ .stopLoading()
+ .setProgress(0.0);
+
+ this._ui.enableTo(action);
+ break;
+ }
+ default: {
+ //this._ui.enableTo(action + 1);
+
+ ASSERT(payload.action !== 'Progress');
+ const { builder, style } = this._getActionMessageBuilder(action, payload.statusMessages);
+ uiOutput.setMessage(builder, style as OutputStyle);
+
+ if (workerJob.callback) {
+ workerJob.callback(payload);
+ }
+ }
+ }
+ };
+
+ this._lastAction = action;
+
+ this._workerController.addJob({
+ id: workerJob.id,
+ payload: workerJob.payload,
+ callback: jobCallback,
+ });
+ }
+
+ private _getActionMessageBuilder(action: EAction, statusMessages: StatusMessage[]) {
+ const infoStatuses = statusMessages
+ .filter((x) => x.status === 'info')
+ .map((x) => x.message);
+ const hasInfos = infoStatuses.length > 0;
+
+ const warningStatuses = statusMessages
+ .filter((x) => x.status === 'warning')
+ .map((x) => x.message);
+ const hasWarnings = warningStatuses.length > 0;
+
+ const builder = new UIMessageBuilder();
+ builder.addBold('action', [StatusHandler.Get.getDefaultSuccessMessage(action) + (hasInfos ? ':' : '')], 'success');
+
+ builder.addItem('action', infoStatuses, 'success');
+ builder.addItem('action', warningStatuses, 'warning');
+
+ return { builder: builder, style: hasWarnings ? 'warning' : 'success' };
+ }
+
+ private _getWorkerJob(action: EAction): (TWorkerJob | undefined) {
+ switch (action) {
+ case EAction.Import:
+ return this._import();
+ case EAction.Voxelise:
+ return this._voxelise();
+ case EAction.Assign:
+ return this._assign();
+ case EAction.Export:
+ return this._export();
+ }
+ ASSERT(false);
+ }
+
+ private _import(): TWorkerJob {
+ const uiElements = this._ui.layout.import.elements;
+
+ this._ui.getActionOutput(EAction.Import)
+ .setTaskInProgress('action', '[Importer]: Loading...');
+
+ const payload: TToWorkerMessage = {
+ action: 'Import',
+ params: {
+ filepath: uiElements.input.getCachedValue(),
+ },
+ };
+
+ const callback = (payload: TFromWorkerMessage) => {
+ // This callback is managed through `AppContext::do`, therefore
+ // this callback is only called if the job is successful.
+ ASSERT(payload.action === 'Import');
+ const outputElement = this._ui.getActionOutput(EAction.Import);
+
+ if (payload.result.triangleCount < AppConfig.Get.RENDER_TRIANGLE_THRESHOLD) {
+ outputElement.setTaskInProgress('render', '[Renderer]: Processing...');
+ this._workerController.addJob(this._renderMesh());
+ } else {
+ const message = `Will not render mesh as its over ${AppConfig.Get.RENDER_TRIANGLE_THRESHOLD.toLocaleString()} triangles.`;
+ outputElement.setTaskComplete('render', '[Renderer]: Stopped', [message], 'warning');
+ }
+ };
+
+ return { id: 'Import', payload: payload, callback: callback };
+ }
+
+ private _renderMesh(): TWorkerJob {
+ const payload: TToWorkerMessage = {
+ action: 'RenderMesh',
+ params: {},
+ };
+
+ const callback = (payload: TFromWorkerMessage) => {
+ // This callback is not managed through `AppContext::do`, therefore
+ // we need to check the payload is not an error
+ this._ui.enableTo(EAction.Voxelise);
+
+ switch (payload.action) {
+ case 'KnownError':
+ case 'UnknownError': {
+ this._ui.getActionOutput(EAction.Import).setTaskComplete(
+ 'render',
+ '[Renderer]: Failed',
+ [payload.action === 'KnownError' ? payload.error.message : 'Something unexpectedly went wrong'],
+ 'error',
+ );
+ LOG_ERROR(payload.error);
+ break;
+ }
+ default: {
+ ASSERT(payload.action === 'RenderMesh');
+ Renderer.Get.useMesh(payload.result);
+
+ this._ui.getActionOutput(EAction.Import).setTaskComplete(
+ 'render',
+ '[Renderer]: Succeeded',
+ [],
+ 'success',
+ );
+ }
+ }
+ };
+
+ return { id: 'RenderMesh', payload: payload, callback: callback };
+ }
+
+ private _voxelise(): TWorkerJob {
+ const uiElements = this._ui.layout.voxelise.elements;
+
+ this._ui.getActionOutput(EAction.Voxelise)
+ .setTaskInProgress('action', '[Voxel Mesh]: Loading...');
+
+ const payload: TToWorkerMessage = {
+ action: 'Voxelise',
+ params: {
+ voxeliser: uiElements.voxeliser.getCachedValue(),
+ desiredHeight: uiElements.desiredHeight.getCachedValue(),
+ useMultisampleColouring: uiElements.multisampleColouring.getCachedValue() === 'on',
+ textureFiltering: uiElements.textureFiltering.getCachedValue() === 'linear' ? TextureFiltering.Linear : TextureFiltering.Nearest,
+ enableAmbientOcclusion: uiElements.ambientOcclusion.getCachedValue() === 'on',
+ voxelOverlapRule: uiElements.voxelOverlapRule.getCachedValue(),
+ },
+ };
+
+ const callback = (payload: TFromWorkerMessage) => {
+ // This callback is managed through `AppContext::do`, therefore
+ // this callback is only called if the job is successful.
+ ASSERT(payload.action === 'Voxelise');
+ const outputElement = this._ui.getActionOutput(EAction.Voxelise);
+
+ outputElement.setTaskInProgress('render', '[Renderer]: Processing...');
+ this._workerController.addJob(this._renderVoxelMesh());
+ };
+
+ return { id: 'Voxelise', payload: payload, callback: callback };
+ }
+
+ private _renderVoxelMesh(): TWorkerJob {
+ const uiElements = this._ui.layout.voxelise.elements;
+
+ const payload: TToWorkerMessage = {
+ action: 'RenderNextVoxelMeshChunk',
+ params: {
+ enableAmbientOcclusion: uiElements.ambientOcclusion.getCachedValue() === 'on',
+ desiredHeight: uiElements.desiredHeight.getCachedValue(),
+ },
+ };
+
+ const callback = (payload: TFromWorkerMessage) => {
+ // This callback is not managed through `AppContext::do`, therefore
+ // we need to check the payload is not an error
+
+ switch (payload.action) {
+ case 'KnownError':
+ case 'UnknownError': {
+ this._ui.getActionOutput(EAction.Voxelise).setTaskComplete(
+ 'render',
+ '[Renderer]: Failed',
+ [payload.action === 'KnownError' ? payload.error.message : 'Something unexpectedly went wrong'],
+ 'error',
+ );
+ LOG_ERROR(payload.error);
+
+ this._ui.enableTo(EAction.Assign);
+ break;
+ }
+ default: {
+ ASSERT(payload.action === 'RenderNextVoxelMeshChunk');
+ Renderer.Get.useVoxelMeshChunk(payload.result);
+
+ if (payload.result.moreVoxelsToBuffer) {
+ this._workerController.addJob(this._renderVoxelMesh());
+ } else {
+ this._ui.getActionOutput(EAction.Voxelise).setTaskComplete(
+ 'render',
+ '[Renderer]: Succeeded',
+ [],
+ 'success',
+ );
+ this._ui.enableTo(EAction.Assign);
+ }
+ }
+ }
+ };
+
+ return { id: 'RenderNextVoxelMeshChunk', payload: payload, callback: callback };
+ }
+
+ private _assign(): TWorkerJob {
+ const uiElements = this._ui.layout.assign.elements;
+
+ this._ui.getActionOutput(EAction.Assign)
+ .setTaskInProgress('action', '[Block Mesh]: Loading...');
+
+ const payload: TToWorkerMessage = {
+ action: 'Assign',
+ params: {
+ textureAtlas: uiElements.textureAtlas.getCachedValue(),
+ blockPalette: uiElements.blockPalette.getCachedValue(),
+ blockAssigner: uiElements.dithering.getCachedValue(),
+ colourSpace: ColourSpace.RGB,
+ fallable: uiElements.fallable.getCachedValue() as FallableBehaviour,
+ resolution: Math.pow(2, uiElements.colourAccuracy.getCachedValue()),
+ },
+ };
+
+ const callback = (payload: TFromWorkerMessage) => {
+ // This callback is managed through `AppContext::do`, therefore
+ // this callback is only called if the job is successful.
+ ASSERT(payload.action === 'Assign');
+
+ const outputElement = this._ui.getActionOutput(EAction.Assign);
+
+ outputElement.setTaskInProgress('render', '[Renderer]: Processing...');
+ this._workerController.addJob(this._renderBlockMesh());
+ };
+
+ return { id: 'Assign', payload: payload, callback: callback };
+ }
+
+ private _renderBlockMesh(): TWorkerJob {
+ const uiElements = this._ui.layout.assign.elements;
+
+ const payload: TToWorkerMessage = {
+ action: 'RenderNextBlockMeshChunk',
+ params: {
+ textureAtlas: uiElements.textureAtlas.getCachedValue(),
+ },
+ };
+
+ const callback = (payload: TFromWorkerMessage) => {
+ // This callback is not managed through `AppContext::do`, therefore
+ // we need to check the payload is not an error
+
+ switch (payload.action) {
+ case 'KnownError':
+ case 'UnknownError': {
+ this._ui.getActionOutput(EAction.Assign).setTaskComplete(
+ 'render',
+ '[Renderer]: Failed',
+ [payload.action === 'KnownError' ? payload.error.message : 'Something unexpectedly went wrong'],
+ 'error',
+ );
+ LOG_ERROR(payload.error);
+
+ this._ui.enableTo(EAction.Export);
+ break;
+ }
+ default: {
+ ASSERT(payload.action === 'RenderNextBlockMeshChunk');
+ Renderer.Get.useBlockMeshChunk(payload.result);
+
+ if (payload.result.moreBlocksToBuffer) {
+ this._workerController.addJob(this._renderBlockMesh());
+ } else {
+ this._ui.getActionOutput(EAction.Assign).setTaskComplete(
+ 'render',
+ '[Renderer]: Succeeded',
+ [],
+ 'success',
+ );
+ this._ui.enableTo(EAction.Export);
+ }
+ }
+ }
+ };
+
+ return { id: 'RenderNextBlockMeshChunk', payload: payload, callback: callback };
+ }
+
+ private _export(): (TWorkerJob | undefined) {
+ const exporterID: TExporters = this._ui.layout.export.elements.export.getCachedValue();
+ const exporter: IExporter = ExporterFactory.GetExporter(exporterID);
+
+ const filepath = remote.dialog.showSaveDialogSync({
+ title: 'Save structure',
+ buttonLabel: 'Save',
+ filters: [exporter.getFormatFilter()],
+ });
+
+ if (filepath === undefined) {
+ return undefined;
+ }
+
+ this._ui.getActionOutput(EAction.Export)
+ .setTaskInProgress('action', '[Exporter]: Saving...');
+
+ const payload: TToWorkerMessage = {
+ action: 'Export',
+ params: {
+ filepath: filepath,
+ exporter: exporterID,
+ },
+ };
+
+ const callback = (payload: TFromWorkerMessage) => {
+ // This callback is managed through `AppContext::do`, therefore
+ // this callback is only called if the job is successful.
+ this._ui.enableTo(EAction.Export);
+ };
+
+ return { id: 'Export', payload: payload, callback: callback };
+ }
+
+ public draw() {
+ Renderer.Get.update();
+ this._ui.tick();
+ Renderer.Get.draw();
+ }
+}
diff --git a/src/assigners/assigners.ts b/src/assigners/assigners.ts
new file mode 100644
index 00000000..845b905b
--- /dev/null
+++ b/src/assigners/assigners.ts
@@ -0,0 +1,19 @@
+import { IBlockAssigner } from './base_assigner';
+import { BasicBlockAssigner } from './basic_assigner';
+import { OrderedDitheringBlockAssigner } from './ordered_dithering_assigner';
+import { RandomDitheringBlockAssigner } from './random_dithering_assigner';
+
+export type TBlockAssigners = 'basic' | 'ordered-dithering' | 'random-dithering';
+
+export class BlockAssignerFactory {
+ public static GetAssigner(blockAssigner: TBlockAssigners): IBlockAssigner {
+ switch (blockAssigner) {
+ case 'basic':
+ return new BasicBlockAssigner();
+ case 'ordered-dithering':
+ return new OrderedDitheringBlockAssigner();
+ case 'random-dithering':
+ return new RandomDitheringBlockAssigner();
+ }
+ }
+}
diff --git a/src/assigners/base_assigner.ts b/src/assigners/base_assigner.ts
new file mode 100644
index 00000000..3ca6cede
--- /dev/null
+++ b/src/assigners/base_assigner.ts
@@ -0,0 +1,9 @@
+import { AtlasPalette, TBlockCollection } from '../block_assigner';
+import { BlockInfo } from '../block_atlas';
+import { RGBA, RGBAUtil } from '../colour';
+import { ColourSpace } from '../util';
+import { Vector3 } from '../vector';
+
+export interface IBlockAssigner {
+ assignBlock(atlasPalette: AtlasPalette, voxelColour: RGBA, voxelPosition: Vector3, resolution: RGBAUtil.TColourAccuracy, colourSpace: ColourSpace, blockCollection: TBlockCollection): BlockInfo;
+}
diff --git a/src/assigners/basic_assigner.ts b/src/assigners/basic_assigner.ts
new file mode 100644
index 00000000..82b9203a
--- /dev/null
+++ b/src/assigners/basic_assigner.ts
@@ -0,0 +1,12 @@
+import { AtlasPalette, TBlockCollection } from '../block_assigner';
+import { BlockInfo } from '../block_atlas';
+import { RGBA, RGBAUtil } from '../colour';
+import { ColourSpace } from '../util';
+import { Vector3 } from '../vector';
+import { IBlockAssigner } from './base_assigner';
+
+export class BasicBlockAssigner implements IBlockAssigner {
+ assignBlock(atlasPalette: AtlasPalette, voxelColour: RGBA, voxelPosition: Vector3, resolution: RGBAUtil.TColourAccuracy, colourSpace: ColourSpace, blockCollection: TBlockCollection): BlockInfo {
+ return atlasPalette.getBlock(voxelColour, blockCollection, resolution);
+ }
+}
diff --git a/src/assigners/ordered_dithering_assigner.ts b/src/assigners/ordered_dithering_assigner.ts
new file mode 100644
index 00000000..51f7b0f7
--- /dev/null
+++ b/src/assigners/ordered_dithering_assigner.ts
@@ -0,0 +1,50 @@
+import { AtlasPalette, TBlockCollection } from '../block_assigner';
+import { BlockInfo } from '../block_atlas';
+import { RGBA, RGBAUtil } from '../colour';
+import { ColourSpace } from '../util';
+import { ASSERT } from '../util/error_util';
+import { Vector3 } from '../vector';
+import { IBlockAssigner } from './base_assigner';
+
+export class OrderedDitheringBlockAssigner implements IBlockAssigner {
+ /** 4x4x4 */
+ private static _size = 4;
+ private static _threshold = 256 / 8;
+
+ private static _mapMatrix = [
+ 0, 16, 2, 18, 48, 32, 50, 34,
+ 6, 22, 4, 20, 54, 38, 52, 36,
+ 24, 40, 26, 42, 8, 56, 10, 58,
+ 30, 46, 28, 44, 14, 62, 12, 60,
+ 3, 19, 5, 21, 51, 35, 53, 37,
+ 1, 17, 7, 23, 49, 33, 55, 39,
+ 27, 43, 29, 45, 11, 59, 13, 61,
+ 25, 41, 31, 47, 9, 57, 15, 63,
+ ];
+
+ private _getThresholdValue(x: number, y: number, z: number) {
+ const size = OrderedDitheringBlockAssigner._size;
+ ASSERT(0 <= x && x < size && 0 <= y && y < size && 0 <= z && z < size);
+ const index = (x + (size * y) + (size * size * z));
+ ASSERT(0 <= index && index < size * size * size);
+ return (OrderedDitheringBlockAssigner._mapMatrix[index] / (size * size * size)) - 0.5;
+ }
+
+ assignBlock(atlasPalette: AtlasPalette, voxelColour: RGBA, voxelPosition: Vector3, resolution: RGBAUtil.TColourAccuracy, colourSpace: ColourSpace, blockCollection: TBlockCollection): BlockInfo {
+ const size = OrderedDitheringBlockAssigner._size;
+ const map = this._getThresholdValue(
+ Math.abs(voxelPosition.x % size),
+ Math.abs(voxelPosition.y % size),
+ Math.abs(voxelPosition.z % size),
+ );
+
+ const newVoxelColour: RGBA = {
+ r: ((255 * voxelColour.r) + map * OrderedDitheringBlockAssigner._threshold) / 255,
+ g: ((255 * voxelColour.g) + map * OrderedDitheringBlockAssigner._threshold) / 255,
+ b: ((255 * voxelColour.b) + map * OrderedDitheringBlockAssigner._threshold) / 255,
+ a: ((255 * voxelColour.a) + map * OrderedDitheringBlockAssigner._threshold) / 255,
+ };
+
+ return atlasPalette.getBlock(newVoxelColour, blockCollection, resolution);
+ }
+}
diff --git a/src/assigners/random_dithering_assigner.ts b/src/assigners/random_dithering_assigner.ts
new file mode 100644
index 00000000..fe8fb19b
--- /dev/null
+++ b/src/assigners/random_dithering_assigner.ts
@@ -0,0 +1,23 @@
+import { AtlasPalette, TBlockCollection } from '../block_assigner';
+import { BlockInfo } from '../block_atlas';
+import { RGBA, RGBAUtil } from '../colour';
+import { ColourSpace } from '../util';
+import { Vector3 } from '../vector';
+import { IBlockAssigner } from './base_assigner';
+
+export class RandomDitheringBlockAssigner implements IBlockAssigner {
+ private static _deviation = 32;
+
+ assignBlock(atlasPalette: AtlasPalette, voxelColour: RGBA, voxelPosition: Vector3, resolution: RGBAUtil.TColourAccuracy, colourSpace: ColourSpace, blockCollection: TBlockCollection): BlockInfo {
+ const map = Math.random() - 0.5;
+
+ const newVoxelColour: RGBA = {
+ r: ((255 * voxelColour.r) + map * RandomDitheringBlockAssigner._deviation) / 255,
+ g: ((255 * voxelColour.g) + map * RandomDitheringBlockAssigner._deviation) / 255,
+ b: ((255 * voxelColour.b) + map * RandomDitheringBlockAssigner._deviation) / 255,
+ a: ((255 * voxelColour.a) + map * RandomDitheringBlockAssigner._deviation) / 255,
+ };
+
+ return atlasPalette.getBlock(newVoxelColour, blockCollection, resolution);
+ }
+}
diff --git a/src/atlas.ts b/src/atlas.ts
new file mode 100644
index 00000000..b2d30fb3
--- /dev/null
+++ b/src/atlas.ts
@@ -0,0 +1,114 @@
+import fs from 'fs';
+import path from 'path';
+
+import { RGBA } from './colour';
+import { AppTypes, AppUtil, TOptional, UV } from './util';
+import { ASSERT } from './util/error_util';
+import { LOG } from './util/log_util';
+import { AppPaths } from './util/path_util';
+
+export type TAtlasBlockFace = {
+ name: string;
+ texcoord: UV;
+}
+
+export type TAtlasBlock = {
+ name: string;
+ colour: RGBA;
+ faces: {
+ up: TAtlasBlockFace,
+ down: TAtlasBlockFace,
+ north: TAtlasBlockFace,
+ east: TAtlasBlockFace,
+ south: TAtlasBlockFace,
+ west: TAtlasBlockFace,
+ };
+}
+
+/**
+ * Atlases, unlike palettes, are not currently designed to be user-facing or
+ * programmatically created. This class simply facilitates loading .atlas
+ * files.
+ */
+export class Atlas {
+ public static ATLAS_NAME_REGEX: RegExp = /^[a-zA-Z\-]+$/;
+ private static _FILE_VERSION: number = 1;
+
+ private _blocks: Map;
+ private _atlasSize: number;
+ private _atlasName: string;
+
+ private constructor(atlasName: string) {
+ this._blocks = new Map();
+ this._atlasSize = 0;
+ this._atlasName = atlasName;
+ }
+
+ public getBlocks() {
+ return this._blocks;
+ }
+
+ public static load(atlasName: string): TOptional {
+ if (!Atlas._isValidAtlasName(atlasName)) {
+ return;
+ }
+
+ const atlasPath = Atlas._getAtlasPath(atlasName);
+ LOG(atlasPath);
+ if (!fs.existsSync(atlasPath)) {
+ return;
+ }
+
+ const atlas = new Atlas(atlasName);
+
+ const atlasFile = fs.readFileSync(atlasPath, 'utf8');
+ const atlasJSON = JSON.parse(atlasFile);
+ const atlasVersion = atlasJSON.version;
+
+ if (atlasVersion === undefined || atlasVersion === 1) {
+ const atlasSize = atlasJSON.atlasSize as number;
+ atlas._atlasSize = atlasSize;
+
+ const blocks = atlasJSON.blocks;
+ for (const block of blocks) {
+ const atlasBlock = block as TAtlasBlock;
+ atlasBlock.name = AppUtil.Text.namespaceBlock(atlasBlock.name);
+ atlas._blocks.set(atlasBlock.name, atlasBlock);
+ }
+ } else {
+ ASSERT(false, `Unrecognised .atlas file version: ${atlasVersion}`);
+ }
+
+ return atlas;
+ }
+
+ public getAtlasSize(): number {
+ return this._atlasSize;
+ }
+
+ public getAtlasTexturePath() {
+ return path.join(AppPaths.Get.atlases, `./${this._atlasName}.png`);
+ }
+
+ /*
+ public getBlocks(): TAtlasBlock[] {
+ return Array.from(this._blocks.values());
+ }
+ */
+
+ public hasBlock(blockName: AppTypes.TNamespacedBlockName): boolean {
+ return this._blocks.has(blockName);
+ }
+
+ public static getVanillaAtlas(): TOptional {
+ return Atlas.load('vanilla');
+ }
+
+ private static _isValidAtlasName(atlasName: string): boolean {
+ return atlasName.length > 0 && Atlas.ATLAS_NAME_REGEX.test(atlasName);
+ }
+
+ private static _getAtlasPath(atlasName: string): string {
+ return path.join(AppPaths.Get.atlases, `./${atlasName}.atlas`);
+ }
+}
diff --git a/src/block_assigner.ts b/src/block_assigner.ts
index 27da90fa..d868f286 100644
--- a/src/block_assigner.ts
+++ b/src/block_assigner.ts
@@ -1,122 +1,94 @@
-import { BlockAtlas, BlockInfo } from './block_atlas';
-import { RGBA } from './colour';
-import { ASSERT, ColourSpace } from './util';
-import { Vector3 } from './vector';
-
-export type TBlockAssigners = 'basic' | 'ordered-dithering' | 'random-dithering';
-
-export class BlockAssignerFactory {
- public static GetAssigner(blockAssigner: TBlockAssigners): IBlockAssigner {
- switch (blockAssigner) {
- case 'basic':
- return new BasicBlockAssigner();
- case 'ordered-dithering':
- return new OrderedDitheringBlockAssigner();
- case 'random-dithering':
- return new RandomDitheringBlockAssigner();
- default:
- ASSERT(false, 'Unreachable');
- }
- }
-}
-
-interface IBlockAssigner {
- assignBlock(voxelColour: RGBA, voxelPosition: Vector3, colourSpace: ColourSpace, exclude?: string[]): BlockInfo;
-}
-
-export class BasicBlockAssigner implements IBlockAssigner {
- assignBlock(voxelColour: RGBA, voxelPosition: Vector3, colourSpace: ColourSpace, exclude?: string[]): BlockInfo {
- return BlockAtlas.Get.getBlock(voxelColour, colourSpace, exclude);
- }
-}
-
-export class OrderedDitheringBlockAssigner implements IBlockAssigner {
- /** 4x4x4 */
- private static _size = 4;
- private static _threshold = 256 / 8;
-
- private static _mapMatrix = [
- 0, 16, 2, 18, 48, 32, 50, 34,
- 6, 22, 4, 20, 54, 38, 52, 36,
- 24, 40, 26, 42, 8, 56, 10, 58,
- 30, 46, 28, 44, 14, 62, 12, 60,
- 3, 19, 5, 21, 51, 35, 53, 37,
- 1, 17, 7, 23, 49, 33, 55, 39,
- 27, 43, 29, 45, 11, 59, 13, 61,
- 25, 41, 31, 47, 9, 57, 15, 63,
- ];
-
- private _getThresholdValue(x: number, y: number, z: number) {
- const size = OrderedDitheringBlockAssigner._size;
- ASSERT(0 <= x && x < size && 0 <= y && y < size && 0 <= z && z < size);
- const index = (x + (size * y) + (size * size * z));
- ASSERT(0 <= index && index < size * size * size);
- return (OrderedDitheringBlockAssigner._mapMatrix[index] / (size * size * size)) - 0.5;
- }
-
- assignBlock(voxelColour: RGBA, voxelPosition: Vector3, colourSpace: ColourSpace, exclude?: string[]): BlockInfo {
- const size = OrderedDitheringBlockAssigner._size;
- const map = this._getThresholdValue(
- Math.abs(voxelPosition.x % size),
- Math.abs(voxelPosition.y % size),
- Math.abs(voxelPosition.z % size),
- );
-
- const newVoxelColour: RGBA = {
- r: ((255 * voxelColour.r) + map * OrderedDitheringBlockAssigner._threshold) / 255,
- g: ((255 * voxelColour.g) + map * OrderedDitheringBlockAssigner._threshold) / 255,
- b: ((255 * voxelColour.b) + map * OrderedDitheringBlockAssigner._threshold) / 255,
- a: ((255 * voxelColour.a) + map * OrderedDitheringBlockAssigner._threshold) / 255,
- };
-
- return BlockAtlas.Get.getBlock(newVoxelColour, colourSpace, exclude);
- }
-}
-
-export class RandomDitheringBlockAssigner implements IBlockAssigner {
- /** 4x4x4 */
- private static _size = 4;
- private static _threshold = 256 / 8;
-
- private _mapMatrix = [
- 0, 16, 2, 18, 48, 32, 50, 34,
- 6, 22, 4, 20, 54, 38, 52, 36,
- 24, 40, 26, 42, 8, 56, 10, 58,
- 30, 46, 28, 44, 14, 62, 12, 60,
- 3, 19, 5, 21, 51, 35, 53, 37,
- 1, 17, 7, 23, 49, 33, 55, 39,
- 27, 43, 29, 45, 11, 59, 13, 61,
- 25, 41, 31, 47, 9, 57, 15, 63,
- ];
-
- private _getThresholdValue(x: number, y: number, z: number) {
- const size = RandomDitheringBlockAssigner._size;
- ASSERT(0 <= x && x < size && 0 <= y && y < size && 0 <= z && z < size);
- const index = (x + (size * y) + (size * size * z));
- ASSERT(0 <= index && index < size * size * size);
- return (this._mapMatrix[index] / (size * size * size)) - 0.5;
- }
-
- assignBlock(voxelColour: RGBA, voxelPosition: Vector3, colourSpace: ColourSpace, exclude?: string[]): BlockInfo {
- this._mapMatrix = this._mapMatrix
- .map((value) => ({ value, sort: Math.random() }))
- .sort((a, b) => a.sort - b.sort)
- .map(({ value }) => value);
-
- const size = RandomDitheringBlockAssigner._size;
- const map = this._getThresholdValue(
- Math.abs(voxelPosition.x % size),
- Math.abs(voxelPosition.y % size),
- Math.abs(voxelPosition.z % size),
- );
-
- const newVoxelColour: RGBA = {
- r: ((255 * voxelColour.r) + map * RandomDitheringBlockAssigner._threshold) / 255,
- g: ((255 * voxelColour.g) + map * RandomDitheringBlockAssigner._threshold) / 255,
- b: ((255 * voxelColour.b) + map * RandomDitheringBlockAssigner._threshold) / 255,
- a: ((255 * voxelColour.a) + map * RandomDitheringBlockAssigner._threshold) / 255,
- };
-
- return BlockAtlas.Get.getBlock(newVoxelColour, colourSpace, exclude);
- }
-}
+import { Atlas, TAtlasBlock } from './atlas';
+import { RGBA, RGBAUtil } from './colour';
+import { Palette } from './palette';
+import { AppTypes, TOptional } from './util';
+import { ASSERT } from './util/error_util';
+
+export type TBlockCollection = {
+ blocks: Map,
+ cache: Map,
+}
+
+/**
+ * A new instance of AtlasPalette is created each time
+ * a new voxel mesh is voxelised.
+ */
+export class AtlasPalette {
+ private _atlas: Atlas;
+ private _palette: Palette;
+
+ public constructor(atlas: Atlas, palette: Palette) {
+ this._atlas = atlas;
+ this._palette = palette;
+
+ this._palette.removeMissingAtlasBlocks(this._atlas);
+ }
+
+ public createBlockCollection(blocksToExclude: AppTypes.TNamespacedBlockName[]): TBlockCollection {
+ const blocksNamesToUse = this._palette.getBlocks();
+ {
+ // Remove excluded blocks
+ for (const blockToExclude of blocksToExclude) {
+ const index = blocksNamesToUse.indexOf(blockToExclude);
+ if (index != -1) {
+ blocksNamesToUse.splice(index, 1);
+ }
+ }
+ }
+
+ const blocksToUse: TBlockCollection = {
+ blocks: new Map(),
+ cache: new Map(),
+ };
+
+ const atlasBlocks = this._atlas.getBlocks();
+ {
+ // Only add block data for blocks in the palette
+ atlasBlocks.forEach((atlasBlock, blockName) => {
+ if (blocksNamesToUse.includes(blockName)) {
+ blocksToUse.blocks.set(blockName, atlasBlock);
+ }
+ });
+ }
+
+ ASSERT(blocksToUse.blocks.size >= 1, 'Must have at least one block cached');
+ return blocksToUse;
+ }
+
+ /**
+ * Convert a colour into a Minecraft block.
+ * @param colour The colour that the returned block should match with.
+ * @param resolution The colour accuracy, a uint8 from 1 to 255, inclusive.
+ * @param blockToExclude A list of blocks that should not be used, this should be a subset of the palette blocks.
+ * @returns
+ */
+ public getBlock(colour: RGBA, blockCollection: TBlockCollection, resolution: RGBAUtil.TColourAccuracy) {
+ const { colourHash, binnedColour } = RGBAUtil.bin(colour, resolution);
+
+ // If we've already calculated the block associated with this colour, return it.
+ const cachedBlock = blockCollection.cache.get(colourHash);
+ if (cachedBlock !== undefined) {
+ return cachedBlock;
+ }
+
+ // Find closest block in colour
+ let minDistance = Infinity;
+ let blockChoice: TOptional;
+ {
+ blockCollection.blocks.forEach((blockData) => {
+ const colourDistance = RGBAUtil.squaredDistance(binnedColour, blockData.colour);
+ if (colourDistance < minDistance) {
+ minDistance = colourDistance;
+ blockChoice = blockData;
+ }
+ });
+ }
+
+ if (blockChoice !== undefined) {
+ blockCollection.cache.set(colourHash, blockChoice);
+ return blockChoice;
+ }
+
+ ASSERT(false, 'Unreachable, always at least one possible block');
+ }
+}
diff --git a/src/block_atlas.ts b/src/block_atlas.ts
index 224f7313..0f0159d4 100644
--- a/src/block_atlas.ts
+++ b/src/block_atlas.ts
@@ -1,164 +1,23 @@
-import { UV, ASSERT, fileExists, ColourSpace, ATLASES_DIR, PALETTES_DIR, AppError, LOG_WARN } from './util';
-
-import fs from 'fs';
-import path from 'path';
-import { StatusHandler } from './status';
-import { RGBA, RGBAUtil } from './colour';
-
-export interface TextureInfo {
- name: string
- texcoord: UV
-}
-
-export interface FaceInfo {
- [face: string]: TextureInfo,
- up: TextureInfo,
- down: TextureInfo,
- north: TextureInfo,
- south: TextureInfo,
- east: TextureInfo,
- west: TextureInfo
-}
-
-export interface BlockInfo {
- name: string;
- colour: RGBA;
- faces: FaceInfo
-}
-
-interface BlockPalette {
- blocks: string[];
-}
-
-/* eslint-enable */
-export class BlockAtlas {
- private _atlasBlocks: Array;
- private _palette: string[];
- private _atlasSize: number;
- private _atlasLoaded: boolean;
- private _paletteLoaded: boolean;
- private _atlasTextureID?: string;
- private _paletteBlockToBlockInfoIndex: Map;
-
- private static _instance: BlockAtlas;
- public static get Get() {
- return this._instance || (this._instance = new this());
- }
-
- private constructor() {
- this._atlasBlocks = [];
- this._atlasSize = 0;
- this._atlasLoaded = false;
- this._palette = [];
- this._paletteLoaded = false;
- this._paletteBlockToBlockInfoIndex = new Map();
- }
-
- public loadAtlas(atlasID: string) {
- const atlasDir = path.join(ATLASES_DIR, atlasID + '.atlas');
- ASSERT(fileExists(atlasDir), `Atlas to load does not exist ${atlasDir}`);
-
- const blocksString = fs.readFileSync(atlasDir, 'utf-8');
- if (!blocksString) {
- throw Error('Could not load vanilla.atlas');
- }
-
- const json = JSON.parse(blocksString);
- this._atlasSize = json.atlasSize;
- this._atlasTextureID = atlasID;
- this._atlasBlocks = json.blocks;
- for (const block of this._atlasBlocks) {
- block.colour = {
- r: block.colour.r,
- g: block.colour.g,
- b: block.colour.b,
- a: block.colour.a,
- };
- }
-
- if (this._atlasBlocks.length === 0) {
- throw new AppError('The chosen atlas has no blocks');
- }
-
- StatusHandler.Get.add('info', `Atlas '${atlasID}' has data for ${this._atlasBlocks.length} blocks`);
-
- this._atlasLoaded = true;
- }
-
- public loadPalette(paletteID: string) {
- ASSERT(this._atlasLoaded, 'An atlas must be loaded before a palette');
-
- const paletteDir = path.join(PALETTES_DIR, paletteID + '.palette');
- ASSERT(fileExists(paletteDir), `Palette to load does not exist ${paletteDir}`);
-
- const palette: BlockPalette = JSON.parse(fs.readFileSync(paletteDir, 'utf8'));
- this._palette = palette.blocks;
- StatusHandler.Get.add('info', `Palette '${paletteID}' has data for ${this._palette.length} blocks`);
-
- // Count the number of palette blocks that are missing from the atlas
- // For example, loading an old atlas with a new palette
- const missingBlocks: string[] = [];
- for (let paletteBlockIndex = palette.blocks.length - 1; paletteBlockIndex >= 0; --paletteBlockIndex) {
- const paletteBlockName = palette.blocks[paletteBlockIndex];
- const atlasBlockIndex = this._atlasBlocks.findIndex((x) => x.name === paletteBlockName);
- if (atlasBlockIndex === -1) {
- missingBlocks.push(paletteBlockName);
- palette.blocks.splice(paletteBlockIndex, 1);
- } else {
- this._paletteBlockToBlockInfoIndex.set(paletteBlockName, atlasBlockIndex);
- }
- }
- if (missingBlocks.length > 0) {
- StatusHandler.Get.add('warning', `${missingBlocks.length} palette block(s) are missing atlas textures, they will not be used`);
- LOG_WARN('Blocks missing atlas textures', missingBlocks);
- }
-
- StatusHandler.Get.add('info', `There are ${this._palette.length} valid blocks to assign from`);
-
- this._paletteLoaded = true;
- }
-
- public getBlock(voxelColour: RGBA, colourSpace: ColourSpace, exclude?: string[]): BlockInfo {
- ASSERT(this._atlasLoaded, 'No atlas has been loaded');
- ASSERT(this._paletteLoaded, 'No palette has been loaded');
-
- let minDistance = Infinity;
- let blockChoiceIndex!: number;
-
- for (const paletteBlockName of this._palette) {
- if (exclude?.includes(paletteBlockName)) {
- continue;
- }
-
- // TODO: Optimise Use hash map for blockIndex instead of linear search
- const blockIndex: (number | undefined) = this._paletteBlockToBlockInfoIndex.get(paletteBlockName);
- ASSERT(blockIndex !== undefined);
-
- const block: BlockInfo = this._atlasBlocks[blockIndex];
- const blockAvgColour = block.colour as RGBA;
- const distance = RGBAUtil.squaredDistance(blockAvgColour, voxelColour);
-
- if (distance < minDistance) {
- minDistance = distance;
- blockChoiceIndex = blockIndex;
- }
- }
-
- if (blockChoiceIndex === undefined) {
- throw new AppError('The chosen palette does not have suitable blocks');
- }
-
- return this._atlasBlocks[blockChoiceIndex];
- }
-
- public getAtlasSize() {
- ASSERT(this._atlasLoaded);
- return this._atlasSize;
- }
-
- public getAtlasTexturePath() {
- ASSERT(this._atlasLoaded, 'No atlas texture available');
- ASSERT(this._atlasTextureID, 'No atlas texture ID available');
- return path.join(ATLASES_DIR, this._atlasTextureID + '.png');
- }
-}
+import { RGBA } from './colour';
+import { UV } from './util';
+
+export interface TextureInfo {
+ name: string
+ texcoord: UV
+}
+
+export interface FaceInfo {
+ [face: string]: TextureInfo,
+ up: TextureInfo,
+ down: TextureInfo,
+ north: TextureInfo,
+ south: TextureInfo,
+ east: TextureInfo,
+ west: TextureInfo
+}
+
+export interface BlockInfo {
+ name: string;
+ colour: RGBA;
+ faces: FaceInfo
+}
diff --git a/src/block_mesh.ts b/src/block_mesh.ts
index 1982219a..49d26164 100644
--- a/src/block_mesh.ts
+++ b/src/block_mesh.ts
@@ -1,169 +1,171 @@
-import { BlockAssignerFactory, TBlockAssigners } from './block_assigner';
-import { Voxel, VoxelMesh } from './voxel_mesh';
-import { BlockAtlas, BlockInfo } from './block_atlas';
-import { ColourSpace, AppError, ASSERT, RESOURCES_DIR } from './util';
-import { Renderer } from './renderer';
-import { AppConstants } from './constants';
-
-import fs from 'fs';
-import path from 'path';
-import { StatusHandler } from './status';
-import { Vector3 } from './vector';
-
-interface Block {
- voxel: Voxel;
- blockInfo: BlockInfo;
-}
-
-export type FallableBehaviour = 'replace-falling' | 'replace-fallable' | 'place-string' | 'do-nothing';
-
-export interface BlockMeshParams {
- textureAtlas: string,
- blockPalette: string,
- blockAssigner: TBlockAssigners,
- colourSpace: ColourSpace,
- fallable: FallableBehaviour,
-}
-
-export class BlockMesh {
- private _blockPalette: string[];
- private _blocks: Block[];
- private _voxelMesh: VoxelMesh;
- private _fallableBlocks: string[];
- private _atlasUsed: string;
-
- public static createFromVoxelMesh(voxelMesh: VoxelMesh, blockMeshParams: BlockMeshParams) {
- const blockMesh = new BlockMesh(voxelMesh);
- blockMesh._assignBlocks(blockMeshParams);
- return blockMesh;
- }
-
- private constructor(voxelMesh: VoxelMesh) {
- this._blockPalette = [];
- this._blocks = [];
- this._voxelMesh = voxelMesh;
- this._atlasUsed = 'Vanilla';
-
- const fallableBlocksString = fs.readFileSync(path.join(RESOURCES_DIR, 'fallable_blocks.json'), 'utf-8');
- this._fallableBlocks = JSON.parse(fallableBlocksString).fallable_blocks;
- }
-
- private _assignBlocks(blockMeshParams: BlockMeshParams) {
- BlockAtlas.Get.loadAtlas(blockMeshParams.textureAtlas);
- BlockAtlas.Get.loadPalette(blockMeshParams.blockPalette);
- this._atlasUsed = blockMeshParams.textureAtlas;
-
- const blockAssigner = BlockAssignerFactory.GetAssigner(blockMeshParams.blockAssigner);
-
- let countFalling = 0;
- const voxels = this._voxelMesh.getVoxels();
- for (let voxelIndex = 0; voxelIndex < voxels.length; ++voxelIndex) {
- const voxel = voxels[voxelIndex];
- let block = blockAssigner.assignBlock(voxel.colour, voxel.position, blockMeshParams.colourSpace);
-
- const isFallable = this._fallableBlocks.includes(block.name);
- const isSupported = this._voxelMesh.isVoxelAt(Vector3.add(voxel.position, new Vector3(0, -1, 0)));
-
- if (isFallable && !isSupported) {
- ++countFalling;
- }
-
- let shouldReplace = (blockMeshParams.fallable === 'replace-fallable' && isFallable);
- shouldReplace ||= (blockMeshParams.fallable === 'replace-falling' && isFallable && !isSupported);
-
- if (shouldReplace) {
- const replacedBlock = blockAssigner.assignBlock(voxel.colour, voxel.position, blockMeshParams.colourSpace, this._fallableBlocks);
- // LOG(`Replacing ${block.name} with ${replacedBlock.name}`);
- block = replacedBlock;
- }
-
- this._blocks.push({
- voxel: voxel,
- blockInfo: block,
- });
- if (!this._blockPalette.includes(block.name)) {
- this._blockPalette.push(block.name);
- }
- }
-
- if (blockMeshParams.fallable === 'do-nothing' && countFalling > 0) {
- StatusHandler.Get.add('warning', `${countFalling.toLocaleString()} blocks will fall under gravity when this structure is placed`);
- }
- }
-
- public getBlocks(): Block[] {
- return this._blocks;
- }
-
- public getBlockPalette() {
- return this._blockPalette;
- }
-
- public getVoxelMesh() {
- if (!this._voxelMesh) {
- throw new AppError('Could not get voxel mesh');
- }
- return this._voxelMesh;
- }
-
- public createBuffer() {
- ASSERT(this._blocks.length === this._voxelMesh.getVoxelCount());
-
- const voxelBufferRaw = (typeof window === 'undefined') ? this._voxelMesh.createBuffer(false) : Renderer.Get._voxelBufferRaw!;
-
- const numBlocks = this._blocks.length;
- const newBuffer = {
- position: {
- numComponents: AppConstants.ComponentSize.POSITION,
- data: voxelBufferRaw.position.data,
- },
- colour: {
- numComponents: AppConstants.ComponentSize.COLOUR,
- data: voxelBufferRaw.colour.data,
- },
- occlusion: {
- numComponents: AppConstants.ComponentSize.OCCLUSION,
- data: voxelBufferRaw.occlusion.data,
- },
- texcoord: {
- numComponents: AppConstants.ComponentSize.TEXCOORD,
- data: voxelBufferRaw.texcoord.data,
- },
- normal: {
- numComponents: AppConstants.ComponentSize.NORMAL,
- data: voxelBufferRaw.normal.data,
- },
- indices: {
- numComponents: AppConstants.ComponentSize.INDICES,
- data: voxelBufferRaw.indices.data,
- },
- blockTexcoord: {
- numComponents: AppConstants.ComponentSize.TEXCOORD,
- data: new Float32Array(numBlocks * AppConstants.VoxelMeshBufferComponentOffsets.TEXCOORD),
- },
- };
-
- const faceOrder = ['north', 'south', 'up', 'down', 'east', 'west'];
- let insertIndex = 0;
- for (let i = 0; i < numBlocks; ++i) {
- for (let f = 0; f < AppConstants.FACES_PER_VOXEL; ++f) {
- const faceName = faceOrder[f];
- const texcoord = this._blocks[i].blockInfo.faces[faceName].texcoord;
- for (let v = 0; v < AppConstants.VERTICES_PER_FACE; ++v) {
- newBuffer.blockTexcoord.data[insertIndex++] = texcoord.u;
- newBuffer.blockTexcoord.data[insertIndex++] = texcoord.v;
- }
- }
- }
-
- return newBuffer;
- }
-
- public getAtlasSize() {
- return BlockAtlas.Get.getAtlasSize();
- }
-
- public getAtlasUsed() {
- return this._atlasUsed;
- }
-}
+import fs from 'fs';
+
+import { BlockAssignerFactory, TBlockAssigners } from './assigners/assigners';
+import { Atlas } from './atlas';
+import { AtlasPalette } from './block_assigner';
+import { BlockInfo } from './block_atlas';
+import { ChunkedBufferGenerator, TBlockMeshBufferDescription } from './buffer';
+import { Palette } from './palette';
+import { ProgressManager } from './progress';
+import { StatusHandler } from './status';
+import { ColourSpace } from './util';
+import { AppError, ASSERT } from './util/error_util';
+import { LOGF } from './util/log_util';
+import { AppPaths, PathUtil } from './util/path_util';
+import { Vector3 } from './vector';
+import { Voxel, VoxelMesh } from './voxel_mesh';
+import { AssignParams } from './worker_types';
+
+interface Block {
+ voxel: Voxel;
+ blockInfo: BlockInfo;
+}
+
+export type FallableBehaviour = 'replace-falling' | 'replace-fallable' | 'place-string' | 'do-nothing';
+
+export interface BlockMeshParams {
+ textureAtlas: Atlas,
+ blockPalette: Palette,
+ blockAssigner: TBlockAssigners,
+ colourSpace: ColourSpace,
+ fallable: FallableBehaviour,
+}
+
+export class BlockMesh {
+ private _blocksUsed: string[];
+ private _blocks: Block[];
+ private _voxelMesh: VoxelMesh;
+ private _fallableBlocks: string[];
+ private _atlas: Atlas;
+
+ public static createFromVoxelMesh(voxelMesh: VoxelMesh, blockMeshParams: AssignParams.Input) {
+ const blockMesh = new BlockMesh(voxelMesh);
+ blockMesh._assignBlocks(blockMeshParams);
+ return blockMesh;
+ }
+
+ private constructor(voxelMesh: VoxelMesh) {
+ this._blocksUsed = [];
+ this._blocks = [];
+ this._voxelMesh = voxelMesh;
+ this._atlas = Atlas.getVanillaAtlas()!;
+ //this._recreateBuffer = true;
+
+ const fallableBlocksString = fs.readFileSync(PathUtil.join(AppPaths.Get.resources, 'fallable_blocks.json'), 'utf-8');
+ this._fallableBlocks = JSON.parse(fallableBlocksString).fallable_blocks;
+ }
+
+ private _assignBlocks(blockMeshParams: AssignParams.Input) {
+ const atlas = Atlas.load(blockMeshParams.textureAtlas);
+ ASSERT(atlas !== undefined, 'Could not load atlas');
+ this._atlas = atlas;
+
+ const palette = Palette.load(blockMeshParams.blockPalette);
+ ASSERT(palette !== undefined, 'Could not load palette');
+
+ const atlasPalette = new AtlasPalette(atlas, palette);
+ const allBlockCollection = atlasPalette.createBlockCollection([]);
+ const nonFallableBlockCollection = atlasPalette.createBlockCollection(this._fallableBlocks);
+
+ const blockAssigner = BlockAssignerFactory.GetAssigner(blockMeshParams.blockAssigner);
+
+ let countFalling = 0;
+ const taskHandle = ProgressManager.Get.start('Assigning');
+ const voxels = this._voxelMesh.getVoxels();
+ for (let voxelIndex = 0; voxelIndex < voxels.length; ++voxelIndex) {
+ ProgressManager.Get.progress(taskHandle, voxelIndex / voxels.length);
+
+ const voxel = voxels[voxelIndex];
+
+ let block = blockAssigner.assignBlock(
+ atlasPalette,
+ voxel.colour,
+ voxel.position,
+ blockMeshParams.resolution,
+ blockMeshParams.colourSpace,
+ allBlockCollection,
+ );
+
+ const isFallable = this._fallableBlocks.includes(block.name);
+ const isSupported = this._voxelMesh.isVoxelAt(Vector3.add(voxel.position, new Vector3(0, -1, 0)));
+
+ if (isFallable && !isSupported) {
+ ++countFalling;
+ }
+
+ let shouldReplace = (blockMeshParams.fallable === 'replace-fallable' && isFallable);
+ shouldReplace ||= (blockMeshParams.fallable === 'replace-falling' && isFallable && !isSupported);
+
+ if (shouldReplace) {
+ const replacedBlock = blockAssigner.assignBlock(
+ atlasPalette,
+ voxel.colour,
+ voxel.position,
+ blockMeshParams.resolution,
+ ColourSpace.RGB,
+ nonFallableBlockCollection,
+ );
+ block = replacedBlock;
+ }
+
+ this._blocks.push({
+ voxel: voxel,
+ blockInfo: block,
+ });
+ if (!this._blocksUsed.includes(block.name)) {
+ this._blocksUsed.push(block.name);
+ }
+ }
+ ProgressManager.Get.end(taskHandle);
+
+ if (blockMeshParams.fallable === 'do-nothing' && countFalling > 0) {
+ StatusHandler.Get.add('warning', `${countFalling.toLocaleString()} blocks will fall under gravity when this structure is placed`);
+ }
+ }
+
+ public getBlocks(): Block[] {
+ return this._blocks;
+ }
+
+ public getBlockPalette() {
+ return this._blocksUsed;
+ }
+
+ public getVoxelMesh() {
+ if (!this._voxelMesh) {
+ throw new AppError('Could not get voxel mesh');
+ }
+ return this._voxelMesh;
+ }
+
+ public getAtlas() {
+ return this._atlas;
+ }
+
+ /*
+ private _buffer?: TBlockMeshBufferDescription;
+ public getBuffer(): TBlockMeshBufferDescription {
+ //ASSERT(this._renderParams, 'Called BlockMesh.getBuffer() without setting render params');
+ if (this._buffer === undefined) {
+ this._buffer = BufferGenerator.fromBlockMesh(this);
+ //this._recreateBuffer = false;
+ }
+ return this._buffer;
+ }
+ */
+
+ private _bufferChunks: Array = [];
+ public getChunkedBuffer(chunkIndex: number): TBlockMeshBufferDescription & { moreBlocksToBuffer: boolean, progress: number } {
+ if (this._bufferChunks[chunkIndex] === undefined) {
+ LOGF(`[BlockMesh]: getChunkedBuffer: ci: ${chunkIndex} not cached`);
+ this._bufferChunks[chunkIndex] = ChunkedBufferGenerator.fromBlockMesh(this, chunkIndex);
+ } else {
+ LOGF(`[BlockMesh]: getChunkedBuffer: ci: ${chunkIndex} not cached`);
+ }
+ return this._bufferChunks[chunkIndex];
+ }
+
+ public getAllChunkedBuffers() {
+ return this._bufferChunks;
+ }
+}
diff --git a/src/bounds.ts b/src/bounds.ts
new file mode 100644
index 00000000..9d878235
--- /dev/null
+++ b/src/bounds.ts
@@ -0,0 +1,48 @@
+import { Vector3 } from './vector';
+
+/**
+ * A 3D cuboid volume defined by two opposing corners
+ */
+export class Bounds {
+ private _min: Vector3;
+ private _max: Vector3;
+
+ constructor(min: Vector3, max: Vector3) {
+ this._min = min;
+ this._max = max;
+ }
+
+ public extendByPoint(point: Vector3) {
+ this._min = Vector3.min(this._min, point);
+ this._max = Vector3.max(this._max, point);
+ }
+
+ public extendByVolume(volume: Bounds) {
+ this._min = Vector3.min(this._min, volume._min);
+ this._max = Vector3.max(this._max, volume._max);
+ }
+
+ public static getInfiniteBounds() {
+ return new Bounds(
+ new Vector3(Infinity, Infinity, Infinity),
+ new Vector3(-Infinity, -Infinity, -Infinity),
+ );
+ }
+
+ public get min() {
+ return this._min;
+ }
+
+ public get max() {
+ return this._max;
+ }
+
+ public getCentre() {
+ const extents = Vector3.sub(this._max, this._min).divScalar(2);
+ return Vector3.add(this.min, extents);
+ }
+
+ public getDimensions() {
+ return Vector3.sub(this._max, this._min);
+ }
+}
diff --git a/src/buffer.ts b/src/buffer.ts
index bb9524bd..840e37bc 100644
--- a/src/buffer.ts
+++ b/src/buffer.ts
@@ -1,219 +1,399 @@
-import { Renderer } from './renderer';
-import { ASSERT } from './util';
+import { BlockMesh } from './block_mesh';
+import { AppConfig } from './config';
+import { AppConstants } from './constants';
+import { GeometryTemplates } from './geometry';
+import { Mesh, SolidMaterial, TexturedMaterial } from './mesh';
+import { OcclusionManager } from './occlusion';
+import { ProgressManager } from './progress';
+import { AttributeData } from './render_buffer';
+import { ASSERT } from './util/error_util';
+import { Vector3 } from './vector';
+import { VoxelMesh } from './voxel_mesh';
+import { RenderNextVoxelMeshChunkParams } from './worker_types';
-import * as twgl from 'twgl.js';
+export type TMeshBuffer = {
+ position: { numComponents: 3, data: Float32Array },
+ texcoord: { numComponents: 2, data: Float32Array },
+ normal: { numComponents: 3, data: Float32Array },
+ indices: { numComponents: 3, data: Uint32Array },
+};
-export interface Attribute {
- name: string,
- numComponents: number
-}
+export type TMeshBufferDescription = {
+ material: SolidMaterial | (TexturedMaterial)
+ buffer: TMeshBuffer,
+ numElements: number,
+};
-interface BottomlessBufferData {
- indices: BottomlessAttributeData,
- [name: string]: BottomlessAttributeData
-}
+export type TVoxelMeshBuffer = {
+ position: { numComponents: 3, data: Float32Array, },
+ colour: { numComponents: 4, data: Float32Array },
+ occlusion: { numComponents: 4, data: Float32Array },
+ texcoord: { numComponents: 2, data: Float32Array },
+ normal: { numComponents: 3, data: Float32Array },
+ indices: { numComponents: 3, data: Uint32Array },
+};
-interface BottomlessAttributeData {
- numComponents: number,
- data: Array
+export type TVoxelMeshBufferDescription = {
+ buffer: TVoxelMeshBuffer,
+ numElements: number,
}
-export interface AttributeData {
- indices: Uint32Array
- custom: {
- [name: string]: Array
- }
+export type TBlockMeshBuffer = {
+ position: { numComponents: 3, data: Float32Array, },
+ colour: { numComponents: 4, data: Float32Array },
+ occlusion: { numComponents: 4, data: Float32Array },
+ texcoord: { numComponents: 2, data: Float32Array },
+ normal: { numComponents: 3, data: Float32Array },
+ blockTexcoord: { numComponents: 2, data: Float32Array },
+ indices: { numComponents: 3, data: Uint32Array },
+};
+
+export type TBlockMeshBufferDescription = {
+ buffer: TBlockMeshBuffer,
+ numElements: number,
}
-export function MergeAttributeData(...data: AttributeData[]): AttributeData {
- if (data.length === 0) {
+type TMaterialID = string;
+
+export class ChunkedBufferGenerator {
+ public static fromVoxelMesh(voxelMesh: VoxelMesh, params: RenderNextVoxelMeshChunkParams.Input, chunkIndex: number): TVoxelMeshBufferDescription & { moreVoxelsToBuffer: boolean, progress: number } {
+ const numTotalVoxels = voxelMesh.getVoxelCount();
+ const voxelsStartIndex = chunkIndex * AppConfig.Get.VOXEL_BUFFER_CHUNK_SIZE;
+ const voxelsEndIndex = Math.min((chunkIndex + 1) * AppConfig.Get.VOXEL_BUFFER_CHUNK_SIZE, numTotalVoxels);
+ ASSERT(voxelsStartIndex < numTotalVoxels, 'Invalid voxel start index');
+
+ const numBufferVoxels = voxelsEndIndex - voxelsStartIndex;
+ const newBuffer: TVoxelMeshBuffer = BufferGenerator.createVoxelMeshBuffer(numBufferVoxels);
+
+ const cube: AttributeData = GeometryTemplates.getBoxBufferData(new Vector3(0, 0, 0));
+ const voxels = voxelMesh.getVoxels();
+
+ for (let i = 0; i < numBufferVoxels; ++i) {
+ const voxelIndex = i + voxelsStartIndex;
+
+ const voxel = voxels[voxelIndex];
+ const voxelColourArray = [voxel.colour.r, voxel.colour.g, voxel.colour.b, voxel.colour.a];
+ const voxelPositionArray = voxel.position.toArray();
+
+ for (let j = 0; j < AppConstants.VoxelMeshBufferComponentOffsets.POSITION; ++j) {
+ newBuffer.position.data[i * AppConstants.VoxelMeshBufferComponentOffsets.POSITION + j] = cube.custom.position[j] + voxelPositionArray[j % 3];
+ }
+
+ for (let j = 0; j < AppConstants.VoxelMeshBufferComponentOffsets.COLOUR; ++j) {
+ newBuffer.colour.data[i * AppConstants.VoxelMeshBufferComponentOffsets.COLOUR + j] = voxelColourArray[j % 4];
+ }
+
+ for (let j = 0; j < AppConstants.VoxelMeshBufferComponentOffsets.NORMAL; ++j) {
+ newBuffer.normal.data[i * AppConstants.VoxelMeshBufferComponentOffsets.NORMAL + j] = cube.custom.normal[j];
+ }
+
+ for (let j = 0; j < AppConstants.VoxelMeshBufferComponentOffsets.TEXCOORD; ++j) {
+ newBuffer.texcoord.data[i * AppConstants.VoxelMeshBufferComponentOffsets.TEXCOORD + j] = cube.custom.texcoord[j];
+ }
+
+ for (let j = 0; j < AppConstants.VoxelMeshBufferComponentOffsets.INDICES; ++j) {
+ newBuffer.indices.data[i * AppConstants.VoxelMeshBufferComponentOffsets.INDICES + j] = cube.indices[j] + (i * AppConstants.INDICES_PER_VOXEL);
+ }
+
+ if (params.enableAmbientOcclusion) {
+ const voxelOcclusionArray = OcclusionManager.Get.getOcclusions(voxel.position, voxelMesh);
+ for (let j = 0; j < AppConstants.VoxelMeshBufferComponentOffsets.OCCLUSION; ++j) {
+ newBuffer.occlusion.data[i * AppConstants.VoxelMeshBufferComponentOffsets.OCCLUSION + j] = voxelOcclusionArray[j];
+ }
+ }
+ }
+
return {
- indices: new Uint32Array(),
- custom: {},
+ buffer: newBuffer,
+ numElements: newBuffer.indices.data.length,
+ moreVoxelsToBuffer: voxelsEndIndex !== numTotalVoxels,
+ progress: voxelsStartIndex / numTotalVoxels,
};
}
- // Check custom attributes match
- const requiredAttributes = Object.keys(data[0].custom);
- for (let i = 1; i < data.length; ++i) {
- const customAttributes = Object.keys(data[i].custom);
- const isAllRequiredInCustom = requiredAttributes.every((attr) => {
- return customAttributes.includes(attr);
- });
- const isAllCustomInRequired = customAttributes.every((attr) => {
- return requiredAttributes.includes(attr);
- });
- ASSERT(isAllRequiredInCustom && isAllCustomInRequired, 'Attributes to merge do not match');
- }
- // Merge data
- const indices = Array.from(data[0].indices);
- const custom = data[0].custom;
- for (let i = 1; i < data.length; ++i) {
- const nextIndex = Math.max(...indices) + 1;
- const d = data[i];
- const newIndices = d.indices.map((index) => index + nextIndex);
- indices.push(...Array.from(newIndices));
- for (const attr of requiredAttributes) {
- const attrData = d.custom[attr];
- custom[attr].push(...attrData);
+
+ public static fromBlockMesh(blockMesh: BlockMesh, chunkIndex: number): TBlockMeshBufferDescription & { moreBlocksToBuffer: boolean, progress: number } {
+ const blocks = blockMesh.getBlocks();
+
+ const numTotalBlocks = blocks.length;
+ const blocksStartIndex = chunkIndex * AppConfig.Get.VOXEL_BUFFER_CHUNK_SIZE;
+ const blocksEndIndex = Math.min((chunkIndex + 1) * AppConfig.Get.VOXEL_BUFFER_CHUNK_SIZE, numTotalBlocks);
+ ASSERT(blocksStartIndex < numTotalBlocks, 'Invalid block start index');
+
+ const numBufferBlocks = blocksEndIndex - blocksStartIndex;
+
+ const voxelChunkBuffer = blockMesh.getVoxelMesh().getChunkedBuffer(chunkIndex);
+ const newBuffer = BufferGenerator.createBlockMeshBuffer(numBufferBlocks, voxelChunkBuffer.buffer);
+
+ const faceOrder = ['north', 'south', 'up', 'down', 'east', 'west'];
+ let insertIndex = 0;
+
+ for (let i = 0; i < numBufferBlocks; ++i) {
+ const blockIndex = i + blocksStartIndex;
+
+ for (let f = 0; f < AppConstants.FACES_PER_VOXEL; ++f) {
+ const faceName = faceOrder[f];
+ const texcoord = blocks[blockIndex].blockInfo.faces[faceName].texcoord;
+ for (let v = 0; v < AppConstants.VERTICES_PER_FACE; ++v) {
+ newBuffer.blockTexcoord.data[insertIndex++] = texcoord.u;
+ newBuffer.blockTexcoord.data[insertIndex++] = texcoord.v;
+ }
+ }
}
- }
- return {
- indices: new Uint32Array(indices),
- custom: custom,
- };
+ return {
+ buffer: newBuffer,
+ numElements: newBuffer.indices.data.length,
+ moreBlocksToBuffer: voxelChunkBuffer.moreVoxelsToBuffer,
+ progress: voxelChunkBuffer.progress,
+ };
+ }
}
-export class RenderBuffer {
- private _WebGLBuffer?: {
- buffer: twgl.BufferInfo,
- numElements: number
- };
- private _buffer!: BottomlessBufferData;
- private _attributes: {[name: string]: Attribute};
- private _maxIndex: number;
- private _compiled: boolean;
- private _needsCompiling: boolean;
-
- public constructor(attributes: Array) {
- this._attributes = {};
- for (const attr of attributes) {
- this._attributes[attr.name] = {
- name: attr.name,
- numComponents: attr.numComponents,
- };
+export class BufferGenerator {
+ public static fromMesh(mesh: Mesh): TMeshBufferDescription[] {
+ const numTris = mesh.getTriangleCount();
+
+ // Count the number of triangles that use each material
+ const materialTriangleCount = new Map();
+ {
+ for (let triIndex = 0; triIndex < numTris; ++triIndex) {
+ const materialName = mesh.getMaterialByTriangle(triIndex);
+ const triangleCount = materialTriangleCount.get(materialName) ?? 0;
+ materialTriangleCount.set(materialName, triangleCount + 1);
+ }
}
-
- this._needsCompiling = false;
- this._compiled = false;
- this._maxIndex = 0;
- this._getNewBuffer();
- }
+ const materialBuffers: TMeshBufferDescription[] = [];
+
+ let trianglesHandled = 0;
+ const taskHandle = ProgressManager.Get.start('MeshBuffer');
+
+ // Create the buffers for each material and fill with data from the triangles
+ materialTriangleCount.forEach((triangleCount: number, materialName: string) => {
+ const materialBuffer: TMeshBuffer = BufferGenerator.createMaterialBuffer(triangleCount);
- public add(data: AttributeData) {
- const mappedIndicesToAdd = new Array(data.indices.length);
- let maxMapped = -1;
- data.indices.forEach((index, i) => {
- const newIndex = index + this._maxIndex;
- maxMapped = Math.max(maxMapped, newIndex);
- mappedIndicesToAdd[i] = newIndex;
+ let insertIndex = 0;
+ for (let triIndex = 0; triIndex < numTris; ++triIndex) {
+ ProgressManager.Get.progress(taskHandle, trianglesHandled / numTris);
+
+ const material = mesh.getMaterialByTriangle(triIndex);
+ if (material === materialName) {
+ ++trianglesHandled;
+
+ const uiTriangle = mesh.getUVTriangle(triIndex);
+
+ // Position
+ {
+ materialBuffer.position.data.set(uiTriangle.v0.toArray(), insertIndex * 9 + 0);
+ materialBuffer.position.data.set(uiTriangle.v1.toArray(), insertIndex * 9 + 3);
+ materialBuffer.position.data.set(uiTriangle.v2.toArray(), insertIndex * 9 + 6);
+ }
+
+ // Texcoord
+ {
+ materialBuffer.texcoord.data.set([uiTriangle.uv0.u, uiTriangle.uv0.v], insertIndex * 6 + 0);
+ materialBuffer.texcoord.data.set([uiTriangle.uv1.u, uiTriangle.uv1.v], insertIndex * 6 + 2);
+ materialBuffer.texcoord.data.set([uiTriangle.uv2.u, uiTriangle.uv2.v], insertIndex * 6 + 4);
+ }
+
+ // Normal
+ {
+ const normalArray = uiTriangle.getNormal().toArray();
+ materialBuffer.normal.data.set(normalArray, insertIndex * 9 + 0);
+ materialBuffer.normal.data.set(normalArray, insertIndex * 9 + 3);
+ materialBuffer.normal.data.set(normalArray, insertIndex * 9 + 6);
+ }
+
+ // Indices
+ {
+ materialBuffer.indices.data.set([
+ insertIndex * 3 + 0,
+ insertIndex * 3 + 1,
+ insertIndex * 3 + 2,
+ ], insertIndex * 3);
+ }
+
+ ++insertIndex;
+ }
+ }
+
+ const material = mesh.getMaterialByName(materialName);
+ materialBuffers.push({
+ buffer: materialBuffer,
+ material: material,
+ numElements: materialBuffer.indices.data.length,
+ });
});
- this._buffer.indices.data.push(...mappedIndicesToAdd);
- this._maxIndex = 1 + maxMapped;
- for (const attr in this._attributes) {
- this._buffer[attr].data.push(...data.custom[attr]);
- }
+ ProgressManager.Get.end(taskHandle);
- this._needsCompiling = true;
+ return materialBuffers;
}
- public attachNewAttribute(attribute: Attribute, data: Array) {
- ASSERT(this._buffer[attribute.name] === undefined, 'Attribute already exists in buffer');
- ASSERT(this._attributes[attribute.name] === undefined, 'Attribute already exists in attributes');
- const expectedDataLength = this._maxIndex * attribute.numComponents;
- ASSERT(data.length === expectedDataLength, `Data length expected to be ${expectedDataLength}, got ${data.length}`);
- this._buffer[attribute.name] = {
- numComponents: attribute.numComponents,
- data: data,
- };
- this._attributes[attribute.name] = attribute;
- this._needsCompiling = true;
- }
+ /*
+ public static fromVoxelMesh(voxelMesh: VoxelMesh, params: RenderVoxelMeshParams.Input): TVoxelMeshBufferDescription {
+ const numVoxels = voxelMesh.getVoxelCount();
+ const newBuffer: TVoxelMeshBuffer = this.createVoxelMeshBuffer(numVoxels);
- public removeAttribute(attributeName: string) {
- delete this._buffer[attributeName];
- delete this._attributes[attributeName];
- this._needsCompiling = true;
- }
+ const cube: AttributeData = GeometryTemplates.getBoxBufferData(new Vector3(0, 0, 0));
+ const voxels = voxelMesh.getVoxels();
- public getWebGLBuffer() {
- this._compile();
- ASSERT(this._WebGLBuffer !== undefined);
- return this._WebGLBuffer;
- }
+ const taskHandle = ProgressManager.Get.start('VoxelMeshBuffer');
+ for (let i = 0; i < numVoxels; ++i) {
+ ProgressManager.Get.progress(taskHandle, i / numVoxels);
- private _compile() {
- if (this._compiled && !this._needsCompiling) {
- return;
- }
+ const voxel = voxels[i];
+ const voxelColourArray = [voxel.colour.r, voxel.colour.g, voxel.colour.b, voxel.colour.a];
+ const voxelPositionArray = voxel.position.toArray();
- const newBuffer: { indices: { data: Uint32Array, numComponents: number }, [arr: string]: { data: (Float32Array | Uint32Array), numComponents: number }} = {
- indices: { data: Uint32Array.from(this._buffer.indices.data), numComponents: this._buffer.indices.numComponents },
- };
- for (const key in this._buffer) {
- if (key !== 'indices') {
- newBuffer[key] = {
- data: Float32Array.from(this._buffer[key].data),
- numComponents: this._buffer[key].numComponents,
- };
+ for (let j = 0; j < AppConstants.VoxelMeshBufferComponentOffsets.POSITION; ++j) {
+ newBuffer.position.data[i * AppConstants.VoxelMeshBufferComponentOffsets.POSITION + j] = cube.custom.position[j] + voxelPositionArray[j % 3];
}
- }
- this._WebGLBuffer = {
- buffer: twgl.createBufferInfoFromArrays(Renderer.Get._gl, newBuffer),
- numElements: this._buffer.indices.data.length,
- };
+ for (let j = 0; j < AppConstants.VoxelMeshBufferComponentOffsets.COLOUR; ++j) {
+ newBuffer.colour.data[i * AppConstants.VoxelMeshBufferComponentOffsets.COLOUR + j] = voxelColourArray[j % 4];
+ }
- this._compiled = true;
- this._needsCompiling = false;
- }
+ for (let j = 0; j < AppConstants.VoxelMeshBufferComponentOffsets.NORMAL; ++j) {
+ newBuffer.normal.data[i * AppConstants.VoxelMeshBufferComponentOffsets.NORMAL + j] = cube.custom.normal[j];
+ }
- private _getNewBuffer() {
- this._buffer = {
- indices: {numComponents: 1, data: []},
- };
- for (const attr in this._attributes) {
- this._buffer[attr] = {
- numComponents: this._attributes[attr].numComponents,
- data: [],
- };
- }
- }
+ for (let j = 0; j < AppConstants.VoxelMeshBufferComponentOffsets.TEXCOORD; ++j) {
+ newBuffer.texcoord.data[i * AppConstants.VoxelMeshBufferComponentOffsets.TEXCOORD + j] = cube.custom.texcoord[j];
+ }
- private _checkDataMatchesAttributes(data: AttributeData) {
- if (!('indices' in data)) {
- throw Error('Given data does not have indices data');
- }
- const setsRequired = data.indices.reduce((a, v) => Math.max(a, v)) + 1;
- for (const attr in this._attributes) {
- if (!(attr in data)) {
- throw Error(`Given data does not have ${attr} data`);
+ for (let j = 0; j < AppConstants.VoxelMeshBufferComponentOffsets.INDICES; ++j) {
+ newBuffer.indices.data[i * AppConstants.VoxelMeshBufferComponentOffsets.INDICES + j] = cube.indices[j] + (i * AppConstants.INDICES_PER_VOXEL);
}
- if (data.custom[attr].length % this._attributes[attr].numComponents != 0) {
- throw Error(`Not enough/too much ${attr} data given`);
+
+ if (params.enableAmbientOcclusion) {
+ const voxelOcclusionArray = OcclusionManager.Get.getOcclusions(voxel.position, voxelMesh);
+ for (let j = 0; j < AppConstants.VoxelMeshBufferComponentOffsets.OCCLUSION; ++j) {
+ newBuffer.occlusion.data[i * AppConstants.VoxelMeshBufferComponentOffsets.OCCLUSION + j] = voxelOcclusionArray[j];
+ }
}
- const numSets = data.custom[attr].length / this._attributes[attr].numComponents;
- if (numSets != setsRequired) {
- // throw `Number of indices does not match number of ${attr} components given`;
- throw Error(`Expected ${setsRequired * this._attributes[attr].numComponents} values for ${attr}, got ${data.custom[attr].length}`);
+ }
+ ProgressManager.Get.end(taskHandle);
+
+ return {
+ buffer: newBuffer,
+ numElements: newBuffer.indices.data.length,
+ };
+ }
+ */
+
+ /*
+ public static fromBlockMesh(blockMesh: BlockMesh): TBlockMeshBufferDescription {
+ const blocks = blockMesh.getBlocks();
+ const numBlocks = blocks.length;
+
+ const newBuffer = this.createBlockMeshBuffer(numBlocks, blockMesh.getVoxelMesh().getBuffer().buffer);
+
+ const faceOrder = ['north', 'south', 'up', 'down', 'east', 'west'];
+ let insertIndex = 0;
+
+ const taskHandle = ProgressManager.Get.start('BlockMeshBuffer');
+ for (let i = 0; i < numBlocks; ++i) {
+ ProgressManager.Get.progress(taskHandle, i / numBlocks);
+
+ for (let f = 0; f < AppConstants.FACES_PER_VOXEL; ++f) {
+ const faceName = faceOrder[f];
+ const texcoord = blocks[i].blockInfo.faces[faceName].texcoord;
+ for (let v = 0; v < AppConstants.VERTICES_PER_FACE; ++v) {
+ newBuffer.blockTexcoord.data[insertIndex++] = texcoord.u;
+ newBuffer.blockTexcoord.data[insertIndex++] = texcoord.v;
+ }
}
}
+ ProgressManager.Get.end(taskHandle);
+
+ return {
+ buffer: newBuffer,
+ numElements: newBuffer.indices.data.length,
+ };
}
+ */
- public copy(): RenderBuffer {
- const copiedBuffer = new RenderBuffer([]);
+ public static createMaterialBuffer(triangleCount: number): TMeshBuffer {
+ return {
+ position: {
+ numComponents: 3,
+ data: new Float32Array(triangleCount * 3 * 3),
+ },
+ texcoord: {
+ numComponents: 2,
+ data: new Float32Array(triangleCount * 3 * 2),
+ },
+ normal: {
+ numComponents: 3,
+ data: new Float32Array(triangleCount * 3 * 3),
+ },
+ indices: {
+ numComponents: 3,
+ data: new Uint32Array(triangleCount * 3),
+ },
+ };
+ }
- copiedBuffer._buffer = {
+ public static createVoxelMeshBuffer(numVoxels: number): TVoxelMeshBuffer {
+ return {
+ position: {
+ numComponents: 3,
+ data: new Float32Array(numVoxels * AppConstants.VoxelMeshBufferComponentOffsets.POSITION),
+ },
+ colour: {
+ numComponents: 4,
+ data: new Float32Array(numVoxels * AppConstants.VoxelMeshBufferComponentOffsets.COLOUR),
+ },
+ occlusion: {
+ numComponents: 4,
+ data: new Float32Array(numVoxels * AppConstants.VoxelMeshBufferComponentOffsets.OCCLUSION).fill(1.0),
+ },
+ texcoord: {
+ numComponents: 2,
+ data: new Float32Array(numVoxels * AppConstants.VoxelMeshBufferComponentOffsets.TEXCOORD),
+ },
+ normal: {
+ numComponents: 3,
+ data: new Float32Array(numVoxels * AppConstants.VoxelMeshBufferComponentOffsets.NORMAL),
+ },
indices: {
- numComponents: this._buffer.indices.numComponents,
- data: Array.from(this._buffer.indices.data),
+ numComponents: 3,
+ data: new Uint32Array(numVoxels * AppConstants.VoxelMeshBufferComponentOffsets.INDICES),
},
};
- for (const key in this._buffer) {
- if (key !== 'indices') {
- copiedBuffer._buffer[key] = {
- numComponents: this._buffer[key].numComponents,
- data: Array.from(this._buffer[key].data),
- };
- }
- }
+ }
- copiedBuffer._attributes = JSON.parse(JSON.stringify(this._attributes));
- copiedBuffer._maxIndex = this._maxIndex;
- copiedBuffer._compiled = false;
- copiedBuffer._needsCompiling = true;
- return copiedBuffer;
+ public static createBlockMeshBuffer(numBlocks: number, voxelMeshBuffer: TVoxelMeshBuffer): TBlockMeshBuffer {
+ return {
+ position: {
+ numComponents: AppConstants.ComponentSize.POSITION,
+ data: voxelMeshBuffer.position.data,
+ },
+ colour: {
+ numComponents: AppConstants.ComponentSize.COLOUR,
+ data: voxelMeshBuffer.colour.data,
+ },
+ occlusion: {
+ numComponents: AppConstants.ComponentSize.OCCLUSION,
+ data: voxelMeshBuffer.occlusion.data,
+ },
+ texcoord: {
+ numComponents: AppConstants.ComponentSize.TEXCOORD,
+ data: voxelMeshBuffer.texcoord.data,
+ },
+ normal: {
+ numComponents: AppConstants.ComponentSize.NORMAL,
+ data: voxelMeshBuffer.normal.data,
+ },
+ indices: {
+ numComponents: AppConstants.ComponentSize.INDICES,
+ data: voxelMeshBuffer.indices.data,
+ },
+ blockTexcoord: {
+ numComponents: AppConstants.ComponentSize.TEXCOORD,
+ data: new Float32Array(numBlocks * AppConstants.VoxelMeshBufferComponentOffsets.TEXCOORD),
+ },
+ };
}
}
diff --git a/src/camera.ts b/src/camera.ts
index 3b998116..d0aac66a 100644
--- a/src/camera.ts
+++ b/src/camera.ts
@@ -1,190 +1,343 @@
-import { m4, v3 } from 'twgl.js';
-import { MouseManager } from './mouse';
-import { degreesToRadians } from './math';
-import { Renderer } from './renderer';
-import { SmoothVariable, SmoothVectorVariable } from './util';
-import { Vector3 } from './vector';
-
-export class ArcballCamera {
- public isUserRotating = false;
- public isUserTranslating = false;
-
- private readonly fov: number;
- private readonly zNear: number;
- private readonly zFar: number;
- public aspect: number;
-
- private readonly _defaultDistance = 18.0;
- private readonly _defaultAzimuth = -1.0;
- private readonly _defaultElevation = 1.3;
-
- private _distance = new SmoothVariable(this._defaultDistance, 0.025);
- private _azimuth = new SmoothVariable(this._defaultAzimuth, 0.025);
- private _elevation = new SmoothVariable(this._defaultElevation, 0.025);
- private _target = new SmoothVectorVariable(new Vector3(0, 0, 0), 0.025);
-
- private readonly up: v3.Vec3 = [0, 1, 0];
- private eye: v3.Vec3 = [0, 0, 0];
-
- private mouseSensitivity = 0.005;
- private scrollSensitivity = 0.005;
-
- private gl: WebGLRenderingContext;
-
- private static _instance: ArcballCamera;
- public static get Get() {
- return this._instance || (this._instance = new this());
- }
-
- private constructor() {
- this.fov = 30 * degreesToRadians;
- this.zNear = 0.5;
- this.zFar = 100.0;
- this.gl = Renderer.Get._gl;
- this.aspect = this.gl.canvas.width / this.gl.canvas.height;
-
- this._elevation.setClamp(0.01, Math.PI - 0.01);
- this._distance.setClamp(1.0, 100.0);
- }
-
- public updateCamera() {
- this.aspect = this.gl.canvas.width / this.gl.canvas.height;
-
- const mouseDelta = MouseManager.Get.getMouseDelta();
- if (this.isUserRotating) {
- this._azimuth.addToTarget(mouseDelta.dx * this.mouseSensitivity);
- this._elevation.addToTarget(mouseDelta.dy * this.mouseSensitivity);
- }
- if (this.isUserTranslating) {
- const my = mouseDelta.dy * this.mouseSensitivity;
- const mx = mouseDelta.dx * this.mouseSensitivity;
- // Up-down
- const dy = -Math.cos(this._elevation.getTarget() - Math.PI/2);
- const df = Math.sin(this._elevation.getTarget() - Math.PI/2);
- this._target.addToTarget(new Vector3(
- -Math.sin(this._azimuth.getTarget() - Math.PI/2) * my * df,
- dy * my,
- Math.cos(this._azimuth.getTarget() - Math.PI/2) * my * df,
- ));
- // Left-right
- const dx = Math.sin(this._azimuth.getTarget());
- const dz = -Math.cos(this._azimuth.getTarget());
- this._target.addToTarget(new Vector3(dx * mx, 0.0, dz * mx));
- }
-
- // Move camera towards target location
- this._distance.tick();
- this._azimuth.tick();
- this._elevation.tick();
- this._target.tick();
-
- const target = this._target.getActual().toArray();
- this.eye = [
- this._distance.getActual() * Math.cos(this._azimuth.getActual()) * -Math.sin(this._elevation.getActual()) + target[0],
- this._distance.getActual() * Math.cos(this._elevation.getActual()) + target[1],
- this._distance.getActual() * Math.sin(this._azimuth.getActual()) * -Math.sin(this._elevation.getActual()) + target[2],
- ];
- }
-
- getCameraPosition(azimuthOffset: number, elevationOffset: number) {
- const azimuth = this._azimuth.getActual() + azimuthOffset;
- const elevation = this._elevation.getActual() + elevationOffset;
- return [
- this._distance.getActual() * Math.cos(azimuth ) * -Math.sin(elevation),
- this._distance.getActual() * Math.cos(elevation),
- this._distance.getActual() * Math.sin(azimuth) * -Math.sin(elevation),
- ];
- }
-
- public onMouseDown(e: MouseEvent) {
- if (e.buttons === 1) {
- this.isUserRotating = true;
- } else if (e.buttons === 2) {
- this.isUserTranslating = true;
- }
- }
-
- public onMouseUp(e: MouseEvent) {
- this.isUserRotating = false;
- this.isUserTranslating = false;
- }
-
- public onWheelScroll(e: WheelEvent) {
- this._distance.addToTarget(e.deltaY * this.scrollSensitivity);
- }
-
- public getProjectionMatrix() {
- return m4.perspective(this.fov, this.aspect, this.zNear, this.zFar);
- }
-
- public getCameraMatrix() {
- return m4.lookAt(this.eye, this._target.getActual().toArray(), this.up);
- }
-
- public getViewMatrix() {
- return m4.inverse(this.getCameraMatrix());
- }
-
- public getViewProjection() {
- return m4.multiply(this.getProjectionMatrix(), this.getViewMatrix());
- }
-
- public getWorldMatrix() {
- return m4.identity();
- }
-
- public getWorldViewProjection() {
- return m4.multiply(this.getViewProjection(), this.getWorldMatrix());
- }
-
- public getWorldInverseTranspose() {
- return m4.transpose(m4.inverse(this.getWorldMatrix()));
- }
-
- public getInverseWorldViewProjection() {
- return m4.inverse(this.getWorldViewProjection());
- }
-
- public onZoomOut() {
- this._distance.addToTarget(1);
- }
-
- public onZoomIn() {
- this._distance.addToTarget(-1);
- }
-
- public reset() {
- this._target.setTarget(new Vector3(0, 0, 0));
- this._distance.setTarget(this._defaultDistance);
- this._azimuth.setTarget(this._defaultAzimuth);
- this._elevation.setTarget(this._defaultElevation);
-
- while (this._azimuth.getActual() < this._defaultAzimuth - Math.PI) {
- this._azimuth.setActual(this._azimuth.getActual() + Math.PI * 2);
- }
- while (this._azimuth.getActual() > this._defaultAzimuth + Math.PI) {
- this._azimuth.setActual(this._azimuth.getActual() - Math.PI * 2);
- }
- }
-
- /*
- public getMouseRay() {
- const mousePos = this.mouseManager.getMousePosNorm();
- const inverseProjectionMatrix = this.getInverseWorldViewProjection();
- var origin = mathUtil.multiplyMatVec4(inverseProjectionMatrix, [mousePos.x, mousePos.y, -1.0, 1.0]);
- var dest = mathUtil.multiplyMatVec4(inverseProjectionMatrix, [mousePos.x, mousePos.y, 1.0, 1.0]);
-
- origin[0] /= origin[3];
- origin[1] /= origin[3];
- origin[2] /= origin[3];
- dest[0] /= dest[3];
- dest[1] /= dest[3];
- dest[2] /= dest[3];
-
- return {origin: origin, dest: dest};
- }
- */
-}
-
-
-module.exports.ArcballCamera = ArcballCamera;
+import { m4, v3 } from 'twgl.js';
+
+import { AppConfig } from './config';
+import { AppMath, between, clamp, degreesToRadians, roundToNearest, SmoothVariable, SmoothVectorVariable } from './math';
+import { MouseManager } from './mouse';
+import { Renderer } from './renderer';
+import { Vector3 } from './vector';
+
+export class ArcballCamera {
+ public isUserRotating = false;
+ public isUserTranslating = false;
+
+ private _isPerspective: boolean;
+ private _fov: number;
+ private _zNear: number;
+ private _zFar: number;
+ private _aspect: number;
+
+ private _distance: SmoothVariable;// = new SmoothVariable(this._defaultDistance, 0.025);
+ private _azimuth: SmoothVariable;// = new SmoothVariable(this._defaultAzimuth, 0.025);
+ private _elevation: SmoothVariable;// = new SmoothVariable(this._defaultElevation, 0.025);
+ private _target: SmoothVectorVariable;// = new SmoothVectorVariable(new Vector3(0, 0, 0), 0.025);
+
+ private readonly up: v3.Vec3 = [0, 1, 0];
+ private eye: v3.Vec3 = [0, 0, 0];
+
+ private _azimuthRelief = 0.0;
+ private _elevationRelief = 0.0;
+ private _isAngleSnapped = false;
+
+ private mouseSensitivity = 0.005;
+ private scrollSensitivity = 0.005;
+
+ private _gl: WebGLRenderingContext;
+
+ private static _instance: ArcballCamera;
+ public static get Get() {
+ return this._instance || (this._instance = new this());
+ }
+
+ private constructor() {
+ this._gl = Renderer.Get._gl;
+
+ this._isPerspective = true;
+ this._fov = AppConfig.Get.CAMERA_FOV_DEGREES * degreesToRadians;
+ this._zNear = 0.5;
+ this._zFar = 100.0;
+ this._aspect = this._gl.canvas.width / this._gl.canvas.height;
+ this._distance = new SmoothVariable(AppConfig.Get.CAMERA_DEFAULT_DISTANCE_UNITS, 0.025);
+ this._azimuth = new SmoothVariable(AppConfig.Get.CAMERA_DEFAULT_AZIMUTH_RADIANS, 0.025);
+ this._elevation = new SmoothVariable(AppConfig.Get.CAMERA_DEFAULT_ELEVATION_RADIANS, 0.025);
+ this._target = new SmoothVectorVariable(new Vector3(0, 0, 0), 0.025);
+
+ this._elevation.setClamp(0.001, Math.PI - 0.001);
+ this._distance.setClamp(1.0, 100.0);
+
+ this.setCameraMode(this._isPerspective ? 'perspective' : 'orthographic');
+ }
+
+ public isPerspective() {
+ return this._isPerspective;
+ }
+
+ public isOrthographic() {
+ return !this._isPerspective;
+ }
+
+ public isAlignedWithAxis(axis: 'x' | 'y' | 'z'): boolean {
+ const azimuth = Math.abs(this._azimuth.getTarget() % (Math.PI * 2));
+ const elevation = this._elevation.getTarget();
+
+ switch (axis) {
+ case 'x':
+ return AppMath.nearlyEqual(azimuth, AppMath.RADIANS_0) || AppMath.nearlyEqual(azimuth, AppMath.RADIANS_180);
+ case 'y':
+ return AppMath.nearlyEqual(elevation, AppMath.RADIANS_0, 0.002) || AppMath.nearlyEqual(elevation, AppMath.RADIANS_180, 0.002);
+ case 'z':
+ return AppMath.nearlyEqual(azimuth, AppMath.RADIANS_90) || AppMath.nearlyEqual(azimuth, AppMath.RADIANS_270);
+ }
+ }
+
+ public setCameraMode(mode: 'perspective' | 'orthographic') {
+ this._isPerspective = mode === 'perspective';
+ }
+
+ private _angleSnap = false;
+ public toggleAngleSnap() {
+ this._angleSnap = !this._angleSnap;
+
+ if (!this._angleSnap) {
+ this._isAngleSnapped = false;
+ this._azimuthRelief = 0.0;
+ this._elevationRelief = 0.0;
+ }
+ }
+ public isAngleSnapEnabled() {
+ return this._angleSnap;
+ }
+
+ public updateCamera() {
+ this._aspect = this._gl.canvas.width / this._gl.canvas.height;
+
+ const mouseDelta = MouseManager.Get.getMouseDelta();
+ mouseDelta.dx *= this.mouseSensitivity;
+ mouseDelta.dy *= this.mouseSensitivity;
+
+ if (this.isUserRotating) {
+ this._azimuth.addToTarget(mouseDelta.dx);
+ this._elevation.addToTarget(mouseDelta.dy);
+ }
+ if (this.isUserTranslating) {
+ const my = mouseDelta.dy;
+ const mx = mouseDelta.dx;
+ // Up-down
+ const dy = -Math.cos(this._elevation.getTarget() - Math.PI/2);
+ const df = Math.sin(this._elevation.getTarget() - Math.PI/2);
+ this._target.addToTarget(new Vector3(
+ -Math.sin(this._azimuth.getTarget() - Math.PI/2) * my * df,
+ dy * my,
+ Math.cos(this._azimuth.getTarget() - Math.PI/2) * my * df,
+ ));
+ // Left-right
+ const dx = Math.sin(this._azimuth.getTarget());
+ const dz = -Math.cos(this._azimuth.getTarget());
+ this._target.addToTarget(new Vector3(dx * mx, 0.0, dz * mx));
+ }
+
+ const axisSnapRadius = clamp(AppConfig.Get.ANGLE_SNAP_RADIUS_DEGREES, 0.0, 90.0) * degreesToRadians;
+
+ if (this._shouldSnapCameraAngle()) {
+ let shouldSnapToAzimuth = false;
+ let shouldSnapToElevation = false;
+ let snapAngleAzimuth = 0.0;
+ let snapAngleElevation = 0.0;
+
+ const azimuth = this._azimuth.getTarget();
+ const elevation = this._elevation.getTarget();
+
+ const modAzimuth = Math.abs(azimuth % (90 * degreesToRadians));
+
+ if (modAzimuth < axisSnapRadius || modAzimuth > (90*degreesToRadians - axisSnapRadius)) {
+ shouldSnapToAzimuth = true;
+ snapAngleAzimuth = roundToNearest(azimuth, 90 * degreesToRadians);
+ }
+
+ const elevationSnapPoints = [0, 90, 180].map((x) => x * degreesToRadians);
+ for (const elevationSnapPoint of elevationSnapPoints) {
+ if (elevationSnapPoint - axisSnapRadius <= elevation && elevation <= elevationSnapPoint + axisSnapRadius) {
+ shouldSnapToElevation = true;
+ snapAngleElevation = elevationSnapPoint;
+ break;
+ }
+ }
+
+ if (shouldSnapToAzimuth && shouldSnapToElevation) {
+ this._azimuth.setTarget(snapAngleAzimuth);
+ this._elevation.setTarget(snapAngleElevation);
+ this._isAngleSnapped = true;
+ }
+ }
+
+ /*
+ if (this.isOrthographic()) {
+ const azimuth0 = between(this._azimuth.getTarget(), 0.0 - axisSnapRadius, 0.0 + axisSnapRadius);
+ const azimuth90 = between(this._azimuth.getTarget(), Math.PI/2 - axisSnapRadius, Math.PI/2 + axisSnapRadius);
+ const azimuth180 = between(this._azimuth.getTarget(), Math.PI - axisSnapRadius, Math.PI + axisSnapRadius);
+ const azimuth270 = between(this._azimuth.getTarget(), 3*Math.PI/2 - axisSnapRadius, 3*Math.PI/2 + axisSnapRadius);
+
+ const elevationTop = between(this._elevation.getTarget(), 0.0 - axisSnapRadius, 0.0 + axisSnapRadius);
+ const elevationMiddle = between(this._elevation.getTarget(), Math.PI/2 - axisSnapRadius, Math.PI/2 + axisSnapRadius);
+ const elevationBottom = between(this._elevation.getTarget(), Math.PI - axisSnapRadius, Math.PI + axisSnapRadius);
+
+ if (elevationMiddle) {
+ if (azimuth0) {
+ this._azimuth.setTarget(0);
+ this._elevation.setTarget(Math.PI/2);
+ this._isAngleSnapped = true;
+ } else if (azimuth90) {
+ this._azimuth.setTarget(90);
+ this._elevation.setTarget(Math.PI/2);
+ this._isAngleSnapped = true;
+ } else if (azimuth180) {
+ this._azimuth.setTarget(180);
+ this._elevation.setTarget(Math.PI/2);
+ this._isAngleSnapped = true;
+ } else if (azimuth270) {
+ this._azimuth.setTarget(270);
+ this._elevation.setTarget(Math.PI/2);
+ this._isAngleSnapped = true;
+ }
+ }
+ }
+ */
+
+ if (this._isAngleSnapped && this.isUserRotating) {
+ this._azimuthRelief += mouseDelta.dx;
+ this._elevationRelief += mouseDelta.dy;
+
+ if (!between(this._azimuthRelief, -axisSnapRadius, axisSnapRadius) || !between(this._elevationRelief, -axisSnapRadius, axisSnapRadius)) {
+ this._azimuth.setTarget(this._azimuth.getTarget() + this._azimuthRelief * 2);
+ this._elevation.setTarget(this._elevation.getTarget() + this._elevationRelief * 2);
+ this._isAngleSnapped = false;
+ }
+ }
+
+ if (!this._isAngleSnapped) {
+ this._azimuthRelief = 0.0;
+ this._elevationRelief = 0.0;
+ }
+
+ // Move camera towards target location
+ this._distance.tick();
+ this._azimuth.tick();
+ this._elevation.tick();
+ this._target.tick();
+
+ const target = this._target.getActual().toArray();
+ this.eye = [
+ this._distance.getActual() * Math.cos(this._azimuth.getActual()) * -Math.sin(this._elevation.getActual()) + target[0],
+ this._distance.getActual() * Math.cos(this._elevation.getActual()) + target[1],
+ this._distance.getActual() * Math.sin(this._azimuth.getActual()) * -Math.sin(this._elevation.getActual()) + target[2],
+ ];
+ }
+
+ private _shouldSnapCameraAngle() {
+ return this.isOrthographic() && this._angleSnap;
+ }
+
+ getCameraPosition(azimuthOffset: number, elevationOffset: number) {
+ const azimuth = this._azimuth.getActual() + azimuthOffset;
+ const elevation = this._elevation.getActual() + elevationOffset;
+ return [
+ this._distance.getActual() * Math.cos(azimuth ) * -Math.sin(elevation),
+ this._distance.getActual() * Math.cos(elevation),
+ this._distance.getActual() * Math.sin(azimuth) * -Math.sin(elevation),
+ ];
+ }
+
+ public onMouseDown(e: MouseEvent) {
+ if (e.buttons === 1) {
+ this.isUserRotating = true;
+ } else if (e.buttons === 2) {
+ this.isUserTranslating = true;
+ }
+ }
+
+ public onMouseUp(e: MouseEvent) {
+ this.isUserRotating = false;
+ this.isUserTranslating = false;
+ }
+
+ public onWheelScroll(e: WheelEvent) {
+ this._distance.addToTarget(e.deltaY * this.scrollSensitivity);
+ }
+
+ public getProjectionMatrix() {
+ if (this._isPerspective) {
+ return m4.perspective(this._fov, this._aspect, this._zNear, this._zFar);
+ } else {
+ const zoom = this._distance.getActual() / 3.6;
+ return m4.ortho(-zoom * this._aspect, zoom * this._aspect, -zoom, zoom, -1000, 1000);
+ }
+ }
+
+ public getCameraMatrix() {
+ return m4.lookAt(this.eye, this._target.getActual().toArray(), this.up);
+ }
+
+ public getViewMatrix() {
+ return m4.inverse(this.getCameraMatrix());
+ }
+
+ public getViewProjection() {
+ return m4.multiply(this.getProjectionMatrix(), this.getViewMatrix());
+ }
+
+ public getWorldMatrix() {
+ return m4.identity();
+ }
+
+ public getWorldViewProjection() {
+ return m4.multiply(this.getViewProjection(), this.getWorldMatrix());
+ }
+
+ public getWorldInverseTranspose() {
+ return m4.transpose(m4.inverse(this.getWorldMatrix()));
+ }
+
+ public getInverseWorldViewProjection() {
+ return m4.inverse(this.getWorldViewProjection());
+ }
+
+ public onZoomOut() {
+ this._distance.addToTarget(1);
+ }
+
+ public onZoomIn() {
+ this._distance.addToTarget(-1);
+ }
+
+ public reset() {
+ this._target.setTarget(new Vector3(0, 0, 0));
+ this._distance.setTarget(AppConfig.Get.CAMERA_DEFAULT_DISTANCE_UNITS);
+ this._azimuth.setTarget(AppConfig.Get.CAMERA_DEFAULT_AZIMUTH_RADIANS);
+ this._elevation.setTarget(AppConfig.Get.CAMERA_DEFAULT_ELEVATION_RADIANS);
+
+ while (this._azimuth.getActual() < AppConfig.Get.CAMERA_DEFAULT_AZIMUTH_RADIANS - Math.PI) {
+ this._azimuth.setActual(this._azimuth.getActual() + Math.PI * 2);
+ }
+ while (this._azimuth.getActual() > AppConfig.Get.CAMERA_DEFAULT_ELEVATION_RADIANS + Math.PI) {
+ this._azimuth.setActual(this._azimuth.getActual() - Math.PI * 2);
+ }
+ }
+
+ public getAspect() {
+ return this._aspect;
+ }
+
+ public setAspect(aspect: number) {
+ this._aspect = aspect;
+ }
+
+ /*
+ public getMouseRay() {
+ const mousePos = this.mouseManager.getMousePosNorm();
+ const inverseProjectionMatrix = this.getInverseWorldViewProjection();
+ var origin = mathUtil.multiplyMatVec4(inverseProjectionMatrix, [mousePos.x, mousePos.y, -1.0, 1.0]);
+ var dest = mathUtil.multiplyMatVec4(inverseProjectionMatrix, [mousePos.x, mousePos.y, 1.0, 1.0]);
+
+ origin[0] /= origin[3];
+ origin[1] /= origin[3];
+ origin[2] /= origin[3];
+ dest[0] /= dest[3];
+ dest[1] /= dest[3];
+ dest[2] /= dest[3];
+
+ return {origin: origin, dest: dest};
+ }
+ */
+}
+
+
+module.exports.ArcballCamera = ArcballCamera;
diff --git a/src/client.ts b/src/client.ts
index c9d4e46d..6864d050 100644
--- a/src/client.ts
+++ b/src/client.ts
@@ -1,36 +1,36 @@
-import { AppContext } from './app_context';
-import { ArcballCamera } from './camera';
-import { MouseManager } from './mouse';
-
-function addEvent(htmlElementID: string, event: string, delegate: (e: any) => void) {
- document.getElementById(htmlElementID)?.addEventListener(event, delegate);
-}
-
-function addDocumentEvent(event: string, delegate: (e: any) => void) {
- document.addEventListener(event, delegate);
-}
-
-const camera = ArcballCamera.Get;
-addEvent('canvas', 'mousedown', (e) => {
- camera.onMouseDown(e);
-});
-addDocumentEvent('mouseup', (e) => {
- camera.onMouseUp(e);
-});
-addEvent('canvas', 'wheel', (e) => {
- camera.onWheelScroll(e);
-});
-
-const mouseManager = MouseManager.Get;
-addDocumentEvent('mousemove', (e) => {
- mouseManager.onMouseMove(e);
-});
-
-
-// Begin draw loop
-const context = new AppContext();
-function render() {
- context.draw();
- requestAnimationFrame(render);
-}
-requestAnimationFrame(render);
+import { AppContext } from './app_context';
+import { ArcballCamera } from './camera';
+import { MouseManager } from './mouse';
+
+function addEvent(htmlElementID: string, event: string, delegate: (e: any) => void) {
+ document.getElementById(htmlElementID)?.addEventListener(event, delegate);
+}
+
+function addDocumentEvent(event: string, delegate: (e: any) => void) {
+ document.addEventListener(event, delegate);
+}
+
+const camera = ArcballCamera.Get;
+addEvent('canvas', 'mousedown', (e) => {
+ camera.onMouseDown(e);
+});
+addDocumentEvent('mouseup', (e) => {
+ camera.onMouseUp(e);
+});
+addEvent('canvas', 'wheel', (e) => {
+ camera.onWheelScroll(e);
+});
+
+const mouseManager = MouseManager.Get;
+addDocumentEvent('mousemove', (e) => {
+ mouseManager.onMouseMove(e);
+});
+
+
+// Begin draw loop
+const context = new AppContext();
+function render() {
+ context.draw();
+ requestAnimationFrame(render);
+}
+requestAnimationFrame(render);
diff --git a/src/colour.ts b/src/colour.ts
index c9e1b59e..bf55b7e0 100644
--- a/src/colour.ts
+++ b/src/colour.ts
@@ -1,65 +1,117 @@
-import { AppConfig } from './config';
-
-export type RGBA = {
- r: number,
- g: number,
- b: number,
- a: number
-}
-
-export namespace RGBAUtil {
- export function lerp(a: RGBA, b: RGBA, alpha: number) {
- return {
- r: a.r * (1 - alpha) + b.r * alpha,
- g: a.g * (1 - alpha) + b.g * alpha,
- b: a.b * (1 - alpha) + b.b * alpha,
- a: a.a * (1 - alpha) + b.a * alpha,
- };
- }
-
- export function average(...colours: RGBA[]) {
- const avg = { r: 0.0, g: 0.0, b: 0.0, a: 0.0 };
- for (let i = 0; i < colours.length; ++i) {
- avg.r += colours[i].r;
- avg.g += colours[i].g;
- avg.b += colours[i].b;
- avg.a += colours[i].a;
- }
- return avg;
- }
-
- export function squaredDistance(a: RGBA, b: RGBA) {
- let squaredDistance = 0.0;
- squaredDistance += Math.pow(a.r - b.r, 2);
- squaredDistance += Math.pow(a.g - b.g, 2);
- squaredDistance += Math.pow(a.b - b.b, 2);
- squaredDistance += Math.pow(a.a - b.a, 2) * AppConfig.ALPHA_BIAS;
- return squaredDistance;
- }
-
- export function copy(a: RGBA): RGBA {
- return {
- r: a.r,
- g: a.g,
- b: a.b,
- a: a.a,
- };
- }
-
- export function toArray(a: RGBA): number[] {
- return [a.r, a.g, a.b, a.a];
- }
-}
-
-export namespace RGBAColours {
- export const RED: RGBA = { r: 1.0, g: 0.0, b: 0.0, a: 1.0 };
- export const GREEN: RGBA = { r: 0.0, g: 1.0, b: 0.0, a: 1.0 };
- export const BLUE: RGBA = { r: 0.0, g: 0.0, b: 1.0, a: 1.0 };
-
- export const YELLOW: RGBA = { r: 1.0, g: 1.0, b: 0.0, a: 1.0 };
- export const CYAN: RGBA = { r: 0.0, g: 1.0, b: 1.0, a: 1.0 };
- export const MAGENTA: RGBA = { r: 1.0, g: 0.0, b: 1.0, a: 1.0 };
-
- export const WHITE: RGBA = { r: 1.0, g: 1.0, b: 1.0, a: 1.0 };
- export const BLACK: RGBA = { r: 0.0, g: 0.0, b: 0.0, a: 1.0 };
-}
+import { AppConfig } from './config';
+
+export type RGBA = {
+ r: number,
+ g: number,
+ b: number,
+ a: number
+}
+
+export namespace RGBAUtil {
+ export function lerp(a: RGBA, b: RGBA, alpha: number) {
+ return {
+ r: a.r * (1 - alpha) + b.r * alpha,
+ g: a.g * (1 - alpha) + b.g * alpha,
+ b: a.b * (1 - alpha) + b.b * alpha,
+ a: a.a * (1 - alpha) + b.a * alpha,
+ };
+ }
+
+ /**
+ * Note this is a very naive approach to averaging a colour
+ */
+ export function average(...colours: RGBA[]) {
+ const avg = { r: 0.0, g: 0.0, b: 0.0, a: 0.0 };
+ for (let i = 0; i < colours.length; ++i) {
+ avg.r += colours[i].r;
+ avg.g += colours[i].g;
+ avg.b += colours[i].b;
+ avg.a += colours[i].a;
+ }
+ avg.r /= colours.length;
+ avg.g /= colours.length;
+ avg.b /= colours.length;
+ avg.a /= colours.length;
+ return avg;
+ }
+
+ export function squaredDistance(a: RGBA, b: RGBA) {
+ let squaredDistance = 0.0;
+ squaredDistance += (a.r - b.r) * (a.r - b.r);
+ squaredDistance += (a.g - b.g) * (a.g - b.g);
+ squaredDistance += (a.b - b.b) * (a.b - b.b);
+ squaredDistance += (a.a - b.a) * (a.a - b.a) * AppConfig.Get.ALPHA_BIAS;
+ return squaredDistance;
+ }
+
+ export function copy(a: RGBA): RGBA {
+ return {
+ r: a.r,
+ g: a.g,
+ b: a.b,
+ a: a.a,
+ };
+ }
+
+ export function toArray(a: RGBA): number[] {
+ return [a.r, a.g, a.b, a.a];
+ }
+
+ export function bin(col: RGBA, resolution: TColourAccuracy) {
+ const r = Math.floor(col.r * resolution);
+ const g = Math.floor(col.g * resolution);
+ const b = Math.floor(col.b * resolution);
+ const a = Math.ceil(col.a * resolution);
+
+ let hash = r;
+ hash = (hash << 8) + g;
+ hash = (hash << 8) + b;
+ hash = (hash << 8) + a;
+
+ const binnedColour: RGBA = {
+ r: r / resolution,
+ g: g / resolution,
+ b: b / resolution,
+ a: a / resolution,
+ };
+
+ return {
+ colourHash: hash,
+ binnedColour: binnedColour,
+ };
+ }
+
+ /**
+ * Encodes a colour as a single number.
+ * Note this will bin colours together.
+ * @param col The colour to hash.
+ * @param resolution An uint8, the larger the more accurate the hash.
+ */
+ export function hash(col: RGBA, resolution: TColourAccuracy): number {
+ const r = Math.floor(col.r * resolution);
+ const g = Math.floor(col.g * resolution);
+ const b = Math.floor(col.b * resolution);
+ const a = Math.floor(col.a * resolution);
+
+ let hash = r;
+ hash = (hash << 8) + g;
+ hash = (hash << 8) + b;
+ hash = (hash << 8) + a;
+ return hash;
+ }
+
+ export type TColourAccuracy = number;
+}
+
+export namespace RGBAColours {
+ export const RED: RGBA = { r: 1.0, g: 0.0, b: 0.0, a: 1.0 };
+ export const GREEN: RGBA = { r: 0.0, g: 1.0, b: 0.0, a: 1.0 };
+ export const BLUE: RGBA = { r: 0.0, g: 0.0, b: 1.0, a: 1.0 };
+
+ export const YELLOW: RGBA = { r: 1.0, g: 1.0, b: 0.0, a: 1.0 };
+ export const CYAN: RGBA = { r: 0.0, g: 1.0, b: 1.0, a: 1.0 };
+ export const MAGENTA: RGBA = { r: 1.0, g: 0.0, b: 1.0, a: 1.0 };
+
+ export const WHITE: RGBA = { r: 1.0, g: 1.0, b: 1.0, a: 1.0 };
+ export const BLACK: RGBA = { r: 0.0, g: 0.0, b: 0.0, a: 1.0 };
+}
diff --git a/src/config.ts b/src/config.ts
index 7942d36f..5e49da26 100644
--- a/src/config.ts
+++ b/src/config.ts
@@ -1,27 +1,62 @@
-// TODO: Replace with UI options
-
-export namespace AppConfig {
- /** Darkens corner even if corner block does not exist, recommended */
- export const AMBIENT_OCCLUSION_OVERRIDE_CORNER = true;
-
- /** Enable logging to the console */
- export const LOGGING_ENABLED = true;
-
- /** Enables runtime assertions, useful for debugging */
- export const ASSERTIONS_ENABLED = true;
-
- /** Optimises rendering by not rendering triangles facing away from camera's view direction */
- export const FACE_CULLING = false;
-
- /** Enables extra runtimes checks that slow execution */
- export const DEBUG_ENABLED = true;
-
- /** The number of samples used when sampling a voxel's colour from a textured material */
- export const MULTISAMPLE_COUNT = 16;
-
- /** Max size of Node's old space in MBs */
- export const OLD_SPACE_SIZE = 2048;
-
- /** This value determines how much more important it is to closely match a block's transparency value than it's colour */
- export const ALPHA_BIAS = 1.0;
-}
+import fs from 'fs';
+
+import { LOG } from './util/log_util';
+import { AppPaths, PathUtil } from './util/path_util';
+
+export class AppConfig {
+ /* Singleton */
+ private static _instance: AppConfig;
+ public static get Get() {
+ return this._instance || (this._instance = new this());
+ }
+
+ public readonly RELEASE_MODE: boolean;
+ public readonly RELEASE_VERSION: string;
+ public readonly VOXEL_BUFFER_CHUNK_SIZE: number;
+
+ // Loaded from .json
+ public readonly AMBIENT_OCCLUSION_OVERRIDE_CORNER: boolean;
+ public readonly LOG_TO_FILE: boolean;
+ public readonly USE_WORKER_THREAD: boolean;
+ public readonly MULTISAMPLE_COUNT: number;
+ public readonly OLD_SPACE_SIZE_MB: number;
+ public readonly ALPHA_BIAS: number;
+ public readonly ANGLE_SNAP_RADIUS_DEGREES: number;
+ public readonly RENDER_TRIANGLE_THRESHOLD: number;
+ public readonly MAXIMUM_IMAGE_MEM_ALLOC: number;
+ public readonly CAMERA_FOV_DEGREES: number;
+ public readonly CAMERA_DEFAULT_DISTANCE_UNITS: number;
+ public readonly CAMERA_DEFAULT_AZIMUTH_RADIANS: number;
+ public readonly CAMERA_DEFAULT_ELEVATION_RADIANS: number;
+ public readonly CAMERA_SENSITIVITY_ROTATION: number;
+ public readonly CAMERA_SENSITIVITY_ZOOM: number;
+
+ private constructor() {
+ this.RELEASE_MODE = true;
+ this.RELEASE_VERSION = '0.6.0r';
+ this.VOXEL_BUFFER_CHUNK_SIZE = 5_000;
+
+ const configFile = fs.readFileSync(PathUtil.join(AppPaths.Get.resources, 'config.json'), 'utf8');
+ const configJSON = JSON.parse(configFile);
+
+ this.AMBIENT_OCCLUSION_OVERRIDE_CORNER = configJSON.AMBIENT_OCCLUSION_OVERRIDE_CORNER;
+ this.LOG_TO_FILE = configJSON.LOG_TO_FILE;
+ this.USE_WORKER_THREAD = configJSON.USE_WORKER_THREAD;
+ this.MULTISAMPLE_COUNT = configJSON.MULTISAMPLE_COUNT;
+ this.OLD_SPACE_SIZE_MB = configJSON.OLD_SPACE_SIZE_MB;
+ this.ALPHA_BIAS = configJSON.ALPHA_BIAS;
+ this.ANGLE_SNAP_RADIUS_DEGREES = configJSON.ANGLE_SNAP_RADIUS_DEGREES;
+ this.RENDER_TRIANGLE_THRESHOLD = configJSON.RENDER_TRIANGLE_THRESHOLD;
+ this.MAXIMUM_IMAGE_MEM_ALLOC = configJSON.MAXIMUM_IMAGE_MEM_ALLOC;
+ this.CAMERA_FOV_DEGREES = configJSON.CAMERA_FOV_DEGREES;
+ this.CAMERA_DEFAULT_DISTANCE_UNITS = configJSON.CAMERA_DEFAULT_DISTANCE_UNITS;
+ this.CAMERA_DEFAULT_AZIMUTH_RADIANS = configJSON.CAMERA_DEFAULT_AZIMUTH_RADIANS;
+ this.CAMERA_DEFAULT_ELEVATION_RADIANS = configJSON.CAMERA_DEFAULT_ELEVATION_RADIANS;
+ this.CAMERA_SENSITIVITY_ROTATION = configJSON.CAMERA_SENSITIVITY_ROTATION;
+ this.CAMERA_SENSITIVITY_ZOOM = configJSON.CAMERA_SENSITIVITY_ZOOM;
+ }
+
+ public dumpConfig() {
+ LOG(this);
+ }
+}
diff --git a/src/constants.ts b/src/constants.ts
index f18bcdd5..b1fa33b5 100644
--- a/src/constants.ts
+++ b/src/constants.ts
@@ -1,26 +1,26 @@
-export namespace AppConstants {
- export const FACES_PER_VOXEL = 6;
- export const VERTICES_PER_FACE = 4;
- export const INDICES_PER_VOXEL = 24;
- export const COMPONENT_PER_SIZE_OFFSET = FACES_PER_VOXEL * VERTICES_PER_FACE;
-
- export namespace ComponentSize {
- export const TEXCOORD = 2;
- export const POSITION = 3;
- export const COLOUR = 4;
- export const NORMAL = 3;
- export const INDICES = 3;
- export const OCCLUSION = 4;
- }
-
- export namespace VoxelMeshBufferComponentOffsets {
- export const TEXCOORD = ComponentSize.TEXCOORD * COMPONENT_PER_SIZE_OFFSET;
- export const POSITION = ComponentSize.POSITION * COMPONENT_PER_SIZE_OFFSET;
- export const COLOUR = ComponentSize.COLOUR * COMPONENT_PER_SIZE_OFFSET;
- export const NORMAL = ComponentSize.NORMAL * COMPONENT_PER_SIZE_OFFSET;
- export const INDICES = 36;
- export const OCCLUSION = ComponentSize.OCCLUSION * COMPONENT_PER_SIZE_OFFSET;
- }
-
- export const DATA_VERSION = 3105; // 1.19
-}
+export namespace AppConstants {
+ export const FACES_PER_VOXEL = 6;
+ export const VERTICES_PER_FACE = 4;
+ export const INDICES_PER_VOXEL = 24;
+ export const COMPONENT_PER_SIZE_OFFSET = FACES_PER_VOXEL * VERTICES_PER_FACE;
+
+ export namespace ComponentSize {
+ export const TEXCOORD = 2;
+ export const POSITION = 3;
+ export const COLOUR = 4;
+ export const NORMAL = 3;
+ export const INDICES = 3;
+ export const OCCLUSION = 4;
+ }
+
+ export namespace VoxelMeshBufferComponentOffsets {
+ export const TEXCOORD = ComponentSize.TEXCOORD * COMPONENT_PER_SIZE_OFFSET;
+ export const POSITION = ComponentSize.POSITION * COMPONENT_PER_SIZE_OFFSET;
+ export const COLOUR = ComponentSize.COLOUR * COMPONENT_PER_SIZE_OFFSET;
+ export const NORMAL = ComponentSize.NORMAL * COMPONENT_PER_SIZE_OFFSET;
+ export const INDICES = 36;
+ export const OCCLUSION = ComponentSize.OCCLUSION * COMPONENT_PER_SIZE_OFFSET;
+ }
+
+ export const DATA_VERSION = 3105; // 1.19
+}
diff --git a/src/event.ts b/src/event.ts
index 0f1423bd..77972001 100644
--- a/src/event.ts
+++ b/src/event.ts
@@ -1,44 +1,41 @@
-import { ASSERT, LOG } from './util';
-
-/* eslint-disable */
-export enum EAppEvent {
- onModelActiveChanged,
- onModelAvailableChanged,
- onGridEnabledChanged,
- onAxesEnabledChanged,
- onWireframeEnabledChanged,
- onNormalsEnabledChanged,
- onDevViewEnabledChanged,
-}
-/* eslint-enable */
-
-export class EventManager {
- private _eventsToListeners: Map void)[]>;
-
- private static _instance: EventManager;
- public static get Get() {
- return this._instance || (this._instance = new this());
- }
-
- private constructor() {
- this._eventsToListeners = new Map();
- }
-
- public add(event: EAppEvent, delegate: () => void) {
- if (!this._eventsToListeners.has(event)) {
- this._eventsToListeners.set(event, []);
- }
- ASSERT(this._eventsToListeners.get(event) !== undefined, 'No event listener list');
- this._eventsToListeners.get(event)!.push(delegate);
- }
-
- public broadcast(event: EAppEvent, ...payload: any) {
- LOG('[BROADCAST]', EAppEvent[event], payload);
- const listeners = this._eventsToListeners.get(event);
- if (listeners) {
- for (const listener of listeners) {
- listener(payload);
- }
- }
- }
-}
+import { ASSERT } from './util/error_util';
+import { LOG } from './util/log_util';
+
+/* eslint-disable */
+export enum EAppEvent {
+ onTaskStart,
+ onTaskProgress,
+ onTaskEnd,
+}
+/* eslint-enable */
+
+export class EventManager {
+ private _eventsToListeners: Map void)[]>;
+
+ private static _instance: EventManager;
+ public static get Get() {
+ return this._instance || (this._instance = new this());
+ }
+
+ private constructor() {
+ this._eventsToListeners = new Map();
+ }
+
+ public add(event: EAppEvent, delegate: (...args: any[]) => void) {
+ if (!this._eventsToListeners.has(event)) {
+ this._eventsToListeners.set(event, []);
+ }
+ ASSERT(this._eventsToListeners.get(event) !== undefined, 'No event listener list');
+ this._eventsToListeners.get(event)!.push(delegate);
+ }
+
+ public broadcast(event: EAppEvent, ...payload: any) {
+ LOG('[BROADCAST]', EAppEvent[event], payload);
+ const listeners = this._eventsToListeners.get(event);
+ if (listeners) {
+ for (const listener of listeners) {
+ listener(payload);
+ }
+ }
+ }
+}
diff --git a/src/exporters/base_exporter.ts b/src/exporters/base_exporter.ts
index c4d85f8e..84227335 100644
--- a/src/exporters/base_exporter.ts
+++ b/src/exporters/base_exporter.ts
@@ -1,29 +1,23 @@
-import { Vector3 } from '../vector';
-import { BlockMesh } from '../block_mesh';
-import { TOptional } from '../util';
-
-export abstract class IExporter {
- protected _sizeVector!: Vector3;
-
- /** The display name of this exporter */
- public abstract getFormatName(): string;
-
- /** The file type extension of this exporter
- * @note Do not include the dot prefix, e.g. 'obj' not '.obj'.
- */
- public abstract getFileExtension(): string;
-
- /** */
- public getFormatDisclaimer(): TOptional {
- return;
- }
-
- public abstract export(blockMesh: BlockMesh, filePath: string): boolean;
-
- public getFormatFilter() {
- return {
- name: this.getFormatName(),
- extensions: [this.getFileExtension()],
- };
- }
-}
+import { BlockMesh } from '../block_mesh';
+import { Vector3 } from '../vector';
+
+export abstract class IExporter {
+ protected _sizeVector!: Vector3;
+
+ /** The display name of this exporter */
+ public abstract getFormatName(): string;
+
+ /** The file type extension of this exporter
+ * @note Do not include the dot prefix, e.g. 'obj' not '.obj'.
+ */
+ public abstract getFileExtension(): string;
+
+ public abstract export(blockMesh: BlockMesh, filePath: string): boolean;
+
+ public getFormatFilter() {
+ return {
+ name: this.getFormatName(),
+ extensions: [this.getFileExtension()],
+ };
+ }
+}
diff --git a/src/exporters/exporters.ts b/src/exporters/exporters.ts
index a6d1732d..e6898d58 100644
--- a/src/exporters/exporters.ts
+++ b/src/exporters/exporters.ts
@@ -1,28 +1,28 @@
-import { IExporter } from './base_exporter';
-import { Schematic } from './schematic_exporter';
-import { Litematic } from './litematic_exporter';
-import { ASSERT } from '../util';
-import { ObjExporter } from './obj_exporter';
-import { SchemExporter } from './schem_exporter';
-import { NBTExporter } from './nbt_exporter';
-
-export type TExporters = 'schematic' | 'litematic' | 'obj' | 'schem' | 'nbt';
-
-export class ExporterFactory {
- public static GetExporter(voxeliser: TExporters): IExporter {
- switch (voxeliser) {
- case 'schematic':
- return new Schematic();
- case 'litematic':
- return new Litematic();
- case 'obj':
- return new ObjExporter();
- case 'schem':
- return new SchemExporter();
- case 'nbt':
- return new NBTExporter();
- default:
- ASSERT(false);
- }
- }
-}
+import { ASSERT } from '../util/error_util';
+import { IExporter } from './base_exporter';
+import { Litematic } from './litematic_exporter';
+import { NBTExporter } from './nbt_exporter';
+import { ObjExporter } from './obj_exporter';
+import { SchemExporter } from './schem_exporter';
+import { Schematic } from './schematic_exporter';
+
+export type TExporters = 'schematic' | 'litematic' | 'obj' | 'schem' | 'nbt';
+
+export class ExporterFactory {
+ public static GetExporter(voxeliser: TExporters): IExporter {
+ switch (voxeliser) {
+ case 'schematic':
+ return new Schematic();
+ case 'litematic':
+ return new Litematic();
+ case 'obj':
+ return new ObjExporter();
+ case 'schem':
+ return new SchemExporter();
+ case 'nbt':
+ return new NBTExporter();
+ default:
+ ASSERT(false);
+ }
+ }
+}
diff --git a/src/exporters/litematic_exporter.ts b/src/exporters/litematic_exporter.ts
index d5565b6d..9e3f3ac2 100644
--- a/src/exporters/litematic_exporter.ts
+++ b/src/exporters/litematic_exporter.ts
@@ -1,193 +1,237 @@
-import { BlockMesh } from '../block_mesh';
-import { Vector3 } from '../vector';
-import { IExporter } from './base_exporter';
-import { saveNBT } from '../util/nbt_util';
-
-import { NBT, TagType } from 'prismarine-nbt';
-
-type BlockID = number;
-type long = [number, number];
-
-interface BlockMapping {
- [name: string]: BlockID
-}
-
-export class Litematic extends IExporter {
- // XZY
- _getBufferIndex(vec: Vector3) {
- return (this._sizeVector.z * this._sizeVector.x * vec.y) + (this._sizeVector.x * vec.z) + vec.x;
- }
-
- _createBlockMapping(blockMesh: BlockMesh): BlockMapping {
- const blockPalette = blockMesh.getBlockPalette();
-
- const blockMapping: BlockMapping = { 'air': 0 };
- for (let i = 0; i < blockPalette.length; ++i) {
- const blockName = blockPalette[i];
- blockMapping[blockName] = i + 1; // Ensure 0 maps to air
- }
-
- return blockMapping;
- }
-
- _createBlockBuffer(blockMesh: BlockMesh, blockMapping: BlockMapping): Array {
- const bufferSize = this._sizeVector.x * this._sizeVector.y * this._sizeVector.z;
-
- const buffer = Array(bufferSize).fill(0);
- const blocks = blockMesh.getBlocks();
- const bounds = blockMesh.getVoxelMesh().getBounds();
-
- for (const block of blocks) {
- const indexVector = Vector3.sub(block.voxel.position, bounds.min);
- const index = this._getBufferIndex(indexVector);
- buffer[index] = blockMapping[block.blockInfo.name || 'air'];
- }
-
- return buffer;
- }
-
- _createBlockStates(blockMesh: BlockMesh, blockMapping: BlockMapping) {
- const blockEncoding = this._encodeBlockBuffer(blockMesh, blockMapping);
-
- const blockStates = new Array();
-
- for (let i = blockEncoding.length; i > 0; i -= 64) {
- let right = parseInt(blockEncoding.substring(i - 32, i), 2);
- let left = parseInt(blockEncoding.substring(i - 64, i - 32), 2);
-
- // TODO: Cleanup, UINT32 -> INT32
- if (right > 2147483647) {
- right -= 4294967296;
- }
- if (left > 2147483647) {
- left -= 4294967296;
- }
-
- blockStates.push([left, right]);
- }
-
- return blockStates;
- }
-
- _encodeBlockBuffer(blockMesh: BlockMesh, blockMapping: BlockMapping) {
- const blockBuffer = this._createBlockBuffer(blockMesh, blockMapping);
-
- const paletteSize = Object.keys(blockMapping).length;
- let stride = (paletteSize - 1).toString(2).length;
- stride = Math.max(2, stride);
-
- let encoding = '';
- for (let i = blockBuffer.length - 1; i >= 0; --i) {
- encoding += blockBuffer[i].toString(2).padStart(stride, '0');
- }
-
- const requiredLength = Math.ceil(encoding.length / 64) * 64;
- encoding = encoding.padStart(requiredLength, '0');
-
- return encoding;
- }
-
- _createBlockStatePalette(blockMapping: BlockMapping) {
- const blockStatePalette = Array(Object.keys(blockMapping).length);
- for (const block of Object.keys(blockMapping)) {
- const index = blockMapping[block];
- const blockName = 'minecraft:' + block;
- blockStatePalette[index] = { Name: { type: TagType.String, value: blockName } };
- }
- blockStatePalette[0] = { Name: { type: TagType.String, value: 'minecraft:air' } };
-
- return blockStatePalette;
- }
-
- private _convertToNBT(blockMesh: BlockMesh) {
- const bufferSize = this._sizeVector.x * this._sizeVector.y * this._sizeVector.z;
- const blockMapping = this._createBlockMapping(blockMesh);
-
- const blockStates = this._createBlockStates(blockMesh, blockMapping);
- const blockStatePalette = this._createBlockStatePalette(blockMapping);
- const numBlocks = blockMesh.getBlocks().length;
-
- const nbt: NBT = {
- type: TagType.Compound,
- name: 'Litematic',
- value: {
- Metadata: {
- type: TagType.Compound, value: {
- Author: { type: TagType.String, value: '' },
- Description: { type: TagType.String, value: '' },
- Size: {
- type: TagType.Compound, value: {
- x: { type: TagType.Int, value: this._sizeVector.x },
- y: { type: TagType.Int, value: this._sizeVector.y },
- z: { type: TagType.Int, value: this._sizeVector.z },
- },
- },
- Name: { type: TagType.String, value: '' },
- RegionCount: { type: TagType.Int, value: 1 },
- TimeCreated: { type: TagType.Long, value: [0, 0] },
- TimeModified: { type: TagType.Long, value: [0, 0] },
- TotalBlocks: { type: TagType.Int, value: numBlocks },
- TotalVolume: { type: TagType.Int, value: bufferSize },
- },
- },
- Regions: {
- type: TagType.Compound, value: {
- Unnamed: {
- type: TagType.Compound, value: {
- BlockStates: { type: TagType.LongArray, value: blockStates },
- PendingBlockTicks: { type: TagType.List, value: { type: TagType.Int, value: [] } },
- Position: {
- type: TagType.Compound, value: {
- x: { type: TagType.Int, value: 0 },
- y: { type: TagType.Int, value: 0 },
- z: { type: TagType.Int, value: 0 },
- },
- },
- BlockStatePalette: { type: TagType.List, value: { type: TagType.Compound, value: blockStatePalette } },
- Size: {
- type: TagType.Compound, value: {
- x: { type: TagType.Int, value: this._sizeVector.x },
- y: { type: TagType.Int, value: this._sizeVector.y },
- z: { type: TagType.Int, value: this._sizeVector.z },
- },
- },
- PendingFluidTicks: { type: TagType.List, value: { type: TagType.Int, value: [] } },
- TileEntities: { type: TagType.List, value: { type: TagType.Int, value: [] } },
- Entities: { type: TagType.List, value: { type: TagType.Int, value: [] } },
- },
- },
- },
- },
- MinecraftDataVersion: { type: TagType.Int, value: 2730 },
- Version: { type: TagType.Int, value: 5 },
- },
- };
-
- return nbt;
- }
-
- getFormatFilter() {
- return {
- name: this.getFormatName(),
- extensions: ['litematic'],
- };
- }
-
- getFormatName() {
- return 'Litematic';
- }
-
- getFileExtension(): string {
- return 'litematic';
- }
-
- public override export(blockMesh: BlockMesh, filePath: string): boolean {
- const bounds = blockMesh.getVoxelMesh()?.getBounds();
- this._sizeVector = Vector3.sub(bounds.max, bounds.min).add(1);
-
- const nbt = this._convertToNBT(blockMesh);
- saveNBT(nbt, filePath);
-
- return false;
- }
-}
+import { NBT, TagType } from 'prismarine-nbt';
+
+import { BlockMesh } from '../block_mesh';
+import { AppConstants } from '../constants';
+import { ceilToNearest } from '../math';
+import { ASSERT } from '../util/error_util';
+import { saveNBT } from '../util/nbt_util';
+import { Vector3 } from '../vector';
+import { IExporter } from './base_exporter';
+
+type BlockID = number;
+type long = [number, number];
+
+interface BlockMapping {
+ [name: string]: BlockID
+}
+
+export class Litematic extends IExporter {
+ // XZY
+ private _getBufferIndex(vec: Vector3) {
+ return (this._sizeVector.z * this._sizeVector.x * vec.y) + (this._sizeVector.x * vec.z) + vec.x;
+ }
+
+ /**
+ * Create a mapping from block names to their respecitve index in the block state palette
+ */
+ private _createBlockMapping(blockMesh: BlockMesh): BlockMapping {
+ const blockMapping: BlockMapping = { 'minecraft:air': 0 };
+
+ blockMesh.getBlockPalette().forEach((blockName, index) => {
+ blockMapping[blockName] = index + 1;
+ });
+
+ return blockMapping;
+ }
+
+ private _createBlockBuffer(blockMesh: BlockMesh, blockMapping: BlockMapping): Uint32Array {
+ const bufferSize = this._sizeVector.x * this._sizeVector.y * this._sizeVector.z;
+ const bounds = blockMesh.getVoxelMesh().getBounds();
+
+ const buffer = new Uint32Array(bufferSize);
+
+ blockMesh.getBlocks().forEach((block) => {
+ const indexVector = Vector3.sub(block.voxel.position, bounds.min);
+ const bufferIndex = this._getBufferIndex(indexVector);
+ buffer[bufferIndex] = blockMapping[block.blockInfo.name || 'minecraft:air'];
+ });
+
+ return buffer;
+ }
+
+ private _createBlockStates(blockMesh: BlockMesh, blockMapping: BlockMapping) {
+ const buffer = this._encodeBlockBuffer(blockMesh, blockMapping);
+
+ const numBytes = buffer.length;
+ const numBits = numBytes * 8;
+
+ const blockStates = new Array(Math.ceil(numBits / 64));
+
+ let index = 0;
+ for (let i = numBits; i > 0; i -= 64) {
+ const rightBaseIndexBit = i - 32;
+ const rightBaseIndexByte = rightBaseIndexBit / 8;
+
+ let right = 0;
+ right = (right << 8) + buffer[rightBaseIndexByte + 0];
+ right = (right << 8) + buffer[rightBaseIndexByte + 1];
+ right = (right << 8) + buffer[rightBaseIndexByte + 2];
+ right = (right << 8) + buffer[rightBaseIndexByte + 3];
+
+ const leftBaseIndexBit = i - 64;
+ const leftBaseIndexByte = leftBaseIndexBit / 8;
+
+ let left = 0;
+ left = (left << 8) + buffer[leftBaseIndexByte + 0];
+ left = (left << 8) + buffer[leftBaseIndexByte + 1];
+ left = (left << 8) + buffer[leftBaseIndexByte + 2];
+ left = (left << 8) + buffer[leftBaseIndexByte + 3];
+
+ blockStates[index++] = [left, right];
+ }
+
+ return blockStates;
+ }
+
+ private _encodeBlockBuffer(blockMesh: BlockMesh, blockMapping: BlockMapping) {
+ const blockBuffer = this._createBlockBuffer(blockMesh, blockMapping);
+
+ const paletteSize = Object.keys(blockMapping).length;
+ const stride = Math.ceil(Math.log2(paletteSize - 1));
+ ASSERT(stride >= 1, 'Stride too small');
+
+ const expectedLengthBits = blockBuffer.length * stride;
+ const requiredLengthBits = ceilToNearest(expectedLengthBits, 64);
+ const startOffsetBits = requiredLengthBits - expectedLengthBits;
+
+ const requiredLengthBytes = requiredLengthBits / 8;
+ const buffer = Buffer.alloc(requiredLengthBytes);
+
+ // Write first few offset bits
+ const fullBytesToWrite = Math.floor(startOffsetBits / 8);
+ for (let i = 0; i < fullBytesToWrite; ++i) {
+ buffer[i] = 0;
+ }
+
+ const remainingBitsToWrite = startOffsetBits - (fullBytesToWrite * 8);
+ let currentByte = 0;
+ let bitsWrittenToByte = remainingBitsToWrite;
+ let nextBufferWriteIndex = fullBytesToWrite;
+
+ for (let i = blockBuffer.length - 1; i >= 0; --i) {
+ for (let j = 0; j < stride; ++j) {
+ if (bitsWrittenToByte === 8) {
+ buffer[nextBufferWriteIndex] = currentByte;
+ ++nextBufferWriteIndex;
+ currentByte = 0; // Shouldn't be actually necessary to reset
+ bitsWrittenToByte = 0;
+ }
+
+ const bitToAddToByte = (blockBuffer[i] >> (stride - j - 1)) & 1;
+ currentByte = (currentByte << 1) + bitToAddToByte;
+ ++bitsWrittenToByte;
+ }
+ }
+
+ // Write remaining partially filled byte
+ buffer[nextBufferWriteIndex] = currentByte;
+ ++nextBufferWriteIndex;
+ currentByte = 0; // Shouldn't be actually necessary to reset
+ bitsWrittenToByte = 0;
+
+ return buffer;
+ }
+
+ private _createBlockStatePalette(blockMapping: BlockMapping) {
+ const blockStatePalette = Array(Object.keys(blockMapping).length);
+ for (const blockName of Object.keys(blockMapping)) {
+ const index = blockMapping[blockName];
+ blockStatePalette[index] = { Name: { type: TagType.String, value: blockName } };
+ }
+ blockStatePalette[0] = { Name: { type: TagType.String, value: 'minecraft:air' } };
+
+ return blockStatePalette;
+ }
+
+ private _convertToNBT(blockMesh: BlockMesh) {
+ const bufferSize = this._sizeVector.x * this._sizeVector.y * this._sizeVector.z;
+ const blockMapping = this._createBlockMapping(blockMesh);
+
+ const blockStates = this._createBlockStates(blockMesh, blockMapping);
+ const blockStatePalette = this._createBlockStatePalette(blockMapping);
+ const numBlocks = blockMesh.getBlocks().length;
+
+ const nbt: NBT = {
+ type: TagType.Compound,
+ name: 'Litematic',
+ value: {
+ Metadata: {
+ type: TagType.Compound, value: {
+ Author: { type: TagType.String, value: '' },
+ Description: { type: TagType.String, value: '' },
+ Size: {
+ type: TagType.Compound, value: {
+ x: { type: TagType.Int, value: this._sizeVector.x },
+ y: { type: TagType.Int, value: this._sizeVector.y },
+ z: { type: TagType.Int, value: this._sizeVector.z },
+ },
+ },
+ Name: { type: TagType.String, value: '' },
+ RegionCount: { type: TagType.Int, value: 1 },
+ TimeCreated: { type: TagType.Long, value: [0, 0] },
+ TimeModified: { type: TagType.Long, value: [0, 0] },
+ TotalBlocks: { type: TagType.Int, value: numBlocks },
+ TotalVolume: { type: TagType.Int, value: bufferSize },
+ },
+ },
+ Regions: {
+ type: TagType.Compound, value: {
+ Unnamed: {
+ type: TagType.Compound, value: {
+ BlockStates: { type: TagType.LongArray, value: blockStates },
+ PendingBlockTicks: { type: TagType.List, value: { type: TagType.Int, value: [] } },
+ Position: {
+ type: TagType.Compound, value: {
+ x: { type: TagType.Int, value: 0 },
+ y: { type: TagType.Int, value: 0 },
+ z: { type: TagType.Int, value: 0 },
+ },
+ },
+ BlockStatePalette: { type: TagType.List, value: { type: TagType.Compound, value: blockStatePalette } },
+ Size: {
+ type: TagType.Compound, value: {
+ x: { type: TagType.Int, value: this._sizeVector.x },
+ y: { type: TagType.Int, value: this._sizeVector.y },
+ z: { type: TagType.Int, value: this._sizeVector.z },
+ },
+ },
+ PendingFluidTicks: { type: TagType.List, value: { type: TagType.Int, value: [] } },
+ TileEntities: { type: TagType.List, value: { type: TagType.Int, value: [] } },
+ Entities: { type: TagType.List, value: { type: TagType.Int, value: [] } },
+ },
+ },
+ },
+ },
+ MinecraftDataVersion: { type: TagType.Int, value: AppConstants.DATA_VERSION },
+ Version: { type: TagType.Int, value: 5 },
+ },
+ };
+
+ return nbt;
+ }
+
+ getFormatFilter() {
+ return {
+ name: this.getFormatName(),
+ extensions: ['litematic'],
+ };
+ }
+
+ getFormatName() {
+ return 'Litematic';
+ }
+
+ getFileExtension(): string {
+ return 'litematic';
+ }
+
+ public override export(blockMesh: BlockMesh, filePath: string): boolean {
+ const bounds = blockMesh.getVoxelMesh()?.getBounds();
+ this._sizeVector = Vector3.sub(bounds.max, bounds.min).add(1);
+
+ const nbt = this._convertToNBT(blockMesh);
+ saveNBT(nbt, filePath);
+
+ return false;
+ }
+}
diff --git a/src/exporters/nbt_exporter.ts b/src/exporters/nbt_exporter.ts
index 60c78201..9261dbdd 100644
--- a/src/exporters/nbt_exporter.ts
+++ b/src/exporters/nbt_exporter.ts
@@ -1,111 +1,112 @@
-import { NBT, TagType } from 'prismarine-nbt';
-import { LOG } from '../util';
-import { Vector3 } from '../vector';
-import { BlockMesh } from '../block_mesh';
-import { IExporter } from './base_exporter';
-import { saveNBT } from '../util/nbt_util';
-import { AppConstants } from '../constants';
-import { StatusHandler } from '../status';
-
-export class NBTExporter extends IExporter {
- public override getFormatFilter() {
- return {
- name: this.getFormatName(),
- extensions: ['nbt'],
- };
- }
-
- public override getFormatName() {
- return 'Structure Blocks';
- }
-
- public override getFileExtension(): string {
- return 'nbt';
- }
-
- public override export(blockMesh: BlockMesh, filePath: string): boolean {
- const bounds = blockMesh.getVoxelMesh().getBounds();
- const sizeVector = bounds.getDimensions().add(1);
-
- const isTooBig = sizeVector.x > 48 && sizeVector.y > 48 && sizeVector.z > 48;
- if (isTooBig) {
- StatusHandler.Get.add('warning', 'Structure blocks only support structures of size 48x48x48, blocks outside this range will be removed');
- }
-
- const blockNameToIndex = new Map();
- const palette: any = [];
- for (const blockName of blockMesh.getBlockPalette()) {
- palette.push({
- Name: {
- type: TagType.String,
- value: 'minecraft:' + blockName, // TODO: Namespace blocks
- },
- });
- blockNameToIndex.set(blockName, palette.length - 1);
- }
-
- const blocks: any = [];
- for (const block of blockMesh.getBlocks()) {
- const pos = block.voxel.position;
- const blockIndex = blockNameToIndex.get(block.blockInfo.name);
- if (blockIndex) {
- if (pos.x > -24 && pos.x <= 24 && pos.y > -24 && pos.y <= 24 && pos.z > -24 && pos.z <= 24) {
- blocks.push({
- pos: {
- type: TagType.List,
- value: {
- type: TagType.Int,
- value: Vector3.sub(block.voxel.position, bounds.min).toArray(),
- },
- },
- state: {
- type: TagType.Int,
- value: blockIndex,
- },
- });
- }
- }
- }
-
- const nbt: NBT = {
- type: TagType.Compound,
- name: 'SchematicBlocks',
- value: {
- DataVersion: {
- type: TagType.Int,
- value: AppConstants.DATA_VERSION,
- },
- size: {
- type: TagType.List,
- value: {
- type: TagType.Int,
- value: sizeVector.toArray(),
- },
- },
- palette: {
- type: TagType.List,
- value: {
- type: TagType.Compound,
- value: palette,
- },
- },
- blocks: {
- type: TagType.List,
- value: {
- type: TagType.Compound,
- value: blocks,
- },
- },
- },
- };
-
- LOG(nbt);
- saveNBT(nbt, filePath);
-
- return false;
- }
-
- private static _getBufferIndex(dimensions: Vector3, vec: Vector3) {
- return vec.x + (vec.z * dimensions.x) + (vec.y * dimensions.x * dimensions.z);
- }
-}
+import { NBT, TagType } from 'prismarine-nbt';
+
+import { BlockMesh } from '../block_mesh';
+import { AppConstants } from '../constants';
+import { StatusHandler } from '../status';
+import { AppUtil } from '../util';
+import { LOG } from '../util/log_util';
+import { saveNBT } from '../util/nbt_util';
+import { Vector3 } from '../vector';
+import { IExporter } from './base_exporter';
+
+export class NBTExporter extends IExporter {
+ public override getFormatFilter() {
+ return {
+ name: this.getFormatName(),
+ extensions: ['nbt'],
+ };
+ }
+
+ public override getFormatName() {
+ return 'Structure Blocks';
+ }
+
+ public override getFileExtension(): string {
+ return 'nbt';
+ }
+
+ public override export(blockMesh: BlockMesh, filePath: string): boolean {
+ const bounds = blockMesh.getVoxelMesh().getBounds();
+ const sizeVector = bounds.getDimensions().add(1);
+
+ const isTooBig = sizeVector.x > 48 && sizeVector.y > 48 && sizeVector.z > 48;
+ if (isTooBig) {
+ StatusHandler.Get.add('warning', 'Structure blocks only support structures of size 48x48x48, blocks outside this range will be removed');
+ }
+
+ const blockNameToIndex = new Map();
+ const palette: any = [];
+ for (const blockName of blockMesh.getBlockPalette()) {
+ palette.push({
+ Name: {
+ type: TagType.String,
+ value: AppUtil.Text.namespaceBlock(blockName),
+ },
+ });
+ blockNameToIndex.set(blockName, palette.length - 1);
+ }
+
+ const blocks: any = [];
+ for (const block of blockMesh.getBlocks()) {
+ const pos = block.voxel.position;
+ const blockIndex = blockNameToIndex.get(block.blockInfo.name);
+ if (blockIndex) {
+ if (pos.x > -24 && pos.x <= 24 && pos.y > -24 && pos.y <= 24 && pos.z > -24 && pos.z <= 24) {
+ blocks.push({
+ pos: {
+ type: TagType.List,
+ value: {
+ type: TagType.Int,
+ value: Vector3.sub(block.voxel.position, bounds.min).toArray(),
+ },
+ },
+ state: {
+ type: TagType.Int,
+ value: blockIndex,
+ },
+ });
+ }
+ }
+ }
+
+ const nbt: NBT = {
+ type: TagType.Compound,
+ name: 'SchematicBlocks',
+ value: {
+ DataVersion: {
+ type: TagType.Int,
+ value: AppConstants.DATA_VERSION,
+ },
+ size: {
+ type: TagType.List,
+ value: {
+ type: TagType.Int,
+ value: sizeVector.toArray(),
+ },
+ },
+ palette: {
+ type: TagType.List,
+ value: {
+ type: TagType.Compound,
+ value: palette,
+ },
+ },
+ blocks: {
+ type: TagType.List,
+ value: {
+ type: TagType.Compound,
+ value: blocks,
+ },
+ },
+ },
+ };
+
+ saveNBT(nbt, filePath);
+
+ return false;
+ }
+
+ private static _getBufferIndex(dimensions: Vector3, vec: Vector3) {
+ return vec.x + (vec.z * dimensions.x) + (vec.y * dimensions.x * dimensions.z);
+ }
+}
diff --git a/src/exporters/obj_exporter.ts b/src/exporters/obj_exporter.ts
index 7ae06cb7..00f719ff 100644
--- a/src/exporters/obj_exporter.ts
+++ b/src/exporters/obj_exporter.ts
@@ -1,106 +1,161 @@
-import { BlockMesh } from '../block_mesh';
-import { IExporter } from './base_exporter';
-import { ASSERT, ATLASES_DIR } from '../util';
-
-import fs from 'fs';
-import path from 'path';
-
-export class ObjExporter extends IExporter {
- public override getFormatFilter(): Electron.FileFilter {
- return {
- name: 'Wavefront Obj',
- extensions: ['obj'],
- };
- }
-
- public override getFileExtension(): string {
- return 'obj';
- }
-
- public override getFormatName(): string {
- return 'Wavefront OBJ';
- }
-
- public override export(blockMesh: BlockMesh, filepath: string) {
- ASSERT(path.isAbsolute(filepath));
- const parsedPath = path.parse(filepath);
-
- const filepathOBJ = filepath;
- const filepathMTL = path.join(parsedPath.dir, parsedPath.name + '.mtl');
- const filepathTexture = path.join(parsedPath.dir, parsedPath.name + '.png');
-
- this._exportOBJ(filepathOBJ, blockMesh, parsedPath.name + '.mtl');
- this._exportMTL(filepathMTL, filepathTexture, blockMesh);
-
- return true;
- }
-
- private _exportOBJ(filepath: string, blockMesh: BlockMesh, mtlRelativePath: string) {
- const buffer = blockMesh.createBuffer();
- const positionData = buffer.position.data as Float32Array;
- const normalData = buffer.normal.data as Float32Array;
- const texcoordData = buffer.texcoord.data as Float32Array;
- const blockTexcoordData = buffer.blockTexcoord.data as Float32Array;
- const indexData = buffer.indices.data as Uint32Array;
-
- const writeStream = fs.createWriteStream(filepath);
-
- writeStream.write('# Created with ObjToSchematic\n');
- writeStream.write('# https://github.com/LucasDower/ObjToSchematic/\n\n');
-
- if (positionData && normalData && texcoordData && indexData && blockTexcoordData) {
- const numTris = indexData.length / 3;
- // Add vertex data
- writeStream.write(`mtllib ${mtlRelativePath}\n`);
- writeStream.write(`o Object\n`);
- for (let i = 0; i < positionData.length / 3; ++i) {
- writeStream.write(`v ${positionData[3 * i + 0]} ${positionData[3 * i + 1]} ${positionData[3 * i + 2]}\n`);
- }
- // Add texcoord data
- const atlasSize = blockMesh.getAtlasSize();
- for (let i = 0; i < texcoordData.length / 2; ++i) {
- // vec2 tex = v_blockTexcoord + (v_texcoord / (u_atlasSize * 3.0));
- const u = blockTexcoordData[2 * i + 0] + (texcoordData[2 * i + 0] / (atlasSize * 3.0));
- const v = blockTexcoordData[2 * i + 1] + (texcoordData[2 * i + 1] / (atlasSize * 3.0));
- writeStream.write(`vt ${u} ${1.0 - v}\n`);
- }
- // Add normal data
- for (let i = 0; i < normalData.length / 3; ++i) {
- writeStream.write(`vn ${normalData[3 * i + 0]} ${normalData[3 * i + 1]} ${normalData[3 * i + 2]}\n`);
- }
-
- writeStream.write(`usemtl Default\n`);
- // Add face data
- for (let i = 0; i < numTris * 3; i += 3) {
- const a = indexData[i + 0] + 1;
- const b = indexData[i + 1] + 1;
- const c = indexData[i + 2] + 1;
- writeStream.write(`f ${a}/${a}/${a} ${b}/${b}/${b} ${c}/${c}/${c}\n`);
- }
- // Export to file
- }
-
- writeStream.end();
- }
-
- private _exportMTL(filepathMTL: string, filepathTexture: string, blockMesh: BlockMesh) {
- ASSERT(path.isAbsolute(filepathMTL));
- ASSERT(path.isAbsolute(filepathTexture));
-
- const mtlData: string[] = [];
- mtlData.push('# Created with ObjToSchematic');
- mtlData.push('# https://github.com/LucasDower/ObjToSchematic/');
-
- mtlData.push('newmtl Default');
- mtlData.push('Kd 1.000000 1.000000 1.000000');
- mtlData.push(`map_Kd ${filepathTexture}`);
-
- // Export to file
- const outputString = mtlData.join('\n');
- fs.writeFileSync(filepathMTL, outputString);
-
- // Export texture
- const filepathAtlasTexture = path.join(ATLASES_DIR, blockMesh.getAtlasUsed() + '.png');
- fs.copyFileSync(filepathAtlasTexture, filepathTexture);
- }
-}
+import fs from 'fs';
+import path from 'path';
+
+import { BlockMesh } from '../block_mesh';
+import { TBlockMeshBufferDescription } from '../buffer';
+import { ASSERT } from '../util/error_util';
+import { IExporter } from './base_exporter';
+
+export class ObjExporter extends IExporter {
+ public override getFormatFilter(): Electron.FileFilter {
+ return {
+ name: 'Wavefront Obj',
+ extensions: ['obj'],
+ };
+ }
+
+ public override getFileExtension(): string {
+ return 'obj';
+ }
+
+ public override getFormatName(): string {
+ return 'Wavefront OBJ';
+ }
+
+ public override export(blockMesh: BlockMesh, filepath: string) {
+ ASSERT(path.isAbsolute(filepath));
+ const parsedPath = path.parse(filepath);
+
+ const filepathOBJ = filepath;
+ const filepathMTL = path.join(parsedPath.dir, parsedPath.name + '.mtl');
+ const filepathTexture = path.join(parsedPath.dir, parsedPath.name + '.png');
+
+ this._exportOBJ(filepathOBJ, blockMesh, parsedPath.name + '.mtl');
+ this._exportMTL(filepathMTL, filepathTexture, blockMesh);
+
+ return true;
+ }
+
+ private _exportOBJ(filepath: string, blockMesh: BlockMesh, mtlRelativePath: string) {
+ const buffers: Array = [];
+ let chunkIndex = 0;
+ do {
+ buffers.push(blockMesh.getChunkedBuffer(chunkIndex));
+ ++chunkIndex;
+ } while (buffers[buffers.length - 1].moreBlocksToBuffer);
+
+ // Fix indices
+ let indexOffset = 0;
+ buffers.forEach(({ buffer }, bufferIndex) => {
+ let maxIndex = 0;
+ for (let i = 0; i < buffer.indices.data.length; ++i) {
+ maxIndex = Math.max(maxIndex, buffer.indices.data[i]);
+ buffer.indices.data[i] += indexOffset;
+ }
+ indexOffset += maxIndex + 1;
+ });
+
+ //const buffers = blockMesh.getAllChunkedBuffers();
+ let numPositions = 0;
+ let numNormals = 0;
+ let numTexcoords = 0;
+ let numBlockTexcoords = 0;
+ let numIndices = 0;
+
+ buffers.forEach(({ buffer }) => {
+ numPositions += buffer.position.data.length;
+ numNormals += buffer.normal.data.length;
+ numTexcoords += buffer.texcoord.data.length;
+ numBlockTexcoords += buffer.blockTexcoord.data.length;
+ numIndices += buffer.indices.data.length;
+ });
+
+ const positionData = new Float32Array(numPositions);
+ const normalData = new Float32Array(numNormals);
+ const texcoordData = new Float32Array(numTexcoords);
+ const blockTexcoordData = new Float32Array(numBlockTexcoords);
+ const indexData = new Float32Array(numIndices);
+
+ let positionIndex = 0;
+ let normalIndex = 0;
+ let texcoordIndex = 0;
+ let blockTexcoordIndex = 0;
+ let indicesIndex = 0;
+
+ buffers.forEach(({ buffer }) => {
+ positionData.set(buffer.position.data, positionIndex);
+ positionIndex += buffer.position.data.length;
+
+ normalData.set(buffer.normal.data, normalIndex);
+ normalIndex += buffer.normal.data.length;
+
+ texcoordData.set(buffer.texcoord.data, texcoordIndex);
+ texcoordIndex += buffer.texcoord.data.length;
+
+ blockTexcoordData.set(buffer.blockTexcoord.data, blockTexcoordIndex);
+ blockTexcoordIndex += buffer.blockTexcoord.data.length;
+
+ indexData.set(buffer.indices.data, indicesIndex);
+ indicesIndex += buffer.indices.data.length;
+ });
+
+ const file = fs.openSync(filepath, 'w');
+ fs.writeSync(file, '# Created with ObjToSchematic\n');
+ fs.writeSync(file, '# https://github.com/LucasDower/ObjToSchematic/\n\n');
+
+ if (positionData && normalData && texcoordData && indexData && blockTexcoordData) {
+ const numTris = indexData.length / 3;
+ // Add vertex data
+ fs.writeSync(file, `mtllib ${mtlRelativePath}\n`);
+ fs.writeSync(file, `o Object\n`);
+ for (let i = 0; i < positionData.length / 3; ++i) {
+ fs.writeSync(file, `v ${positionData[3 * i + 0]} ${positionData[3 * i + 1]} ${positionData[3 * i + 2]}\n`);
+ }
+ // Add texcoord data
+ const atlasSize = blockMesh.getAtlas().getAtlasSize();
+ for (let i = 0; i < texcoordData.length / 2; ++i) {
+ // vec2 tex = v_blockTexcoord + (v_texcoord / (u_atlasSize * 3.0));
+ const u = blockTexcoordData[2 * i + 0] + (texcoordData[2 * i + 0] / (atlasSize * 3.0));
+ const v = blockTexcoordData[2 * i + 1] + (texcoordData[2 * i + 1] / (atlasSize * 3.0));
+ fs.writeSync(file, `vt ${u} ${1.0 - v}\n`);
+ }
+ // Add normal data
+ for (let i = 0; i < normalData.length / 3; ++i) {
+ fs.writeSync(file, `vn ${normalData[3 * i + 0]} ${normalData[3 * i + 1]} ${normalData[3 * i + 2]}\n`);
+ }
+
+ fs.writeSync(file, `usemtl Default\n`);
+ // Add face data
+ for (let i = 0; i < numTris * 3; i += 3) {
+ const a = indexData[i + 0] + 1;
+ const b = indexData[i + 1] + 1;
+ const c = indexData[i + 2] + 1;
+ fs.writeSync(file, `f ${a}/${a}/${a} ${b}/${b}/${b} ${c}/${c}/${c}\n`);
+ }
+ // Export to file
+ }
+
+ fs.closeSync(file);
+ }
+
+ private _exportMTL(filepathMTL: string, filepathTexture: string, blockMesh: BlockMesh) {
+ ASSERT(path.isAbsolute(filepathMTL));
+ ASSERT(path.isAbsolute(filepathTexture));
+
+ const mtlData: string[] = [];
+ mtlData.push('# Created with ObjToSchematic');
+ mtlData.push('# https://github.com/LucasDower/ObjToSchematic/');
+
+ mtlData.push('newmtl Default');
+ mtlData.push('Kd 1.000000 1.000000 1.000000');
+ mtlData.push(`map_Kd ${filepathTexture}`);
+
+ // Export to file
+ const outputString = mtlData.join('\n');
+ fs.writeFileSync(filepathMTL, outputString);
+
+ // Export texture
+ const filepathAtlasTexture = blockMesh.getAtlas().getAtlasTexturePath();
+ fs.copyFileSync(filepathAtlasTexture, filepathTexture);
+ }
+}
diff --git a/src/exporters/schem_exporter.ts b/src/exporters/schem_exporter.ts
index 9e19f685..045f9327 100644
--- a/src/exporters/schem_exporter.ts
+++ b/src/exporters/schem_exporter.ts
@@ -1,82 +1,96 @@
-import { NBT, TagType } from 'prismarine-nbt';
-import { LOG } from '../util';
-import { Vector3 } from '../vector';
-import { BlockMesh } from '../block_mesh';
-import { IExporter } from './base_exporter';
-import { saveNBT } from '../util/nbt_util';
-import { AppConstants } from '../constants';
-
-const varintarray = require('varint-array');
-
-export class SchemExporter extends IExporter {
- public override getFormatFilter() {
- return {
- name: this.getFormatName(),
- extensions: ['schem'],
- };
- }
-
- public override getFormatName() {
- return 'Sponge Schematic';
- }
-
- public override getFileExtension(): string {
- return 'schem';
- }
-
- private static SCHEMA_VERSION = 2;
-
- public override export(blockMesh: BlockMesh, filePath: string): boolean {
- const bounds = blockMesh.getVoxelMesh().getBounds();
- const sizeVector = bounds.getDimensions().add(1);
-
- // https://github.com/SpongePowered/Schematic-Specification/blob/master/versions/schematic-3.md#paletteObject
- // const blockMapping: BlockMapping = {};
- const test: {[name: string]: { type: TagType, value: any }} = {
- 'minecraft:air': { type: TagType.Int, value: 0 },
- };
-
- let blockIndex = 1;
- for (const blockName of blockMesh.getBlockPalette()) {
- const namespacedBlockName = 'minecraft:' + blockName; // FIXME: All block names should be namespaced on import
- // ASSERT(!(namespacedBlockName in blockMapping));
- // blockMapping[namespacedBlockName] = blockIndex;
- test[namespacedBlockName] = { type: TagType.Int, value: blockIndex };
- ++blockIndex;
- }
- LOG(test);
-
- // const paletteObject = SchemExporter._createBlockStatePalette(blockMapping);
- const blockData = new Array(sizeVector.x * sizeVector.y * sizeVector.z).fill(0);
- for (const block of blockMesh.getBlocks()) {
- const indexVector = Vector3.sub(block.voxel.position, bounds.min);
- const bufferIndex = SchemExporter._getBufferIndex(sizeVector, indexVector);
- const namespacedBlockName = 'minecraft:' + block.blockInfo.name;
- blockData[bufferIndex] = test[namespacedBlockName].value;
- }
-
- const nbt: NBT = {
- type: TagType.Compound,
- name: 'Schematic',
- value: {
- Version: { type: TagType.Int, value: SchemExporter.SCHEMA_VERSION },
- DataVersion: { type: TagType.Int, value: AppConstants.DATA_VERSION },
- Width: { type: TagType.Short, value: sizeVector.x },
- Height: { type: TagType.Short, value: sizeVector.y },
- Length: { type: TagType.Short, value: sizeVector.z },
- PaletteMax: { type: TagType.Int, value: blockIndex },
- Palette: { type: TagType.Compound, value: test },
- BlockData: { type: TagType.ByteArray, value: varintarray.encode(blockData) },
- },
- };
-
- LOG(nbt);
- saveNBT(nbt, filePath);
-
- return false;
- }
-
- private static _getBufferIndex(dimensions: Vector3, vec: Vector3) {
- return vec.x + (vec.z * dimensions.x) + (vec.y * dimensions.x * dimensions.z);
- }
-}
+import { NBT, TagType } from 'prismarine-nbt';
+
+import { BlockMesh } from '../block_mesh';
+import { AppConstants } from '../constants';
+import { AppUtil } from '../util';
+import { LOG } from '../util/log_util';
+import { MathUtil } from '../util/math_util';
+import { saveNBT } from '../util/nbt_util';
+import { Vector3 } from '../vector';
+import { IExporter } from './base_exporter';
+
+export class SchemExporter extends IExporter {
+ public override getFormatFilter() {
+ return {
+ name: this.getFormatName(),
+ extensions: ['schem'],
+ };
+ }
+
+ public override getFormatName() {
+ return 'Sponge Schematic';
+ }
+
+ public override getFileExtension(): string {
+ return 'schem';
+ }
+
+ private static SCHEMA_VERSION = 2;
+
+ public override export(blockMesh: BlockMesh, filePath: string): boolean {
+ const bounds = blockMesh.getVoxelMesh().getBounds();
+ const sizeVector = bounds.getDimensions().add(1);
+
+ // https://github.com/SpongePowered/Schematic-Specification/blob/master/versions/schematic-3.md#paletteObject
+ // const blockMapping: BlockMapping = {};
+ const blockMapping: {[name: string]: { type: TagType, value: any }} = {
+ 'minecraft:air': { type: TagType.Int, value: 0 },
+ };
+
+ let blockIndex = 1;
+ for (const blockName of blockMesh.getBlockPalette()) {
+ const namespacedBlockName = AppUtil.Text.namespaceBlock(blockName);
+
+ blockMapping[namespacedBlockName] = { type: TagType.Int, value: blockIndex };
+ ++blockIndex;
+ }
+ LOG(blockMapping);
+
+ // const paletteObject = SchemExporter._createBlockStatePalette(blockMapping);
+ const blockData = new Array(sizeVector.x * sizeVector.y * sizeVector.z).fill(0);
+ for (const block of blockMesh.getBlocks()) {
+ const indexVector = Vector3.sub(block.voxel.position, bounds.min);
+ const bufferIndex = SchemExporter._getBufferIndex(sizeVector, indexVector);
+ const namespacedBlockName = AppUtil.Text.namespaceBlock(block.blockInfo.name);
+ blockData[bufferIndex] = blockMapping[namespacedBlockName].value;
+ }
+
+ const blockEncoding: number[] = [];
+ for (let i = 0; i < blockData.length; ++i) {
+ let id = blockData[i];
+
+ while ((id & -128) != 0) {
+ blockEncoding.push(id & 127 | 128);
+ id >>>= 7;
+ }
+ blockEncoding.push(id);
+ }
+
+ for (let i = 0; i < blockEncoding.length; ++i) {
+ blockEncoding[i] = MathUtil.int8(blockEncoding[i]);
+ }
+
+ const nbt: NBT = {
+ type: TagType.Compound,
+ name: 'Schematic',
+ value: {
+ Version: { type: TagType.Int, value: SchemExporter.SCHEMA_VERSION },
+ DataVersion: { type: TagType.Int, value: AppConstants.DATA_VERSION },
+ Width: { type: TagType.Short, value: sizeVector.x },
+ Height: { type: TagType.Short, value: sizeVector.y },
+ Length: { type: TagType.Short, value: sizeVector.z },
+ PaletteMax: { type: TagType.Int, value: blockIndex },
+ Palette: { type: TagType.Compound, value: blockMapping },
+ BlockData: { type: TagType.ByteArray, value: blockEncoding },
+ },
+ };
+
+ saveNBT(nbt, filePath);
+
+ return false;
+ }
+
+ private static _getBufferIndex(dimensions: Vector3, vec: Vector3) {
+ return vec.x + (vec.z * dimensions.x) + (vec.y * dimensions.x * dimensions.z);
+ }
+}
diff --git a/src/exporters/schematic_exporter.ts b/src/exporters/schematic_exporter.ts
index 14c06b48..fdc8a93c 100644
--- a/src/exporters/schematic_exporter.ts
+++ b/src/exporters/schematic_exporter.ts
@@ -1,99 +1,97 @@
-import { BlockMesh } from '../block_mesh';
-import { RESOURCES_DIR } from '../util';
-import { IExporter } from './base_exporter';
-import { Vector3 } from '../vector';
-import { StatusHandler } from '../status';
-
-import path from 'path';
-import fs from 'fs';
-import { NBT, TagType } from 'prismarine-nbt';
-import { saveNBT } from '../util/nbt_util';
-
-export class Schematic extends IExporter {
- private _convertToNBT(blockMesh: BlockMesh) {
- const bufferSize = this._sizeVector.x * this._sizeVector.y * this._sizeVector.z;
-
- const blocksData = Array(bufferSize);
- const metaData = Array(bufferSize);
- const bounds = blockMesh.getVoxelMesh().getBounds();
-
- const schematicBlocks: { [blockName: string]: { id: number, meta: number, name: string } } = JSON.parse(
- fs.readFileSync(path.join(RESOURCES_DIR, './block_ids.json'), 'utf8'),
- );
-
- const blocks = blockMesh.getBlocks();
- const unsupportedBlocks = new Set();
- let numBlocksUnsupported = 0;
- for (const block of blocks) {
- const indexVector = Vector3.sub(block.voxel.position, bounds.min);
- const index = this._getBufferIndex(indexVector, this._sizeVector);
- if (block.blockInfo.name in schematicBlocks) {
- const schematicBlock = schematicBlocks[block.blockInfo.name];
- blocksData[index] = new Int8Array([schematicBlock.id])[0];
- metaData[index] = new Int8Array([schematicBlock.meta])[0];
- } else {
- blocksData[index] = 1; // Default to a Stone block
- metaData[index] = 0;
- unsupportedBlocks.add(block.blockInfo.name);
- ++numBlocksUnsupported;
- }
- }
-
- if (unsupportedBlocks.size > 0) {
- StatusHandler.Get.add(
- 'warning',
- `${numBlocksUnsupported} blocks (${unsupportedBlocks.size} unique) are not supported by the .schematic format, Stone block are used in their place. Try using the schematic-friendly palette, or export using .litematica`,
- );
- }
-
- const nbt: NBT = {
- type: TagType.Compound,
- name: 'Schematic',
- value: {
- Width: { type: TagType.Short, value: this._sizeVector.x },
- Height: { type: TagType.Short, value: this._sizeVector.y },
- Length: { type: TagType.Short, value: this._sizeVector.z },
- Materials: { type: TagType.String, value: 'Alpha' },
- Blocks: { type: TagType.ByteArray, value: blocksData },
- Data: { type: TagType.ByteArray, value: metaData },
- Entities: { type: TagType.List, value: { type: TagType.Int, value: Array(0) } },
- TileEntities: { type: TagType.List, value: { type: TagType.Int, value: Array(0) } },
- },
- };
-
- return nbt;
- }
-
- _getBufferIndex(vec: Vector3, sizeVector: Vector3) {
- return (sizeVector.z * sizeVector.x * vec.y) + (sizeVector.x * vec.z) + vec.x;
- }
-
- getFormatFilter() {
- return {
- name: this.getFormatName(),
- extensions: ['schematic'],
- };
- }
-
- getFormatName() {
- return 'Schematic';
- }
-
- getFormatDisclaimer() {
- return 'Schematic files only support pre-1.13 blocks. As a result, all blocks will be exported as Stone. To export the blocks, use the .litematic format with the Litematica mod.';
- }
-
- getFileExtension(): string {
- return 'schematic';
- }
-
- public override export(blockMesh: BlockMesh, filePath: string): boolean {
- const bounds = blockMesh.getVoxelMesh()?.getBounds();
- this._sizeVector = Vector3.sub(bounds.max, bounds.min).add(1);
-
- const nbt = this._convertToNBT(blockMesh);
- saveNBT(nbt, filePath);
-
- return false;
- }
-}
+import fs from 'fs';
+import { NBT, TagType } from 'prismarine-nbt';
+
+import { BlockMesh } from '../block_mesh';
+import { StatusHandler, StatusID } from '../status';
+import { LOG_WARN } from '../util/log_util';
+import { saveNBT } from '../util/nbt_util';
+import { AppPaths, PathUtil } from '../util/path_util';
+import { Vector3 } from '../vector';
+import { IExporter } from './base_exporter';
+
+export class Schematic extends IExporter {
+ private _convertToNBT(blockMesh: BlockMesh) {
+ const bufferSize = this._sizeVector.x * this._sizeVector.y * this._sizeVector.z;
+
+ const blocksData = Array(bufferSize);
+ const metaData = Array(bufferSize);
+ const bounds = blockMesh.getVoxelMesh().getBounds();
+
+ const schematicBlocks: { [blockName: string]: { id: number, meta: number, name: string } } = JSON.parse(
+ fs.readFileSync(PathUtil.join(AppPaths.Get.resources, './block_ids.json'), 'utf8'),
+ );
+
+ const blocks = blockMesh.getBlocks();
+ const unsupportedBlocks = new Set();
+ let numBlocksUnsupported = 0;
+ for (const block of blocks) {
+ const indexVector = Vector3.sub(block.voxel.position, bounds.min);
+ const index = this._getBufferIndex(indexVector, this._sizeVector);
+ if (block.blockInfo.name in schematicBlocks) {
+ const schematicBlock = schematicBlocks[block.blockInfo.name];
+ blocksData[index] = new Int8Array([schematicBlock.id])[0];
+ metaData[index] = new Int8Array([schematicBlock.meta])[0];
+ } else {
+ blocksData[index] = 1; // Default to a Stone block
+ metaData[index] = 0;
+ unsupportedBlocks.add(block.blockInfo.name);
+ ++numBlocksUnsupported;
+ }
+ }
+
+ if (unsupportedBlocks.size > 0) {
+ StatusHandler.Get.add(
+ 'warning',
+ `${numBlocksUnsupported} blocks (${unsupportedBlocks.size} unique) are not supported by the .schematic format, Stone block are used in their place. Try using the schematic-friendly palette, or export using .litematica`,
+ StatusID.SchematicUnsupportedBlocks,
+ );
+ LOG_WARN(unsupportedBlocks);
+ }
+
+ const nbt: NBT = {
+ type: TagType.Compound,
+ name: 'Schematic',
+ value: {
+ Width: { type: TagType.Short, value: this._sizeVector.x },
+ Height: { type: TagType.Short, value: this._sizeVector.y },
+ Length: { type: TagType.Short, value: this._sizeVector.z },
+ Materials: { type: TagType.String, value: 'Alpha' },
+ Blocks: { type: TagType.ByteArray, value: blocksData },
+ Data: { type: TagType.ByteArray, value: metaData },
+ Entities: { type: TagType.List, value: { type: TagType.Int, value: Array(0) } },
+ TileEntities: { type: TagType.List, value: { type: TagType.Int, value: Array(0) } },
+ },
+ };
+
+ return nbt;
+ }
+
+ _getBufferIndex(vec: Vector3, sizeVector: Vector3) {
+ return (sizeVector.z * sizeVector.x * vec.y) + (sizeVector.x * vec.z) + vec.x;
+ }
+
+ getFormatFilter() {
+ return {
+ name: this.getFormatName(),
+ extensions: ['schematic'],
+ };
+ }
+
+ getFormatName() {
+ return 'Schematic';
+ }
+
+ getFileExtension(): string {
+ return 'schematic';
+ }
+
+ public override export(blockMesh: BlockMesh, filePath: string): boolean {
+ const bounds = blockMesh.getVoxelMesh().getBounds();
+ this._sizeVector = Vector3.sub(bounds.max, bounds.min).add(1);
+
+ const nbt = this._convertToNBT(blockMesh);
+ saveNBT(nbt, filePath);
+
+ return false;
+ }
+}
diff --git a/src/geometry.ts b/src/geometry.ts
index af7bd31d..9c2bafe0 100644
--- a/src/geometry.ts
+++ b/src/geometry.ts
@@ -1,377 +1,484 @@
-import * as twgl from 'twgl.js';
-import { Triangle, UVTriangle } from './triangle';
-import { Vector3 } from './vector';
-import { AttributeData, MergeAttributeData, RenderBuffer } from './buffer';
-import { ASSERT, Bounds } from './util';
-import { Mesh } from './mesh';
-import { VoxelMesh } from './voxel_mesh';
-import { RGBA } from './colour';
-
-export class GeometryTemplates {
- private static readonly _default_cube = twgl.primitives.createCubeVertices(1.0);
-
- static getTriangleBufferData(triangle: UVTriangle): AttributeData {
- const n = triangle.getNormal();
-
- return {
- custom: {
- position: [
- triangle.v0.x, triangle.v0.y, triangle.v0.z,
- triangle.v1.x, triangle.v1.y, triangle.v1.z,
- triangle.v2.x, triangle.v2.y, triangle.v2.z,
- ],
- texcoord: [
- triangle.uv0.u, triangle.uv0.v,
- triangle.uv1.u, triangle.uv1.v,
- triangle.uv2.u, triangle.uv2.v,
- ],
- normal: [
- n.x, n.y, n.z,
- n.x, n.y, n.z,
- n.x, n.y, n.z,
- ],
- },
- indices: new Uint32Array([
- 0, 1, 2,
- ]),
- };
- }
-
- static getBoxBufferData(centre: Vector3): AttributeData {
- const cube: AttributeData = {
- custom: {
- position: new Array(72),
- texcoord: new Array(48),
- normal: new Array(72),
- },
- indices: new Uint32Array(72),
- };
-
- cube.custom.position = Array.from(GeometryTemplates._default_cube.position);
- cube.custom.normal = Array.from(GeometryTemplates._default_cube.normal);
- cube.custom.texcoord = Array.from(GeometryTemplates._default_cube.texcoord);
- cube.indices = Uint32Array.from(GeometryTemplates._default_cube.indices);
-
- for (let i = 0; i < 72; i += 3) {
- cube.custom.position[i + 0] += centre.x;
- cube.custom.position[i + 1] += centre.y;
- cube.custom.position[i + 2] += centre.z;
- }
-
- return cube;
- }
-}
-
-export class DebugGeometryTemplates {
- public static cross(centre: Vector3, radius: number, colour: RGBA): AttributeData {
- return {
- indices: new Uint32Array([0, 1, 2, 3, 4, 5]),
- custom: {
- position: [
- centre.x + radius, centre.y, centre.z,
- centre.x - radius, centre.y, centre.z,
- centre.x, centre.y + radius, centre.z,
- centre.x, centre.y - radius, centre.z,
- centre.x, centre.y, centre.z + radius,
- centre.x, centre.y, centre.z - radius,
- ],
- colour: [
- colour.r, colour.g, colour.b, colour.a,
- colour.r, colour.g, colour.b, colour.a,
- colour.r, colour.g, colour.b, colour.a,
- colour.r, colour.g, colour.b, colour.a,
- colour.r, colour.g, colour.b, colour.a,
- ],
- },
- };
- }
-
- public static line(start: Vector3, end: Vector3, colour: RGBA): AttributeData {
- return {
- indices: new Uint32Array([0, 1]),
- custom: {
- position: [
- start.x, start.y, start.z,
- end.x, end.y, end.z,
- ],
- colour: [
- colour.r, colour.g, colour.b, colour.a,
- colour.r, colour.g, colour.b, colour.a,
- ],
- },
- };
- }
-
- public static cube(centre: Vector3, size: number, colour: RGBA): AttributeData {
- const min = Vector3.sub(centre, size/2);
- const max = Vector3.add(centre, size/2);
- const bounds = new Bounds(min, max);
- return this.bounds(bounds, colour);
- }
-
- public static bounds(bounds: Bounds, colour: RGBA): AttributeData {
- return {
- indices: new Uint32Array([
- 0, 1,
- 1, 2,
- 2, 3,
- 3, 0,
- 4, 5,
- 5, 6,
- 6, 7,
- 7, 4,
- 0, 4,
- 1, 5,
- 2, 6,
- 3, 7,
- ]),
- custom: {
- position: [
- bounds.min.x, bounds.min.y, bounds.min.z,
- bounds.max.x, bounds.min.y, bounds.min.z,
- bounds.max.x, bounds.min.y, bounds.max.z,
- bounds.min.x, bounds.min.y, bounds.max.z,
- bounds.min.x, bounds.max.y, bounds.min.z,
- bounds.max.x, bounds.max.y, bounds.min.z,
- bounds.max.x, bounds.max.y, bounds.max.z,
- bounds.min.x, bounds.max.y, bounds.max.z,
- ],
- colour: [
- colour.r, colour.g, colour.b, colour.a,
- colour.r, colour.g, colour.b, colour.a,
- colour.r, colour.g, colour.b, colour.a,
- colour.r, colour.g, colour.b, colour.a,
- colour.r, colour.g, colour.b, colour.a,
- colour.r, colour.g, colour.b, colour.a,
- colour.r, colour.g, colour.b, colour.a,
- colour.r, colour.g, colour.b, colour.a,
- ],
- },
- };
- }
-
- public static circle(centre: Vector3, normal: Vector3, radius: number, colour: RGBA, steps: number = 8): AttributeData {
- const indices = [];
- const positions = [];
- const colours = [];
-
- const circlePoints = DebugGeometryTemplates._generateCirclePoints(centre, normal, radius, steps);
- for (let i = 0; i < steps; ++i) {
- const point = circlePoints[i];
- positions.push(point.x, point.y, point.z);
- indices.push(i, (i+1) % steps);
- colours.push(colour.r, colour.g, colour.b, colour.a);
- }
-
- return {
- indices: new Uint32Array(indices),
- custom: {
- position: positions,
- colour: colours,
- },
- };
- }
-
- public static cone(tipCentre: Vector3, tipHeight: number, normal: Vector3, radius: number, colour: RGBA, quarterSteps: number): AttributeData {
- const indices = [];
- const positions = [];
- const colours = [];
-
- const steps = quarterSteps * 4;
- const circleCentre = Vector3.add(tipCentre, Vector3.mulScalar(normal.copy().normalise(), -tipHeight));
- const circlePoints = DebugGeometryTemplates._generateCirclePoints(circleCentre, normal, radius, steps);
-
- // Add circle data
- for (let i = 0; i < steps; ++i) {
- const point = circlePoints[i];
- positions.push(point.x, point.y, point.z);
- indices.push(i, (i+1) % steps);
- colours.push(colour.r, colour.g, colour.b, colour.a);
- }
- // Add cone tip
- positions.push(tipCentre.x, tipCentre.y, tipCentre.z);
- colours.push(colour.r, colour.g, colour.b, colour.a);
- const tipIndex = steps;
- // Add cone lines
- for (let i = 0; i < 4; ++i) {
- const coneIndex = i * quarterSteps;
- indices.push(tipIndex, coneIndex);
- }
-
- return {
- indices: new Uint32Array(indices),
- custom: {
- position: positions,
- colour: colours,
- },
- };
- }
-
- public static arrow(start: Vector3, end: Vector3, colour: RGBA): AttributeData {
- const line = DebugGeometryTemplates.line(start, end, colour);
- const lineLength = Vector3.sub(end, start).magnitude();
- const coneHeight = 0.15 * lineLength;
- const coneRadius = 0.15 * coneHeight;
-
- const normal = Vector3.sub(end, start).normalise();
- const cone = DebugGeometryTemplates.cone(end, coneHeight, normal, coneRadius, colour, 1);
-
- return MergeAttributeData(line, cone);
- }
-
- public static grid(dimensions: Vector3, spacing?: number): RenderBuffer {
- const buffer = new RenderBuffer([
- { name: 'position', numComponents: 3 },
- { name: 'colour', numComponents: 4 },
- ]);
- const COLOUR_MINOR: RGBA = { r: 0.5, g: 0.5, b: 0.5, a: 0.3 };
- const COLOUR_MAJOR: RGBA = { r: 1.0, g: 1.0, b: 1.0, a: 0.3 };
-
- buffer.add(DebugGeometryTemplates.line(
- new Vector3(-dimensions.x / 2, 0, -dimensions.z / 2),
- new Vector3(-dimensions.x / 2, 0, dimensions.z / 2),
- COLOUR_MAJOR,
- ));
-
- buffer.add(DebugGeometryTemplates.line(
- new Vector3(dimensions.x / 2, 0, -dimensions.z / 2),
- new Vector3(dimensions.x / 2, 0, dimensions.z / 2),
- COLOUR_MAJOR,
- ));
-
- buffer.add(DebugGeometryTemplates.line(
- new Vector3(-dimensions.x / 2, 0, -dimensions.z / 2),
- new Vector3(dimensions.x / 2, 0, -dimensions.z / 2),
- COLOUR_MAJOR,
- ));
-
- buffer.add(DebugGeometryTemplates.line(
- new Vector3(-dimensions.x / 2, 0, dimensions.z / 2),
- new Vector3(dimensions.x / 2, 0, dimensions.z / 2),
- COLOUR_MAJOR,
- ));
-
- if (spacing) {
- ASSERT(spacing > 0.0);
- for (let x = -dimensions.x / 2; x < dimensions.x / 2; x += spacing) {
- buffer.add(DebugGeometryTemplates.line(
- new Vector3(x, 0, -dimensions.z / 2),
- new Vector3(x, 0, dimensions.z / 2),
- COLOUR_MINOR,
- ));
- }
-
- for (let z = -dimensions.z / 2; z < dimensions.z / 2; z += spacing) {
- buffer.add(DebugGeometryTemplates.line(
- new Vector3(-dimensions.x / 2, 0, z),
- new Vector3(dimensions.x / 2, 0, z),
- COLOUR_MINOR,
- ));
- }
- }
-
- return buffer;
- }
-
- public static meshWireframe(mesh: Mesh, colour: RGBA): RenderBuffer {
- const buffer = new RenderBuffer([
- { name: 'position', numComponents: 3 },
- { name: 'colour', numComponents: 4 },
- ]);
-
- let v0: Vector3 = new Vector3(0, 0, 0);
- let v1: Vector3 = new Vector3(0, 0, 0);
- let v2: Vector3 = new Vector3(0, 0, 0);
- for (let triIndex = 0; triIndex < mesh.getTriangleCount(); ++triIndex) {
- ({ v0, v1, v2 } = mesh.getVertices(triIndex));
- buffer.add(DebugGeometryTemplates.line(
- v0, v1, colour,
- ));
- buffer.add(DebugGeometryTemplates.line(
- v1, v2, colour,
- ));
- buffer.add(DebugGeometryTemplates.line(
- v2, v0, colour,
- ));
- }
-
- return buffer;
- }
-
- public static voxelMeshWireframe(voxelMesh: VoxelMesh, colour: RGBA, voxelSize: number): RenderBuffer {
- const buffer = new RenderBuffer([
- { name: 'position', numComponents: 3 },
- { name: 'colour', numComponents: 4 },
- ]);
-
- const dimensions = voxelMesh.getBounds().getDimensions();
- const gridOffset = new Vector3(
- dimensions.x % 2 === 0 ? 0 : -0.5,
- dimensions.y % 2 === 0 ? 0 : -0.5,
- dimensions.z % 2 === 0 ? 0 : -0.5,
- );
- for (const voxel of voxelMesh.getVoxels()) {
- buffer.add(DebugGeometryTemplates.cube(
- Vector3.mulScalar(Vector3.add(voxel.position, gridOffset), voxelSize), voxelSize, colour,
- ));
- }
-
- return buffer;
- }
-
- public static meshNormals(mesh: Mesh, colour: RGBA): RenderBuffer {
- const buffer = new RenderBuffer([
- { name: 'position', numComponents: 3 },
- { name: 'colour', numComponents: 4 },
- ]);
-
- for (let triIndex = 0; triIndex < mesh.getTriangleCount(); ++triIndex) {
- const normalLength = 0.5;
- const vertices = mesh.getVertices(triIndex);
- const normals = mesh.getNormals(triIndex);
- const avgNormal = Vector3.add(normals.v0, normals.v1).add(normals.v2).divScalar(3.0);
- const tri = new Triangle(vertices.v0, vertices.v1, vertices.v2);
- const start = tri.getCentre();
- const end = Vector3.add(start, Vector3.mulScalar(avgNormal, normalLength));
- buffer.add(DebugGeometryTemplates.arrow(
- start,
- end,
- colour,
- ));
- }
-
- return buffer;
- }
-
- static _generateCirclePoints(centre: Vector3, normal: Vector3, radius: number, steps: number): Vector3[] {
- normal = normal.copy().normalise();
-
- const c = [{ i: 0, v: normal.x }, { i: 1, v: normal.y }, { i: 2, v: normal.z }];
- {
- let comps = c.sort((a, b) => {
- return b.v - a.v;
- }); // largest -> smallest
- comps[2].v = 0;
- const temp = comps[0].v;
- comps[0].v = comps[1].v;
- comps[1].v = temp;
- comps = c.sort((a, b) => {
- return a.i - b.i;
- });
- }
- const aVec = new Vector3(c[0].v, c[1].v, c[2].v);
- const bVec = Vector3.cross(normal, aVec);
- aVec.normalise();
- bVec.normalise();
-
- const circlePoints: Vector3[] = [];
- for (let i = 0; i < steps; ++i) {
- const t = i / steps * Math.PI * 2;
- const point = centre.copy()
- .add(Vector3.mulScalar(aVec, radius * Math.cos(t)))
- .add(Vector3.mulScalar(bVec, radius * Math.sin(t)));
- circlePoints.push(point);
- }
- return circlePoints;
- }
-}
+import * as twgl from 'twgl.js';
+
+import { Bounds } from './bounds';
+import { RGBA } from './colour';
+import { Mesh } from './mesh';
+import { AttributeData, MergeAttributeData, RenderBuffer } from './render_buffer';
+import { Triangle, UVTriangle } from './triangle';
+import { ASSERT } from './util/error_util';
+import { Vector3 } from './vector';
+import { VoxelMesh } from './voxel_mesh';
+
+export class GeometryTemplates {
+ private static readonly _default_cube = twgl.primitives.createCubeVertices(1.0);
+
+ static getTriangleBufferData(triangle: UVTriangle): AttributeData {
+ const n = triangle.getNormal();
+
+ return {
+ custom: {
+ position: [
+ triangle.v0.x, triangle.v0.y, triangle.v0.z,
+ triangle.v1.x, triangle.v1.y, triangle.v1.z,
+ triangle.v2.x, triangle.v2.y, triangle.v2.z,
+ ],
+ texcoord: [
+ triangle.uv0.u, triangle.uv0.v,
+ triangle.uv1.u, triangle.uv1.v,
+ triangle.uv2.u, triangle.uv2.v,
+ ],
+ normal: [
+ n.x, n.y, n.z,
+ n.x, n.y, n.z,
+ n.x, n.y, n.z,
+ ],
+ },
+ indices: new Uint32Array([
+ 0, 1, 2,
+ ]),
+ };
+ }
+
+ static getBoxBufferData(centre: Vector3): AttributeData {
+ const cube: AttributeData = {
+ custom: {
+ position: new Array(72),
+ texcoord: new Array(48),
+ normal: new Array(72),
+ },
+ indices: new Uint32Array(72),
+ };
+
+ cube.custom.position = Array.from(GeometryTemplates._default_cube.position);
+ cube.custom.normal = Array.from(GeometryTemplates._default_cube.normal);
+ cube.custom.texcoord = Array.from(GeometryTemplates._default_cube.texcoord);
+ cube.indices = Uint32Array.from(GeometryTemplates._default_cube.indices);
+
+ for (let i = 0; i < 72; i += 3) {
+ cube.custom.position[i + 0] += centre.x;
+ cube.custom.position[i + 1] += centre.y;
+ cube.custom.position[i + 2] += centre.z;
+ }
+
+ return cube;
+ }
+}
+
+export class DebugGeometryTemplates {
+ public static cross(centre: Vector3, radius: number, colour: RGBA): AttributeData {
+ return {
+ indices: new Uint32Array([0, 1, 2, 3, 4, 5]),
+ custom: {
+ position: [
+ centre.x + radius, centre.y, centre.z,
+ centre.x - radius, centre.y, centre.z,
+ centre.x, centre.y + radius, centre.z,
+ centre.x, centre.y - radius, centre.z,
+ centre.x, centre.y, centre.z + radius,
+ centre.x, centre.y, centre.z - radius,
+ ],
+ colour: [
+ colour.r, colour.g, colour.b, colour.a,
+ colour.r, colour.g, colour.b, colour.a,
+ colour.r, colour.g, colour.b, colour.a,
+ colour.r, colour.g, colour.b, colour.a,
+ colour.r, colour.g, colour.b, colour.a,
+ ],
+ },
+ };
+ }
+
+ public static line(start: Vector3, end: Vector3, colour: RGBA): AttributeData {
+ return {
+ indices: new Uint32Array([0, 1]),
+ custom: {
+ position: [
+ start.x, start.y, start.z,
+ end.x, end.y, end.z,
+ ],
+ colour: [
+ colour.r, colour.g, colour.b, colour.a,
+ colour.r, colour.g, colour.b, colour.a,
+ ],
+ },
+ };
+ }
+
+ public static cube(centre: Vector3, size: number, colour: RGBA): AttributeData {
+ const min = Vector3.sub(centre, size/2);
+ const max = Vector3.add(centre, size/2);
+ const bounds = new Bounds(min, max);
+ return this.bounds(bounds, colour);
+ }
+
+ public static bounds(bounds: Bounds, colour: RGBA): AttributeData {
+ return {
+ indices: new Uint32Array([
+ 0, 1,
+ 1, 2,
+ 2, 3,
+ 3, 0,
+ 4, 5,
+ 5, 6,
+ 6, 7,
+ 7, 4,
+ 0, 4,
+ 1, 5,
+ 2, 6,
+ 3, 7,
+ ]),
+ custom: {
+ position: [
+ bounds.min.x, bounds.min.y, bounds.min.z,
+ bounds.max.x, bounds.min.y, bounds.min.z,
+ bounds.max.x, bounds.min.y, bounds.max.z,
+ bounds.min.x, bounds.min.y, bounds.max.z,
+ bounds.min.x, bounds.max.y, bounds.min.z,
+ bounds.max.x, bounds.max.y, bounds.min.z,
+ bounds.max.x, bounds.max.y, bounds.max.z,
+ bounds.min.x, bounds.max.y, bounds.max.z,
+ ],
+ colour: [
+ colour.r, colour.g, colour.b, colour.a,
+ colour.r, colour.g, colour.b, colour.a,
+ colour.r, colour.g, colour.b, colour.a,
+ colour.r, colour.g, colour.b, colour.a,
+ colour.r, colour.g, colour.b, colour.a,
+ colour.r, colour.g, colour.b, colour.a,
+ colour.r, colour.g, colour.b, colour.a,
+ colour.r, colour.g, colour.b, colour.a,
+ ],
+ },
+ };
+ }
+
+ public static circle(centre: Vector3, normal: Vector3, radius: number, colour: RGBA, steps: number = 8): AttributeData {
+ const indices = [];
+ const positions = [];
+ const colours = [];
+
+ const circlePoints = DebugGeometryTemplates._generateCirclePoints(centre, normal, radius, steps);
+ for (let i = 0; i < steps; ++i) {
+ const point = circlePoints[i];
+ positions.push(point.x, point.y, point.z);
+ indices.push(i, (i+1) % steps);
+ colours.push(colour.r, colour.g, colour.b, colour.a);
+ }
+
+ return {
+ indices: new Uint32Array(indices),
+ custom: {
+ position: positions,
+ colour: colours,
+ },
+ };
+ }
+
+ public static cone(tipCentre: Vector3, tipHeight: number, normal: Vector3, radius: number, colour: RGBA, quarterSteps: number): AttributeData {
+ const indices = [];
+ const positions = [];
+ const colours = [];
+
+ const steps = quarterSteps * 4;
+ const circleCentre = Vector3.add(tipCentre, Vector3.mulScalar(normal.copy().normalise(), -tipHeight));
+ const circlePoints = DebugGeometryTemplates._generateCirclePoints(circleCentre, normal, radius, steps);
+
+ // Add circle data
+ for (let i = 0; i < steps; ++i) {
+ const point = circlePoints[i];
+ positions.push(point.x, point.y, point.z);
+ indices.push(i, (i+1) % steps);
+ colours.push(colour.r, colour.g, colour.b, colour.a);
+ }
+ // Add cone tip
+ positions.push(tipCentre.x, tipCentre.y, tipCentre.z);
+ colours.push(colour.r, colour.g, colour.b, colour.a);
+ const tipIndex = steps;
+ // Add cone lines
+ for (let i = 0; i < 4; ++i) {
+ const coneIndex = i * quarterSteps;
+ indices.push(tipIndex, coneIndex);
+ }
+
+ return {
+ indices: new Uint32Array(indices),
+ custom: {
+ position: positions,
+ colour: colours,
+ },
+ };
+ }
+
+ public static arrow(start: Vector3, end: Vector3, colour: RGBA): AttributeData {
+ const line = DebugGeometryTemplates.line(start, end, colour);
+ const lineLength = Vector3.sub(end, start).magnitude();
+ const coneHeight = 0.15 * lineLength;
+ const coneRadius = 0.15 * coneHeight;
+
+ const normal = Vector3.sub(end, start).normalise();
+ const cone = DebugGeometryTemplates.cone(end, coneHeight, normal, coneRadius, colour, 1);
+
+ return MergeAttributeData(line, cone);
+ }
+
+ public static COLOUR_MINOR: RGBA = { r: 0.5, g: 0.5, b: 0.5, a: 0.3 };
+ public static COLOUR_MAJOR: RGBA = { r: 1.0, g: 1.0, b: 1.0, a: 0.3 };
+
+ public static gridX(dimensions: Vector3, spacing?: number): RenderBuffer {
+ const buffer = new RenderBuffer([
+ { name: 'position', numComponents: 3 },
+ { name: 'colour', numComponents: 4 },
+ ]);
+
+ buffer.add(DebugGeometryTemplates.line(
+ new Vector3(0, -dimensions.y / 2, -dimensions.z / 2),
+ new Vector3(0, -dimensions.y / 2, dimensions.z / 2),
+ DebugGeometryTemplates.COLOUR_MAJOR,
+ ));
+
+ buffer.add(DebugGeometryTemplates.line(
+ new Vector3(0, dimensions.y / 2, -dimensions.z / 2),
+ new Vector3(0, dimensions.y / 2, dimensions.z / 2),
+ DebugGeometryTemplates.COLOUR_MAJOR,
+ ));
+
+ buffer.add(DebugGeometryTemplates.line(
+ new Vector3(0, -dimensions.y / 2, -dimensions.z / 2),
+ new Vector3(0, dimensions.y / 2, -dimensions.z / 2),
+ DebugGeometryTemplates.COLOUR_MAJOR,
+ ));
+
+ buffer.add(DebugGeometryTemplates.line(
+ new Vector3(0, -dimensions.y / 2, dimensions.z / 2),
+ new Vector3(0, dimensions.y / 2, dimensions.z / 2),
+ DebugGeometryTemplates.COLOUR_MAJOR,
+ ));
+
+ if (spacing) {
+ ASSERT(spacing > 0.0);
+ for (let y = -dimensions.y / 2; y < dimensions.y / 2; y += spacing) {
+ buffer.add(DebugGeometryTemplates.line(
+ new Vector3(0, y, -dimensions.z / 2),
+ new Vector3(0, y, dimensions.z / 2),
+ DebugGeometryTemplates.COLOUR_MINOR,
+ ));
+ }
+
+ for (let z = -dimensions.z / 2; z < dimensions.z / 2; z += spacing) {
+ buffer.add(DebugGeometryTemplates.line(
+ new Vector3(0, -dimensions.y / 2, z),
+ new Vector3(0, dimensions.y / 2, z),
+ DebugGeometryTemplates.COLOUR_MINOR,
+ ));
+ }
+ }
+
+ return buffer;
+ }
+
+ public static gridY(dimensions: Vector3, spacing?: number): RenderBuffer {
+ const buffer = new RenderBuffer([
+ { name: 'position', numComponents: 3 },
+ { name: 'colour', numComponents: 4 },
+ ]);
+
+ buffer.add(DebugGeometryTemplates.line(
+ new Vector3(-dimensions.x / 2, 0, -dimensions.z / 2),
+ new Vector3(-dimensions.x / 2, 0, dimensions.z / 2),
+ DebugGeometryTemplates.COLOUR_MAJOR,
+ ));
+
+ buffer.add(DebugGeometryTemplates.line(
+ new Vector3(dimensions.x / 2, 0, -dimensions.z / 2),
+ new Vector3(dimensions.x / 2, 0, dimensions.z / 2),
+ DebugGeometryTemplates.COLOUR_MAJOR,
+ ));
+
+ buffer.add(DebugGeometryTemplates.line(
+ new Vector3(-dimensions.x / 2, 0, -dimensions.z / 2),
+ new Vector3(dimensions.x / 2, 0, -dimensions.z / 2),
+ DebugGeometryTemplates.COLOUR_MAJOR,
+ ));
+
+ buffer.add(DebugGeometryTemplates.line(
+ new Vector3(-dimensions.x / 2, 0, dimensions.z / 2),
+ new Vector3(dimensions.x / 2, 0, dimensions.z / 2),
+ DebugGeometryTemplates.COLOUR_MAJOR,
+ ));
+
+ if (spacing) {
+ ASSERT(spacing > 0.0);
+ for (let x = -dimensions.x / 2; x < dimensions.x / 2; x += spacing) {
+ buffer.add(DebugGeometryTemplates.line(
+ new Vector3(x, 0, -dimensions.z / 2),
+ new Vector3(x, 0, dimensions.z / 2),
+ DebugGeometryTemplates.COLOUR_MINOR,
+ ));
+ }
+
+ for (let z = -dimensions.z / 2; z < dimensions.z / 2; z += spacing) {
+ buffer.add(DebugGeometryTemplates.line(
+ new Vector3(-dimensions.x / 2, 0, z),
+ new Vector3(dimensions.x / 2, 0, z),
+ DebugGeometryTemplates.COLOUR_MINOR,
+ ));
+ }
+ }
+
+ return buffer;
+ }
+
+ public static gridZ(dimensions: Vector3, spacing?: number): RenderBuffer {
+ const buffer = new RenderBuffer([
+ { name: 'position', numComponents: 3 },
+ { name: 'colour', numComponents: 4 },
+ ]);
+
+ buffer.add(DebugGeometryTemplates.line(
+ new Vector3(-dimensions.x / 2, -dimensions.y / 2, 0),
+ new Vector3(-dimensions.x / 2, dimensions.y / 2, 0),
+ DebugGeometryTemplates.COLOUR_MAJOR,
+ ));
+
+ buffer.add(DebugGeometryTemplates.line(
+ new Vector3(dimensions.x / 2, -dimensions.y / 2, 0),
+ new Vector3(dimensions.x / 2, dimensions.y / 2, 0),
+ DebugGeometryTemplates.COLOUR_MAJOR,
+ ));
+
+ buffer.add(DebugGeometryTemplates.line(
+ new Vector3(-dimensions.x / 2, -dimensions.y / 2, 0),
+ new Vector3(dimensions.x / 2, -dimensions.y / 2, 0),
+ DebugGeometryTemplates.COLOUR_MAJOR,
+ ));
+
+ buffer.add(DebugGeometryTemplates.line(
+ new Vector3(-dimensions.x / 2, dimensions.y / 2, 0),
+ new Vector3(dimensions.x / 2, dimensions.y / 2, 0),
+ DebugGeometryTemplates.COLOUR_MAJOR,
+ ));
+
+ if (spacing) {
+ ASSERT(spacing > 0.0);
+ for (let x = -dimensions.x / 2; x < dimensions.x / 2; x += spacing) {
+ buffer.add(DebugGeometryTemplates.line(
+ new Vector3(x, -dimensions.y / 2, 0),
+ new Vector3(x, dimensions.y / 2, 0),
+ DebugGeometryTemplates.COLOUR_MINOR,
+ ));
+ }
+
+ for (let y = -dimensions.y / 2; y < dimensions.y / 2; y += spacing) {
+ buffer.add(DebugGeometryTemplates.line(
+ new Vector3(-dimensions.x / 2, y, 0),
+ new Vector3(dimensions.x / 2, y, 0),
+ DebugGeometryTemplates.COLOUR_MINOR,
+ ));
+ }
+ }
+
+ return buffer;
+ }
+
+ public static meshWireframe(mesh: Mesh, colour: RGBA): RenderBuffer {
+ const buffer = new RenderBuffer([
+ { name: 'position', numComponents: 3 },
+ { name: 'colour', numComponents: 4 },
+ ]);
+
+ let v0: Vector3 = new Vector3(0, 0, 0);
+ let v1: Vector3 = new Vector3(0, 0, 0);
+ let v2: Vector3 = new Vector3(0, 0, 0);
+ for (let triIndex = 0; triIndex < mesh.getTriangleCount(); ++triIndex) {
+ ({ v0, v1, v2 } = mesh.getVertices(triIndex));
+ buffer.add(DebugGeometryTemplates.line(
+ v0, v1, colour,
+ ));
+ buffer.add(DebugGeometryTemplates.line(
+ v1, v2, colour,
+ ));
+ buffer.add(DebugGeometryTemplates.line(
+ v2, v0, colour,
+ ));
+ }
+
+ return buffer;
+ }
+
+ public static voxelMeshWireframe(voxelMesh: VoxelMesh, colour: RGBA, voxelSize: number): RenderBuffer {
+ const buffer = new RenderBuffer([
+ { name: 'position', numComponents: 3 },
+ { name: 'colour', numComponents: 4 },
+ ]);
+
+ const dimensions = voxelMesh.getBounds().getDimensions();
+ const gridOffset = new Vector3(
+ dimensions.x % 2 === 0 ? 0 : -0.5,
+ dimensions.y % 2 === 0 ? 0 : -0.5,
+ dimensions.z % 2 === 0 ? 0 : -0.5,
+ );
+ for (const voxel of voxelMesh.getVoxels()) {
+ buffer.add(DebugGeometryTemplates.cube(
+ Vector3.mulScalar(Vector3.add(voxel.position, gridOffset), voxelSize), voxelSize, colour,
+ ));
+ }
+
+ return buffer;
+ }
+
+ public static meshNormals(mesh: Mesh, colour: RGBA): RenderBuffer {
+ const buffer = new RenderBuffer([
+ { name: 'position', numComponents: 3 },
+ { name: 'colour', numComponents: 4 },
+ ]);
+
+ for (let triIndex = 0; triIndex < mesh.getTriangleCount(); ++triIndex) {
+ const normalLength = 0.5;
+ const vertices = mesh.getVertices(triIndex);
+ const normals = mesh.getNormals(triIndex);
+ const avgNormal = Vector3.add(normals.v0, normals.v1).add(normals.v2).divScalar(3.0);
+ const tri = new Triangle(vertices.v0, vertices.v1, vertices.v2);
+ const start = tri.getCentre();
+ const end = Vector3.add(start, Vector3.mulScalar(avgNormal, normalLength));
+ buffer.add(DebugGeometryTemplates.arrow(
+ start,
+ end,
+ colour,
+ ));
+ }
+
+ return buffer;
+ }
+
+ static _generateCirclePoints(centre: Vector3, normal: Vector3, radius: number, steps: number): Vector3[] {
+ normal = normal.copy().normalise();
+
+ const c = [{ i: 0, v: normal.x }, { i: 1, v: normal.y }, { i: 2, v: normal.z }];
+ {
+ let comps = c.sort((a, b) => {
+ return b.v - a.v;
+ }); // largest -> smallest
+ comps[2].v = 0;
+ const temp = comps[0].v;
+ comps[0].v = comps[1].v;
+ comps[1].v = temp;
+ comps = c.sort((a, b) => {
+ return a.i - b.i;
+ });
+ }
+ const aVec = new Vector3(c[0].v, c[1].v, c[2].v);
+ const bVec = Vector3.cross(normal, aVec);
+ aVec.normalise();
+ bVec.normalise();
+
+ const circlePoints: Vector3[] = [];
+ for (let i = 0; i < steps; ++i) {
+ const t = i / steps * Math.PI * 2;
+ const point = centre.copy()
+ .add(Vector3.mulScalar(aVec, radius * Math.cos(t)))
+ .add(Vector3.mulScalar(bVec, radius * Math.sin(t)));
+ circlePoints.push(point);
+ }
+ return circlePoints;
+ }
+}
diff --git a/src/hash_map.ts b/src/hash_map.ts
index 92ccfb4a..383ba1bc 100644
--- a/src/hash_map.ts
+++ b/src/hash_map.ts
@@ -1,91 +1,4 @@
-export interface IHashable {
- hash(): number;
- equals(other: IHashable): boolean;
-}
-
-export class HashSet {
- private _numBins: number;
- protected _bins: Array>;
-
- constructor(numBins: number) {
- this._numBins = numBins;
- this._bins = new Array(numBins);
-
- for (let i = 0; i < numBins; ++i) {
- this._bins[i] = [];
- }
- }
-
- protected _getBin(key: T) {
- const hash = key.hash();
- return Math.abs(hash) % this._numBins;
- }
-
- public add(key: T) {
- const binIndex = this._getBin(key);
- this._bins[binIndex].push(key);
- }
-
- public contains(key: T) {
- const binIndex = this._getBin(key);
-
- const list = this._bins[binIndex];
- for (const item of list) {
- if (item.equals(key)) {
- return true;
- }
- }
- return false;
- }
-}
-
-
-export class HashMap {
- private _numBins: number;
- protected _bins: Array>;
-
- constructor(numBins: number) {
- this._numBins = numBins;
- this._bins = new Array(numBins);
-
- for (let i = 0; i < numBins; ++i) {
- this._bins[i] = [];
- }
- }
-
- protected _getBin(key: K) {
- const hash = key.hash();
- return Math.abs(hash) % this._numBins;
- }
-
- public get(item: K): (V | undefined) {
- const binIndex = this._getBin(item);
-
- const list = this._bins[binIndex];
- for (const {key, value} of list) {
- if (item.equals(key)) {
- return value;
- }
- }
- }
-
- /* eslint-disable */
- public has(item: K): boolean {
- const binIndex = this._getBin(item);
-
- const list = this._bins[binIndex];
- for (const { key, value } of list) {
- if (item.equals(key)) {
- return true;
- }
- }
-
- return false;
- }
- /* eslint-enable */
-
- public add(key: K, value: V) {
- const binIndex = this._getBin(key);
- this._bins[binIndex].push({key, value});
- }
-}
+export interface IHashable {
+ hash(): number;
+ equals(other: IHashable): boolean;
+}
diff --git a/src/importers/base_importer.ts b/src/importers/base_importer.ts
index 3f86b3ef..80ad5d78 100644
--- a/src/importers/base_importer.ts
+++ b/src/importers/base_importer.ts
@@ -1,6 +1,6 @@
-import { Mesh } from '../mesh';
-
-export abstract class IImporter {
- abstract parseFile(filePath: string): void;
- abstract toMesh(): Mesh;
-}
+import { Mesh } from '../mesh';
+
+export abstract class IImporter {
+ abstract parseFile(filePath: string): void;
+ abstract toMesh(): Mesh;
+}
diff --git a/src/importers/importers.ts b/src/importers/importers.ts
index fbb32e32..a1ac0d56 100644
--- a/src/importers/importers.ts
+++ b/src/importers/importers.ts
@@ -1,16 +1,16 @@
-import { ASSERT } from '../util';
-import { IImporter } from './base_importer';
-import { ObjImporter } from './obj_importer';
-
-export type TImporters = 'obj';
-
-export class ImporterFactor {
- public static GetImporter(importer: TImporters): IImporter {
- switch (importer) {
- case 'obj':
- return new ObjImporter();
- default:
- ASSERT(false);
- }
- }
-}
+import { ASSERT } from '../util/error_util';
+import { IImporter } from './base_importer';
+import { ObjImporter } from './obj_importer';
+
+export type TImporters = 'obj';
+
+export class ImporterFactor {
+ public static GetImporter(importer: TImporters): IImporter {
+ switch (importer) {
+ case 'obj':
+ return new ObjImporter();
+ default:
+ ASSERT(false);
+ }
+ }
+}
diff --git a/src/importers/obj_importer.ts b/src/importers/obj_importer.ts
index aaabaf0e..5d3ddebf 100644
--- a/src/importers/obj_importer.ts
+++ b/src/importers/obj_importer.ts
@@ -1,404 +1,410 @@
-import { MaterialType, Mesh, SolidMaterial, TexturedMaterial, Tri } from '../mesh';
-import { Vector3 } from '../vector';
-import { UV, ASSERT, AppError, REGEX_NUMBER, RegExpBuilder, REGEX_NZ_ANY, LOG_ERROR, LOG } from '../util';
-import { checkFractional, checkNaN } from '../math';
-
-import fs from 'fs';
-import path from 'path';
-import { StatusHandler } from '../status';
-import { IImporter } from './base_importer';
-import { RGBA, RGBAColours } from '../colour';
-
-export class ObjImporter extends IImporter {
- private _vertices: Vector3[] = [];
- private _normals: Vector3[] = [];
- private _uvs: UV[] = [];
- private _tris: Tri[] = [];
-
- private _materials: {[key: string]: (SolidMaterial | TexturedMaterial)} = {
- 'DEFAULT_UNASSIGNED': { type: MaterialType.solid, colour: RGBAColours.WHITE },
- };
- private _mtlLibs: string[] = [];
- private _currentMaterialName: string = 'DEFAULT_UNASSIGNED';
-
- private _objPath?: path.ParsedPath;
- private _objParsers = [
- {
- // e.g. 'mtllib my_file.mtl'
- regex: new RegExpBuilder().add(/^mtllib/).add(/ /).add(REGEX_NZ_ANY, 'path').toRegExp(),
- delegate: (match: { [key: string]: string }) => {
- this._mtlLibs.push(match.path.trim());
- },
- },
- {
- // e.g. 'usemtl my_material'
- regex: new RegExpBuilder().add(/^usemtl/).add(/ /).add(REGEX_NZ_ANY, 'name').toRegExp(),
- delegate: (match: { [key: string]: string }) => {
- this._currentMaterialName = match.name.trim();
- ASSERT(this._currentMaterialName, 'invalid material name');
- },
- },
- {
- // e.g. 'v 0.123 0.456 0.789'
- regex: new RegExpBuilder()
- .add(/^v/)
- .addNonzeroWhitespace()
- .add(REGEX_NUMBER, 'x')
- .addNonzeroWhitespace()
- .add(REGEX_NUMBER, 'y')
- .addNonzeroWhitespace()
- .add(REGEX_NUMBER, 'z')
- .toRegExp(),
- delegate: (match: { [key: string]: string }) => {
- const x = parseFloat(match.x);
- const y = parseFloat(match.y);
- const z = parseFloat(match.z);
- checkNaN(x, y, z);
- this._vertices.push(new Vector3(x, y, z));
- },
- },
- {
- // e.g. 'vn 0.123 0.456 0.789'
- regex: new RegExpBuilder()
- .add(/^vn/)
- .addNonzeroWhitespace()
- .add(REGEX_NUMBER, 'x')
- .addNonzeroWhitespace()
- .add(REGEX_NUMBER, 'y')
- .addNonzeroWhitespace()
- .add(REGEX_NUMBER, 'z')
- .toRegExp(),
- delegate: (match: { [key: string]: string }) => {
- const x = parseFloat(match.x);
- const y = parseFloat(match.y);
- const z = parseFloat(match.z);
- checkNaN(x, y, z);
- this._normals.push(new Vector3(x, y, z));
- },
- },
- {
- // e.g. 'vt 0.123 0.456'
- regex: new RegExpBuilder()
- .add(/^vt/)
- .addNonzeroWhitespace()
- .add(REGEX_NUMBER, 'u')
- .addNonzeroWhitespace()
- .add(REGEX_NUMBER, 'v')
- .toRegExp(),
- delegate: (match: { [key: string]: string }) => {
- const u = parseFloat(match.u);
- const v = parseFloat(match.v);
- checkNaN(u, v);
- this._uvs.push(new UV(u, v));
- },
- },
- {
- // e.g. 'f 1/2/3 ...' or 'f 1/2 ...' or 'f 1 ...'
- regex: new RegExpBuilder()
- .add(/^f/)
- .addNonzeroWhitespace()
- .add(/.*/, 'line')
- .toRegExp(),
- delegate: (match: { [key: string]: string }) => {
- const line = match.line.trim();
-
- const vertices = line.split(' ').filter((x) => {
- return x.length !== 0;
- });
-
- if (vertices.length < 3) {
- // this.addWarning('')
- // throw new AppError('Face data should have at least 3 vertices');
- }
-
- const points: {
- positionIndex: number;
- texcoordIndex?: number;
- normalIndex?: number;
- }[] = [];
-
- for (const vertex of vertices) {
- const vertexData = vertex.split('/');
- switch (vertexData.length) {
- case 1: {
- const index = parseInt(vertexData[0]);
- points.push({
- positionIndex: index,
- texcoordIndex: index,
- normalIndex: index,
- });
- break;
- }
- case 2: {
- const positionIndex = parseInt(vertexData[0]);
- const texcoordIndex = parseInt(vertexData[1]);
- points.push({
- positionIndex: positionIndex,
- texcoordIndex: texcoordIndex,
- });
- break;
- }
- case 3: {
- const positionIndex = parseInt(vertexData[0]);
- const texcoordIndex = parseInt(vertexData[1]);
- const normalIndex = parseInt(vertexData[2]);
- points.push({
- positionIndex: positionIndex,
- texcoordIndex: texcoordIndex,
- normalIndex: normalIndex,
- });
- break;
- }
- default:
- throw new AppError(`Face data has unexpected number of vertex data: ${vertexData.length}`);
- }
- }
-
- const pointBase = points[0];
- for (let i = 1; i < points.length - 1; ++i) {
- const pointA = points[i];
- const pointB = points[i+1];
- const tri: Tri = {
- positionIndices: {
- x: pointBase.positionIndex - 1,
- y: pointA.positionIndex - 1,
- z: pointB.positionIndex - 1,
- },
- material: this._currentMaterialName,
- };
- if (pointBase.normalIndex || pointA.normalIndex || pointB.normalIndex) {
- ASSERT(pointBase.normalIndex && pointA.normalIndex && pointB.normalIndex);
- tri.normalIndices = {
- x: pointBase.normalIndex - 1,
- y: pointA.normalIndex - 1,
- z: pointB.normalIndex - 1,
- };
- }
- if (pointBase.texcoordIndex || pointA.texcoordIndex || pointB.texcoordIndex) {
- ASSERT(pointBase.texcoordIndex && pointA.texcoordIndex && pointB.texcoordIndex);
- tri.texcoordIndices = {
- x: pointBase.texcoordIndex - 1,
- y: pointA.texcoordIndex - 1,
- z: pointB.texcoordIndex - 1,
- };
- }
- this._tris.push(tri);
- }
- },
- },
- ];
-
- private _currentColour: RGBA = RGBAColours.BLACK;
- private _currentAlpha: number = 1.0;
- private _currentTexture: string = '';
- private _currentTransparencyTexture: string = '';
- private _materialReady: boolean = false;
- private _mtlParsers = [
- {
- // e.g. 'newmtl my_material'
- regex: new RegExpBuilder().add(/^newmtl/).add(REGEX_NZ_ANY, 'name').toRegExp(),
- delegate: (match: { [key: string]: string }) => {
- this._addCurrentMaterial();
- this._currentMaterialName = match.name.trim();
- this._currentTexture = '';
- this._materialReady = false;
- },
- },
- {
- // e.g. 'Kd 0.123 0.456 0.789'
- regex: new RegExpBuilder()
- .add(/^Kd/)
- .addNonzeroWhitespace()
- .add(REGEX_NUMBER, 'r')
- .addNonzeroWhitespace()
- .add(REGEX_NUMBER, 'g')
- .addNonzeroWhitespace()
- .add(REGEX_NUMBER, 'b')
- .toRegExp(),
- delegate: (match: { [key: string]: string }) => {
- const r = parseFloat(match.r);
- const g = parseFloat(match.g);
- const b = parseFloat(match.b);
- checkNaN(r, g, b);
- checkFractional(r, g, b);
- this._currentColour = { r: r, g: g, b: b, a: this._currentAlpha };
- this._materialReady = true;
- },
- },
- {
- // e.g. 'map_Kd my/path/to/file.png'
- regex: new RegExpBuilder().add(/^map_Kd/).add(REGEX_NZ_ANY, 'path').toRegExp(),
- delegate: (match: { [key: string]: string }) => {
- let mtlPath = match.path.trim();
- if (!path.isAbsolute(mtlPath)) {
- ASSERT(this._objPath, 'no obj path');
- mtlPath = path.join(this._objPath.dir, mtlPath);
- }
- this._currentTexture = mtlPath;
- this._materialReady = true;
- },
- },
- {
- // Transparency map
- // e.g. 'map_d my/path/to/file.png'
- regex: new RegExpBuilder().add(/^map_d/).add(REGEX_NZ_ANY, 'path').toRegExp(),
- delegate: (match: { [key: string]: string }) => {
- let texturePath = match.path.trim();
- if (!path.isAbsolute(texturePath)) {
- ASSERT(this._objPath, 'no obj path');
- texturePath = path.join(this._objPath.dir, texturePath);
- }
- this._currentTransparencyTexture = texturePath;
- this._materialReady = true;
- },
- },
- {
- // Transparency value
- // e.g. 'd 0.7500'
- regex: new RegExpBuilder()
- .add(/^d/)
- .addNonzeroWhitespace()
- .add(REGEX_NUMBER, 'alpha')
- .toRegExp(),
- delegate: (match: { [key: string]: string }) => {
- const alpha = parseFloat(match.alpha);
- checkNaN(alpha);
- checkFractional(alpha);
- this._currentAlpha = alpha;
- },
- },
- ];
-
- override parseFile(filePath: string) {
- ASSERT(path.isAbsolute(filePath), 'path not absolute');
-
- this._objPath = path.parse(filePath);
-
- this._parseOBJ(filePath);
-
- if (this._mtlLibs.length === 0) {
- StatusHandler.Get.add('warning', 'Could not find associated .mtl file');
- }
- for (let i = 0; i < this._mtlLibs.length; ++i) {
- const mtlLib = this._mtlLibs[i];
- if (!path.isAbsolute(mtlLib)) {
- this._mtlLibs[i] = path.join(this._objPath.dir, mtlLib);
- }
- ASSERT(path.isAbsolute(this._mtlLibs[i]), 'path not absolute');
- }
-
- this._parseMTL();
- LOG('Materials', this._materials);
- }
-
- override toMesh(): Mesh {
- return new Mesh(this._vertices, this._normals, this._uvs, this._tris, this._materials);
- }
-
- private _parseOBJ(path: string) {
- if (!fs.existsSync(path)) {
- throw new AppError(`Could not find ${path}`);
- }
- const fileContents = fs.readFileSync(path, 'utf8');
- if (fileContents.includes('�')) {
- throw new AppError(`Unrecognised character found, please encode ${path} using UTF-8`);
- }
-
- fileContents.replace('\r', ''); // Convert Windows carriage return
- const fileLines = fileContents.split('\n');
-
- for (const line of fileLines) {
- this.parseOBJLine(line);
- }
- }
-
- public parseOBJLine(line: string) {
- const essentialTokens = ['mtllib ', 'usemtl ', 'v ', 'vt ', 'f ', 'vn '];
-
- for (const parser of this._objParsers) {
- const match = parser.regex.exec(line);
- if (match && match.groups) {
- try {
- parser.delegate(match.groups);
- } catch (error) {
- LOG_ERROR('Caught', error);
- if (error instanceof AppError) {
- throw new AppError(`Failed attempt to parse '${line}', because '${error.message}'`);
- }
- }
- return;
- }
- }
-
- const beginsWithEssentialToken = essentialTokens.some((token) => {
- return line.startsWith(token);
- });
- if (beginsWithEssentialToken) {
- throw new AppError(`Failed to parse essential token for ${line} `);
- }
- }
-
- private _parseMTL() {
- for (const mtlLib of this._mtlLibs) {
- if (!fs.existsSync(mtlLib)) {
- StatusHandler.Get.add('warning', `Could not find ${mtlLib}`);
- continue;
- }
- const fileContents = fs.readFileSync(mtlLib, 'utf8');
-
- fileContents.replace('\r', ''); // Convert Windows carriage return
- const fileLines = fileContents.split('\n');
-
- for (const line of fileLines) {
- this._parseMTLLine(line);
- }
-
- this._addCurrentMaterial();
- }
- }
-
- private _parseMTLLine(line: string) {
- const essentialTokens = ['newmtl ', 'Kd ', 'map_Kd '];
-
- for (const parser of this._mtlParsers) {
- const match = parser.regex.exec(line);
- if (match && match.groups) {
- try {
- parser.delegate(match.groups);
- } catch (error) {
- if (error instanceof AppError) {
- throw new AppError(`Failed attempt to parse '${line}', because '${error.message}'`);
- }
- }
- return;
- }
- }
-
- const beginsWithEssentialToken = essentialTokens.some((token) => {
- return line.startsWith(token);
- });
- if (beginsWithEssentialToken) {
- throw new AppError(`Failed to parse essential token for ${line}`);
- }
- }
-
- private _addCurrentMaterial() {
- if (this._materialReady && this._currentMaterialName !== '') {
- if (this._currentTexture !== '') {
- this._materials[this._currentMaterialName] = {
- type: MaterialType.textured,
- path: this._currentTexture,
- alphaPath: this._currentTransparencyTexture === '' ? undefined : this._currentTransparencyTexture,
- alphaFactor: this._currentAlpha,
- };
- this._currentTransparencyTexture = '';
- } else {
- this._materials[this._currentMaterialName] = {
- type: MaterialType.solid,
- colour: this._currentColour,
- };
- }
- this._currentAlpha = 1.0;
- }
- }
-}
+import fs from 'fs';
+import path from 'path';
+
+import { RGBA, RGBAColours } from '../colour';
+import { checkFractional, checkNaN } from '../math';
+import { MaterialType, Mesh, SolidMaterial, TexturedMaterial, Tri } from '../mesh';
+import { StatusHandler } from '../status';
+import { UV } from '../util';
+import { AppError, ASSERT } from '../util/error_util';
+import { LOG } from '../util/log_util';
+import { LOG_ERROR } from '../util/log_util';
+import { RegExpBuilder } from '../util/regex_util';
+import { REGEX_NZ_ANY } from '../util/regex_util';
+import { REGEX_NUMBER } from '../util/regex_util';
+import { Vector3 } from '../vector';
+import { IImporter } from './base_importer';
+
+export class ObjImporter extends IImporter {
+ private _vertices: Vector3[] = [];
+ private _normals: Vector3[] = [];
+ private _uvs: UV[] = [];
+ private _tris: Tri[] = [];
+
+ private _materials: { [key: string]: (SolidMaterial | TexturedMaterial) } = {
+ 'DEFAULT_UNASSIGNED': { type: MaterialType.solid, colour: RGBAColours.WHITE },
+ };
+ private _mtlLibs: string[] = [];
+ private _currentMaterialName: string = 'DEFAULT_UNASSIGNED';
+
+ private _objPath?: path.ParsedPath;
+ private _objParsers = [
+ {
+ // e.g. 'mtllib my_file.mtl'
+ regex: new RegExpBuilder().add(/^mtllib/).add(/ /).add(REGEX_NZ_ANY, 'path').toRegExp(),
+ delegate: (match: { [key: string]: string }) => {
+ this._mtlLibs.push(match.path.trim());
+ },
+ },
+ {
+ // e.g. 'usemtl my_material'
+ regex: new RegExpBuilder().add(/^usemtl/).add(/ /).add(REGEX_NZ_ANY, 'name').toRegExp(),
+ delegate: (match: { [key: string]: string }) => {
+ this._currentMaterialName = match.name.trim();
+ ASSERT(this._currentMaterialName, 'invalid material name');
+ },
+ },
+ {
+ // e.g. 'v 0.123 0.456 0.789'
+ regex: new RegExpBuilder()
+ .add(/^v/)
+ .addNonzeroWhitespace()
+ .add(REGEX_NUMBER, 'x')
+ .addNonzeroWhitespace()
+ .add(REGEX_NUMBER, 'y')
+ .addNonzeroWhitespace()
+ .add(REGEX_NUMBER, 'z')
+ .toRegExp(),
+ delegate: (match: { [key: string]: string }) => {
+ const x = parseFloat(match.x);
+ const y = parseFloat(match.y);
+ const z = parseFloat(match.z);
+ checkNaN(x, y, z);
+ this._vertices.push(new Vector3(x, y, z));
+ },
+ },
+ {
+ // e.g. 'vn 0.123 0.456 0.789'
+ regex: new RegExpBuilder()
+ .add(/^vn/)
+ .addNonzeroWhitespace()
+ .add(REGEX_NUMBER, 'x')
+ .addNonzeroWhitespace()
+ .add(REGEX_NUMBER, 'y')
+ .addNonzeroWhitespace()
+ .add(REGEX_NUMBER, 'z')
+ .toRegExp(),
+ delegate: (match: { [key: string]: string }) => {
+ const x = parseFloat(match.x);
+ const y = parseFloat(match.y);
+ const z = parseFloat(match.z);
+ checkNaN(x, y, z);
+ this._normals.push(new Vector3(x, y, z));
+ },
+ },
+ {
+ // e.g. 'vt 0.123 0.456'
+ regex: new RegExpBuilder()
+ .add(/^vt/)
+ .addNonzeroWhitespace()
+ .add(REGEX_NUMBER, 'u')
+ .addNonzeroWhitespace()
+ .add(REGEX_NUMBER, 'v')
+ .toRegExp(),
+ delegate: (match: { [key: string]: string }) => {
+ const u = parseFloat(match.u);
+ const v = parseFloat(match.v);
+ checkNaN(u, v);
+ this._uvs.push(new UV(u, v));
+ },
+ },
+ {
+ // e.g. 'f 1/2/3 ...' or 'f 1/2 ...' or 'f 1 ...'
+ regex: new RegExpBuilder()
+ .add(/^f/)
+ .addNonzeroWhitespace()
+ .add(/.*/, 'line')
+ .toRegExp(),
+ delegate: (match: { [key: string]: string }) => {
+ const line = match.line.trim();
+
+ const vertices = line.split(' ').filter((x) => {
+ return x.length !== 0;
+ });
+
+ if (vertices.length < 3) {
+ // this.addWarning('')
+ // throw new AppError('Face data should have at least 3 vertices');
+ }
+
+ const points: {
+ positionIndex: number;
+ texcoordIndex?: number;
+ normalIndex?: number;
+ }[] = [];
+
+ for (const vertex of vertices) {
+ const vertexData = vertex.split('/');
+ switch (vertexData.length) {
+ case 1: {
+ const index = parseInt(vertexData[0]);
+ points.push({
+ positionIndex: index,
+ texcoordIndex: index,
+ normalIndex: index,
+ });
+ break;
+ }
+ case 2: {
+ const positionIndex = parseInt(vertexData[0]);
+ const texcoordIndex = parseInt(vertexData[1]);
+ points.push({
+ positionIndex: positionIndex,
+ texcoordIndex: texcoordIndex,
+ });
+ break;
+ }
+ case 3: {
+ const positionIndex = parseInt(vertexData[0]);
+ const texcoordIndex = parseInt(vertexData[1]);
+ const normalIndex = parseInt(vertexData[2]);
+ points.push({
+ positionIndex: positionIndex,
+ texcoordIndex: texcoordIndex,
+ normalIndex: normalIndex,
+ });
+ break;
+ }
+ default:
+ throw new AppError(`Face data has unexpected number of vertex data: ${vertexData.length}`);
+ }
+ }
+
+ const pointBase = points[0];
+ for (let i = 1; i < points.length - 1; ++i) {
+ const pointA = points[i];
+ const pointB = points[i + 1];
+ const tri: Tri = {
+ positionIndices: {
+ x: pointBase.positionIndex - 1,
+ y: pointA.positionIndex - 1,
+ z: pointB.positionIndex - 1,
+ },
+ material: this._currentMaterialName,
+ };
+ if (pointBase.normalIndex || pointA.normalIndex || pointB.normalIndex) {
+ ASSERT(pointBase.normalIndex && pointA.normalIndex && pointB.normalIndex);
+ tri.normalIndices = {
+ x: pointBase.normalIndex - 1,
+ y: pointA.normalIndex - 1,
+ z: pointB.normalIndex - 1,
+ };
+ }
+ if (pointBase.texcoordIndex || pointA.texcoordIndex || pointB.texcoordIndex) {
+ ASSERT(pointBase.texcoordIndex && pointA.texcoordIndex && pointB.texcoordIndex);
+ tri.texcoordIndices = {
+ x: pointBase.texcoordIndex - 1,
+ y: pointA.texcoordIndex - 1,
+ z: pointB.texcoordIndex - 1,
+ };
+ }
+ this._tris.push(tri);
+ }
+ },
+ },
+ ];
+
+ private _currentColour: RGBA = RGBAColours.BLACK;
+ private _currentAlpha: number = 1.0;
+ private _currentTexture: string = '';
+ private _currentTransparencyTexture: string = '';
+ private _materialReady: boolean = false;
+ private _mtlParsers = [
+ {
+ // e.g. 'newmtl my_material'
+ regex: new RegExpBuilder().add(/^newmtl/).add(REGEX_NZ_ANY, 'name').toRegExp(),
+ delegate: (match: { [key: string]: string }) => {
+ this._addCurrentMaterial();
+ this._currentMaterialName = match.name.trim();
+ this._currentTexture = '';
+ this._materialReady = false;
+ },
+ },
+ {
+ // e.g. 'Kd 0.123 0.456 0.789'
+ regex: new RegExpBuilder()
+ .add(/^Kd/)
+ .addNonzeroWhitespace()
+ .add(REGEX_NUMBER, 'r')
+ .addNonzeroWhitespace()
+ .add(REGEX_NUMBER, 'g')
+ .addNonzeroWhitespace()
+ .add(REGEX_NUMBER, 'b')
+ .toRegExp(),
+ delegate: (match: { [key: string]: string }) => {
+ const r = parseFloat(match.r);
+ const g = parseFloat(match.g);
+ const b = parseFloat(match.b);
+ checkNaN(r, g, b);
+ checkFractional(r, g, b);
+ this._currentColour = { r: r, g: g, b: b, a: this._currentAlpha };
+ this._materialReady = true;
+ },
+ },
+ {
+ // e.g. 'map_Kd my/path/to/file.png'
+ regex: new RegExpBuilder().add(/^map_Kd/).add(REGEX_NZ_ANY, 'path').toRegExp(),
+ delegate: (match: { [key: string]: string }) => {
+ let mtlPath = match.path.trim();
+ if (!path.isAbsolute(mtlPath)) {
+ ASSERT(this._objPath, 'no obj path');
+ mtlPath = path.join(this._objPath.dir, mtlPath);
+ }
+ this._currentTexture = mtlPath;
+ this._materialReady = true;
+ },
+ },
+ {
+ // Transparency map
+ // e.g. 'map_d my/path/to/file.png'
+ regex: new RegExpBuilder().add(/^map_d/).add(REGEX_NZ_ANY, 'path').toRegExp(),
+ delegate: (match: { [key: string]: string }) => {
+ let texturePath = match.path.trim();
+ if (!path.isAbsolute(texturePath)) {
+ ASSERT(this._objPath, 'no obj path');
+ texturePath = path.join(this._objPath.dir, texturePath);
+ }
+ this._currentTransparencyTexture = texturePath;
+ this._materialReady = true;
+ },
+ },
+ {
+ // Transparency value
+ // e.g. 'd 0.7500'
+ regex: new RegExpBuilder()
+ .add(/^d/)
+ .addNonzeroWhitespace()
+ .add(REGEX_NUMBER, 'alpha')
+ .toRegExp(),
+ delegate: (match: { [key: string]: string }) => {
+ const alpha = parseFloat(match.alpha);
+ checkNaN(alpha);
+ checkFractional(alpha);
+ this._currentAlpha = alpha;
+ },
+ },
+ ];
+
+ override parseFile(filePath: string) {
+ ASSERT(path.isAbsolute(filePath), `ObjImporter: ${filePath} not absolute`);
+
+ this._objPath = path.parse(filePath);
+
+ this._parseOBJ(filePath);
+
+ if (this._mtlLibs.length === 0) {
+ StatusHandler.Get.add('warning', 'Could not find associated .mtl file');
+ }
+ for (let i = 0; i < this._mtlLibs.length; ++i) {
+ const mtlLib = this._mtlLibs[i];
+ if (!path.isAbsolute(mtlLib)) {
+ this._mtlLibs[i] = path.join(this._objPath.dir, mtlLib);
+ }
+ ASSERT(path.isAbsolute(this._mtlLibs[i]), 'path not absolute');
+ }
+
+ this._parseMTL();
+ LOG('Materials', this._materials);
+ }
+
+ override toMesh(): Mesh {
+ return new Mesh(this._vertices, this._normals, this._uvs, this._tris, this._materials);
+ }
+
+ private _parseOBJ(path: string) {
+ if (!fs.existsSync(path)) {
+ throw new AppError(`Could not find ${path}`);
+ }
+ const fileContents = fs.readFileSync(path, 'utf8');
+ if (fileContents.includes('�')) {
+ throw new AppError(`Unrecognised character found, please encode ${path} using UTF-8`);
+ }
+
+ fileContents.replace('\r', ''); // Convert Windows carriage return
+ const fileLines = fileContents.split('\n');
+
+ for (const line of fileLines) {
+ this.parseOBJLine(line);
+ }
+ }
+
+ public parseOBJLine(line: string) {
+ const essentialTokens = ['mtllib ', 'usemtl ', 'v ', 'vt ', 'f ', 'vn '];
+
+ for (const parser of this._objParsers) {
+ const match = parser.regex.exec(line);
+ if (match && match.groups) {
+ try {
+ parser.delegate(match.groups);
+ } catch (error) {
+ LOG_ERROR('Caught', error);
+ if (error instanceof AppError) {
+ throw new AppError(`Failed attempt to parse '${line}', because '${error.message}'`);
+ }
+ }
+ return;
+ }
+ }
+
+ const beginsWithEssentialToken = essentialTokens.some((token) => {
+ return line.startsWith(token);
+ });
+ if (beginsWithEssentialToken) {
+ throw new AppError(`Failed to parse essential token for ${line} `);
+ }
+ }
+
+ private _parseMTL() {
+ for (const mtlLib of this._mtlLibs) {
+ if (!fs.existsSync(mtlLib)) {
+ StatusHandler.Get.add('warning', `Could not find ${mtlLib}`);
+ continue;
+ }
+ const fileContents = fs.readFileSync(mtlLib, 'utf8');
+
+ fileContents.replace('\r', ''); // Convert Windows carriage return
+ const fileLines = fileContents.split('\n');
+
+ for (const line of fileLines) {
+ this._parseMTLLine(line);
+ }
+
+ this._addCurrentMaterial();
+ }
+ }
+
+ private _parseMTLLine(line: string) {
+ const essentialTokens = ['newmtl ', 'Kd ', 'map_Kd '];
+
+ for (const parser of this._mtlParsers) {
+ const match = parser.regex.exec(line);
+ if (match && match.groups) {
+ try {
+ parser.delegate(match.groups);
+ } catch (error) {
+ if (error instanceof AppError) {
+ throw new AppError(`Failed attempt to parse '${line}', because '${error.message}'`);
+ }
+ }
+ return;
+ }
+ }
+
+ const beginsWithEssentialToken = essentialTokens.some((token) => {
+ return line.startsWith(token);
+ });
+ if (beginsWithEssentialToken) {
+ throw new AppError(`Failed to parse essential token for ${line}`);
+ }
+ }
+
+ private _addCurrentMaterial() {
+ if (this._materialReady && this._currentMaterialName !== '') {
+ if (this._currentTexture !== '') {
+ this._materials[this._currentMaterialName] = {
+ type: MaterialType.textured,
+ path: this._currentTexture,
+ alphaPath: this._currentTransparencyTexture === '' ? undefined : this._currentTransparencyTexture,
+ alphaFactor: this._currentAlpha,
+ };
+ this._currentTransparencyTexture = '';
+ } else {
+ this._materials[this._currentMaterialName] = {
+ type: MaterialType.solid,
+ colour: this._currentColour,
+ };
+ }
+ this._currentAlpha = 1.0;
+ }
+ }
+}
diff --git a/src/main.ts b/src/main.ts
index 75796aca..86a125de 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -1,97 +1,111 @@
-
-/**
- ,d
- 88
- ,adPPYba, MM88MMM ,adPPYba, 8b,dPPYba,
- I8[ "" 88 a8" "8a 88P' "8a
- `"Y8ba, 88 8b d8 88 d8
- aa ]8I 88, "8a, ,a8" 88b, ,a8"
- `"YbbdP"' "Y888 `"YbbdP"' 88`YbbdP"'
- 88
- 88
-
- If you're interested in the code, I recommend starting in /src/AppContext.ts
- The stuff here is boring Electron boilerplate \(•◡•)/
-*/
-
-import { app, BrowserWindow } from 'electron';
-import path from 'path';
-import url from 'url';
-import { AppConfig } from './config';
-import { BASE_DIR, STATIC_DIR } from './util';
-
-app.commandLine.appendSwitch('js-flags', `--max-old-space-size=${AppConfig.OLD_SPACE_SIZE}`);
-
-// Keep a global reference of the window object, if you don't, the window will
-// be closed automatically when the JavaScript object is garbage collected.
-let mainWindow: BrowserWindow;
-
-function createWindow() {
- // Create the browser window.
- // const {width, height} = electron.screen.getPrimaryDisplay().workAreaSize;
- const width = 1400;
- const height = 800;
-
- // const appIcon = new Tray("../resources/icon.png");
- mainWindow = new BrowserWindow({
- width: width,
- height: height,
- icon: path.join(STATIC_DIR, process.platform === 'win32' ? './icon.ico' : './icon.png'),
- minWidth: 1280,
- minHeight: 720,
- webPreferences: {
- nodeIntegration: true,
- contextIsolation: false,
- enableRemoteModule: true,
- },
- });
- if (!AppConfig.DEBUG_ENABLED) {
- mainWindow.removeMenu();
- }
-
- // Load index.html
- mainWindow.loadURL(url.format({
- pathname: path.join(BASE_DIR, './index.html'),
- protocol: 'file:',
- slashes: true,
- }));
-
- const baseTitle = 'ObjToSchematic – Convert 3D models into Minecraft builds';
- try {
- const branchName: Buffer = require('child_process').execSync('git rev-parse --abbrev-ref HEAD').toString().replace('\n', '');
- const commitHash: (string | Buffer) = require('child_process').execSync('git rev-parse --short HEAD').toString().replace('\n', '');
- mainWindow.setTitle(`${baseTitle} (git//${branchName.toString()}++${commitHash.toString().trim()})`);
- } catch (e: any) {
- mainWindow.setTitle(`${baseTitle} (release//v0.5.1)`);
- }
-
- // Open the DevTools.
- // mainWindow.webContents.openDevTools();
-
- // Emitted when the window is closed.
- mainWindow.on('closed', function() {
- app.quit();
- });
-}
-
-// This method will be called when Electron has finished
-// initialization and is ready to create browser windows.
-// Some APIs can only be used after this event occurs.
-app.on('ready', createWindow);
-
-// Quit when all windows are closed.
-app.on('window-all-closed', function() {
- // On OS X it is common for applications and their menu bar
- // to stay active until the user quits explicitly with Cmd + Q
- if (process.platform !== 'darwin') {
- app.quit();
- }
-});
-
-app.on('activate', function() {
- // On OS X it's common to re-create a window in the app when the
- // dock icon is clicked and there are no other windows open.
- if (mainWindow === null) {
- createWindow();
- }
-});
+
+/**
+ ,d
+ 88
+ ,adPPYba, MM88MMM ,adPPYba, 8b,dPPYba,
+ I8[ "" 88 a8" "8a 88P' "8a
+ `"Y8ba, 88 8b d8 88 d8
+ aa ]8I 88, "8a, ,a8" 88b, ,a8"
+ `"YbbdP"' "Y888 `"YbbdP"' 88`YbbdP"'
+ 88
+ 88
+
+ If you're interested in the code, I recommend starting in /src/AppContext.ts
+ The stuff here is boring Electron boilerplate \(•◡•)/
+*/
+
+import { app, BrowserWindow } from 'electron';
+import url from 'url';
+
+import { AppConfig } from './config';
+import { AppPaths, PathUtil } from './util/path_util';
+
+app.commandLine.appendSwitch('js-flags', `--max-old-space-size=${AppConfig.Get.OLD_SPACE_SIZE_MB}`);
+
+// Keep a global reference of the window object, if you don't, the window will
+// be closed automatically when the JavaScript object is garbage collected.
+let mainWindow: BrowserWindow;
+
+function createWindow() {
+ // Create the browser window.
+ // const {width, height} = electron.screen.getPrimaryDisplay().workAreaSize;
+ const width = 1400;
+ const height = 800;
+
+ // const appIcon = new Tray("../resources/icon.png");
+ mainWindow = new BrowserWindow({
+ width: width,
+ height: height,
+ icon: PathUtil.join(AppPaths.Get.static, process.platform === 'win32' ? './icon.ico' : './icon.png'),
+ minWidth: 1280,
+ minHeight: 720,
+ webPreferences: {
+ nodeIntegration: true,
+ nodeIntegrationInWorker: true,
+ contextIsolation: false,
+ enableRemoteModule: true,
+ },
+ });
+ if (AppConfig.Get.RELEASE_MODE) {
+ mainWindow.removeMenu();
+ }
+
+ // Load index.html
+ mainWindow.loadURL(url.format({
+ pathname: PathUtil.join(AppPaths.Get.base, './index.html'),
+ protocol: 'file:',
+ slashes: true,
+ }));
+
+ const baseTitle = 'ObjToSchematic – Convert 3D models into Minecraft builds';
+ if (AppConfig.Get.RELEASE_MODE) {
+ mainWindow.setTitle(`${baseTitle} (${AppConfig.Get.RELEASE_VERSION})`);
+ } else {
+ try {
+ const branchName: Buffer = require('child_process')
+ .execSync('git rev-parse --abbrev-ref HEAD')
+ .toString()
+ .replace('\n', '');
+
+ const commitHash: (string | Buffer) = require('child_process')
+ .execSync('git rev-parse --short HEAD')
+ .toString()
+ .replace('\n', '');
+
+ mainWindow.setTitle(`${baseTitle} (git ${branchName.toString()}${commitHash.toString().trim()})`);
+ } catch (e: any) {
+ mainWindow.setTitle(`${baseTitle} (git)`);
+ }
+ }
+
+
+ // Open the DevTools.
+ // mainWindow.webContents.openDevTools();
+
+ // Emitted when the window is closed.
+ mainWindow.on('closed', function () {
+ app.quit();
+ });
+}
+
+// This method will be called when Electron has finished
+// initialization and is ready to create browser windows.
+// Some APIs can only be used after this event occurs.
+app.on('ready', createWindow);
+
+// Quit when all windows are closed.
+app.on('window-all-closed', function () {
+ // On OS X it is common for applications and their menu bar
+ // to stay active until the user quits explicitly with Cmd + Q
+ if (process.platform !== 'darwin') {
+ app.quit();
+ }
+});
+
+app.on('activate', function () {
+ // On OS X it's common to re-create a window in the app when the
+ // dock icon is clicked and there are no other windows open.
+ if (mainWindow === null) {
+ createWindow();
+ }
+});
diff --git a/src/math.ts b/src/math.ts
index 4595b09a..6292a97a 100644
--- a/src/math.ts
+++ b/src/math.ts
@@ -1,71 +1,163 @@
-import { AppError, LOG_ERROR } from './util';
-import { Vector3 } from './vector';
-
-
-export const argMax = (array: [number]) => {
- return array.map((x, i) => [x, i]).reduce((r, a) => (a[0] > r[0] ? a : r))[1];
-};
-
-export const fastCrossXAxis = (vec: Vector3) => {
- return new Vector3(0.0, -vec.z, vec.y);
-};
-
-export const fastCrossYAxis = (vec: Vector3) => {
- return new Vector3(vec.z, 0.0, -vec.x);
-};
-
-export const fastCrossZAxis = (vec: Vector3) => {
- return new Vector3(-vec.y, vec.x, 0.0);
-};
-
-export const clamp = (value: number, min: number, max: number) => {
- return Math.max(Math.min(max, value), min);
-};
-
-export const floorToNearest = (value: number, base: number) => {
- return Math.floor(value / base) * base;
-};
-
-export const ceilToNearest = (value: number, base: number) => {
- return Math.ceil(value / base) * base;
-};
-
-export const roundToNearest = (value: number, base: number) => {
- return Math.round(value / base) * base;
-};
-
-export const mapRange = (value: number, fromMin: number, fromMax: number, toMin: number, toMax: number) => {
- return (value - fromMin)/(fromMax - fromMin) * (toMax - toMin) + toMin;
-};
-
-export const wayThrough = (value: number, min: number, max: number) => {
- // ASSERT(value >= min && value <= max);
- return (value - min) / (max - min);
-};
-
-/**
- * Throws is any number in args is NaN
- */
-export const checkNaN = (...args: number[]) => {
- const existsNaN = args.some((arg) => {
- return isNaN(arg);
- });
- if (existsNaN) {
- LOG_ERROR(args);
- throw new AppError('Found NaN');
- }
-};
-
-/**
- * Throws if any number in not within [0, 1]
- */
-export const checkFractional = (...args: number[]) => {
- const existsOutside = args.some((arg) => {
- return arg > 1.0 || arg < 0.0;
- });
- if (existsOutside) {
- throw new AppError('Found value outside of [0, 1]');
- }
-};
-
-export const degreesToRadians = Math.PI / 180;
+import { AppError } from './util/error_util';
+import { LOG_ERROR } from './util/log_util';
+import { Vector3 } from './vector';
+
+export namespace AppMath {
+ export const RADIANS_0 = degreesToRadians(0.0);
+ export const RADIANS_90 = degreesToRadians(90.0);
+ export const RADIANS_180 = degreesToRadians(180.0);
+ export const RADIANS_270 = degreesToRadians(270.0);
+
+ export function nearlyEqual(a: number, b: number, tolerance: number = 0.0001) {
+ return Math.abs(a - b) < tolerance;
+ }
+
+ export function degreesToRadians(degrees: number) {
+ return degrees * (Math.PI / 180.0);
+ }
+
+ /**
+ * Converts a float in [0, 1] to an int in [0, 255]
+ * @param decimal A number in [0, 1]
+ */
+ export function uint8(decimal: number) {
+ return Math.floor(decimal * 255);
+ }
+}
+
+export const argMax = (array: [number]) => {
+ return array.map((x, i) => [x, i]).reduce((r, a) => (a[0] > r[0] ? a : r))[1];
+};
+
+export const clamp = (value: number, min: number, max: number) => {
+ return Math.max(Math.min(max, value), min);
+};
+
+export const floorToNearest = (value: number, base: number) => {
+ return Math.floor(value / base) * base;
+};
+
+export const ceilToNearest = (value: number, base: number) => {
+ return Math.ceil(value / base) * base;
+};
+
+export const roundToNearest = (value: number, base: number) => {
+ return Math.round(value / base) * base;
+};
+
+export const between = (value: number, min: number, max: number) => {
+ return min <= value && value <= max;
+};
+
+export const mapRange = (value: number, fromMin: number, fromMax: number, toMin: number, toMax: number) => {
+ return (value - fromMin) / (fromMax - fromMin) * (toMax - toMin) + toMin;
+};
+
+export const wayThrough = (value: number, min: number, max: number) => {
+ // ASSERT(value >= min && value <= max);
+ return (value - min) / (max - min);
+};
+
+/**
+ * Throws is any number in args is NaN
+ */
+export const checkNaN = (...args: number[]) => {
+ const existsNaN = args.some((arg) => {
+ return isNaN(arg);
+ });
+ if (existsNaN) {
+ LOG_ERROR(args);
+ throw new AppError('Found NaN');
+ }
+};
+
+/**
+ * Throws if any number in not within [0, 1]
+ */
+export const checkFractional = (...args: number[]) => {
+ const existsOutside = args.some((arg) => {
+ return arg > 1.0 || arg < 0.0;
+ });
+ if (existsOutside) {
+ throw new AppError('Found value outside of [0, 1]');
+ }
+};
+
+export const degreesToRadians = Math.PI / 180;
+
+export class SmoothVariable {
+ private _actual: number;
+ private _target: number;
+ private _smoothing: number;
+ private _min: number;
+ private _max: number;
+
+ public constructor(value: number, smoothing: number) {
+ this._actual = value;
+ this._target = value;
+ this._smoothing = smoothing;
+ this._min = -Infinity;
+ this._max = Infinity;
+ }
+
+ public setClamp(min: number, max: number) {
+ this._min = min;
+ this._max = max;
+ }
+
+ public addToTarget(delta: number) {
+ this._target = clamp(this._target + delta, this._min, this._max);
+ }
+
+ public setTarget(target: number) {
+ this._target = clamp(target, this._min, this._max);
+ }
+
+ public setActual(actual: number) {
+ this._actual = actual;
+ }
+
+ public tick() {
+ this._actual += (this._target - this._actual) * this._smoothing;
+ }
+
+ public getActual() {
+ return this._actual;
+ }
+
+ public getTarget() {
+ return this._target;
+ }
+}
+
+export class SmoothVectorVariable {
+ private _actual: Vector3;
+ private _target: Vector3;
+ private _smoothing: number;
+
+ public constructor(value: Vector3, smoothing: number) {
+ this._actual = value;
+ this._target = value;
+ this._smoothing = smoothing;
+ }
+
+ public addToTarget(delta: Vector3) {
+ this._target = Vector3.add(this._target, delta);
+ }
+
+ public setTarget(target: Vector3) {
+ this._target = target;
+ }
+
+ public tick() {
+ this._actual.add(Vector3.sub(this._target, this._actual).mulScalar(this._smoothing));
+ }
+
+ public getActual() {
+ return this._actual;
+ }
+
+ public getTarget() {
+ return this._target;
+ }
+}
diff --git a/src/mesh.ts b/src/mesh.ts
index ed4ad25c..832109d2 100644
--- a/src/mesh.ts
+++ b/src/mesh.ts
@@ -1,403 +1,336 @@
-import { Vector3 } from './vector';
-import { UV, Bounds, ASSERT, AppError, LOG_WARN, getRandomID } from './util';
-import { Triangle, UVTriangle } from './triangle';
-
-import path from 'path';
-import fs from 'fs';
-import { Texture, TextureFiltering } from './texture';
-import { StatusHandler } from './status';
-import { RGBA, RGBAColours, RGBAUtil } from './colour';
-
-interface VertexIndices {
- x: number;
- y: number;
- z: number;
-}
-
-export interface Tri {
- positionIndices: VertexIndices;
- texcoordIndices?: VertexIndices;
- normalIndices?: VertexIndices;
- material: string;
-}
-
-/* eslint-disable */
-export enum MaterialType { solid, textured }
-/* eslint-enable */
-export interface SolidMaterial { colour: RGBA; type: MaterialType.solid }
-export interface TexturedMaterial {
- path: string;
- type: MaterialType.textured;
- alphaPath?: string;
- alphaFactor: number;
-}
-export type MaterialMap = {[key: string]: (SolidMaterial | TexturedMaterial)};
-
-export class Mesh {
- public readonly id: string;
-
- public _vertices: Vector3[];
- public _normals!: Vector3[];
- public _uvs!: UV[];
- public _tris!: Tri[];
-
- private _materials!: MaterialMap;
- private _loadedTextures: { [materialName: string]: Texture };
- public static desiredHeight = 8.0;
-
- constructor(vertices: Vector3[], normals: Vector3[], uvs: UV[], tris: Tri[], materials: MaterialMap) {
- this.id = getRandomID();
-
- this._vertices = vertices;
- this._normals = normals;
- this._uvs = uvs;
- this._tris = tris;
- this._materials = materials;
- this._loadedTextures = {};
- }
-
- // TODO: Always check
- public processMesh() {
- this._checkMesh();
- this._checkMaterials();
-
- this._centreMesh();
- this._normaliseMesh();
-
- this._loadTextures();
- }
-
- public getBounds() {
- const bounds = Bounds.getInfiniteBounds();
- for (const vertex of this._vertices) {
- bounds.extendByPoint(vertex);
- }
- return bounds;
- }
-
- public translateMesh(offset: Vector3) {
- this._vertices.forEach((vertex) => {
- vertex.add(offset);
- });
- }
-
- public scaleMesh(scaleFactor: number) {
- this._vertices.forEach((vertex) => {
- vertex.mulScalar(scaleFactor);
- });
- }
-
- private _checkMesh() {
- // TODO: Check indices exist
-
- if (this._vertices.length === 0) {
- throw new AppError('No vertices were loaded');
- }
-
- if (this._tris.length === 0) {
- throw new AppError('No triangles were loaded');
- }
-
- if (this._tris.length >= 100_000) {
- StatusHandler.Get.add(
- 'warning',
- `The imported mesh has ${this._tris.length.toLocaleString()} triangles, consider simplifying it in a DDC such as Blender`,
- );
- }
-
- StatusHandler.Get.add(
- 'info',
- `${this._vertices.length.toLocaleString()} vertices, ${this._tris.length.toLocaleString()} triangles`,
- );
-
- // Give warning if normals are not defined
- let giveNormalsWarning = false;
- for (let triIndex = 0; triIndex < this.getTriangleCount(); ++triIndex) {
- const tri = this._tris[triIndex];
- if (tri.normalIndices) {
- const xWellDefined = tri.normalIndices.x < this._normals.length;
- const yWellDefined = tri.normalIndices.y < this._normals.length;
- const zWellDefined = tri.normalIndices.z < this._normals.length;
- if (!xWellDefined || !yWellDefined || !zWellDefined) {
- giveNormalsWarning = true;
- break;
- }
- }
- if (!tri.normalIndices) {
- giveNormalsWarning = true;
- break;
- }
- }
- if (giveNormalsWarning) {
- StatusHandler.Get.add(
- 'warning',
- 'Some vertices do not have their normals defined, this may cause voxels to be aligned incorrectly',
- );
- };
- }
-
- private _checkMaterials() {
- if (Object.keys(this._materials).length === 0) {
- throw new AppError('Loaded mesh has no materials');
- }
-
- // Check used materials exist
- let wasRemapped = false;
- let debugName = (Math.random() + 1).toString(36).substring(7);
- while (debugName in this._materials) {
- debugName = (Math.random() + 1).toString(36).substring(7);
- }
-
- const missingMaterials = new Set();
- for (const tri of this._tris) {
- if (!(tri.material in this._materials)) {
- missingMaterials.add(tri.material);
- wasRemapped = true;
- tri.material = debugName;
- }
- }
- if (wasRemapped) {
- LOG_WARN('Triangles use these materials but they were not found', missingMaterials);
- StatusHandler.Get.add(
- 'warning',
- 'Some materials were not loaded correctly',
- );
- this._materials[debugName] = {
- type: MaterialType.solid,
- colour: RGBAColours.WHITE,
- };
- }
-
- // Check texture paths are absolute and exist
- for (const materialName in this._materials) {
- const material = this._materials[materialName];
- if (material.type === MaterialType.textured) {
- ASSERT(path.isAbsolute(material.path), 'Material texture path not absolute');
- if (!fs.existsSync(material.path)) {
- StatusHandler.Get.add(
- 'warning',
- `Could not find ${material.path}`,
- );
- LOG_WARN(`Could not find ${material.path} for material ${materialName}, changing to solid-white material`);
- this._materials[materialName] = {
- type: MaterialType.solid,
- colour: RGBAColours.WHITE,
- };
- }
- }
- }
- }
-
- private _centreMesh() {
- /*
- const centre = new Vector3(0, 0, 0);
- let totalWeight = 0.0;
-
- // Find the weighted centre
- this.tris.forEach((tri, triIndex) => {
- const verts = this.getVertices(triIndex);
- const triangle = new Triangle(verts.v0, verts.v1, verts.v2);
-
- const weight = triangle.getArea();
- totalWeight += weight;
- centre.add(triangle.getCentre().mulScalar(weight));
- });
- centre.divScalar(totalWeight);
- */
- const centre = this.getBounds().getCentre();
-
- if (!centre.isNumber()) {
- throw new AppError('Could not find centre of mesh');
- }
-
- // Translate each triangle
- this.translateMesh(centre.negate());
- }
-
- private _normaliseMesh() {
- const bounds = this.getBounds();
- const size = Vector3.sub(bounds.max, bounds.min);
- const scaleFactor = Mesh.desiredHeight / size.y;
-
- if (isNaN(scaleFactor) || !isFinite(scaleFactor)) {
- throw new AppError('Could not scale mesh correctly - mesh is likely 2D, rotate it so that it has a non-zero height');
- } else {
- this.scaleMesh(scaleFactor);
- }
- }
-
- private _loadTextures() {
- this._loadedTextures = {};
- for (const tri of this._tris) {
- const material = this._materials[tri.material];
- if (material.type == MaterialType.textured) {
- if (!(tri.material in this._loadedTextures)) {
- this._loadedTextures[tri.material] = new Texture(material.path, material.alphaPath);
- }
- }
- }
- }
-
- public getVertices(triIndex: number) {
- const tri = this._tris[triIndex];
- return {
- v0: this._vertices[tri.positionIndices.x],
- v1: this._vertices[tri.positionIndices.y],
- v2: this._vertices[tri.positionIndices.z],
- };
- }
-
- public getUVs(triIndex: number) {
- const tri = this._tris[triIndex];
- if (tri.texcoordIndices) {
- return {
- uv0: this._uvs[tri.texcoordIndices.x] || new UV(0.0, 0.0),
- uv1: this._uvs[tri.texcoordIndices.y] || new UV(0.0, 0.0),
- uv2: this._uvs[tri.texcoordIndices.z] || new UV(0.0, 0.0),
- };
- }
- return {
- uv0: new UV(0.0, 0.0),
- uv1: new UV(0.0, 0.0),
- uv2: new UV(0.0, 0.0),
- };
- }
-
- public getNormals(triIndex: number) {
- const vertexData = this.getVertices(triIndex);
- const faceNormal = new Triangle(vertexData.v0, vertexData.v1, vertexData.v2).getNormal();
- const tri = this._tris[triIndex];
- if (tri.normalIndices) {
- return {
- v0: this._normals[tri.normalIndices.x] || faceNormal,
- v1: this._normals[tri.normalIndices.y] || faceNormal,
- v2: this._normals[tri.normalIndices.z] || faceNormal,
- };
- }
- return {
- v0: faceNormal,
- v1: faceNormal,
- v2: faceNormal,
- };
- }
-
- public getUVTriangle(triIndex: number): UVTriangle {
- const vertices = this.getVertices(triIndex);
- const texcoords = this.getUVs(triIndex);
- return new UVTriangle(
- vertices.v0,
- vertices.v1,
- vertices.v2,
- texcoords.uv0,
- texcoords.uv1,
- texcoords.uv2,
- );
- }
-
- public getMaterialByTriangle(triIndex: number) {
- return this._tris[triIndex].material;
- }
-
- public getMaterialByName(materialName: string) {
- return this._materials[materialName];
- }
-
- public getMaterials() {
- return this._materials;
- }
-
- public sampleMaterial(materialName: string, uv: UV, textureFiltering: TextureFiltering): RGBA {
- ASSERT(materialName in this._materials, `Sampling material that does not exist: ${materialName}`);
- const material = this._materials[materialName];
- if (material.type === MaterialType.solid) {
- return material.colour;
- } else {
- ASSERT(materialName in this._loadedTextures, 'Sampling texture that is not loaded');
- const colour = this._loadedTextures[materialName].getRGBA(uv, textureFiltering);
- colour.a *= material.alphaFactor;
- return colour;
- }
- }
-
- /*
- public simplify(ratio: number) {
- ASSERT(ratio > 0.0 && ratio <= 1.0);
- const cells: Array = Array(this.tris.length);
- this.tris.forEach((tris, index) => {
- cells[index] = [tris.iX, tris.iY, tris.iZ];
- });
- const positions: Array = Array(this.vertices.length);
- this.vertices.forEach((vertex, index) => {
- positions[index] = vertex.toArray();
- });
- const targetNumTris = positions.length * ratio;
- const simplified = meshSimplify(cells, positions)(targetNumTris);
-
- const placeHolderMat = this.tris[0].material;
- this.tris = new Array(simplified.cells.length);
- simplified.cells.forEach((cell: number[], index: number) => {
- this.tris[index] = {
- iX: cell[0],
- iY: cell[1],
- iZ: cell[2],
- iXUV: 0.5,
- iYUV: 0.5,
- iZUV: 0.5,
- material: placeHolderMat,
- };
- });
-
- this.vertices = new Array(simplified.positions.length);
- simplified.positions.forEach((position: number[], index: number) => {
- this.vertices[index] = Vector3.fromArray(position);
- });
- }
- */
-
- public copy(): Mesh {
- const newVertices = new Array(this._vertices.length);
- for (let i = 0; i < this._vertices.length; ++i) {
- newVertices[i] = this._vertices[i].copy();
- }
-
- const newNormals = new Array(this._normals.length);
- for (let i = 0; i < this._normals.length; ++i) {
- newNormals[i] = this._normals[i].copy();
- }
-
- const newUVs = new Array(this._uvs.length);
- for (let i = 0; i < this._uvs.length; ++i) {
- newUVs[i] = this._uvs[i].copy();
- }
-
- const newTris = new Array(this._tris.length);
- for (let i = 0; i < this._tris.length; ++i) {
- // FIXME: Replace
- newTris[i] = JSON.parse(JSON.stringify(this._tris[i]));
- }
-
- const materials: { [materialName: string]: (SolidMaterial | TexturedMaterial) } = {}; // JSON.parse(JSON.stringify(this.materials));
- for (const materialName in this._materials) {
- const material = this._materials[materialName];
- if (material.type === MaterialType.solid) {
- materials[materialName] = {
- type: MaterialType.solid,
- colour: RGBAUtil.copy(material.colour),
- };
- } else {
- materials[materialName] = {
- type: MaterialType.textured,
- alphaFactor: material.alphaFactor,
- alphaPath: material.alphaPath,
- path: material.path,
- };
- };
- }
-
- return new Mesh(newVertices, newNormals, newUVs, newTris, materials);
- }
-
- public getTriangleCount(): number {
- return this._tris.length;
- }
-}
+import fs from 'fs';
+import path from 'path';
+
+import { Bounds } from './bounds';
+import { RGBA, RGBAColours } from './colour';
+import { StatusHandler } from './status';
+import { Texture, TextureFiltering } from './texture';
+import { Triangle, UVTriangle } from './triangle';
+import { getRandomID, UV } from './util';
+import { AppError, ASSERT } from './util/error_util';
+import { LOG_WARN } from './util/log_util';
+import { Vector3 } from './vector';
+
+interface VertexIndices {
+ x: number;
+ y: number;
+ z: number;
+}
+
+export interface Tri {
+ positionIndices: VertexIndices;
+ texcoordIndices?: VertexIndices;
+ normalIndices?: VertexIndices;
+ material: string;
+}
+
+/* eslint-disable */
+export enum MaterialType { solid, textured }
+/* eslint-enable */
+export interface SolidMaterial { colour: RGBA; type: MaterialType.solid }
+export interface TexturedMaterial {
+ path: string;
+ type: MaterialType.textured;
+ alphaPath?: string;
+ alphaFactor: number;
+}
+export type MaterialMap = { [key: string]: (SolidMaterial | TexturedMaterial) };
+
+export class Mesh {
+ public readonly id: string;
+
+ public _vertices: Vector3[];
+ public _normals!: Vector3[];
+ public _uvs!: UV[];
+ public _tris!: Tri[];
+
+ private _materials!: MaterialMap;
+ private _loadedTextures: { [materialName: string]: Texture };
+ public static desiredHeight = 8.0;
+
+ constructor(vertices: Vector3[], normals: Vector3[], uvs: UV[], tris: Tri[], materials: MaterialMap) {
+ this.id = getRandomID();
+
+ this._vertices = vertices;
+ this._normals = normals;
+ this._uvs = uvs;
+ this._tris = tris;
+ this._materials = materials;
+ this._loadedTextures = {};
+ }
+
+ // TODO: Always check
+ public processMesh() {
+ this._checkMesh();
+ this._checkMaterials();
+
+ this._centreMesh();
+ this._normaliseMesh();
+
+ this._loadTextures();
+ }
+
+ public getBounds() {
+ const bounds = Bounds.getInfiniteBounds();
+ if (this._transform) {
+ for (const vertex of this._vertices) {
+ bounds.extendByPoint(this._transform(vertex));
+ }
+ } else {
+ for (const vertex of this._vertices) {
+ bounds.extendByPoint(vertex);
+ }
+ }
+ return bounds;
+ }
+
+ public translateMesh(offset: Vector3) {
+ this._vertices.forEach((vertex) => {
+ vertex.add(offset);
+ });
+ }
+
+ public scaleMesh(scaleFactor: number) {
+ this._vertices.forEach((vertex) => {
+ vertex.mulScalar(scaleFactor);
+ });
+ }
+
+ private _checkMesh() {
+ // TODO: Check indices exist
+
+ if (this._vertices.length === 0) {
+ throw new AppError('No vertices were loaded');
+ }
+
+ if (this._tris.length === 0) {
+ throw new AppError('No triangles were loaded');
+ }
+
+ if (this._tris.length >= 100_000) {
+ StatusHandler.Get.add(
+ 'warning',
+ `The imported mesh has ${this._tris.length.toLocaleString()} triangles, consider simplifying it in a DDC such as Blender`,
+ );
+ }
+
+ StatusHandler.Get.add(
+ 'info',
+ `${this._vertices.length.toLocaleString()} vertices, ${this._tris.length.toLocaleString()} triangles`,
+ );
+
+ // Give warning if normals are not defined
+ let giveNormalsWarning = false;
+ for (let triIndex = 0; triIndex < this.getTriangleCount(); ++triIndex) {
+ const tri = this._tris[triIndex];
+ if (tri.normalIndices) {
+ const xWellDefined = tri.normalIndices.x < this._normals.length;
+ const yWellDefined = tri.normalIndices.y < this._normals.length;
+ const zWellDefined = tri.normalIndices.z < this._normals.length;
+ if (!xWellDefined || !yWellDefined || !zWellDefined) {
+ giveNormalsWarning = true;
+ break;
+ }
+ }
+ if (!tri.normalIndices) {
+ giveNormalsWarning = true;
+ break;
+ }
+ }
+ if (giveNormalsWarning) {
+ StatusHandler.Get.add(
+ 'warning',
+ 'Some vertices do not have their normals defined, this may cause voxels to be aligned incorrectly',
+ );
+ };
+ }
+
+ private _checkMaterials() {
+ if (Object.keys(this._materials).length === 0) {
+ throw new AppError('Loaded mesh has no materials');
+ }
+
+ // Check used materials exist
+ let wasRemapped = false;
+ let debugName = (Math.random() + 1).toString(36).substring(7);
+ while (debugName in this._materials) {
+ debugName = (Math.random() + 1).toString(36).substring(7);
+ }
+
+ const missingMaterials = new Set();
+ for (const tri of this._tris) {
+ if (!(tri.material in this._materials)) {
+ missingMaterials.add(tri.material);
+ wasRemapped = true;
+ tri.material = debugName;
+ }
+ }
+ if (wasRemapped) {
+ LOG_WARN('Triangles use these materials but they were not found', missingMaterials);
+ StatusHandler.Get.add(
+ 'warning',
+ 'Some materials were not loaded correctly',
+ );
+ this._materials[debugName] = {
+ type: MaterialType.solid,
+ colour: RGBAColours.WHITE,
+ };
+ }
+
+ // Check texture paths are absolute and exist
+ for (const materialName in this._materials) {
+ const material = this._materials[materialName];
+ if (material.type === MaterialType.textured) {
+ ASSERT(path.isAbsolute(material.path), 'Material texture path not absolute');
+ if (!fs.existsSync(material.path)) {
+ StatusHandler.Get.add(
+ 'warning',
+ `Could not find ${material.path}`,
+ );
+ LOG_WARN(`Could not find ${material.path} for material ${materialName}, changing to solid-white material`);
+ this._materials[materialName] = {
+ type: MaterialType.solid,
+ colour: RGBAColours.WHITE,
+ };
+ }
+ }
+ }
+ }
+
+ private _centreMesh() {
+ const centre = this.getBounds().getCentre();
+
+ if (!centre.isNumber()) {
+ throw new AppError('Could not find centre of mesh');
+ }
+
+ // Translate each triangle
+ this.translateMesh(centre.negate());
+ }
+
+ private _normaliseMesh() {
+ const bounds = this.getBounds();
+ const size = Vector3.sub(bounds.max, bounds.min);
+ const scaleFactor = Mesh.desiredHeight / size.y;
+
+ if (isNaN(scaleFactor) || !isFinite(scaleFactor)) {
+ throw new AppError('Could not scale mesh correctly - mesh is likely 2D, rotate it so that it has a non-zero height');
+ } else {
+ this.scaleMesh(scaleFactor);
+ }
+ }
+
+ private _loadTextures() {
+ this._loadedTextures = {};
+ for (const tri of this._tris) {
+ const material = this._materials[tri.material];
+ if (material.type == MaterialType.textured) {
+ if (!(tri.material in this._loadedTextures)) {
+ this._loadedTextures[tri.material] = new Texture(material.path, material.alphaPath);
+ }
+ }
+ }
+ }
+
+ public getVertices(triIndex: number) {
+ const tri = this._tris[triIndex];
+ if (this._transform) {
+ return {
+ v0: this._transform(this._vertices[tri.positionIndices.x]),
+ v1: this._transform(this._vertices[tri.positionIndices.y]),
+ v2: this._transform(this._vertices[tri.positionIndices.z]),
+ };
+ } else {
+ return {
+ v0: this._vertices[tri.positionIndices.x],
+ v1: this._vertices[tri.positionIndices.y],
+ v2: this._vertices[tri.positionIndices.z],
+ };
+ }
+ }
+
+ public getUVs(triIndex: number) {
+ const tri = this._tris[triIndex];
+ if (tri.texcoordIndices) {
+ return {
+ uv0: this._uvs[tri.texcoordIndices.x] || new UV(0.0, 0.0),
+ uv1: this._uvs[tri.texcoordIndices.y] || new UV(0.0, 0.0),
+ uv2: this._uvs[tri.texcoordIndices.z] || new UV(0.0, 0.0),
+ };
+ }
+ return {
+ uv0: new UV(0.0, 0.0),
+ uv1: new UV(0.0, 0.0),
+ uv2: new UV(0.0, 0.0),
+ };
+ }
+
+ public getNormals(triIndex: number) {
+ const vertexData = this.getVertices(triIndex);
+ const faceNormal = new Triangle(vertexData.v0, vertexData.v1, vertexData.v2).getNormal();
+ const tri = this._tris[triIndex];
+ if (tri.normalIndices) {
+ return {
+ v0: this._normals[tri.normalIndices.x] || faceNormal,
+ v1: this._normals[tri.normalIndices.y] || faceNormal,
+ v2: this._normals[tri.normalIndices.z] || faceNormal,
+ };
+ }
+ return {
+ v0: faceNormal,
+ v1: faceNormal,
+ v2: faceNormal,
+ };
+ }
+
+ public getUVTriangle(triIndex: number): UVTriangle {
+ const vertices = this.getVertices(triIndex);
+ const texcoords = this.getUVs(triIndex);
+ return new UVTriangle(
+ vertices.v0,
+ vertices.v1,
+ vertices.v2,
+ texcoords.uv0,
+ texcoords.uv1,
+ texcoords.uv2,
+ );
+ }
+
+ public getMaterialByTriangle(triIndex: number) {
+ return this._tris[triIndex].material;
+ }
+
+ public getMaterialByName(materialName: string) {
+ return this._materials[materialName];
+ }
+
+ public getMaterials() {
+ return this._materials;
+ }
+
+ public sampleMaterial(materialName: string, uv: UV, textureFiltering: TextureFiltering): RGBA {
+ ASSERT(materialName in this._materials, `Sampling material that does not exist: ${materialName}`);
+ const material = this._materials[materialName];
+ if (material.type === MaterialType.solid) {
+ return material.colour;
+ } else {
+ ASSERT(materialName in this._loadedTextures, 'Sampling texture that is not loaded');
+ const colour = this._loadedTextures[materialName].getRGBA(uv, textureFiltering);
+ colour.a *= material.alphaFactor;
+ return colour;
+ }
+ }
+
+ public getTriangleCount(): number {
+ return this._tris.length;
+ }
+
+ private _transform?: (vertex: Vector3) => Vector3;
+ public setTransform(transform: (vertex: Vector3) => Vector3) {
+ this._transform = transform;
+ }
+
+ public clearTransform() {
+ this._transform = undefined;
+ }
+}
diff --git a/src/mouse.ts b/src/mouse.ts
index 7ba5dc35..36b735f0 100644
--- a/src/mouse.ts
+++ b/src/mouse.ts
@@ -1,58 +1,58 @@
-import { Renderer } from './renderer';
-
-interface MouseState {
- x: number,
- y: number,
- buttons: number
-}
-
-export class MouseManager {
- private _gl: WebGLRenderingContext;
-
- private static readonly MOUSE_LEFT = 1;
- private static readonly MOUSE_RIGHT = 2;
-
- private prevMouse: MouseState;
- private currMouse: MouseState;
-
- private static _instance: MouseManager;
-
- public static get Get() {
- return this._instance || (this._instance = new this(Renderer.Get._gl));
- }
-
- private constructor(gl: WebGLRenderingContext) {
- this._gl = gl;
-
- this.currMouse = { x: -1, y: -1, buttons: 0 };
- this.prevMouse = { x: -1, y: -1, buttons: 0 };
- }
-
- public onMouseMove(e: MouseEvent) {
- this.prevMouse = this.currMouse;
- this.currMouse = { x: e.clientX, y: e.clientY, buttons: e.buttons };
- }
-
- public isMouseLeftDown() {
- this.currMouse.buttons & MouseManager.MOUSE_LEFT;
- }
-
- public isMouseRightDown() {
- this.currMouse.buttons & MouseManager.MOUSE_RIGHT;
- }
-
- public getMouseDelta() {
- const delta = {
- dx: this.currMouse.x - this.prevMouse.x,
- dy: -(this.currMouse.y - this.prevMouse.y),
- };
- this.prevMouse = this.currMouse;
- return delta;
- };
-
- public getMousePosNorm() {
- const normX = 2 * (this.currMouse.x / this._gl.canvas.width ) - 1;
- const normY = -(2 * (this.currMouse.y / this._gl.canvas.height) - 1);
- return { x: normX, y: normY };
- }
-}
+import { Renderer } from './renderer';
+
+interface MouseState {
+ x: number,
+ y: number,
+ buttons: number
+}
+
+export class MouseManager {
+ private _gl: WebGLRenderingContext;
+
+ private static readonly MOUSE_LEFT = 1;
+ private static readonly MOUSE_RIGHT = 2;
+
+ private prevMouse: MouseState;
+ private currMouse: MouseState;
+
+ private static _instance: MouseManager;
+
+ public static get Get() {
+ return this._instance || (this._instance = new this(Renderer.Get._gl));
+ }
+
+ private constructor(gl: WebGLRenderingContext) {
+ this._gl = gl;
+
+ this.currMouse = { x: -1, y: -1, buttons: 0 };
+ this.prevMouse = { x: -1, y: -1, buttons: 0 };
+ }
+
+ public onMouseMove(e: MouseEvent) {
+ this.prevMouse = this.currMouse;
+ this.currMouse = { x: e.clientX, y: e.clientY, buttons: e.buttons };
+ }
+
+ public isMouseLeftDown() {
+ this.currMouse.buttons & MouseManager.MOUSE_LEFT;
+ }
+
+ public isMouseRightDown() {
+ this.currMouse.buttons & MouseManager.MOUSE_RIGHT;
+ }
+
+ public getMouseDelta() {
+ const delta = {
+ dx: this.currMouse.x - this.prevMouse.x,
+ dy: -(this.currMouse.y - this.prevMouse.y),
+ };
+ this.prevMouse = this.currMouse;
+ return delta;
+ };
+
+ public getMousePosNorm() {
+ const normX = 2 * (this.currMouse.x / this._gl.canvas.width ) - 1;
+ const normY = -(2 * (this.currMouse.y / this._gl.canvas.height) - 1);
+ return { x: normX, y: normY };
+ }
+}
diff --git a/src/occlusion.ts b/src/occlusion.ts
index fbf89a8c..3751c879 100644
--- a/src/occlusion.ts
+++ b/src/occlusion.ts
@@ -1,155 +1,155 @@
-import { AppConfig } from './config';
-import { ASSERT } from './util';
-import { Vector3 } from './vector';
-import { VoxelMesh } from './voxel_mesh';
-
-export class OcclusionManager {
- private _occlusionNeighboursIndices!: Array>>; // Ew
- private _occlusions: number[];
- private _localNeighbourhoodCache: number[];
- private _occlusionsSetup: boolean;
- private _faceNormals: Vector3[];
-
- private static _instance: OcclusionManager;
- public static get Get() {
- return this._instance || (this._instance = new this());
- }
-
- private constructor() {
- this._occlusionsSetup = false;
- this._setupOcclusions();
- this._occlusions = new Array(6 * 4 * 4);
- this._localNeighbourhoodCache = Array(27);
- this._faceNormals = this.getFaceNormals();
- }
-
- public getBlankOcclusions() {
- return new Array(96).fill(1.0);
- }
-
- public getOcclusions(centre: Vector3, voxelMesh: VoxelMesh) {
- // Cache local neighbours
- const neighbourData = voxelMesh.getNeighbourhoodMap().get(centre.stringify());
- if (neighbourData === undefined) {
- // This voxel has no neighbours within a 1-block radius
- return this.getBlankOcclusions();
- }
-
- for (let i = 0; i < 27; ++i) {
- this._localNeighbourhoodCache[i] = (neighbourData.value & (1 << i)) > 0 ? 1 : 0;
- }
-
- // For each face
- for (let f = 0; f < 6; ++f) {
- for (let v = 0; v < 4; ++v) {
- let numNeighbours = 0;
- let occlusionValue = 1.0;
- for (let i = 0; i < 2; ++i) {
- const neighbourIndex = this._occlusionNeighboursIndices[f][v][i];
- numNeighbours += this._localNeighbourhoodCache[neighbourIndex];
- }
- // If both edge blocks along this vertex exist,
- // assume corner exists (even if it doesnt)
- // (This is a stylistic choice)
- if (numNeighbours == 2 && AppConfig.AMBIENT_OCCLUSION_OVERRIDE_CORNER) {
- ++numNeighbours;
- } else {
- const neighbourIndex = this._occlusionNeighboursIndices[f][v][2];
- numNeighbours += this._localNeighbourhoodCache[neighbourIndex];
- }
-
- // Convert from occlusion denoting the occlusion factor to the
- // attenuation in light value: 0 -> 1.0, 1 -> 0.8, 2 -> 0.6, 3 -> 0.4
- occlusionValue = 1.0 - 0.2 * numNeighbours;
-
-
- const baseIndex = f * 16 + v;
- this._occlusions[baseIndex + 0] = occlusionValue;
- this._occlusions[baseIndex + 4] = occlusionValue;
- this._occlusions[baseIndex + 8] = occlusionValue;
- this._occlusions[baseIndex + 12] = occlusionValue;
- }
- }
-
- return this._occlusions;
- }
-
- public getFaceNormals() {
- return [
- new Vector3(1, 0, 0), new Vector3(-1, 0, 0),
- new Vector3(0, 1, 0), new Vector3(0, -1, 0),
- new Vector3(0, 0, 1), new Vector3(0, 0, -1),
- ];
- }
-
- public static getNeighbourIndex(neighbour: Vector3) {
- return 9*(neighbour.x+1) + 3*(neighbour.y+1) + (neighbour.z+1);
- }
-
- private _setupOcclusions() {
- ASSERT(!this._occlusionsSetup);
-
- // TODO: Find some for-loop to clean this up
- // [Edge, Edge, Corrner]
- const occlusionNeighbours = [
- [
- // +X
- [new Vector3(1, 1, 0), new Vector3(1, 0, -1), new Vector3(1, 1, -1)],
- [new Vector3(1, -1, 0), new Vector3(1, 0, -1), new Vector3(1, -1, -1)],
- [new Vector3(1, 1, 0), new Vector3(1, 0, 1), new Vector3(1, 1, 1)],
- [new Vector3(1, -1, 0), new Vector3(1, 0, 1), new Vector3(1, -1, 1)],
- ],
-
- [
- // -X
- [new Vector3(-1, 1, 0), new Vector3(-1, 0, 1), new Vector3(-1, 1, 1)],
- [new Vector3(-1, -1, 0), new Vector3(-1, 0, 1), new Vector3(-1, -1, 1)],
- [new Vector3(-1, 1, 0), new Vector3(-1, 0, -1), new Vector3(-1, 1, -1)],
- [new Vector3(-1, -1, 0), new Vector3(-1, 0, -1), new Vector3(-1, -1, -1)],
- ],
-
- [
- // +Y
- [new Vector3(-1, 1, 0), new Vector3(0, 1, 1), new Vector3(-1, 1, 1)],
- [new Vector3(-1, 1, 0), new Vector3(0, 1, -1), new Vector3(-1, 1, -1)],
- [new Vector3(1, 1, 0), new Vector3(0, 1, 1), new Vector3(1, 1, 1)],
- [new Vector3(1, 1, 0), new Vector3(0, 1, -1), new Vector3(1, 1, -1)],
- ],
-
- [
- // -Y
- [new Vector3(-1, -1, 0), new Vector3(0, -1, -1), new Vector3(-1, -1, -1)],
- [new Vector3(-1, -1, 0), new Vector3(0, -1, 1), new Vector3(-1, -1, 1)],
- [new Vector3(1, -1, 0), new Vector3(0, -1, -1), new Vector3(1, -1, -1)],
- [new Vector3(1, -1, 0), new Vector3(0, -1, 1), new Vector3(1, -1, 1)],
- ],
-
- [
- // + Z
- [new Vector3(0, 1, 1), new Vector3(1, 0, 1), new Vector3(1, 1, 1)],
- [new Vector3(0, -1, 1), new Vector3(1, 0, 1), new Vector3(1, -1, 1)],
- [new Vector3(0, 1, 1), new Vector3(-1, 0, 1), new Vector3(-1, 1, 1)],
- [new Vector3(0, -1, 1), new Vector3(-1, 0, 1), new Vector3(-1, -1, 1)],
- ],
-
- [
- // -Z
- [new Vector3(0, 1, -1), new Vector3(-1, 0, -1), new Vector3(-1, 1, -1)],
- [new Vector3(0, -1, -1), new Vector3(-1, 0, -1), new Vector3(-1, -1, -1)],
- [new Vector3(0, 1, -1), new Vector3(1, 0, -1), new Vector3(1, 1, -1)],
- [new Vector3(0, -1, -1), new Vector3(1, 0, -1), new Vector3(1, -1, -1)],
- ],
- ];
-
- this._occlusionNeighboursIndices = new Array>>();
- for (let i = 0; i < 6; ++i) {
- const row = new Array>();
- for (let j = 0; j < 4; ++j) {
- row.push(occlusionNeighbours[i][j].map((x) => OcclusionManager.getNeighbourIndex(x)));
- }
- this._occlusionNeighboursIndices.push(row);
- }
-
- this._occlusionsSetup = true;
- }
-}
+import { AppConfig } from './config';
+import { ASSERT } from './util/error_util';
+import { Vector3 } from './vector';
+import { VoxelMesh } from './voxel_mesh';
+
+export class OcclusionManager {
+ private _occlusionNeighboursIndices!: Array>>; // Ew
+ private _occlusions: number[];
+ private _localNeighbourhoodCache: number[];
+ private _occlusionsSetup: boolean;
+ private _faceNormals: Vector3[];
+
+ private static _instance: OcclusionManager;
+ public static get Get() {
+ return this._instance || (this._instance = new this());
+ }
+
+ private constructor() {
+ this._occlusionsSetup = false;
+ this._setupOcclusions();
+ this._occlusions = new Array(6 * 4 * 4);
+ this._localNeighbourhoodCache = Array(27);
+ this._faceNormals = this.getFaceNormals();
+ }
+
+ public getBlankOcclusions() {
+ return new Array(96).fill(1.0);
+ }
+
+ public getOcclusions(centre: Vector3, voxelMesh: VoxelMesh) {
+ // Cache local neighbours
+ const neighbourData = voxelMesh.getNeighbourhoodMap().get(centre.stringify());
+ if (neighbourData === undefined) {
+ // This voxel has no neighbours within a 1-block radius
+ return this.getBlankOcclusions();
+ }
+
+ for (let i = 0; i < 27; ++i) {
+ this._localNeighbourhoodCache[i] = (neighbourData.value & (1 << i)) > 0 ? 1 : 0;
+ }
+
+ // For each face
+ for (let f = 0; f < 6; ++f) {
+ for (let v = 0; v < 4; ++v) {
+ let numNeighbours = 0;
+ let occlusionValue = 1.0;
+ for (let i = 0; i < 2; ++i) {
+ const neighbourIndex = this._occlusionNeighboursIndices[f][v][i];
+ numNeighbours += this._localNeighbourhoodCache[neighbourIndex];
+ }
+ // If both edge blocks along this vertex exist,
+ // assume corner exists (even if it doesnt)
+ // (This is a stylistic choice)
+ if (numNeighbours == 2 && AppConfig.Get.AMBIENT_OCCLUSION_OVERRIDE_CORNER) {
+ ++numNeighbours;
+ } else {
+ const neighbourIndex = this._occlusionNeighboursIndices[f][v][2];
+ numNeighbours += this._localNeighbourhoodCache[neighbourIndex];
+ }
+
+ // Convert from occlusion denoting the occlusion factor to the
+ // attenuation in light value: 0 -> 1.0, 1 -> 0.8, 2 -> 0.6, 3 -> 0.4
+ occlusionValue = 1.0 - 0.2 * numNeighbours;
+
+
+ const baseIndex = f * 16 + v;
+ this._occlusions[baseIndex + 0] = occlusionValue;
+ this._occlusions[baseIndex + 4] = occlusionValue;
+ this._occlusions[baseIndex + 8] = occlusionValue;
+ this._occlusions[baseIndex + 12] = occlusionValue;
+ }
+ }
+
+ return this._occlusions;
+ }
+
+ public getFaceNormals() {
+ return [
+ new Vector3(1, 0, 0), new Vector3(-1, 0, 0),
+ new Vector3(0, 1, 0), new Vector3(0, -1, 0),
+ new Vector3(0, 0, 1), new Vector3(0, 0, -1),
+ ];
+ }
+
+ public static getNeighbourIndex(neighbour: Vector3) {
+ return 9*(neighbour.x+1) + 3*(neighbour.y+1) + (neighbour.z+1);
+ }
+
+ private _setupOcclusions() {
+ ASSERT(!this._occlusionsSetup);
+
+ // TODO: Find some for-loop to clean this up
+ // [Edge, Edge, Corrner]
+ const occlusionNeighbours = [
+ [
+ // +X
+ [new Vector3(1, 1, 0), new Vector3(1, 0, -1), new Vector3(1, 1, -1)],
+ [new Vector3(1, -1, 0), new Vector3(1, 0, -1), new Vector3(1, -1, -1)],
+ [new Vector3(1, 1, 0), new Vector3(1, 0, 1), new Vector3(1, 1, 1)],
+ [new Vector3(1, -1, 0), new Vector3(1, 0, 1), new Vector3(1, -1, 1)],
+ ],
+
+ [
+ // -X
+ [new Vector3(-1, 1, 0), new Vector3(-1, 0, 1), new Vector3(-1, 1, 1)],
+ [new Vector3(-1, -1, 0), new Vector3(-1, 0, 1), new Vector3(-1, -1, 1)],
+ [new Vector3(-1, 1, 0), new Vector3(-1, 0, -1), new Vector3(-1, 1, -1)],
+ [new Vector3(-1, -1, 0), new Vector3(-1, 0, -1), new Vector3(-1, -1, -1)],
+ ],
+
+ [
+ // +Y
+ [new Vector3(-1, 1, 0), new Vector3(0, 1, 1), new Vector3(-1, 1, 1)],
+ [new Vector3(-1, 1, 0), new Vector3(0, 1, -1), new Vector3(-1, 1, -1)],
+ [new Vector3(1, 1, 0), new Vector3(0, 1, 1), new Vector3(1, 1, 1)],
+ [new Vector3(1, 1, 0), new Vector3(0, 1, -1), new Vector3(1, 1, -1)],
+ ],
+
+ [
+ // -Y
+ [new Vector3(-1, -1, 0), new Vector3(0, -1, -1), new Vector3(-1, -1, -1)],
+ [new Vector3(-1, -1, 0), new Vector3(0, -1, 1), new Vector3(-1, -1, 1)],
+ [new Vector3(1, -1, 0), new Vector3(0, -1, -1), new Vector3(1, -1, -1)],
+ [new Vector3(1, -1, 0), new Vector3(0, -1, 1), new Vector3(1, -1, 1)],
+ ],
+
+ [
+ // + Z
+ [new Vector3(0, 1, 1), new Vector3(1, 0, 1), new Vector3(1, 1, 1)],
+ [new Vector3(0, -1, 1), new Vector3(1, 0, 1), new Vector3(1, -1, 1)],
+ [new Vector3(0, 1, 1), new Vector3(-1, 0, 1), new Vector3(-1, 1, 1)],
+ [new Vector3(0, -1, 1), new Vector3(-1, 0, 1), new Vector3(-1, -1, 1)],
+ ],
+
+ [
+ // -Z
+ [new Vector3(0, 1, -1), new Vector3(-1, 0, -1), new Vector3(-1, 1, -1)],
+ [new Vector3(0, -1, -1), new Vector3(-1, 0, -1), new Vector3(-1, -1, -1)],
+ [new Vector3(0, 1, -1), new Vector3(1, 0, -1), new Vector3(1, 1, -1)],
+ [new Vector3(0, -1, -1), new Vector3(1, 0, -1), new Vector3(1, -1, -1)],
+ ],
+ ];
+
+ this._occlusionNeighboursIndices = new Array>>();
+ for (let i = 0; i < 6; ++i) {
+ const row = new Array>();
+ for (let j = 0; j < 4; ++j) {
+ row.push(occlusionNeighbours[i][j].map((x) => OcclusionManager.getNeighbourIndex(x)));
+ }
+ this._occlusionNeighboursIndices.push(row);
+ }
+
+ this._occlusionsSetup = true;
+ }
+}
diff --git a/src/palette.ts b/src/palette.ts
new file mode 100644
index 00000000..6256d89e
--- /dev/null
+++ b/src/palette.ts
@@ -0,0 +1,156 @@
+import fs from 'fs';
+import path from 'path';
+
+import { Atlas } from './atlas';
+import { StatusHandler } from './status';
+import { AppTypes, AppUtil, TOptional } from './util';
+import { ASSERT } from './util/error_util';
+import { LOG_WARN } from './util/log_util';
+import { AppPaths, PathUtil } from './util/path_util';
+
+export class PaletteManager {
+ public static getPalettesInfo(): { paletteID: string, paletteDisplayName: string }[] {
+ const palettes: { paletteID: string, paletteDisplayName: string }[] = [];
+
+ fs.readdirSync(AppPaths.Get.palettes).forEach((file) => {
+ const paletteFilePath = path.parse(file);
+ if (paletteFilePath.ext === Palette.PALETTE_FILE_EXT) {
+ const paletteID = paletteFilePath.name;
+
+ let paletteDisplayName = paletteID.replace('-', ' ').toLowerCase();
+ paletteDisplayName = AppUtil.Text.capitaliseFirstLetter(paletteDisplayName);
+
+ palettes.push({ paletteID: paletteID, paletteDisplayName: paletteDisplayName });
+ }
+ });
+
+ return palettes;
+ }
+}
+
+export class Palette {
+ public static PALETTE_NAME_REGEX: RegExp = /^[a-zA-Z\-]+$/;
+ public static PALETTE_FILE_EXT: string = '.palette';
+ private static _FILE_VERSION: number = 1;
+
+ private _blocks: AppTypes.TNamespacedBlockName[];
+
+ private constructor() {
+ this._blocks = [];
+ }
+
+ public static create(): Palette {
+ return new Palette();
+ }
+
+ public static load(paletteName: string): TOptional {
+ if (!Palette._isValidPaletteName(paletteName)) {
+ return;
+ }
+
+ const palettePath = Palette._getPalettePath(paletteName);
+ if (!fs.existsSync(palettePath)) {
+ return;
+ }
+
+ const palette = Palette.create();
+
+ const paletteFile = fs.readFileSync(palettePath, 'utf8');
+ const paletteJSON = JSON.parse(paletteFile);
+ const paletteVersion = paletteJSON.version;
+
+ if (paletteVersion === undefined) {
+ const paletteBlocks = paletteJSON.blocks;
+ for (const blockName of paletteBlocks) {
+ palette.add(AppUtil.Text.namespaceBlock(blockName));
+ }
+ } else if (paletteVersion === 1) {
+ const paletteBlocks = paletteJSON.blocks;
+ for (const blockName of paletteBlocks) {
+ palette.add(blockName);
+ }
+ } else {
+ ASSERT(false, `Unrecognised .palette file version: ${paletteVersion}`);
+ }
+
+ return palette;
+ }
+
+ public save(paletteName: string): boolean {
+ if (!Palette._isValidPaletteName(paletteName)) {
+ return false;
+ }
+ const filePath = Palette._getPalettePath(paletteName);
+
+ const paletteJSON = {
+ version: Palette._FILE_VERSION,
+ blocks: this._blocks,
+ };
+
+ try {
+ fs.writeFileSync(filePath, JSON.stringify(paletteJSON, null, 4));
+ return true;
+ } catch {
+ return false;
+ }
+ }
+
+ public add(blockName: AppTypes.TNamespacedBlockName): void {
+ if (!this._blocks.includes(blockName)) {
+ this._blocks.push(AppUtil.Text.namespaceBlock(blockName));
+ }
+ }
+
+ public remove(blockName: string): boolean {
+ const index = this._blocks.indexOf(AppUtil.Text.namespaceBlock(blockName));
+ if (index !== -1) {
+ this._blocks.splice(index, 1);
+ return true;
+ }
+ return false;
+ }
+
+ public has(blockName: string): boolean {
+ return this._blocks.includes(AppUtil.Text.namespaceBlock(blockName));
+ }
+
+ public count() {
+ return this._blocks.length;
+ }
+
+ public getBlocks() {
+ return this._blocks;
+ }
+
+ public static getAllPalette(): TOptional {
+ return Palette.load('all-release');
+ }
+
+ /**
+ * Removes blocks from the palette if they do not
+ * have texture data in the given atlas.
+ */
+ public removeMissingAtlasBlocks(atlas: Atlas) {
+ const missingBlocks: AppTypes.TNamespacedBlockName[] = [];
+ for (let blockIndex = this._blocks.length - 1; blockIndex >= 0; --blockIndex) {
+ const blockName = this._blocks[blockIndex];
+ if (!atlas.hasBlock(blockName)) {
+ missingBlocks.push(blockName);
+ this.remove(blockName);
+ }
+ }
+
+ if (missingBlocks.length > 0) {
+ StatusHandler.Get.add('warning', `${missingBlocks.length} palette block(s) are missing atlas textures, they will not be used`);
+ LOG_WARN('Blocks missing atlas textures', missingBlocks);
+ }
+ }
+
+ private static _isValidPaletteName(paletteName: string): boolean {
+ return paletteName.length > 0 && Palette.PALETTE_NAME_REGEX.test(paletteName);
+ }
+
+ private static _getPalettePath(paletteName: string): string {
+ return PathUtil.join(AppPaths.Get.palettes, `./${paletteName}.palette`);
+ }
+}
diff --git a/src/progress.ts b/src/progress.ts
new file mode 100644
index 00000000..85843670
--- /dev/null
+++ b/src/progress.ts
@@ -0,0 +1,78 @@
+import { EAppEvent, EventManager } from './event';
+import { ASSERT } from './util/error_util';
+import { LOGF } from './util/log_util';
+
+export type TTaskID =
+ | 'Importing'
+ | 'MeshBuffer'
+ | 'Voxelising'
+ | 'VoxelMeshBuffer'
+ | 'Assigning'
+ | 'BlockMeshBuffer'
+ | 'Exporting';
+
+export type TTaskHandle = {
+ nextPercentage: number,
+ id: TTaskID,
+}
+
+export class ProgressManager {
+ /* Singleton */
+ private static _instance: ProgressManager;
+ public static get Get() {
+ return this._instance || (this._instance = new this());
+ }
+
+ private _tasks: TTaskID[];
+
+ private constructor() {
+ this._tasks = [];
+ }
+
+ /**
+ * Start tracking the progress of a task.
+ * @param taskId The id of the task (created here).
+ */
+ public start(taskId: TTaskID): TTaskHandle {
+ ASSERT(!this._tasks.includes(taskId), `Task with id '${taskId}' already being tracked`);
+ this._tasks.push(taskId);
+ EventManager.Get.broadcast(EAppEvent.onTaskStart, taskId);
+
+ LOGF(`[PROGRESS]: Start '${taskId} (${this._tasks.length} task(s))'`);
+
+ return {
+ nextPercentage: 0.0,
+ id: taskId,
+ };
+ }
+
+ /**
+ * Announce progress has been made on a task.
+ * @param taskId The id of the task (created in `start`).
+ * @param percentage A number between 0.0 and 1.0, inclusive.
+ */
+ public progress(tracker: TTaskHandle, percentage: number) {
+ if (percentage > tracker.nextPercentage) {
+ //LOGF(`[PROGRESS]: Progress '${tracker.id}' (${this._tasks.length} task(s))'`);
+ EventManager.Get.broadcast(EAppEvent.onTaskProgress, tracker.id, percentage);
+ tracker.nextPercentage += 0.05;
+ }
+ }
+
+ /**
+ * Announce a task has completed.
+ * @param taskId The id of the task (created in `start`).
+ */
+ public end(tracker: TTaskHandle) {
+ LOGF(`[PROGRESS]: End '${tracker.id}' (${this._tasks.length} task(s))'`);
+
+ const taskIndex = this._tasks.findIndex((task) => { return task === tracker.id; });
+ ASSERT(taskIndex !== -1, `Task with that id '${tracker.id}' is not being tracked, ${this._tasks}`);
+ this._tasks.splice(taskIndex, 1);
+ EventManager.Get.broadcast(EAppEvent.onTaskEnd, tracker.id);
+ }
+
+ public clear() {
+ this._tasks = [];
+ }
+}
diff --git a/src/ray.ts b/src/ray.ts
index 75f0ad7d..4a94cde5 100644
--- a/src/ray.ts
+++ b/src/ray.ts
@@ -1,62 +1,62 @@
-import { Vector3 } from './vector';
-import { ASSERT } from './util';
-
-const EPSILON = 0.0000001;
-
-/* eslint-disable */
-export enum Axes {
- x, y, z,
-}
-/* eslint-enable */
-
-export function axesToDirection(axis: Axes) {
- if (axis === Axes.x) {
- return new Vector3(1, 0, 0);
- }
- if (axis === Axes.y) {
- return new Vector3(0, 1, 0);
- }
- if (axis === Axes.z) {
- return new Vector3(0, 0, 1);
- }
- ASSERT(false);
-}
-
-export interface Ray {
- origin: Vector3,
- axis: Axes
-}
-
-export function rayIntersectTriangle(ray: Ray, v0: Vector3, v1: Vector3, v2: Vector3): (Vector3 | undefined) {
- const edge1 = Vector3.sub(v1, v0);
- const edge2 = Vector3.sub(v2, v0);
-
- const rayDirection = axesToDirection(ray.axis);
- const h = Vector3.cross(rayDirection, edge2);
- const a = Vector3.dot(edge1, h);
-
- if (a > -EPSILON && a < EPSILON) {
- return; // Ray is parallel to triangle
- }
-
- const f = 1.0 / a;
- const s = Vector3.sub(ray.origin, v0);
- const u = f * Vector3.dot(s, h);
-
- if (u < 0.0 || u > 1.0) {
- return;
- }
-
- const q = Vector3.cross(s, edge1);
- const v = f * Vector3.dot(rayDirection, q);
-
- if (v < 0.0 || u + v > 1.0) {
- return;
- }
-
- const t = f * Vector3.dot(edge2, q);
-
- if (t > EPSILON) {
- return Vector3.add(ray.origin, Vector3.mulScalar(rayDirection, t));
- }
-}
+import { ASSERT } from './util/error_util';
+import { Vector3 } from './vector';
+
+const EPSILON = 0.0000001;
+
+/* eslint-disable */
+export enum Axes {
+ x, y, z,
+}
+/* eslint-enable */
+
+export function axesToDirection(axis: Axes) {
+ if (axis === Axes.x) {
+ return new Vector3(1, 0, 0);
+ }
+ if (axis === Axes.y) {
+ return new Vector3(0, 1, 0);
+ }
+ if (axis === Axes.z) {
+ return new Vector3(0, 0, 1);
+ }
+ ASSERT(false);
+}
+
+export interface Ray {
+ origin: Vector3,
+ axis: Axes
+}
+
+export function rayIntersectTriangle(ray: Ray, v0: Vector3, v1: Vector3, v2: Vector3): (Vector3 | undefined) {
+ const edge1 = Vector3.sub(v1, v0);
+ const edge2 = Vector3.sub(v2, v0);
+
+ const rayDirection = axesToDirection(ray.axis);
+ const h = Vector3.cross(rayDirection, edge2);
+ const a = Vector3.dot(edge1, h);
+
+ if (a > -EPSILON && a < EPSILON) {
+ return; // Ray is parallel to triangle
+ }
+
+ const f = 1.0 / a;
+ const s = Vector3.sub(ray.origin, v0);
+ const u = f * Vector3.dot(s, h);
+
+ if (u < 0.0 || u > 1.0) {
+ return;
+ }
+
+ const q = Vector3.cross(s, edge1);
+ const v = f * Vector3.dot(rayDirection, q);
+
+ if (v < 0.0 || u + v > 1.0) {
+ return;
+ }
+
+ const t = f * Vector3.dot(edge2, q);
+
+ if (t > EPSILON) {
+ return Vector3.add(ray.origin, Vector3.mulScalar(rayDirection, t));
+ }
+}
diff --git a/src/render_buffer.ts b/src/render_buffer.ts
new file mode 100644
index 00000000..86d68174
--- /dev/null
+++ b/src/render_buffer.ts
@@ -0,0 +1,229 @@
+import * as twgl from 'twgl.js';
+
+import { Renderer } from './renderer';
+import { ASSERT } from './util/error_util';
+
+export interface Attribute {
+ name: string,
+ numComponents: number
+}
+
+interface BottomlessBufferData {
+ indices: BottomlessAttributeData,
+ [name: string]: BottomlessAttributeData
+}
+
+interface BottomlessAttributeData {
+ numComponents: number,
+ data: Array
+}
+
+export interface AttributeData {
+ indices: Uint32Array
+ custom: {
+ [name: string]: Array
+ }
+}
+
+export function MergeAttributeData(...data: AttributeData[]): AttributeData {
+ if (data.length === 0) {
+ return {
+ indices: new Uint32Array(),
+ custom: {},
+ };
+ }
+ // Check custom attributes match
+ const requiredAttributes = Object.keys(data[0].custom);
+ for (let i = 1; i < data.length; ++i) {
+ const customAttributes = Object.keys(data[i].custom);
+ const isAllRequiredInCustom = requiredAttributes.every((attr) => {
+ return customAttributes.includes(attr);
+ });
+ const isAllCustomInRequired = customAttributes.every((attr) => {
+ return requiredAttributes.includes(attr);
+ });
+ ASSERT(isAllRequiredInCustom && isAllCustomInRequired, 'Attributes to merge do not match');
+ }
+ // Merge data
+ const indices = Array.from(data[0].indices);
+ const custom = data[0].custom;
+ for (let i = 1; i < data.length; ++i) {
+ const nextIndex = Math.max(...indices) + 1;
+ const d = data[i];
+ const newIndices = d.indices.map((index) => index + nextIndex);
+ indices.push(...Array.from(newIndices));
+ for (const attr of requiredAttributes) {
+ const attrData = d.custom[attr];
+ custom[attr].push(...attrData);
+ }
+ }
+
+ return {
+ indices: new Uint32Array(indices),
+ custom: custom,
+ };
+}
+
+export class RenderBuffer {
+ private _WebGLBuffer?: {
+ buffer: twgl.BufferInfo,
+ numElements: number
+ };
+ private _buffer!: BottomlessBufferData;
+ private _attributes: {[name: string]: Attribute};
+ private _maxIndex: number;
+ private _compiled: boolean;
+ private _needsCompiling: boolean;
+
+ public constructor(attributes: Array) {
+ this._attributes = {};
+ for (const attr of attributes) {
+ this._attributes[attr.name] = {
+ name: attr.name,
+ numComponents: attr.numComponents,
+ };
+ }
+
+ this._needsCompiling = false;
+ this._compiled = false;
+ this._maxIndex = 0;
+
+ this._getNewBuffer();
+ }
+
+ public add(data: AttributeData) {
+ const mappedIndicesToAdd = new Array(data.indices.length);
+ let maxMapped = -1;
+ data.indices.forEach((index, i) => {
+ const newIndex = index + this._maxIndex;
+ maxMapped = Math.max(maxMapped, newIndex);
+ mappedIndicesToAdd[i] = newIndex;
+ });
+ this._buffer.indices.data.push(...mappedIndicesToAdd);
+ this._maxIndex = 1 + maxMapped;
+
+ for (const attr in this._attributes) {
+ this._buffer[attr].data.push(...data.custom[attr]);
+ }
+
+ this._needsCompiling = true;
+ }
+
+ public static from(other: RenderBuffer): RenderBuffer {
+ const buffer = new RenderBuffer([]);
+ buffer._buffer = other._buffer;
+ buffer._attributes = other._attributes;
+ buffer._maxIndex = other._maxIndex;
+ buffer._compiled = other._compiled;
+ buffer._needsCompiling = other._needsCompiling;
+ return buffer;
+ }
+
+ public attachNewAttribute(attribute: Attribute, data: Array) {
+ ASSERT(this._buffer[attribute.name] === undefined, 'Attribute already exists in buffer');
+ ASSERT(this._attributes[attribute.name] === undefined, 'Attribute already exists in attributes');
+ const expectedDataLength = this._maxIndex * attribute.numComponents;
+ ASSERT(data.length === expectedDataLength, `Data length expected to be ${expectedDataLength}, got ${data.length}`);
+ this._buffer[attribute.name] = {
+ numComponents: attribute.numComponents,
+ data: data,
+ };
+ this._attributes[attribute.name] = attribute;
+ this._needsCompiling = true;
+ }
+
+ public removeAttribute(attributeName: string) {
+ delete this._buffer[attributeName];
+ delete this._attributes[attributeName];
+ this._needsCompiling = true;
+ }
+
+ public getWebGLBuffer() {
+ this._compile();
+ ASSERT(this._WebGLBuffer !== undefined);
+ return this._WebGLBuffer;
+ }
+
+ private _compile() {
+ if (this._compiled && !this._needsCompiling) {
+ return;
+ }
+
+ const newBuffer: { indices: { data: Uint32Array, numComponents: number }, [arr: string]: { data: (Float32Array | Uint32Array), numComponents: number }} = {
+ indices: { data: Uint32Array.from(this._buffer.indices.data), numComponents: this._buffer.indices.numComponents },
+ };
+ for (const key in this._buffer) {
+ if (key !== 'indices') {
+ newBuffer[key] = {
+ data: Float32Array.from(this._buffer[key].data),
+ numComponents: this._buffer[key].numComponents,
+ };
+ }
+ }
+
+ this._WebGLBuffer = {
+ buffer: twgl.createBufferInfoFromArrays(Renderer.Get._gl, newBuffer),
+ numElements: this._buffer.indices.data.length,
+ };
+
+ this._compiled = true;
+ this._needsCompiling = false;
+ }
+
+ private _getNewBuffer() {
+ this._buffer = {
+ indices: {numComponents: 1, data: []},
+ };
+ for (const attr in this._attributes) {
+ this._buffer[attr] = {
+ numComponents: this._attributes[attr].numComponents,
+ data: [],
+ };
+ }
+ }
+
+ private _checkDataMatchesAttributes(data: AttributeData) {
+ if (!('indices' in data)) {
+ throw Error('Given data does not have indices data');
+ }
+ const setsRequired = data.indices.reduce((a, v) => Math.max(a, v)) + 1;
+ for (const attr in this._attributes) {
+ if (!(attr in data)) {
+ throw Error(`Given data does not have ${attr} data`);
+ }
+ if (data.custom[attr].length % this._attributes[attr].numComponents != 0) {
+ throw Error(`Not enough/too much ${attr} data given`);
+ }
+ const numSets = data.custom[attr].length / this._attributes[attr].numComponents;
+ if (numSets != setsRequired) {
+ // throw `Number of indices does not match number of ${attr} components given`;
+ throw Error(`Expected ${setsRequired * this._attributes[attr].numComponents} values for ${attr}, got ${data.custom[attr].length}`);
+ }
+ }
+ }
+
+ public copy(): RenderBuffer {
+ const copiedBuffer = new RenderBuffer([]);
+
+ copiedBuffer._buffer = {
+ indices: {
+ numComponents: this._buffer.indices.numComponents,
+ data: Array.from(this._buffer.indices.data),
+ },
+ };
+ for (const key in this._buffer) {
+ if (key !== 'indices') {
+ copiedBuffer._buffer[key] = {
+ numComponents: this._buffer[key].numComponents,
+ data: Array.from(this._buffer[key].data),
+ };
+ }
+ }
+
+ copiedBuffer._attributes = JSON.parse(JSON.stringify(this._attributes));
+ copiedBuffer._maxIndex = this._maxIndex;
+ copiedBuffer._compiled = false;
+ copiedBuffer._needsCompiling = true;
+ return copiedBuffer;
+ }
+}
diff --git a/src/renderer.ts b/src/renderer.ts
index 1e4e4460..be8482ae 100644
--- a/src/renderer.ts
+++ b/src/renderer.ts
@@ -1,444 +1,445 @@
-import { Vector3 } from './vector';
-import { ArcballCamera } from './camera';
-import { ShaderManager } from './shaders';
-import { RenderBuffer } from './buffer';
-import { DebugGeometryTemplates } from './geometry';
-import { Mesh, SolidMaterial, TexturedMaterial, MaterialType } from './mesh';
-import { BlockAtlas } from './block_atlas';
-import { ASSERT, LOG } from './util';
-import { VoxelMesh } from './voxel_mesh';
-import { BlockMesh } from './block_mesh';
-
-import * as twgl from 'twgl.js';
-import { EAppEvent, EventManager } from './event';
-import { RGBA, RGBAUtil } from './colour';
-import { Texture } from './texture';
-
-/* eslint-disable */
-export enum MeshType {
- None,
- TriangleMesh,
- VoxelMesh,
- BlockMesh
-}
-/* eslint-enable */
-
-/* eslint-disable */
-enum EDebugBufferComponents {
- Grid,
- Wireframe,
- Normals,
- Bounds,
- Dev,
-}
-/* eslint-enable */
-
-export class Renderer {
- public _gl: WebGLRenderingContext;
-
- private _backgroundColour: RGBA = { r: 0.125, g: 0.125, b: 0.125, a: 1.0 };
- private _atlasTexture?: WebGLTexture;
-
- private _meshToUse: MeshType = MeshType.None;
- private _voxelSize: number = 1.0;
- private _gridOffset: Vector3 = new Vector3(0, 0, 0);
-
- private _modelsAvailable: number;
-
- private _materialBuffers: Array<{
- material: (SolidMaterial | (TexturedMaterial & { texture: WebGLTexture, alpha?: WebGLTexture, useAlphaChannel?: boolean }))
- buffer: twgl.BufferInfo,
- numElements: number,
- }>;
- public _voxelBuffer?: twgl.BufferInfo;
- public _voxelBufferRaw?: {[attribute: string]: { numComponents: number, data: Float32Array | Uint32Array }};
- private _blockBuffer?: twgl.BufferInfo;
- private _debugBuffers: { [meshType: string]: { [bufferComponent: string]: RenderBuffer } };
- private _axisBuffer: RenderBuffer;
-
- private _isGridComponentEnabled: { [bufferComponent: string]: boolean };
- private _axesEnabled: boolean;
-
- private static _instance: Renderer;
- public static get Get() {
- return this._instance || (this._instance = new this());
- }
-
- private constructor() {
- this._gl = (document.getElementById('canvas')).getContext('webgl', {
- alpha: false,
- })!;
- twgl.addExtensionsToContext(this._gl);
-
- this._modelsAvailable = 0;
- this._materialBuffers = [];
-
- this._debugBuffers = {};
- this._debugBuffers[MeshType.None] = {};
- this._debugBuffers[MeshType.TriangleMesh] = {};
- this._debugBuffers[MeshType.VoxelMesh] = {};
- this._debugBuffers[MeshType.BlockMesh] = {};
-
- this._isGridComponentEnabled = {};
- this._isGridComponentEnabled[EDebugBufferComponents.Grid] = false;
- this._axesEnabled = false;
-
- this._axisBuffer = new RenderBuffer([
- { name: 'position', numComponents: 3 },
- { name: 'colour', numComponents: 4 },
- ]);
- this._axisBuffer.add(DebugGeometryTemplates.arrow(new Vector3(0, 0, 0), new Vector3(1, 0, 0), { r: 0.96, g: 0.21, b: 0.32, a: 1.0 }));
- this._axisBuffer.add(DebugGeometryTemplates.arrow(new Vector3(0, 0, 0), new Vector3(0, 1, 0), { r: 0.44, g: 0.64, b: 0.11, a: 1.0 }));
- this._axisBuffer.add(DebugGeometryTemplates.arrow(new Vector3(0, 0, 0), new Vector3(0, 0, 1), { r: 0.18, g: 0.52, b: 0.89, a: 1.0 }));
- }
-
- public update() {
- ArcballCamera.Get.updateCamera();
- }
-
- public draw() {
- this._setupScene();
-
- switch (this._meshToUse) {
- case MeshType.TriangleMesh:
- this._drawMesh();
- break;
- case MeshType.VoxelMesh:
- this._drawVoxelMesh();
- break;
- case MeshType.BlockMesh:
- this._drawBlockMesh();
- break;
- };
-
- this._drawDebug();
- }
-
- // /////////////////////////////////////////////////////////////////////////
-
- public toggleIsGridEnabled() {
- const isEnabled = !this._isGridComponentEnabled[EDebugBufferComponents.Grid];
- this._isGridComponentEnabled[EDebugBufferComponents.Grid] = isEnabled;
- EventManager.Get.broadcast(EAppEvent.onGridEnabledChanged, isEnabled);
- }
-
- public toggleIsAxesEnabled() {
- this._axesEnabled = !this._axesEnabled;
- EventManager.Get.broadcast(EAppEvent.onAxesEnabledChanged, this._axesEnabled);
- }
-
- public toggleIsWireframeEnabled() {
- const isEnabled = !this._isGridComponentEnabled[EDebugBufferComponents.Wireframe];
- this._isGridComponentEnabled[EDebugBufferComponents.Wireframe] = isEnabled;
- EventManager.Get.broadcast(EAppEvent.onWireframeEnabledChanged, isEnabled);
- }
-
- public toggleIsNormalsEnabled() {
- const isEnabled = !this._isGridComponentEnabled[EDebugBufferComponents.Normals];
- this._isGridComponentEnabled[EDebugBufferComponents.Normals] = isEnabled;
- EventManager.Get.broadcast(EAppEvent.onNormalsEnabledChanged, isEnabled);
- }
-
- public toggleIsDevDebugEnabled() {
- const isEnabled = !this._isGridComponentEnabled[EDebugBufferComponents.Dev];
- this._isGridComponentEnabled[EDebugBufferComponents.Dev] = isEnabled;
- EventManager.Get.broadcast(EAppEvent.onDevViewEnabledChanged, isEnabled);
- }
-
- public clearMesh() {
- EventManager.Get.broadcast(EAppEvent.onModelAvailableChanged, MeshType.TriangleMesh, false);
- EventManager.Get.broadcast(EAppEvent.onModelAvailableChanged, MeshType.VoxelMesh, false);
- EventManager.Get.broadcast(EAppEvent.onModelAvailableChanged, MeshType.BlockMesh, false);
-
- this._materialBuffers = [];
-
- this._modelsAvailable = 0;
- this.setModelToUse(MeshType.None);
- }
-
- public useMesh(mesh: Mesh) {
- EventManager.Get.broadcast(EAppEvent.onModelAvailableChanged, MeshType.TriangleMesh, false);
- EventManager.Get.broadcast(EAppEvent.onModelAvailableChanged, MeshType.VoxelMesh, false);
- EventManager.Get.broadcast(EAppEvent.onModelAvailableChanged, MeshType.BlockMesh, false);
-
- LOG('Using mesh');
- this._materialBuffers = [];
-
- const materialTriangleCount = new Map();
- for (let triIndex = 0; triIndex < mesh.getTriangleCount(); ++triIndex) {
- const materialName = mesh.getMaterialByTriangle(triIndex);
- const triangleCount = materialTriangleCount.get(materialName) ?? 0;
- materialTriangleCount.set(materialName, triangleCount + 1);
- }
-
- materialTriangleCount.forEach((triangleCount: number, materialName: string) => {
- const materialBuffer = {
- 'position': {
- numComponents: 3,
- data: new Float32Array(triangleCount * 3 * 3),
- },
- 'texcoord': {
- numComponents: 2,
- data: new Float32Array(triangleCount * 3 * 2),
- },
- 'normal': {
- numComponents: 3,
- data: new Float32Array(triangleCount * 3 * 3),
- },
- 'indices': {
- numComponents: 3,
- data: new Uint32Array(triangleCount * 3),
- },
- };
-
- let insertIndex = 0;
- for (let triIndex = 0; triIndex < mesh.getTriangleCount(); ++triIndex) {
- const material = mesh.getMaterialByTriangle(triIndex);
- if (material === materialName) {
- const uiTriangle = mesh.getUVTriangle(triIndex);
- // const tmp = GeometryTemplates.getTriangleBufferData(uiTriangle);
-
- materialBuffer.position.data.set(uiTriangle.v0.toArray(), insertIndex * 9 + 0);
- materialBuffer.position.data.set(uiTriangle.v1.toArray(), insertIndex * 9 + 3);
- materialBuffer.position.data.set(uiTriangle.v2.toArray(), insertIndex * 9 + 6);
-
- materialBuffer.texcoord.data.set([uiTriangle.uv0.u, uiTriangle.uv0.v], insertIndex * 6 + 0);
- materialBuffer.texcoord.data.set([uiTriangle.uv1.u, uiTriangle.uv1.v], insertIndex * 6 + 2);
- materialBuffer.texcoord.data.set([uiTriangle.uv2.u, uiTriangle.uv2.v], insertIndex * 6 + 4);
-
- const normalArray = uiTriangle.getNormal().toArray();
- materialBuffer.normal.data.set(normalArray, insertIndex * 9 + 0);
- materialBuffer.normal.data.set(normalArray, insertIndex * 9 + 3);
- materialBuffer.normal.data.set(normalArray, insertIndex * 9 + 6);
-
- // materialBuffer.position.data.set(tmp.custom['position'], insertIndex * 9);
- // materialBuffer.normal.data.set(tmp.custom['normal'], insertIndex * 9);
- // materialBuffer.texcoord.data.set(tmp.custom['texcoord'], insertIndex * 6);
-
- materialBuffer.indices.data.set([
- insertIndex * 3 + 0,
- insertIndex * 3 + 1,
- insertIndex * 3 + 2,
- ], insertIndex * 3);
-
- ++insertIndex;
- }
- }
-
- const material = mesh.getMaterialByName(materialName);
- if (material.type === MaterialType.solid) {
- this._materialBuffers.push({
- buffer: twgl.createBufferInfoFromArrays(this._gl, materialBuffer),
- material: material,
- numElements: materialBuffer.indices.data.length,
- });
- } else {
- this._materialBuffers.push({
- buffer: twgl.createBufferInfoFromArrays(this._gl, materialBuffer),
- material: {
- type: MaterialType.textured,
- path: material.path,
- texture: twgl.createTexture(this._gl, {
- src: material.path,
- mag: this._gl.LINEAR,
- }),
- alphaFactor: material.alphaFactor,
- alpha: material.alphaPath ? twgl.createTexture(this._gl, {
- src: material.alphaPath,
- mag: this._gl.LINEAR,
- }) : undefined,
- useAlphaChannel: material.alphaPath ? new Texture(material.path, material.alphaPath)._useAlphaChannel() : undefined,
- },
- numElements: materialBuffer.indices.data.length,
- });
- }
- });
-
- const dimensions = mesh.getBounds().getDimensions();
- this._debugBuffers[MeshType.TriangleMesh][EDebugBufferComponents.Grid] = DebugGeometryTemplates.grid(dimensions);
- // this._debugBuffers[MeshType.TriangleMesh][EDebugBufferComponents.Wireframe] = DebugGeometryTemplates.meshWireframe(mesh, new RGB(0.18, 0.52, 0.89).toRGBA());
- // this._debugBuffers[MeshType.TriangleMesh][EDebugBufferComponents.Normals] = DebugGeometryTemplates.meshNormals(mesh, new RGB(0.89, 0.52, 0.18).toRGBA());
- // delete this._debugBuffers[MeshType.TriangleMesh][EDebugBufferComponents.Dev];
-
- this._modelsAvailable = 1;
- this.setModelToUse(MeshType.TriangleMesh);
-
- EventManager.Get.broadcast(EAppEvent.onModelAvailableChanged, MeshType.TriangleMesh, true);
- }
-
- public useVoxelMesh(voxelMesh: VoxelMesh, voxelSize: number, ambientOcclusionEnabled: boolean) {
- EventManager.Get.broadcast(EAppEvent.onModelAvailableChanged, MeshType.VoxelMesh, false);
- EventManager.Get.broadcast(EAppEvent.onModelAvailableChanged, MeshType.BlockMesh, false);
-
- LOG('Using voxel mesh');
- LOG(voxelMesh);
-
- this._voxelBufferRaw = voxelMesh.createBuffer(ambientOcclusionEnabled);
- this._voxelBuffer = twgl.createBufferInfoFromArrays(this._gl, this._voxelBufferRaw);
- this._voxelSize = voxelSize;
-
- const dimensions = voxelMesh.getBounds().getDimensions();
- this._gridOffset = new Vector3(
- dimensions.x % 2 === 0 ? 0 : -0.5,
- dimensions.y % 2 === 0 ? 0 : -0.5,
- dimensions.z % 2 === 0 ? 0 : -0.5,
- );
- dimensions.add(1);
-
- this._debugBuffers[MeshType.VoxelMesh][EDebugBufferComponents.Grid] = DebugGeometryTemplates.grid(Vector3.mulScalar(dimensions, voxelSize), voxelSize);
- // this._debugBuffers[MeshType.VoxelMesh][EDebugBufferComponents.Wireframe] = DebugGeometryTemplates.voxelMeshWireframe(voxelMesh, new RGB(0.18, 0.52, 0.89).toRGBA(), this._voxelSize);
-
- this._modelsAvailable = 2;
- this.setModelToUse(MeshType.VoxelMesh);
-
- EventManager.Get.broadcast(EAppEvent.onModelAvailableChanged, MeshType.VoxelMesh, true);
- }
-
- public useBlockMesh(blockMesh: BlockMesh) {
- EventManager.Get.broadcast(EAppEvent.onModelAvailableChanged, MeshType.BlockMesh, false);
-
- LOG('Using block mesh');
- LOG(blockMesh);
- this._blockBuffer = twgl.createBufferInfoFromArrays(this._gl, blockMesh.createBuffer());
-
- this._atlasTexture = twgl.createTexture(this._gl, {
- src: BlockAtlas.Get.getAtlasTexturePath(),
- mag: this._gl.NEAREST,
- });
-
- this._debugBuffers[MeshType.BlockMesh][EDebugBufferComponents.Grid] = this._debugBuffers[MeshType.VoxelMesh][EDebugBufferComponents.Grid];
-
- this._modelsAvailable = 3;
- this.setModelToUse(MeshType.BlockMesh);
-
- EventManager.Get.broadcast(EAppEvent.onModelAvailableChanged, MeshType.BlockMesh, true);
- }
-
- // /////////////////////////////////////////////////////////////////////////
-
- private _drawDebug() {
- const debugComponents = [EDebugBufferComponents.Grid];
- for (const debugComp of debugComponents) {
- if (this._isGridComponentEnabled[debugComp]) {
- ASSERT(this._debugBuffers[this._meshToUse]);
- const buffer = this._debugBuffers[this._meshToUse][debugComp];
- if (buffer) {
- if (debugComp === EDebugBufferComponents.Dev) {
- this._gl.disable(this._gl.DEPTH_TEST);
- }
- this._drawBuffer(this._gl.LINES, buffer.getWebGLBuffer(), ShaderManager.Get.debugProgram, {
- u_worldViewProjection: ArcballCamera.Get.getWorldViewProjection(),
- });
- this._gl.enable(this._gl.DEPTH_TEST);
- }
- }
- }
- // Draw axis
- if (this._axesEnabled) {
- this._gl.disable(this._gl.DEPTH_TEST);
- this._drawBuffer(this._gl.LINES, this._axisBuffer.getWebGLBuffer(), ShaderManager.Get.debugProgram, {
- u_worldViewProjection: ArcballCamera.Get.getWorldViewProjection(),
- });
- this._gl.enable(this._gl.DEPTH_TEST);
- }
- }
-
- private _drawMesh() {
- for (const materialBuffer of this._materialBuffers) {
- if (materialBuffer.material.type === MaterialType.textured) {
- this._drawMeshBuffer(materialBuffer.buffer, materialBuffer.numElements, ShaderManager.Get.textureTriProgram, {
- u_lightWorldPos: ArcballCamera.Get.getCameraPosition(0.0, 0.0),
- u_worldViewProjection: ArcballCamera.Get.getWorldViewProjection(),
- u_worldInverseTranspose: ArcballCamera.Get.getWorldInverseTranspose(),
- u_texture: materialBuffer.material.texture,
- u_alpha: materialBuffer.material.alpha,
- u_useAlphaMap: materialBuffer.material.alpha !== undefined,
- u_useAlphaChannel: materialBuffer.material.useAlphaChannel,
- u_alphaFactor: materialBuffer.material.alphaFactor,
- });
- } else {
- this._drawMeshBuffer(materialBuffer.buffer, materialBuffer.numElements, ShaderManager.Get.solidTriProgram, {
- u_lightWorldPos: ArcballCamera.Get.getCameraPosition(0.0, 0.0),
- u_worldViewProjection: ArcballCamera.Get.getWorldViewProjection(),
- u_worldInverseTranspose: ArcballCamera.Get.getWorldInverseTranspose(),
- u_fillColour: RGBAUtil.toArray(materialBuffer.material.colour),
- });
- }
- }
- }
-
- private _drawVoxelMesh() {
- const shader = ShaderManager.Get.voxelProgram;
- const uniforms = {
- u_worldViewProjection: ArcballCamera.Get.getWorldViewProjection(),
- u_voxelSize: this._voxelSize,
- u_gridOffset: this._gridOffset.toArray(),
- };
- if (this._voxelBuffer) {
- this._gl.useProgram(shader.program);
- twgl.setBuffersAndAttributes(this._gl, shader, this._voxelBuffer);
- twgl.setUniforms(shader, uniforms);
- this._gl.drawElements(this._gl.TRIANGLES, this._voxelBuffer.numElements, this._gl.UNSIGNED_INT, 0);
- }
- }
-
- private _drawBlockMesh() {
- this._gl.enable(this._gl.CULL_FACE);
- const shader = ShaderManager.Get.blockProgram;
- const uniforms = {
- u_worldViewProjection: ArcballCamera.Get.getWorldViewProjection(),
- u_texture: this._atlasTexture,
- u_voxelSize: this._voxelSize,
- u_atlasSize: BlockAtlas.Get.getAtlasSize(),
- u_gridOffset: this._gridOffset.toArray(),
- };
- if (this._blockBuffer) {
- this._gl.useProgram(shader.program);
- twgl.setBuffersAndAttributes(this._gl, shader, this._blockBuffer);
- twgl.setUniforms(shader, uniforms);
- this._gl.drawElements(this._gl.TRIANGLES, this._blockBuffer.numElements, this._gl.UNSIGNED_INT, 0);
- }
- this._gl.disable(this._gl.CULL_FACE);
- }
-
- // /////////////////////////////////////////////////////////////////////////
-
- private _drawMeshBuffer(register: twgl.BufferInfo, numElements: number, shaderProgram: twgl.ProgramInfo, uniforms: any) {
- this._drawBuffer(this._gl.TRIANGLES, { buffer: register, numElements: numElements }, shaderProgram, uniforms);
- }
-
- public setModelToUse(meshType: MeshType) {
- const isModelAvailable = this._modelsAvailable >= meshType;
- if (isModelAvailable) {
- this._meshToUse = meshType;
- EventManager.Get.broadcast(EAppEvent.onModelActiveChanged, meshType);
- }
- }
-
- private _setupScene() {
- twgl.resizeCanvasToDisplaySize( this._gl.canvas);
- this._gl.viewport(0, 0, this._gl.canvas.width, this._gl.canvas.height);
- ArcballCamera.Get.aspect = this._gl.canvas.width / this._gl.canvas.height;
- this._gl.blendFuncSeparate(this._gl.SRC_ALPHA, this._gl.ONE_MINUS_SRC_ALPHA, this._gl.ONE, this._gl.ONE_MINUS_SRC_ALPHA);
-
- this._gl.enable(this._gl.DEPTH_TEST);
- this._gl.enable(this._gl.BLEND);
- this._gl.clearColor(this._backgroundColour.r, this._backgroundColour.g, this._backgroundColour.b, 1.0);
- this._gl.clear(this._gl.COLOR_BUFFER_BIT | this._gl.DEPTH_BUFFER_BIT);
- }
-
- private _drawBuffer(drawMode: number, buffer: { numElements: number, buffer: twgl.BufferInfo }, shader: twgl.ProgramInfo, uniforms: any) {
- this._gl.useProgram(shader.program);
- twgl.setBuffersAndAttributes(this._gl, shader, buffer.buffer);
- twgl.setUniforms(shader, uniforms);
- this._gl.drawElements(drawMode, buffer.numElements, this._gl.UNSIGNED_INT, 0);
- }
-
- public getModelsAvailable() {
- return this._modelsAvailable;
- }
-
- public getActiveMeshType() {
- return this._meshToUse;
- }
-}
+import * as twgl from 'twgl.js';
+
+import { ArcballCamera } from './camera';
+import { RGBA, RGBAUtil } from './colour';
+import { DebugGeometryTemplates } from './geometry';
+import { MaterialType, SolidMaterial, TexturedMaterial } from './mesh';
+import { RenderBuffer } from './render_buffer';
+import { ShaderManager } from './shaders';
+import { Texture } from './texture';
+import { Vector3 } from './vector';
+import { RenderMeshParams, RenderNextBlockMeshChunkParams, RenderNextVoxelMeshChunkParams } from './worker_types';
+
+/* eslint-disable */
+export enum MeshType {
+ None,
+ TriangleMesh,
+ VoxelMesh,
+ BlockMesh
+}
+/* eslint-enable */
+
+/* eslint-disable */
+enum EDebugBufferComponents {
+ Wireframe,
+ Normals,
+ Bounds,
+ Dev,
+}
+/* eslint-enable */
+
+export type TextureMaterialRenderAddons = {
+ texture: WebGLTexture, alpha?: WebGLTexture, useAlphaChannel?: boolean,
+}
+
+export class Renderer {
+ public _gl: WebGLRenderingContext;
+
+ private _backgroundColour: RGBA = { r: 0.125, g: 0.125, b: 0.125, a: 1.0 };
+ private _atlasTexture?: WebGLTexture;
+
+ private _atlasSize: number = 1.0;
+ private _meshToUse: MeshType = MeshType.None;
+ private _voxelSize: number = 1.0;
+ private _gridOffset: Vector3 = new Vector3(0, 0, 0);
+
+ private _modelsAvailable: number;
+
+ private _materialBuffers: Array<{
+ material: SolidMaterial | (TexturedMaterial & TextureMaterialRenderAddons)
+ buffer: twgl.BufferInfo,
+ numElements: number,
+ }>;
+ public _voxelBuffer?: twgl.BufferInfo[];
+ private _blockBuffer?: twgl.BufferInfo[];
+ private _debugBuffers: { [meshType: string]: { [bufferComponent: string]: RenderBuffer } };
+ private _axisBuffer: RenderBuffer;
+
+ private _isGridComponentEnabled: { [bufferComponent: string]: boolean };
+ private _axesEnabled: boolean;
+
+ private _gridBuffers: {
+ x: { [meshType: string]: RenderBuffer };
+ y: { [meshType: string]: RenderBuffer };
+ z: { [meshType: string]: RenderBuffer };
+ };
+ private _gridEnabled: boolean;
+
+ private static _instance: Renderer;
+ public static get Get() {
+ return this._instance || (this._instance = new this());
+ }
+
+ private constructor() {
+ this._gl = (document.getElementById('canvas')).getContext('webgl', {
+ alpha: false,
+ })!;
+ twgl.addExtensionsToContext(this._gl);
+
+ this._modelsAvailable = 0;
+ this._materialBuffers = [];
+
+ this._gridBuffers = { x: {}, y: {}, z: {} };
+ this._gridEnabled = false;
+
+ this._debugBuffers = {};
+ this._debugBuffers[MeshType.None] = {};
+ this._debugBuffers[MeshType.TriangleMesh] = {};
+ this._debugBuffers[MeshType.VoxelMesh] = {};
+ this._debugBuffers[MeshType.BlockMesh] = {};
+
+ this._isGridComponentEnabled = {};
+ this._axesEnabled = false;
+
+ this._axisBuffer = new RenderBuffer([
+ { name: 'position', numComponents: 3 },
+ { name: 'colour', numComponents: 4 },
+ ]);
+ this._axisBuffer.add(DebugGeometryTemplates.arrow(new Vector3(0, 0, 0), new Vector3(1, 0, 0), { r: 0.96, g: 0.21, b: 0.32, a: 1.0 }));
+ this._axisBuffer.add(DebugGeometryTemplates.arrow(new Vector3(0, 0, 0), new Vector3(0, 1, 0), { r: 0.44, g: 0.64, b: 0.11, a: 1.0 }));
+ this._axisBuffer.add(DebugGeometryTemplates.arrow(new Vector3(0, 0, 0), new Vector3(0, 0, 1), { r: 0.18, g: 0.52, b: 0.89, a: 1.0 }));
+ }
+
+ public update() {
+ ArcballCamera.Get.updateCamera();
+ }
+
+ public draw() {
+ this._setupScene();
+
+ switch (this._meshToUse) {
+ case MeshType.TriangleMesh:
+ this._drawMesh();
+ break;
+ case MeshType.VoxelMesh:
+ this._drawVoxelMesh();
+ break;
+ case MeshType.BlockMesh:
+ this._drawBlockMesh();
+ break;
+ };
+
+ this._drawDebug();
+ }
+
+ // /////////////////////////////////////////////////////////////////////////
+
+ public toggleIsGridEnabled() {
+ this._gridEnabled = !this._gridEnabled;
+ }
+
+ public isGridEnabled() {
+ return this._gridEnabled;
+ }
+
+ public isAxesEnabled() {
+ return this._axesEnabled;
+ }
+
+ public toggleIsAxesEnabled() {
+ this._axesEnabled = !this._axesEnabled;
+ }
+
+ public toggleIsWireframeEnabled() {
+ const isEnabled = !this._isGridComponentEnabled[EDebugBufferComponents.Wireframe];
+ this._isGridComponentEnabled[EDebugBufferComponents.Wireframe] = isEnabled;
+ }
+
+ public toggleIsNormalsEnabled() {
+ const isEnabled = !this._isGridComponentEnabled[EDebugBufferComponents.Normals];
+ this._isGridComponentEnabled[EDebugBufferComponents.Normals] = isEnabled;
+ }
+
+ public toggleIsDevDebugEnabled() {
+ const isEnabled = !this._isGridComponentEnabled[EDebugBufferComponents.Dev];
+ this._isGridComponentEnabled[EDebugBufferComponents.Dev] = isEnabled;
+ }
+
+ public clearMesh() {
+ this._materialBuffers = [];
+
+ this._modelsAvailable = 0;
+ this.setModelToUse(MeshType.None);
+ }
+
+ public useMesh(params: RenderMeshParams.Output) {
+ this._materialBuffers = [];
+
+ for (const { material, buffer, numElements } of params.buffers) {
+ if (material.type === MaterialType.solid) {
+ this._materialBuffers.push({
+ buffer: twgl.createBufferInfoFromArrays(this._gl, buffer),
+ material: material,
+ numElements: numElements,
+ });
+ } else {
+ this._materialBuffers.push({
+ buffer: twgl.createBufferInfoFromArrays(this._gl, buffer),
+ material: {
+ type: MaterialType.textured,
+ path: material.path,
+ texture: twgl.createTexture(this._gl, {
+ src: material.path,
+ mag: this._gl.LINEAR,
+ }),
+ alphaFactor: material.alphaFactor,
+ alpha: material.alphaPath ? twgl.createTexture(this._gl, {
+ src: material.alphaPath,
+ mag: this._gl.LINEAR,
+ }) : undefined,
+ useAlphaChannel: material.alphaPath ? new Texture(material.path, material.alphaPath)._useAlphaChannel() : undefined,
+ },
+ numElements: numElements,
+ });
+ }
+ }
+
+ this._gridBuffers.x[MeshType.TriangleMesh] = DebugGeometryTemplates.gridX(params.dimensions);
+ this._gridBuffers.y[MeshType.TriangleMesh] = DebugGeometryTemplates.gridY(params.dimensions);
+ this._gridBuffers.z[MeshType.TriangleMesh] = DebugGeometryTemplates.gridZ(params.dimensions);
+
+ this._modelsAvailable = 1;
+ this.setModelToUse(MeshType.TriangleMesh);
+ }
+
+ private _allVoxelChunks = false;
+ public useVoxelMeshChunk(params: RenderNextVoxelMeshChunkParams.Output) {
+ if (params.isFirstChunk) {
+ this._voxelBuffer = [];
+ }
+
+ this._allVoxelChunks = !params.moreVoxelsToBuffer;
+
+ this._voxelBuffer?.push(twgl.createBufferInfoFromArrays(this._gl, params.buffer.buffer));
+ this._voxelSize = params.voxelSize;
+
+ if (params.isFirstChunk) {
+ const voxelSize = this._voxelSize;
+ const dimensions = new Vector3(0, 0, 0);
+ dimensions.setFrom(params.dimensions);
+
+ this._gridOffset = new Vector3(
+ dimensions.x % 2 === 0 ? 0 : -0.5,
+ dimensions.y % 2 === 0 ? 0 : -0.5,
+ dimensions.z % 2 === 0 ? 0 : -0.5,
+ );
+ dimensions.add(1);
+
+ this._gridBuffers.x[MeshType.VoxelMesh] = DebugGeometryTemplates.gridX(Vector3.mulScalar(dimensions, voxelSize), voxelSize);
+ this._gridBuffers.y[MeshType.VoxelMesh] = DebugGeometryTemplates.gridY(Vector3.mulScalar(dimensions, voxelSize), voxelSize);
+ this._gridBuffers.z[MeshType.VoxelMesh] = DebugGeometryTemplates.gridZ(Vector3.mulScalar(dimensions, voxelSize), voxelSize);
+
+ this._modelsAvailable = 2;
+ this.setModelToUse(MeshType.VoxelMesh);
+ }
+ }
+
+ /*
+ public useVoxelMesh(params: RenderNextVoxelMeshChunkParams.Output) {
+ this._voxelBuffer?.push(twgl.createBufferInfoFromArrays(this._gl, params.buffer.buffer));
+ this._voxelSize = params.voxelSize;
+
+ const voxelSize = this._voxelSize;
+ const dimensions = new Vector3(0, 0, 0);
+ dimensions.setFrom(params.dimensions);
+
+ this._gridOffset = new Vector3(
+ dimensions.x % 2 === 0 ? 0 : -0.5,
+ dimensions.y % 2 === 0 ? 0 : -0.5,
+ dimensions.z % 2 === 0 ? 0 : -0.5,
+ );
+ dimensions.add(1);
+
+ this._gridBuffers.x[MeshType.VoxelMesh] = DebugGeometryTemplates.gridX(Vector3.mulScalar(dimensions, voxelSize), voxelSize);
+ this._gridBuffers.y[MeshType.VoxelMesh] = DebugGeometryTemplates.gridY(Vector3.mulScalar(dimensions, voxelSize), voxelSize);
+ this._gridBuffers.z[MeshType.VoxelMesh] = DebugGeometryTemplates.gridZ(Vector3.mulScalar(dimensions, voxelSize), voxelSize);
+
+ this._modelsAvailable = 2;
+ this.setModelToUse(MeshType.VoxelMesh);
+ }
+ */
+
+ public useBlockMeshChunk(params: RenderNextBlockMeshChunkParams.Output) {
+ if (params.isFirstChunk) {
+ this._blockBuffer = [];
+ }
+
+ this._blockBuffer?.push(twgl.createBufferInfoFromArrays(this._gl, params.buffer.buffer));
+
+ if (params.isFirstChunk) {
+ this._atlasTexture = twgl.createTexture(this._gl, {
+ src: params.atlasTexturePath,
+ mag: this._gl.NEAREST,
+ });
+
+ this._atlasSize = params.atlasSize;
+
+ this._gridBuffers.y[MeshType.BlockMesh] = this._gridBuffers.y[MeshType.VoxelMesh];
+
+ this._modelsAvailable = 3;
+ this.setModelToUse(MeshType.BlockMesh);
+ }
+ }
+
+ // /////////////////////////////////////////////////////////////////////////
+
+ private _drawDebug() {
+ /*
+ const debugComponents = [EDebugBufferComponents.GridY];
+ for (const debugComp of debugComponents) {
+ if (this._isGridComponentEnabled[debugComp]) {
+ ASSERT(this._debugBuffers[this._meshToUse]);
+ const buffer = this._debugBuffers[this._meshToUse][debugComp];
+ if (buffer) {
+ if (debugComp === EDebugBufferComponents.Dev) {
+ this._gl.disable(this._gl.DEPTH_TEST);
+ }
+ if (debugComp === EDebugBufferComponents.GridY && !ArcballCamera.Get.isAlignedWithAxis('y')) {
+ continue;
+ }
+ this._drawBuffer(this._gl.LINES, buffer.getWebGLBuffer(), ShaderManager.Get.debugProgram, {
+ u_worldViewProjection: ArcballCamera.Get.getWorldViewProjection(),
+ });
+ this._gl.enable(this._gl.DEPTH_TEST);
+ }
+ }
+ }
+ */
+ // Draw grid
+ if (this._gridEnabled) {
+ if (ArcballCamera.Get.isAlignedWithAxis('x') && !ArcballCamera.Get.isAlignedWithAxis('y') && !ArcballCamera.Get.isUserRotating) {
+ const gridBuffer = this._gridBuffers.x[this._meshToUse];
+ if (gridBuffer !== undefined) {
+ this._drawBuffer(this._gl.LINES, gridBuffer.getWebGLBuffer(), ShaderManager.Get.debugProgram, {
+ u_worldViewProjection: ArcballCamera.Get.getWorldViewProjection(),
+ });
+ }
+ } else if (ArcballCamera.Get.isAlignedWithAxis('z') && !ArcballCamera.Get.isAlignedWithAxis('y') && !ArcballCamera.Get.isUserRotating) {
+ const gridBuffer = this._gridBuffers.z[this._meshToUse];
+ if (gridBuffer !== undefined) {
+ this._drawBuffer(this._gl.LINES, gridBuffer.getWebGLBuffer(), ShaderManager.Get.debugProgram, {
+ u_worldViewProjection: ArcballCamera.Get.getWorldViewProjection(),
+ });
+ }
+ } else {
+ const gridBuffer = this._gridBuffers.y[this._meshToUse];
+ if (gridBuffer !== undefined) {
+ this._drawBuffer(this._gl.LINES, gridBuffer.getWebGLBuffer(), ShaderManager.Get.debugProgram, {
+ u_worldViewProjection: ArcballCamera.Get.getWorldViewProjection(),
+ });
+ }
+ }
+ }
+
+ // Draw axis
+ if (this._axesEnabled) {
+ this._gl.disable(this._gl.DEPTH_TEST);
+ this._drawBuffer(this._gl.LINES, this._axisBuffer.getWebGLBuffer(), ShaderManager.Get.debugProgram, {
+ u_worldViewProjection: ArcballCamera.Get.getWorldViewProjection(),
+ });
+ this._gl.enable(this._gl.DEPTH_TEST);
+ }
+ }
+
+ public parseRawMeshData(buffer: string, dimensions: Vector3) {
+ }
+
+ private _drawMesh() {
+ for (const materialBuffer of this._materialBuffers) {
+ if (materialBuffer.material.type === MaterialType.textured) {
+ this._drawMeshBuffer(materialBuffer.buffer, materialBuffer.numElements, ShaderManager.Get.textureTriProgram, {
+ u_lightWorldPos: ArcballCamera.Get.getCameraPosition(0.0, 0.0),
+ u_worldViewProjection: ArcballCamera.Get.getWorldViewProjection(),
+ u_worldInverseTranspose: ArcballCamera.Get.getWorldInverseTranspose(),
+ u_texture: materialBuffer.material.texture,
+ u_alpha: materialBuffer.material.alpha || materialBuffer.material.texture,
+ u_useAlphaMap: materialBuffer.material.alpha !== undefined,
+ u_useAlphaChannel: materialBuffer.material.useAlphaChannel,
+ u_alphaFactor: materialBuffer.material.alphaFactor,
+ });
+ } else {
+ this._drawMeshBuffer(materialBuffer.buffer, materialBuffer.numElements, ShaderManager.Get.solidTriProgram, {
+ u_lightWorldPos: ArcballCamera.Get.getCameraPosition(0.0, 0.0),
+ u_worldViewProjection: ArcballCamera.Get.getWorldViewProjection(),
+ u_worldInverseTranspose: ArcballCamera.Get.getWorldInverseTranspose(),
+ u_fillColour: RGBAUtil.toArray(materialBuffer.material.colour),
+ });
+ }
+ }
+ }
+
+ private _drawVoxelMesh() {
+ const shader = ShaderManager.Get.voxelProgram;
+ const uniforms = {
+ u_worldViewProjection: ArcballCamera.Get.getWorldViewProjection(),
+ u_voxelSize: this._voxelSize,
+ u_gridOffset: this._gridOffset.toArray(),
+ u_ambientOcclusion: this._allVoxelChunks,
+ };
+ this._voxelBuffer?.forEach((buffer) => {
+ this._gl.useProgram(shader.program);
+ twgl.setBuffersAndAttributes(this._gl, shader, buffer);
+ twgl.setUniforms(shader, uniforms);
+ this._gl.drawElements(this._gl.TRIANGLES, buffer.numElements, this._gl.UNSIGNED_INT, 0);
+ });
+ }
+
+ private _drawBlockMesh() {
+ this._gl.enable(this._gl.CULL_FACE);
+ const shader = ShaderManager.Get.blockProgram;
+ const uniforms = {
+ u_worldViewProjection: ArcballCamera.Get.getWorldViewProjection(),
+ u_texture: this._atlasTexture,
+ u_voxelSize: this._voxelSize,
+ u_atlasSize: this._atlasSize,
+ u_gridOffset: this._gridOffset.toArray(),
+ };
+ this._blockBuffer?.forEach((buffer) => {
+ this._gl.useProgram(shader.program);
+ twgl.setBuffersAndAttributes(this._gl, shader, buffer);
+ twgl.setUniforms(shader, uniforms);
+ this._gl.drawElements(this._gl.TRIANGLES, buffer.numElements, this._gl.UNSIGNED_INT, 0);
+ });
+ this._gl.disable(this._gl.CULL_FACE);
+ }
+
+ // /////////////////////////////////////////////////////////////////////////
+
+ private _drawMeshBuffer(register: twgl.BufferInfo, numElements: number, shaderProgram: twgl.ProgramInfo, uniforms: any) {
+ this._drawBuffer(this._gl.TRIANGLES, { buffer: register, numElements: numElements }, shaderProgram, uniforms);
+ }
+
+ public setModelToUse(meshType: MeshType) {
+ const isModelAvailable = this._modelsAvailable >= meshType;
+ if (isModelAvailable) {
+ this._meshToUse = meshType;
+ }
+ }
+
+ private _setupScene() {
+ twgl.resizeCanvasToDisplaySize(this._gl.canvas);
+ this._gl.viewport(0, 0, this._gl.canvas.width, this._gl.canvas.height);
+ ArcballCamera.Get.setAspect(this._gl.canvas.width / this._gl.canvas.height);
+ this._gl.blendFuncSeparate(this._gl.SRC_ALPHA, this._gl.ONE_MINUS_SRC_ALPHA, this._gl.ONE, this._gl.ONE_MINUS_SRC_ALPHA);
+
+ this._gl.enable(this._gl.DEPTH_TEST);
+ this._gl.enable(this._gl.BLEND);
+ this._gl.clearColor(this._backgroundColour.r, this._backgroundColour.g, this._backgroundColour.b, 1.0);
+ this._gl.clear(this._gl.COLOR_BUFFER_BIT | this._gl.DEPTH_BUFFER_BIT);
+ }
+
+ private _drawBuffer(drawMode: number, buffer: { numElements: number, buffer: twgl.BufferInfo }, shader: twgl.ProgramInfo, uniforms: any) {
+ this._gl.useProgram(shader.program);
+ twgl.setBuffersAndAttributes(this._gl, shader, buffer.buffer);
+ twgl.setUniforms(shader, uniforms);
+ this._gl.drawElements(drawMode, buffer.numElements, this._gl.UNSIGNED_INT, 0);
+ }
+
+ public getModelsAvailable() {
+ return this._modelsAvailable;
+ }
+
+ public getActiveMeshType() {
+ return this._meshToUse;
+ }
+}
diff --git a/src/shaders.ts b/src/shaders.ts
index 2902f5d3..cb0b1325 100644
--- a/src/shaders.ts
+++ b/src/shaders.ts
@@ -1,47 +1,47 @@
-import * as twgl from 'twgl.js';
-import * as fs from 'fs';
-import * as path from 'path';
-import { Renderer } from './renderer';
-import { SHADERS_DIR } from './util';
-
-export class ShaderManager {
- public readonly textureTriProgram: twgl.ProgramInfo;
- public readonly solidTriProgram: twgl.ProgramInfo;
- public readonly voxelProgram: twgl.ProgramInfo;
- public readonly blockProgram: twgl.ProgramInfo;
- public readonly debugProgram: twgl.ProgramInfo;
-
- private static _instance: ShaderManager;
- public static get Get() {
- return this._instance || (this._instance = new this());
- }
-
- private constructor() {
- const gl = Renderer.Get._gl;
-
- const textureTriVertex = this._getShader('texture_tri_vertex.vs');
- const textureTriFragment = this._getShader('texture_tri_fragment.fs');
- this.textureTriProgram = twgl.createProgramInfo(gl, [textureTriVertex, textureTriFragment]);
-
- const solidTriVertex = this._getShader('solid_tri_vertex.vs');
- const solidTriFragment = this._getShader('solid_tri_fragment.fs');
- this.solidTriProgram = twgl.createProgramInfo(gl, [solidTriVertex, solidTriFragment]);
-
- const voxelVertexShader = this._getShader('voxel_vertex.vs');
- const voxelFragmentShader = this._getShader('voxel_fragment.fs');
- this.voxelProgram = twgl.createProgramInfo(gl, [voxelVertexShader, voxelFragmentShader]);
-
- const blockVertexShader = this._getShader('block_vertex.vs');
- const blockFragmentShader = this._getShader('block_fragment.fs');
- this.blockProgram = twgl.createProgramInfo(gl, [blockVertexShader, blockFragmentShader]);
-
- const debugVertexShader = this._getShader('debug_vertex.vs');
- const debugFragmentShader = this._getShader('debug_fragment.fs');
- this.debugProgram = twgl.createProgramInfo(gl, [debugVertexShader, debugFragmentShader]);
- }
-
- private _getShader(filename: string) {
- const absPath = path.join(SHADERS_DIR, filename);
- return fs.readFileSync(absPath, 'utf8');
- }
-}
+import * as fs from 'fs';
+import * as twgl from 'twgl.js';
+
+import { Renderer } from './renderer';
+import { AppPaths, PathUtil } from './util/path_util';
+
+export class ShaderManager {
+ public readonly textureTriProgram: twgl.ProgramInfo;
+ public readonly solidTriProgram: twgl.ProgramInfo;
+ public readonly voxelProgram: twgl.ProgramInfo;
+ public readonly blockProgram: twgl.ProgramInfo;
+ public readonly debugProgram: twgl.ProgramInfo;
+
+ private static _instance: ShaderManager;
+ public static get Get() {
+ return this._instance || (this._instance = new this());
+ }
+
+ private constructor() {
+ const gl = Renderer.Get._gl;
+
+ const textureTriVertex = this._getShader('texture_tri_vertex.vs');
+ const textureTriFragment = this._getShader('texture_tri_fragment.fs');
+ this.textureTriProgram = twgl.createProgramInfo(gl, [textureTriVertex, textureTriFragment]);
+
+ const solidTriVertex = this._getShader('solid_tri_vertex.vs');
+ const solidTriFragment = this._getShader('solid_tri_fragment.fs');
+ this.solidTriProgram = twgl.createProgramInfo(gl, [solidTriVertex, solidTriFragment]);
+
+ const voxelVertexShader = this._getShader('voxel_vertex.vs');
+ const voxelFragmentShader = this._getShader('voxel_fragment.fs');
+ this.voxelProgram = twgl.createProgramInfo(gl, [voxelVertexShader, voxelFragmentShader]);
+
+ const blockVertexShader = this._getShader('block_vertex.vs');
+ const blockFragmentShader = this._getShader('block_fragment.fs');
+ this.blockProgram = twgl.createProgramInfo(gl, [blockVertexShader, blockFragmentShader]);
+
+ const debugVertexShader = this._getShader('debug_vertex.vs');
+ const debugFragmentShader = this._getShader('debug_fragment.fs');
+ this.debugProgram = twgl.createProgramInfo(gl, [debugVertexShader, debugFragmentShader]);
+ }
+
+ private _getShader(filename: string) {
+ const absPath = PathUtil.join(AppPaths.Get.shaders, filename);
+ return fs.readFileSync(absPath, 'utf8');
+ }
+}
diff --git a/src/status.ts b/src/status.ts
index 79e80a05..55297506 100644
--- a/src/status.ts
+++ b/src/status.ts
@@ -1,75 +1,99 @@
-import { EAction } from './app_context';
-import { LOG, LOG_WARN } from './util';
-
-export type StatusType = 'warning' | 'info';
-
-export type StatusMessage = {
- status: StatusType,
- message: string,
-}
-
-export class StatusHandler {
- /** Singleton accessor */
- private static _instance: StatusHandler;
- public static get Get() {
- return this._instance || (this._instance = new this());
- }
-
- private _statusMessages: StatusMessage[];
-
- private constructor() {
- this._statusMessages = [];
- }
-
- public clear() {
- this._statusMessages = [];
- }
-
- public add(status: StatusType, message: string) {
- (status === 'warning' ? LOG_WARN : LOG)(message);
- this._statusMessages.push({ status: status, message: message });
- }
-
- public hasStatusMessages(statusType: StatusType): boolean {
- return this.getStatusMessages(statusType).length > 0;
- }
-
- public getStatusMessages(statusType: StatusType): string[] {
- const messagesToReturn = (statusType !== undefined) ? this._statusMessages.filter((m) => m.status === statusType ): this._statusMessages;
- return messagesToReturn.map((m) => m.message);
- }
-
- public getDefaultSuccessMessage(action: EAction): string {
- switch (action) {
- case EAction.Import:
- return 'Successfully loaded mesh';
- case EAction.Simplify:
- return 'Successfully simplified mesh';
- case EAction.Voxelise:
- return 'Successfully voxelised mesh';
- case EAction.Assign:
- return 'Successfully assigned blocks';
- case EAction.Export:
- return 'Successfully exported mesh';
- default:
- return 'Successfully performed action';
- }
- }
-
- public getDefaultFailureMessage(action: EAction): string {
- switch (action) {
- case EAction.Import:
- return 'Failed to load mesh';
- case EAction.Simplify:
- return 'Failed to simplify mesh';
- case EAction.Voxelise:
- return 'Failed to voxelise mesh';
- case EAction.Assign:
- return 'Failed to assign blocks';
- case EAction.Export:
- return 'Failed to export mesh';
- default:
- return 'Failed to perform action';
- }
- }
-}
+import { EAction } from './util';
+import { ASSERT } from './util/error_util';
+import { LOG, LOG_MAJOR, LOG_WARN } from './util/log_util';
+
+export type StatusType = 'warning' | 'info';
+
+/* eslint-disable */
+export enum StatusID {
+ SchematicUnsupportedBlocks
+}
+/* eslint-enable */
+
+
+export type StatusMessage = {
+ status: StatusType,
+ message: string,
+ id?: StatusID,
+}
+
+export class StatusHandler {
+ /** Singleton accessor */
+ private static _instance: StatusHandler;
+ public static get Get() {
+ return this._instance || (this._instance = new this());
+ }
+
+ private _statusMessages: StatusMessage[];
+
+ private constructor() {
+ this._statusMessages = [];
+ }
+
+ public clear() {
+ this._statusMessages = [];
+ }
+
+ public add(status: StatusType, message: string, id?: StatusID) {
+ (status === 'warning' ? LOG_WARN : LOG)(message);
+ this._statusMessages.push({ status: status, message: message, id: id });
+ }
+
+ public hasId(id: StatusID) {
+ return this._statusMessages.some((x) => { return x.id === id; });
+ }
+
+ public hasStatusMessages(statusType: StatusType): boolean {
+ return this.getStatusMessages(statusType).length > 0;
+ }
+
+ public getStatusMessages(statusType: StatusType): string[] {
+ const messagesToReturn = (statusType !== undefined) ? this._statusMessages.filter((m) => m.status === statusType) : this._statusMessages;
+ return messagesToReturn.map((m) => m.message);
+ }
+
+ public getAllStatusMessages(): StatusMessage[] {
+ return this._statusMessages;
+ }
+
+ public getDefaultSuccessMessage(action: EAction): string {
+ switch (action) {
+ case EAction.Import:
+ return '[Importer]: Loaded';
+ case EAction.Voxelise:
+ return '[Voxeliser]: Succeeded';
+ case EAction.Assign:
+ return '[Assigner]: Succeeded';
+ case EAction.Export:
+ return '[Exporter]: Saved';
+ default:
+ ASSERT(false);
+ }
+ }
+
+ public getDefaultFailureMessage(action: EAction): string {
+ switch (action) {
+ case EAction.Import:
+ return '[Importer]: Failed';
+ case EAction.Voxelise:
+ return '[Voxeliser]: Failed';
+ case EAction.Assign:
+ return '[Assigner]: Failed';
+ case EAction.Export:
+ return '[Exporter]: Failed';
+ default:
+ ASSERT(false);
+ }
+ }
+
+ public dump() {
+ for (const { message, status } of this._statusMessages) {
+ if (status === 'warning') {
+ LOG_WARN(message);
+ } else {
+ LOG_MAJOR(' - ' + message);
+ }
+ }
+ return this;
+ }
+}
diff --git a/src/texture.ts b/src/texture.ts
index 779981d6..99701f6c 100644
--- a/src/texture.ts
+++ b/src/texture.ts
@@ -1,162 +1,167 @@
-import { UV, ASSERT, AppError, LOG } from './util';
-
-import * as fs from 'fs';
-import * as jpeg from 'jpeg-js';
-import { PNG } from 'pngjs';
-import path from 'path';
-import { clamp, wayThrough } from './math';
-import { RGBA, RGBAColours, RGBAUtil } from './colour';
-
-/* eslint-disable */
-export enum TextureFormat {
- PNG,
- JPEG
-}
-/* eslint-enable */
-
-/* eslint-disable */
-export enum TextureFiltering {
- Linear,
- Nearest
-}
-/* eslint-enable */
-
-type ImageData = {
- data: Buffer,
- width: number,
- height: number
-}
-
-export class Texture {
- private _image: ImageData;
- private _alphaImage?: ImageData;
-
- constructor(filename: string, transparencyFilename?: string) {
- ASSERT(path.isAbsolute(filename));
-
- this._image = this._loadImageFile(filename);
-
- if (transparencyFilename) {
- this._alphaImage = this._loadImageFile(transparencyFilename);
- }
- }
-
- private _loadImageFile(filename: string): ImageData {
- ASSERT(path.isAbsolute(filename));
- const filePath = path.parse(filename);
- try {
- const data = fs.readFileSync(filename);
- if (filePath.ext.toLowerCase() === '.png') {
- return PNG.sync.read(data);
- } else if (['.jpg', '.jpeg'].includes(filePath.ext.toLowerCase())) {
- this._useAlphaChannelValue = false;
- return jpeg.decode(data);
- } else {
- throw new AppError(`Failed to load ${filename}`);
- }
- } catch (err) {
- throw new AppError(`Could not read ${filename}`);
- }
- }
-
- public getRGBA(uv: UV, filtering: TextureFiltering): RGBA {
- if (filtering === TextureFiltering.Nearest) {
- return this._getNearestRGBA(uv);
- } else {
- return this._getLinearRGBA(uv);
- }
- }
-
- private _getLinearRGBA(uv: UV): RGBA {
- uv.v = 1.0 - uv.v;
-
- uv.u = uv.u % 1.0;
- uv.v = uv.v % 1.0;
-
- const x = uv.u * this._image.width;
- const y = uv.v * this._image.height;
-
- const xL = Math.floor(x);
- const xU = xL + 1;
- const yL = Math.floor(y);
- const yU = yL + 1;
-
- const u = wayThrough(x, xL, xU);
- const v = wayThrough(y, yL, yU);
-
- if (!(u >= 0.0 && u <= 1.0 && v >= 0.0 && v <= 1.0)) {
- return RGBAColours.MAGENTA;
- }
-
- const A = this._getFromXY(xL, yU);
- const B = this._getFromXY(xU, yU);
- const AB = RGBAUtil.lerp(A, B, u);
-
- const C = this._getFromXY(xL, yL);
- const D = this._getFromXY(xU, yL);
- const CD = RGBAUtil.lerp(C, D, u);
-
- return RGBAUtil.lerp(AB, CD, v);
- }
-
- private _getNearestRGBA(uv: UV): RGBA {
- const x = Math.floor(uv.u * this._image.width);
- const y = Math.floor((1 - uv.v) * this._image.height);
-
- return this._getFromXY(x, y);
- }
-
- private _getFromXY(x: number, y: number): RGBA {
- const diffuse = Texture._sampleImage(this._image, x, y);
-
- if (this._alphaImage) {
- const alpha = Texture._sampleImage(this._alphaImage, x, y);
- return {
- r: diffuse.r,
- g: diffuse.g,
- b: diffuse.b,
- a: this._useAlphaChannel() ? alpha.a : alpha.r,
- };
- }
-
- return diffuse;
- }
-
- public _useAlphaChannelValue?: boolean;
- public _useAlphaChannel() {
- ASSERT(this._alphaImage !== undefined);
- if (this._useAlphaChannelValue !== undefined) {
- return this._useAlphaChannelValue;
- }
-
- for (let i = 0; i < this._alphaImage.width; ++i) {
- for (let j = 0; j < this._alphaImage.height; ++j) {
- const value = Texture._sampleImage(this._alphaImage, i, j);
- if (value.a != 1.0) {
- LOG(`Using alpha channel`);
- this._useAlphaChannelValue = true;
- return true;
- }
- }
- }
-
- LOG(`Using red channel`);
- this._useAlphaChannelValue = false;
- return false;
- }
-
- private static _sampleImage(image: ImageData, x: number, y: number) {
- x = clamp(x, 0, image.width - 1);
- y = clamp(y, 0, image.height - 1);
-
- const index = 4 * (image.width * y + x);
- const rgba = image.data.slice(index, index + 4);
-
- return {
- r: rgba[0] / 255,
- g: rgba[1] / 255,
- b: rgba[2] / 255,
- a: rgba[3] / 255,
- };
- }
-}
+import * as fs from 'fs';
+import * as jpeg from 'jpeg-js';
+import path from 'path';
+import { PNG } from 'pngjs';
+
+import { RGBA, RGBAColours, RGBAUtil } from './colour';
+import { AppConfig } from './config';
+import { clamp, wayThrough } from './math';
+import { UV } from './util';
+import { AppError, ASSERT } from './util/error_util';
+import { LOG, LOG_ERROR } from './util/log_util';
+
+/* eslint-disable */
+export enum TextureFormat {
+ PNG,
+ JPEG
+}
+/* eslint-enable */
+
+/* eslint-disable */
+export enum TextureFiltering {
+ Linear,
+ Nearest
+}
+/* eslint-enable */
+
+type ImageData = {
+ data: Buffer,
+ width: number,
+ height: number
+}
+
+export class Texture {
+ private _image: ImageData;
+ private _alphaImage?: ImageData;
+
+ constructor(filename: string, transparencyFilename?: string) {
+ ASSERT(path.isAbsolute(filename));
+
+ this._image = this._loadImageFile(filename);
+
+ if (transparencyFilename) {
+ this._alphaImage = this._loadImageFile(transparencyFilename);
+ }
+ }
+
+ private _loadImageFile(filename: string): ImageData {
+ ASSERT(path.isAbsolute(filename));
+ const filePath = path.parse(filename);
+ try {
+ const data = fs.readFileSync(filename);
+ if (filePath.ext.toLowerCase() === '.png') {
+ return PNG.sync.read(data);
+ } else if (['.jpg', '.jpeg'].includes(filePath.ext.toLowerCase())) {
+ this._useAlphaChannelValue = false;
+ return jpeg.decode(data, {
+ maxMemoryUsageInMB: AppConfig.Get.MAXIMUM_IMAGE_MEM_ALLOC,
+ });
+ }
+ ASSERT(false);
+ } catch (err) {
+ LOG_ERROR(err);
+ throw new AppError(`Could not read ${filename}`);
+ }
+ }
+
+ public getRGBA(uv: UV, filtering: TextureFiltering): RGBA {
+ if (filtering === TextureFiltering.Nearest) {
+ return this._getNearestRGBA(uv);
+ } else {
+ return this._getLinearRGBA(uv);
+ }
+ }
+
+ private _getLinearRGBA(uv: UV): RGBA {
+ uv.v = 1.0 - uv.v;
+
+ uv.u = uv.u % 1.0;
+ uv.v = uv.v % 1.0;
+
+ const x = uv.u * this._image.width;
+ const y = uv.v * this._image.height;
+
+ const xL = Math.floor(x);
+ const xU = xL + 1;
+ const yL = Math.floor(y);
+ const yU = yL + 1;
+
+ const u = wayThrough(x, xL, xU);
+ const v = wayThrough(y, yL, yU);
+
+ if (!(u >= 0.0 && u <= 1.0 && v >= 0.0 && v <= 1.0)) {
+ return RGBAColours.MAGENTA;
+ }
+
+ const A = this._getFromXY(xL, yU);
+ const B = this._getFromXY(xU, yU);
+ const AB = RGBAUtil.lerp(A, B, u);
+
+ const C = this._getFromXY(xL, yL);
+ const D = this._getFromXY(xU, yL);
+ const CD = RGBAUtil.lerp(C, D, u);
+
+ return RGBAUtil.lerp(AB, CD, v);
+ }
+
+ private _getNearestRGBA(uv: UV): RGBA {
+ const x = Math.floor(uv.u * this._image.width);
+ const y = Math.floor((1 - uv.v) * this._image.height);
+
+ return this._getFromXY(x, y);
+ }
+
+ private _getFromXY(x: number, y: number): RGBA {
+ const diffuse = Texture._sampleImage(this._image, x, y);
+
+ if (this._alphaImage) {
+ const alpha = Texture._sampleImage(this._alphaImage, x, y);
+ return {
+ r: diffuse.r,
+ g: diffuse.g,
+ b: diffuse.b,
+ a: this._useAlphaChannel() ? alpha.a : alpha.r,
+ };
+ }
+
+ return diffuse;
+ }
+
+ public _useAlphaChannelValue?: boolean;
+ public _useAlphaChannel() {
+ ASSERT(this._alphaImage !== undefined);
+ if (this._useAlphaChannelValue !== undefined) {
+ return this._useAlphaChannelValue;
+ }
+
+ for (let i = 0; i < this._alphaImage.width; ++i) {
+ for (let j = 0; j < this._alphaImage.height; ++j) {
+ const value = Texture._sampleImage(this._alphaImage, i, j);
+ if (value.a != 1.0) {
+ LOG(`Using alpha channel`);
+ this._useAlphaChannelValue = true;
+ return true;
+ }
+ }
+ }
+
+ LOG(`Using red channel`);
+ this._useAlphaChannelValue = false;
+ return false;
+ }
+
+ private static _sampleImage(image: ImageData, x: number, y: number) {
+ x = clamp(x, 0, image.width - 1);
+ y = clamp(y, 0, image.height - 1);
+
+ const index = 4 * (image.width * y + x);
+ const rgba = image.data.slice(index, index + 4);
+
+ return {
+ r: rgba[0] / 255,
+ g: rgba[1] / 255,
+ b: rgba[2] / 255,
+ a: rgba[3] / 255,
+ };
+ }
+}
diff --git a/src/triangle.ts b/src/triangle.ts
index daa225a9..3ef54ef1 100644
--- a/src/triangle.ts
+++ b/src/triangle.ts
@@ -1,59 +1,60 @@
-import { Vector3 } from './vector';
-import { Bounds, UV } from './util';
-export class Triangle {
- public v0: Vector3;
- public v1: Vector3;
- public v2: Vector3;
-
- constructor(v0: Vector3, v1: Vector3, v2: Vector3) {
- this.v0 = v0;
- this.v1 = v1;
- this.v2 = v2;
- }
-
- public getCentre(): Vector3 {
- return Vector3.divScalar(Vector3.add(Vector3.add(this.v0, this.v1), this.v2), 3.0);
- }
-
- public getArea(): number {
- const a = Vector3.sub(this.v0, this.v1).magnitude();
- const b = Vector3.sub(this.v1, this.v2).magnitude();
- const c = Vector3.sub(this.v2, this.v0).magnitude();
- const p = (a + b + c) / 2;
- return Math.sqrt(p * (p - a) * (p - b) * (p - c));
- }
-
- public getNormal(): Vector3 {
- const u = Vector3.sub(this.v0, this.v1);
- const v = Vector3.sub(this.v0, this.v2);
- return Vector3.cross(u, v).normalise();
- }
-
- public getBounds(): Bounds {
- return new Bounds(
- new Vector3(
- Math.min(this.v0.x, this.v1.x, this.v2.x),
- Math.min(this.v0.y, this.v1.y, this.v2.y),
- Math.min(this.v0.z, this.v1.z, this.v2.z),
- ),
- new Vector3(
- Math.max(this.v0.x, this.v1.x, this.v2.x),
- Math.max(this.v0.y, this.v1.y, this.v2.y),
- Math.max(this.v0.z, this.v1.z, this.v2.z),
- ),
- );
- }
-}
-
-export class UVTriangle extends Triangle {
- public uv0: UV;
- public uv1: UV;
- public uv2: UV;
-
- constructor(v0: Vector3, v1: Vector3, v2: Vector3, uv0: UV, uv1: UV, uv2: UV) {
- super(v0, v1, v2);
- this.uv0 = uv0;
- this.uv1 = uv1;
- this.uv2 = uv2;
- }
-}
+import { Bounds } from './bounds';
+import { UV } from './util';
+import { Vector3 } from './vector';
+export class Triangle {
+ public v0: Vector3;
+ public v1: Vector3;
+ public v2: Vector3;
+
+ constructor(v0: Vector3, v1: Vector3, v2: Vector3) {
+ this.v0 = v0;
+ this.v1 = v1;
+ this.v2 = v2;
+ }
+
+ public getCentre(): Vector3 {
+ return Vector3.divScalar(Vector3.add(Vector3.add(this.v0, this.v1), this.v2), 3.0);
+ }
+
+ public getArea(): number {
+ const a = Vector3.sub(this.v0, this.v1).magnitude();
+ const b = Vector3.sub(this.v1, this.v2).magnitude();
+ const c = Vector3.sub(this.v2, this.v0).magnitude();
+ const p = (a + b + c) / 2;
+ return Math.sqrt(p * (p - a) * (p - b) * (p - c));
+ }
+
+ public getNormal(): Vector3 {
+ const u = Vector3.sub(this.v0, this.v1);
+ const v = Vector3.sub(this.v0, this.v2);
+ return Vector3.cross(u, v).normalise();
+ }
+
+ public getBounds(): Bounds {
+ return new Bounds(
+ new Vector3(
+ Math.min(this.v0.x, this.v1.x, this.v2.x),
+ Math.min(this.v0.y, this.v1.y, this.v2.y),
+ Math.min(this.v0.z, this.v1.z, this.v2.z),
+ ),
+ new Vector3(
+ Math.max(this.v0.x, this.v1.x, this.v2.x),
+ Math.max(this.v0.y, this.v1.y, this.v2.y),
+ Math.max(this.v0.z, this.v1.z, this.v2.z),
+ ),
+ );
+ }
+}
+
+export class UVTriangle extends Triangle {
+ public uv0: UV;
+ public uv1: UV;
+ public uv2: UV;
+
+ constructor(v0: Vector3, v1: Vector3, v2: Vector3, uv0: UV, uv1: UV, uv2: UV) {
+ super(v0, v1, v2);
+ this.uv0 = uv0;
+ this.uv1 = uv1;
+ this.uv2 = uv2;
+ }
+}
diff --git a/src/ui/elements/base.ts b/src/ui/elements/base.ts
index ed917a63..a0c1ff43 100644
--- a/src/ui/elements/base.ts
+++ b/src/ui/elements/base.ts
@@ -1,40 +1,40 @@
-import { ASSERT } from '../../util';
-
-export abstract class BaseUIElement {
- protected _id: string;
- protected _label: string;
- protected _isEnabled: boolean;
- protected _value?: Type;
- protected _cachedValue?: any;
-
- constructor(label: string) {
- this._id = '_' + Math.random().toString(16);
- this._label = label;
- this._isEnabled = true;
- }
-
- public setEnabled(isEnabled: boolean) {
- this._isEnabled = isEnabled;
- this._onEnabledChanged();
- }
-
- public getCachedValue(): Type {
- ASSERT(this._cachedValue !== undefined, 'Attempting to access value before cached');
- return this._cachedValue as Type;
- }
-
- protected getValue() {
- ASSERT(this._value);
- return this._value;
- }
-
- public cacheValue() {
- this._cachedValue = this.getValue();
- }
-
- public abstract generateHTML(): string;
- public abstract registerEvents(): void;
-
-
- protected abstract _onEnabledChanged(): void;
-}
+import { ASSERT } from '../../util/error_util';
+
+export abstract class BaseUIElement {
+ protected _id: string;
+ protected _label: string;
+ protected _isEnabled: boolean;
+ protected _value?: Type;
+ protected _cachedValue?: any;
+
+ constructor(label: string) {
+ this._id = '_' + Math.random().toString(16);
+ this._label = label;
+ this._isEnabled = true;
+ }
+
+ public setEnabled(isEnabled: boolean) {
+ this._isEnabled = isEnabled;
+ this._onEnabledChanged();
+ }
+
+ public getCachedValue(): Type {
+ ASSERT(this._cachedValue !== undefined, 'Attempting to access value before cached');
+ return this._cachedValue as Type;
+ }
+
+ protected getValue(): Type {
+ ASSERT(this._value);
+ return this._value;
+ }
+
+ public cacheValue() {
+ this._cachedValue = this.getValue();
+ }
+
+ public abstract generateHTML(): string;
+ public abstract registerEvents(): void;
+
+
+ protected abstract _onEnabledChanged(): void;
+}
diff --git a/src/ui/elements/button.ts b/src/ui/elements/button.ts
index 0a5110ea..f3318079 100644
--- a/src/ui/elements/button.ts
+++ b/src/ui/elements/button.ts
@@ -1,42 +1,87 @@
-import { BaseUIElement } from './base';
-import { ASSERT } from '../../util';
-
-export class ButtonElement extends BaseUIElement {
- private _onClick: () => void;
-
- public constructor(label: string, onClick: () => void) {
- super(label);
- this._onClick = onClick;
- this._isEnabled = true;
- }
-
- public generateHTML() {
- return `
-
- ${this._label}
-
- `;
- }
-
- public registerEvents(): void {
- const element = document.getElementById(this._id) as HTMLDivElement;
- ASSERT(element !== null);
-
- element.addEventListener('click', () => {
- if (this._isEnabled) {
- this._onClick();
- }
- });
- }
-
- protected _onEnabledChanged() {
- const element = document.getElementById(this._id) as HTMLDivElement;
- ASSERT(element !== null);
-
- if (this._isEnabled) {
- element.classList.remove('button-disabled');
- } else {
- element.classList.add('button-disabled');
- }
- }
-}
+import { ASSERT } from '../../util/error_util';
+import { BaseUIElement } from './base';
+
+export class ButtonElement extends BaseUIElement {
+ private _onClick: () => void;
+
+ public constructor(label: string, onClick: () => void) {
+ super(label);
+ this._onClick = onClick;
+ this._isEnabled = true;
+ }
+
+ public generateHTML() {
+ return `
+
+ `;
+ }
+
+ public registerEvents(): void {
+ const element = document.getElementById(this._id) as HTMLDivElement;
+ ASSERT(element !== null);
+
+ element.addEventListener('click', () => {
+ if (this._isEnabled) {
+ this._onClick();
+ }
+ });
+ }
+
+ protected _onEnabledChanged() {
+ const element = document.getElementById(this._id) as HTMLDivElement;
+ ASSERT(element !== null);
+
+ if (this._isEnabled) {
+ element.classList.remove('button-disabled');
+ } else {
+ element.classList.add('button-disabled');
+ }
+ }
+
+ public setLabelOverride(label: string) {
+ const element = document.getElementById(this._id) as HTMLDivElement;
+ ASSERT(element !== null, 'Updating label override of element that does not exist');
+
+ element.innerHTML = label;
+ return this;
+ }
+
+ public removeLabelOverride() {
+ const element = document.getElementById(this._id) as HTMLDivElement;
+ ASSERT(element !== null, 'Removing label override of element that does not exist');
+
+ element.innerHTML = this._label;
+ return this;
+ }
+
+ /**
+ * Set the progress bar progress.
+ * @param progress A number between 0.0 and 1.0 inclusive.
+ */
+ public setProgress(progress: number) {
+ const element = document.getElementById(this._id + '-progress') as HTMLDivElement;
+ ASSERT(element !== null);
+
+ element.style.width = `${progress * 100}%`;
+ return this;
+ }
+
+ public startLoading() {
+ const element = document.getElementById(this._id) as HTMLDivElement;
+ ASSERT(element !== null);
+
+ element.classList.add('button-loading');
+ return this;
+ }
+
+ public stopLoading() {
+ const element = document.getElementById(this._id) as HTMLDivElement;
+ ASSERT(element !== null);
+
+ element.classList.remove('button-loading');
+ return this;
+ }
+}
diff --git a/src/ui/elements/combobox.ts b/src/ui/elements/combobox.ts
index c67d04f2..8885b575 100644
--- a/src/ui/elements/combobox.ts
+++ b/src/ui/elements/combobox.ts
@@ -1,47 +1,47 @@
-import { LabelledElement } from './labelled_element';
-import { ASSERT } from '../../util';
-
-export type ComboBoxItem = {
- id: T;
- displayText: string;
- tooltip?: string;
-}
-
-export class ComboBoxElement extends LabelledElement {
- private _items: ComboBoxItem[];
-
- public constructor(id: string, items: ComboBoxItem[]) {
- super(id);
- this._items = items;
- }
-
- public generateInnerHTML() {
- let itemsHTML = '';
- for (const item of this._items) {
- itemsHTML += `${item.displayText} `;
- }
-
- return `
-
- ${itemsHTML}
-
- `;
- }
-
- public registerEvents(): void {
- }
-
- protected getValue() {
- const element = document.getElementById(this._id) as HTMLSelectElement;
- ASSERT(element !== null);
- return this._items[element.selectedIndex].id;
- }
-
- protected _onEnabledChanged() {
- super._onEnabledChanged();
-
- const element = document.getElementById(this._id) as HTMLSelectElement;
- ASSERT(element !== null);
- element.disabled = !this._isEnabled;
- }
-}
+import { ASSERT } from '../../util/error_util';
+import { LabelledElement } from './labelled_element';
+
+export type ComboBoxItem = {
+ id: T;
+ displayText: string;
+ tooltip?: string;
+}
+
+export class ComboBoxElement extends LabelledElement {
+ private _items: ComboBoxItem[];
+
+ public constructor(id: string, items: ComboBoxItem[]) {
+ super(id);
+ this._items = items;
+ }
+
+ public generateInnerHTML() {
+ let itemsHTML = '';
+ for (const item of this._items) {
+ itemsHTML += `${item.displayText} `;
+ }
+
+ return `
+
+ ${itemsHTML}
+
+ `;
+ }
+
+ public registerEvents(): void {
+ }
+
+ protected getValue() {
+ const element = document.getElementById(this._id) as HTMLSelectElement;
+ ASSERT(element !== null);
+ return this._items[element.selectedIndex].id;
+ }
+
+ protected _onEnabledChanged() {
+ super._onEnabledChanged();
+
+ const element = document.getElementById(this._id) as HTMLSelectElement;
+ ASSERT(element !== null);
+ element.disabled = !this._isEnabled;
+ }
+}
diff --git a/src/ui/elements/file_input.ts b/src/ui/elements/file_input.ts
index 05a2faff..752ec745 100644
--- a/src/ui/elements/file_input.ts
+++ b/src/ui/elements/file_input.ts
@@ -1,67 +1,87 @@
-import { LabelledElement } from './labelled_element';
-import { ASSERT } from '../../util';
-
-import { remote } from 'electron';
-import * as path from 'path';
-
-export class FileInputElement extends LabelledElement {
- private _fileExtension: string;
- private _loadedFilePath: string;
-
- public constructor(label: string, fileExtension: string) {
- super(label);
- this._fileExtension = fileExtension;
- this._loadedFilePath = '';
- }
-
- public generateInnerHTML() {
- return `
-
- ${this._loadedFilePath}
-
- `;
- }
-
- public registerEvents(): void {
- const element = document.getElementById(this._id) as HTMLDivElement;
- ASSERT(element !== null);
-
- element.onclick = () => {
- if (!this._isEnabled) {
- return;
- }
-
- const files = remote.dialog.showOpenDialogSync({
- title: 'Load file',
- buttonLabel: 'Load',
- filters: [{
- name: 'Waveform obj file',
- extensions: [`${this._fileExtension}`],
- }],
- });
- if (files && files.length === 1) {
- const filePath = files[0];
- this._loadedFilePath = filePath;
- this._value = filePath;
- } else {
- this._loadedFilePath = '';
- this._value = '';
- }
- const parsedPath = path.parse(this._loadedFilePath);
- element.innerHTML = parsedPath.name + parsedPath.ext;
- };
- }
-
- protected _onEnabledChanged() {
- super._onEnabledChanged();
-
- const element = document.getElementById(this._id) as HTMLDivElement;
- ASSERT(element !== null);
-
- if (this._isEnabled) {
- element.classList.remove('input-text-disabled');
- } else {
- element.classList.add('input-text-disabled');
- }
- }
-}
+import { remote } from 'electron';
+import * as path from 'path';
+
+import { ASSERT } from '../../util/error_util';
+import { LabelledElement } from './labelled_element';
+
+export class FileInputElement extends LabelledElement {
+ private _fileExtension: string;
+ private _loadedFilePath: string;
+ private _hovering: boolean;
+
+ public constructor(label: string, fileExtension: string) {
+ super(label);
+ this._fileExtension = fileExtension;
+ this._loadedFilePath = '';
+ this._hovering = false;
+ }
+
+ public generateInnerHTML() {
+ return `
+
+ ${this._loadedFilePath}
+
+ `;
+ }
+
+ public registerEvents(): void {
+ const element = document.getElementById(this._id) as HTMLDivElement;
+ ASSERT(element !== null);
+
+ element.onmouseenter = () => {
+ this._hovering = true;
+ };
+
+ element.onmouseleave = () => {
+ this._hovering = false;
+ };
+
+ element.onclick = () => {
+ if (!this._isEnabled) {
+ return;
+ }
+
+ const files = remote.dialog.showOpenDialogSync({
+ title: 'Load file',
+ buttonLabel: 'Load',
+ filters: [{
+ name: 'Waveform obj file',
+ extensions: [`${this._fileExtension}`],
+ }],
+ });
+ if (files && files.length === 1) {
+ const filePath = files[0];
+ this._loadedFilePath = filePath;
+ this._value = filePath;
+ }
+ const parsedPath = path.parse(this._loadedFilePath);
+ element.innerHTML = parsedPath.name + parsedPath.ext;
+ };
+
+ document.onmousemove = () => {
+ element.classList.remove('input-text-disabled');
+ element.classList.remove('input-text-hover');
+
+ if (this._isEnabled) {
+ if (this._hovering) {
+ element.classList.add('input-text-hover');
+ }
+ } else {
+ element.classList.add('input-text-disabled');
+ }
+ };
+ }
+
+ protected _onEnabledChanged() {
+ super._onEnabledChanged();
+
+ const element = document.getElementById(this._id) as HTMLDivElement;
+ ASSERT(element !== null);
+
+ if (this._isEnabled) {
+ element.classList.remove('input-text-disabled');
+ } else {
+ element.classList.add('input-text-disabled');
+ }
+ }
+}
diff --git a/src/ui/elements/label.ts b/src/ui/elements/label.ts
index d7be38b0..da9581cf 100644
--- a/src/ui/elements/label.ts
+++ b/src/ui/elements/label.ts
@@ -1,35 +1,36 @@
-import { ASSERT, getRandomID } from '../../util';
-
-export class LabelElement {
- private _id: string;
- private _text: string;
- private _description?: string;
-
- constructor(text: string, description?: string) {
- this._id = getRandomID();
- this._text = text;
- this._description = description;
- }
-
- public generateHTML(): string {
- const description = this._description ? `
- ${this._description}
-
` : '';
- return `
-
- ${this._text}${description}
-
- `;
- }
-
- public setEnabled(isEnabled: boolean) {
- const element = document.getElementById(this._id) as HTMLDivElement;
- ASSERT(element !== null);
-
- if (isEnabled) {
- element.classList.remove('prop-left-disabled');
- } else {
- element.classList.add('prop-left-disabled');
- }
- }
-}
+import { getRandomID } from '../../util';
+import { ASSERT } from '../../util/error_util';
+
+export class LabelElement {
+ private _id: string;
+ private _text: string;
+ private _description?: string;
+
+ constructor(text: string, description?: string) {
+ this._id = getRandomID();
+ this._text = text;
+ this._description = description;
+ }
+
+ public generateHTML(): string {
+ const description = false && this._description ? `
+ ${this._description}
+
` : '';
+ return `
+
+ ${this._text}${description}
+
+ `;
+ }
+
+ public setEnabled(isEnabled: boolean) {
+ const element = document.getElementById(this._id) as HTMLDivElement;
+ ASSERT(element !== null);
+
+ if (isEnabled) {
+ element.classList.remove('prop-left-disabled');
+ } else {
+ element.classList.add('prop-left-disabled');
+ }
+ }
+}
diff --git a/src/ui/elements/labelled_element.ts b/src/ui/elements/labelled_element.ts
index 6ffe2507..f54e7953 100644
--- a/src/ui/elements/labelled_element.ts
+++ b/src/ui/elements/labelled_element.ts
@@ -1,32 +1,31 @@
-import { BaseUIElement } from './base';
-import { LabelElement } from './label';
-
-export abstract class LabelledElement extends BaseUIElement {
- private _labelElement: LabelElement;
-
- public constructor(label: string) {
- super(label);
- this._label = label;
- this._labelElement = new LabelElement(label);
- }
-
- public generateHTML() {
- return `
- ${this._labelElement.generateHTML()}
-
-
- ${this.generateInnerHTML()}
-
- `;
- }
-
- protected abstract generateInnerHTML(): string;
-
- protected _onEnabledChanged() {
- this._labelElement.setEnabled(this._isEnabled);
- }
-
- public addDescription(text: string) {
- this._labelElement = new LabelElement(this._label, text);
- }
-}
+import { BaseUIElement } from './base';
+import { LabelElement } from './label';
+
+export abstract class LabelledElement extends BaseUIElement {
+ private _labelElement: LabelElement;
+
+ public constructor(label: string) {
+ super(label);
+ this._label = label;
+ this._labelElement = new LabelElement(label);
+ }
+
+ public generateHTML() {
+ return `
+ ${this._labelElement.generateHTML()}
+
+ ${this.generateInnerHTML()}
+
+ `;
+ }
+
+ protected abstract generateInnerHTML(): string;
+
+ protected _onEnabledChanged() {
+ this._labelElement.setEnabled(this._isEnabled);
+ }
+
+ public addDescription(text: string) {
+ this._labelElement = new LabelElement(this._label, text);
+ }
+}
diff --git a/src/ui/elements/output.ts b/src/ui/elements/output.ts
index eb557c0a..6d5ce644 100644
--- a/src/ui/elements/output.ts
+++ b/src/ui/elements/output.ts
@@ -1,48 +1,85 @@
-import { ASSERT } from '../../util';
-import { UIMessageBuilder } from '../misc';
-
-export type OutputStyle = 'success' | 'warning' | 'error';
-
-export class OutputElement {
- private _id: string;
-
- public constructor() {
- this._id = '_' + Math.random().toString(16);
- }
-
- public generateHTML() {
- return `
-
-
- `;
- }
-
- public clearMessage() {
- const element = document.getElementById(this._id) as HTMLDivElement;
- ASSERT(element !== null);
-
- element.innerHTML = '';
- element.classList.remove('border-success');
- element.classList.remove('border-warning');
- element.classList.remove('border-error');
- }
-
- public setMessage(message: UIMessageBuilder, style: OutputStyle) {
- const element = document.getElementById(this._id) as HTMLDivElement;
- ASSERT(element !== null);
-
- this.clearMessage();
- element.innerHTML = message.toString();
- switch (style) {
- case 'success':
- element.classList.add('border-success');
- break;
- case 'warning':
- element.classList.add('border-warning');
- break;
- case 'error':
- element.classList.add('border-error');
- break;
- }
- }
-}
+import { ASSERT } from '../../util/error_util';
+import { UIMessageBuilder } from '../misc';
+
+export type OutputStyle = 'success' | 'warning' | 'error' | 'none';
+
+export class OutputElement {
+ private _id: string;
+
+ public constructor() {
+ this._id = '_' + Math.random().toString(16);
+ this._message = new UIMessageBuilder();
+ }
+
+ public generateHTML() {
+ return `
+
+
+ `;
+ }
+
+ private _message: UIMessageBuilder;
+
+ public setMessage(message: UIMessageBuilder, style?: OutputStyle) {
+ const element = document.getElementById(this._id) as HTMLDivElement;
+ ASSERT(element !== null);
+
+ this._message = message;
+
+ element.innerHTML = this._message.toString();
+ }
+
+ public getMessage() {
+ return this._message;
+ }
+
+ public setTaskInProgress(taskId: string, taskHeading: string) {
+ this.getMessage()
+ .clear(taskId)
+ .addTask(taskId, taskHeading);
+
+ this.updateMessage();
+ }
+
+ public setTaskComplete(taskId: string, taskHeading: string, taskItems: string[], style: OutputStyle) {
+ const builder = this.getMessage().clear(taskId);
+
+ if (taskItems.length > 0) {
+ builder.addHeading(taskId, taskHeading, style);
+ } else {
+ builder.addBold(taskId, [taskHeading], style);
+ }
+
+ builder.addItem(taskId, taskItems, style);
+
+ this.updateMessage();
+ }
+
+ public updateMessage() {
+ const element = document.getElementById(this._id) as HTMLDivElement;
+ ASSERT(element !== null);
+
+ element.innerHTML = this._message.toString();
+ }
+
+ public setStyle(style: OutputStyle) {
+ const element = document.getElementById(this._id) as HTMLDivElement;
+ ASSERT(element !== null);
+
+ element.classList.remove('border-success');
+ element.classList.remove('border-warning');
+ element.classList.remove('border-error');
+
+ switch (style) {
+ case 'success':
+ element.classList.add('border-success');
+ break;
+ case 'warning':
+ element.classList.add('border-warning');
+ break;
+ case 'error':
+ element.classList.add('border-error');
+ break;
+ }
+ }
+}
diff --git a/src/ui/elements/slider.ts b/src/ui/elements/slider.ts
index 322b0469..72458614 100644
--- a/src/ui/elements/slider.ts
+++ b/src/ui/elements/slider.ts
@@ -1,151 +1,151 @@
-import { ASSERT } from '../../util';
-import { clamp, mapRange, wayThrough } from '../../math';
-import { LabelledElement } from './labelled_element';
-
-export class SliderElement extends LabelledElement {
- private _min: number;
- private _max: number;
- private _decimals: number;
- private _dragging: boolean;
- private _step: number;
- private _hovering: boolean;
-
- public constructor(label: string, min: number, max: number, decimals: number, value: number, step: number) {
- super(label);
- this._min = min;
- this._max = max;
- this._decimals = decimals;
- this._value = value;
- this._step = step;
- this._dragging = false;
- this._hovering = false;
- }
-
- public generateInnerHTML() {
- const norm = (this.getValue() - this._min) / (this._max - this._min);
- return `
-
- `;
- }
-
- public registerEvents() {
- const element = document.getElementById(this._id) as HTMLDivElement;
- const elementBar = document.getElementById(this._id + '-bar') as HTMLDivElement;
- ASSERT(element !== null);
-
- element.onmouseenter = () => {
- this._hovering = true;
- if (this._isEnabled) {
- element.classList.add('new-slider-hover');
- elementBar.classList.add('new-slider-bar-hover');
- }
- };
-
- element.onmouseleave = () => {
- this._hovering = false;
- if (!this._dragging) {
- element.classList.remove('new-slider-hover');
- elementBar.classList.remove('new-slider-bar-hover');
- }
- };
-
- element.onmousedown = () => {
- this._dragging = true;
- };
-
- document.addEventListener('mousemove', (e: MouseEvent) => {
- if (this._dragging) {
- this._onDragSlider(e);
- }
- });
-
- document.addEventListener('mouseup', (e: MouseEvent) => {
- if (this._dragging) {
- this._onDragSlider(e);
- }
- if (!this._hovering) {
- element.classList.remove('new-slider-hover');
- elementBar.classList.remove('new-slider-bar-hover');
- }
- this._dragging = false;
- });
-
- element.addEventListener('wheel', (e: WheelEvent) => {
- if (!this._dragging && this._isEnabled) {
- e.preventDefault();
- this._onScrollSlider(e);
- }
- });
- }
-
- private _onScrollSlider(e: WheelEvent) {
- if (!this._isEnabled) {
- return;
- }
- ASSERT(this._value);
-
- this._value -= (e.deltaY / 150) * this._step;
- this._value = clamp(this._value, this._min, this._max);
-
- this._onValueUpdated();
- }
-
- private _onDragSlider(e: MouseEvent) {
- if (!this._isEnabled) {
- return;
- }
-
- const element = document.getElementById(this._id) as HTMLDivElement;
- ASSERT(element !== null);
-
- const box = element.getBoundingClientRect();
- const left = box.x;
- const right = box.x + box.width;
-
- this._value = mapRange(e.clientX, left, right, this._min, this._max);
- this._value = clamp(this._value, this._min, this._max);
-
- this._onValueUpdated();
- }
-
- private _onValueUpdated() {
- const elementBar = document.getElementById(this._id + '-bar') as HTMLDivElement;
- const elementValue = document.getElementById(this._id + '-value') as HTMLDivElement;
- ASSERT(elementBar !== null && elementValue !== null);
-
- const norm = wayThrough(this.getValue(), this._min, this._max);
- elementBar.style.width = `${norm * 100}%`;
- elementValue.innerHTML = this.getValue().toFixed(this._decimals);
- }
-
- public getDisplayValue() {
- return parseFloat(this.getValue().toFixed(this._decimals));
- }
-
- protected _onEnabledChanged() {
- super._onEnabledChanged();
-
- const element = document.getElementById(this._id) as HTMLDivElement;
- const elementBar = document.getElementById(this._id + '-bar') as HTMLDivElement;
- const elementValue = document.getElementById(this._id + '-value') as HTMLDivElement;
- ASSERT(element !== null && elementBar !== null && elementValue !== null);
-
- if (this._isEnabled) {
- element.classList.remove('new-slider-disabled');
- elementBar.classList.remove('new-slider-bar-disabled');
- elementValue.classList.remove('slider-value-disabled');
- } else {
- element.classList.add('new-slider-disabled');
- elementBar.classList.add('new-slider-bar-disabled');
- elementValue.classList.add('slider-value-disabled');
- }
- }
-}
+import { clamp, mapRange, wayThrough } from '../../math';
+import { ASSERT } from '../../util/error_util';
+import { LabelledElement } from './labelled_element';
+
+export class SliderElement extends LabelledElement {
+ private _min: number;
+ private _max: number;
+ private _decimals: number;
+ private _dragging: boolean;
+ private _step: number;
+ private _hovering: boolean;
+
+ public constructor(label: string, min: number, max: number, decimals: number, value: number, step: number) {
+ super(label);
+ this._min = min;
+ this._max = max;
+ this._decimals = decimals;
+ this._value = value;
+ this._step = step;
+ this._dragging = false;
+ this._hovering = false;
+ }
+
+ public generateInnerHTML() {
+ const norm = (this.getValue() - this._min) / (this._max - this._min);
+ return `
+
+
+ ${this._value?.toFixed(this._decimals)}
+
+
+
+ `;
+ }
+
+ public registerEvents() {
+ const element = document.getElementById(this._id) as HTMLDivElement;
+ const elementBar = document.getElementById(this._id + '-bar') as HTMLDivElement;
+ ASSERT(element !== null);
+
+ element.onmouseenter = () => {
+ this._hovering = true;
+ if (this._isEnabled) {
+ element.classList.add('new-slider-hover');
+ elementBar.classList.add('new-slider-bar-hover');
+ }
+ };
+
+ element.onmouseleave = () => {
+ this._hovering = false;
+ if (!this._dragging) {
+ element.classList.remove('new-slider-hover');
+ elementBar.classList.remove('new-slider-bar-hover');
+ }
+ };
+
+ element.onmousedown = () => {
+ this._dragging = true;
+ };
+
+ document.addEventListener('mousemove', (e: MouseEvent) => {
+ if (this._dragging) {
+ this._onDragSlider(e);
+ }
+ });
+
+ document.addEventListener('mouseup', (e: MouseEvent) => {
+ if (this._dragging) {
+ this._onDragSlider(e);
+ }
+ if (!this._hovering) {
+ element.classList.remove('new-slider-hover');
+ elementBar.classList.remove('new-slider-bar-hover');
+ }
+ this._dragging = false;
+ });
+
+ element.addEventListener('wheel', (e: WheelEvent) => {
+ if (!this._dragging && this._isEnabled) {
+ e.preventDefault();
+ this._onScrollSlider(e);
+ }
+ });
+ }
+
+ private _onScrollSlider(e: WheelEvent) {
+ if (!this._isEnabled) {
+ return;
+ }
+ ASSERT(this._value);
+
+ this._value -= (e.deltaY / 150) * this._step;
+ this._value = clamp(this._value, this._min, this._max);
+
+ this._onValueUpdated();
+ }
+
+ private _onDragSlider(e: MouseEvent) {
+ if (!this._isEnabled) {
+ return;
+ }
+
+ const element = document.getElementById(this._id) as HTMLDivElement;
+ ASSERT(element !== null);
+
+ const box = element.getBoundingClientRect();
+ const left = box.x;
+ const right = box.x + box.width;
+
+ this._value = mapRange(e.clientX, left, right, this._min, this._max);
+ this._value = clamp(this._value, this._min, this._max);
+
+ this._onValueUpdated();
+ }
+
+ private _onValueUpdated() {
+ const elementBar = document.getElementById(this._id + '-bar') as HTMLDivElement;
+ const elementValue = document.getElementById(this._id + '-value') as HTMLDivElement;
+ ASSERT(elementBar !== null && elementValue !== null);
+
+ const norm = wayThrough(this.getValue(), this._min, this._max);
+ elementBar.style.width = `${norm * 100}%`;
+ elementValue.innerHTML = this.getValue().toFixed(this._decimals);
+ }
+
+ public getDisplayValue() {
+ return parseFloat(this.getValue().toFixed(this._decimals));
+ }
+
+ protected _onEnabledChanged() {
+ super._onEnabledChanged();
+
+ const element = document.getElementById(this._id) as HTMLDivElement;
+ const elementBar = document.getElementById(this._id + '-bar') as HTMLDivElement;
+ const elementValue = document.getElementById(this._id + '-value') as HTMLDivElement;
+ ASSERT(element !== null && elementBar !== null && elementValue !== null);
+
+ if (this._isEnabled) {
+ element.classList.remove('new-slider-disabled');
+ elementBar.classList.remove('new-slider-bar-disabled');
+ elementValue.classList.remove('slider-value-disabled');
+ } else {
+ element.classList.add('new-slider-disabled');
+ elementBar.classList.add('new-slider-bar-disabled');
+ elementValue.classList.add('slider-value-disabled');
+ }
+ }
+}
diff --git a/src/ui/elements/toolbar_item.ts b/src/ui/elements/toolbar_item.ts
index 6d552ed5..689cb052 100644
--- a/src/ui/elements/toolbar_item.ts
+++ b/src/ui/elements/toolbar_item.ts
@@ -1,109 +1,124 @@
-import { ASSERT, getRandomID, STATIC_DIR } from '../../util';
-
-import path from 'path';
-import fs from 'fs';
-import { EAppEvent, EventManager } from '../../event';
-
-export class ToolbarItemElement {
- private _id: string;
- private _iconName: string;
- private _iconPath: string;
- private _isEnabled: boolean;
- private _isActive: boolean;
- private _onClick: () => void;
-
- public constructor(iconName: string, onClick: () => void,
- _activeChangedEvent?: EAppEvent, _activeChangedDelegate?: (...args: any[]) => boolean,
- _enableChangedEvent?: EAppEvent, _enableChangedDelegate?: (...args: any[]) => boolean,
- ) {
- this._id = getRandomID();
- this._iconName = iconName;
- this._iconPath = path.join(STATIC_DIR, iconName + '.svg');
- this._isEnabled = false;
- this._isActive = false;
- this._onClick = onClick;
-
- // Enabled/Disabled Event
- if (_enableChangedEvent !== undefined && _enableChangedDelegate) {
- EventManager.Get.add(_enableChangedEvent, (...args: any[]) => {
- const isEnabled = _enableChangedDelegate(args);
- this.setEnabled(isEnabled);
- });
- } else {
- this._isEnabled = true;
- }
-
- // Active/Inactive Event
- if (_activeChangedEvent !== undefined && _activeChangedDelegate) {
- EventManager.Get.add(_activeChangedEvent, (...args: any[]) => {
- const isActive = _activeChangedDelegate(args);
- this.setActive(isActive);
- });
- }
- }
-
- public generateHTML() {
- const svg = fs.readFileSync(this._iconPath, 'utf8');
- return `
-
- ${svg}
-
- `;
- }
-
- public registerEvents(): void {
- const element = document.getElementById(this._id) as HTMLDivElement;
- ASSERT(element !== null);
-
- element.addEventListener('click', () => {
- if (this._isEnabled) {
- this._onClick();
- }
- });
-
- element.addEventListener('mouseenter', () => {
- if (this._isEnabled) {
- element.classList.add('toolbar-item-hover');
- }
- });
-
- element.addEventListener('mouseleave', () => {
- if (this._isEnabled) {
- element.classList.remove('toolbar-item-hover');
- }
- });
-
- this._updateElements();
- }
-
- private _updateElements() {
- const element = document.getElementById(this._id) as HTMLDivElement;
- const svgElement = document.getElementById(this._iconName + '-svg') as HTMLDivElement;
- ASSERT(element !== null && svgElement !== null);
-
- element.classList.remove('toolbar-item-disabled');
- element.classList.remove('toolbar-item-active');
- svgElement.classList.remove('icon-disabled');
- svgElement.classList.remove('icon-active');
-
- if (this._isEnabled) {
- if (this._isActive) {
- element.classList.add('toolbar-item-active');
- svgElement.classList.add('icon-active');
- }
- } else {
- element.classList.add('toolbar-item-disabled');
- svgElement.classList.add('icon-disabled');
- }
- }
-
- public setEnabled(isEnabled: boolean) {
- this._isEnabled = isEnabled;
- this._updateElements();
- }
-
- public setActive(isActive: boolean) {
- this._isActive = isActive;
- this._updateElements();
- }
-}
+import fs from 'fs';
+
+import { getRandomID } from '../../util';
+import { ASSERT } from '../../util/error_util';
+import { AppPaths } from '../../util/path_util';
+import { PathUtil } from '../../util/path_util';
+
+export type TToolbarBooleanProperty = 'enabled' | 'active';
+
+export type TToolbarItemParams = {
+ icon: string;
+}
+
+export class ToolbarItemElement {
+ private _id: string;
+ private _iconName: string;
+ private _iconPath: string;
+ private _isEnabled: boolean;
+ private _isActive: boolean;
+ private _onClick?: () => void;
+
+ public constructor(params: TToolbarItemParams) {
+ this._id = getRandomID();
+
+ this._iconName = params.icon;
+ this._iconPath = PathUtil.join(AppPaths.Get.static, params.icon + '.svg');
+
+ this._isEnabled = true;
+ this._isActive = false;
+ }
+
+ public tick() {
+ if (this._isEnabledDelegate !== undefined) {
+ this.setEnabled(this._isEnabledDelegate());
+ }
+
+ if (this._isActiveDelegate !== undefined) {
+ this.setActive(this._isActiveDelegate());
+ }
+ }
+
+ private _isActiveDelegate?: () => boolean;
+ public isActive(delegate: () => boolean) {
+ this._isActiveDelegate = delegate;
+ return this;
+ }
+
+ private _isEnabledDelegate?: () => boolean;
+ public isEnabled(delegate: () => boolean) {
+ this._isEnabledDelegate = delegate;
+ return this;
+ }
+
+ public onClick(delegate: () => void) {
+ this._onClick = delegate;
+
+ return this;
+ }
+
+ public generateHTML() {
+ const svg = fs.readFileSync(this._iconPath, 'utf8');
+ return `
+
+ ${svg}
+
+ `;
+ }
+
+ public registerEvents(): void {
+ const element = document.getElementById(this._id) as HTMLDivElement;
+ ASSERT(element !== null);
+
+ element.addEventListener('click', () => {
+ if (this._isEnabled && this._onClick) {
+ this._onClick();
+ }
+ });
+
+ element.addEventListener('mouseenter', () => {
+ if (this._isEnabled) {
+ element.classList.add('toolbar-item-hover');
+ }
+ });
+
+ element.addEventListener('mouseleave', () => {
+ if (this._isEnabled) {
+ element.classList.remove('toolbar-item-hover');
+ }
+ });
+
+ this._updateElements();
+ }
+
+ private _updateElements() {
+ const element = document.getElementById(this._id) as HTMLDivElement;
+ const svgElement = document.getElementById(this._iconName + '-svg') as HTMLDivElement;
+ ASSERT(element !== null && svgElement !== null);
+
+ element.classList.remove('toolbar-item-disabled');
+ element.classList.remove('toolbar-item-active');
+ svgElement.classList.remove('icon-disabled');
+ svgElement.classList.remove('icon-active');
+
+ if (this._isEnabled) {
+ if (this._isActive) {
+ element.classList.add('toolbar-item-active');
+ svgElement.classList.add('icon-active');
+ }
+ } else {
+ element.classList.add('toolbar-item-disabled');
+ svgElement.classList.add('icon-disabled');
+ }
+ }
+
+ public setEnabled(isEnabled: boolean) {
+ this._isEnabled = isEnabled;
+ this._updateElements();
+ }
+
+ public setActive(isActive: boolean) {
+ this._isActive = isActive;
+ this._updateElements();
+ }
+}
diff --git a/src/ui/elements/vector_spinbox.ts b/src/ui/elements/vector_spinbox.ts
index 1549f29a..1ca6ddb0 100644
--- a/src/ui/elements/vector_spinbox.ts
+++ b/src/ui/elements/vector_spinbox.ts
@@ -1,199 +1,200 @@
-import { ASSERT, LOG } from '../../util';
-import { LabelledElement } from './labelled_element';
-import { Vector3 } from '../../vector';
-
-/* eslint-disable */
-enum EAxis {
- None = 'none',
- X = 'x',
- Y = 'y',
- Z = 'z',
-};
-/* eslint-enable */
-
-export class VectorSpinboxElement extends LabelledElement {
- private _mouseover: EAxis;
- private _dragging: EAxis;
- private _lastClientX: number;
-
- public constructor(label: string, decimals: number, value: Vector3) {
- super(label);
- this._value = value;
- this._mouseover = EAxis.None;
- this._dragging = EAxis.None;
- this._lastClientX = 0.0;
- }
-
- public generateInnerHTML() {
- ASSERT(this._value, 'Value not found');
- return `
-
-
-
X
-
- ${this._value.x}
-
-
-
-
-
Y
-
- ${this._value.y}
-
-
-
-
-
Z
-
- ${this._value.z}
-
-
-
- `;
- }
-
- private _registerAxis(axis: EAxis) {
- ASSERT(axis !== EAxis.None);
-
- const elementXK = document.getElementById(this._id + '-k' + axis) as HTMLDivElement;
- const elementXV = document.getElementById(this._id + '-v' + axis) as HTMLDivElement;
- ASSERT(elementXK !== null && elementXV !== null);
-
- elementXK.onmouseenter = () => {
- this._mouseover = axis;
- if (this._isEnabled) {
- elementXK.classList.add('spinbox-key-hover');
- elementXV.classList.add('spinbox-value-hover');
- }
- };
-
- elementXV.onmouseenter = () => {
- this._mouseover = axis;
- if (this._isEnabled) {
- elementXK.classList.add('spinbox-key-hover');
- elementXV.classList.add('spinbox-value-hover');
- }
- };
-
- elementXK.onmouseleave = () => {
- this._mouseover = EAxis.None;
- if (this._dragging !== axis) {
- elementXK.classList.remove('spinbox-key-hover');
- elementXV.classList.remove('spinbox-value-hover');
- }
- };
-
- elementXV.onmouseleave = () => {
- this._mouseover = EAxis.None;
- if (this._dragging !== axis) {
- elementXK.classList.remove('spinbox-key-hover');
- elementXV.classList.remove('spinbox-value-hover');
- }
- };
- }
-
- public registerEvents() {
- this._registerAxis(EAxis.X);
- this._registerAxis(EAxis.Y);
- this._registerAxis(EAxis.Z);
-
- document.addEventListener('mousedown', (e: any) => {
- if (this._isEnabled && this._mouseover !== EAxis.None) {
- this._dragging = this._mouseover;
- this._lastClientX = e.clientX;
- }
- });
-
- document.addEventListener('mousemove', (e: any) => {
- if (this._isEnabled && this._dragging !== EAxis.None) {
- this._updateValue(e);
- }
- });
-
- document.addEventListener('mouseup', () => {
- const elementXK = document.getElementById(this._id + '-kx') as HTMLDivElement;
- const elementYK = document.getElementById(this._id + '-ky') as HTMLDivElement;
- const elementZK = document.getElementById(this._id + '-kz') as HTMLDivElement;
- const elementXV = document.getElementById(this._id + '-vx') as HTMLDivElement;
- const elementYV = document.getElementById(this._id + '-vy') as HTMLDivElement;
- const elementZV = document.getElementById(this._id + '-vz') as HTMLDivElement;
-
- switch (this._dragging) {
- case EAxis.X:
- elementXK.classList.remove('spinbox-key-hover');
- elementXV.classList.remove('spinbox-value-hover');
- break;
- case EAxis.Y:
- elementYK.classList.remove('spinbox-key-hover');
- elementYV.classList.remove('spinbox-value-hover');
- break;
- case EAxis.Z:
- elementZK.classList.remove('spinbox-key-hover');
- elementZV.classList.remove('spinbox-value-hover');
- break;
- }
- this._dragging = EAxis.None;
- });
- }
-
- private _updateValue(e: MouseEvent) {
- ASSERT(this._isEnabled, 'Not enabled');
- ASSERT(this._dragging !== EAxis.None, 'Dragging nothing');
- ASSERT(this._value, 'No value to update');
-
- const deltaX = e.clientX - this._lastClientX;
- this._lastClientX = e.clientX;
-
- switch (this._dragging) {
- case EAxis.X:
- this._value.x += deltaX;
- break;
- case EAxis.Y:
- this._value.y += deltaX;
- break;
- case EAxis.Z:
- this._value.z += deltaX;
- break;
- }
-
- const elementXV = document.getElementById(this._id + '-vx') as HTMLDivElement;
- const elementYV = document.getElementById(this._id + '-vy') as HTMLDivElement;
- const elementZV = document.getElementById(this._id + '-vz') as HTMLDivElement;
- elementXV.innerHTML = this._value.x.toString();
- elementYV.innerHTML = this._value.y.toString();
- elementZV.innerHTML = this._value.z.toString();
- }
-
- protected _onEnabledChanged() {
- super._onEnabledChanged();
-
- LOG(this._label, 'is now enabled', this._isEnabled);
-
- const keyElements = [
- document.getElementById(this._id + '-kx') as HTMLDivElement,
- document.getElementById(this._id + '-ky') as HTMLDivElement,
- document.getElementById(this._id + '-kz') as HTMLDivElement,
- ];
- const valueElements = [
- document.getElementById(this._id + '-vx') as HTMLDivElement,
- document.getElementById(this._id + '-vy') as HTMLDivElement,
- document.getElementById(this._id + '-vz') as HTMLDivElement,
- ];
-
- if (this._isEnabled) {
- for (const keyElement of keyElements) {
- keyElement.classList.remove('spinbox-key-disabled');
- }
- for (const valueElement of valueElements) {
- valueElement.classList.remove('spinbox-value-disabled');
- }
- } else {
- for (const keyElement of keyElements) {
- keyElement.classList.add('spinbox-key-disabled');
- }
- for (const valueElement of valueElements) {
- valueElement.classList.add('spinbox-value-disabled');
- }
- }
- }
-}
+import { ASSERT } from '../../util/error_util';
+import { LOG } from '../../util/log_util';
+import { Vector3 } from '../../vector';
+import { LabelledElement } from './labelled_element';
+
+/* eslint-disable */
+enum EAxis {
+ None = 'none',
+ X = 'x',
+ Y = 'y',
+ Z = 'z',
+};
+/* eslint-enable */
+
+export class VectorSpinboxElement extends LabelledElement {
+ private _mouseover: EAxis;
+ private _dragging: EAxis;
+ private _lastClientX: number;
+
+ public constructor(label: string, decimals: number, value: Vector3) {
+ super(label);
+ this._value = value;
+ this._mouseover = EAxis.None;
+ this._dragging = EAxis.None;
+ this._lastClientX = 0.0;
+ }
+
+ public generateInnerHTML() {
+ ASSERT(this._value, 'Value not found');
+ return `
+
+
+
X
+
+ ${this._value.x}
+
+
+
+
+
Y
+
+ ${this._value.y}
+
+
+
+
+
Z
+
+ ${this._value.z}
+
+
+
+ `;
+ }
+
+ private _registerAxis(axis: EAxis) {
+ ASSERT(axis !== EAxis.None);
+
+ const elementXK = document.getElementById(this._id + '-k' + axis) as HTMLDivElement;
+ const elementXV = document.getElementById(this._id + '-v' + axis) as HTMLDivElement;
+ ASSERT(elementXK !== null && elementXV !== null);
+
+ elementXK.onmouseenter = () => {
+ this._mouseover = axis;
+ if (this._isEnabled) {
+ elementXK.classList.add('spinbox-key-hover');
+ elementXV.classList.add('spinbox-value-hover');
+ }
+ };
+
+ elementXV.onmouseenter = () => {
+ this._mouseover = axis;
+ if (this._isEnabled) {
+ elementXK.classList.add('spinbox-key-hover');
+ elementXV.classList.add('spinbox-value-hover');
+ }
+ };
+
+ elementXK.onmouseleave = () => {
+ this._mouseover = EAxis.None;
+ if (this._dragging !== axis) {
+ elementXK.classList.remove('spinbox-key-hover');
+ elementXV.classList.remove('spinbox-value-hover');
+ }
+ };
+
+ elementXV.onmouseleave = () => {
+ this._mouseover = EAxis.None;
+ if (this._dragging !== axis) {
+ elementXK.classList.remove('spinbox-key-hover');
+ elementXV.classList.remove('spinbox-value-hover');
+ }
+ };
+ }
+
+ public registerEvents() {
+ this._registerAxis(EAxis.X);
+ this._registerAxis(EAxis.Y);
+ this._registerAxis(EAxis.Z);
+
+ document.addEventListener('mousedown', (e: any) => {
+ if (this._isEnabled && this._mouseover !== EAxis.None) {
+ this._dragging = this._mouseover;
+ this._lastClientX = e.clientX;
+ }
+ });
+
+ document.addEventListener('mousemove', (e: any) => {
+ if (this._isEnabled && this._dragging !== EAxis.None) {
+ this._updateValue(e);
+ }
+ });
+
+ document.addEventListener('mouseup', () => {
+ const elementXK = document.getElementById(this._id + '-kx') as HTMLDivElement;
+ const elementYK = document.getElementById(this._id + '-ky') as HTMLDivElement;
+ const elementZK = document.getElementById(this._id + '-kz') as HTMLDivElement;
+ const elementXV = document.getElementById(this._id + '-vx') as HTMLDivElement;
+ const elementYV = document.getElementById(this._id + '-vy') as HTMLDivElement;
+ const elementZV = document.getElementById(this._id + '-vz') as HTMLDivElement;
+
+ switch (this._dragging) {
+ case EAxis.X:
+ elementXK.classList.remove('spinbox-key-hover');
+ elementXV.classList.remove('spinbox-value-hover');
+ break;
+ case EAxis.Y:
+ elementYK.classList.remove('spinbox-key-hover');
+ elementYV.classList.remove('spinbox-value-hover');
+ break;
+ case EAxis.Z:
+ elementZK.classList.remove('spinbox-key-hover');
+ elementZV.classList.remove('spinbox-value-hover');
+ break;
+ }
+ this._dragging = EAxis.None;
+ });
+ }
+
+ private _updateValue(e: MouseEvent) {
+ ASSERT(this._isEnabled, 'Not enabled');
+ ASSERT(this._dragging !== EAxis.None, 'Dragging nothing');
+ ASSERT(this._value, 'No value to update');
+
+ const deltaX = e.clientX - this._lastClientX;
+ this._lastClientX = e.clientX;
+
+ switch (this._dragging) {
+ case EAxis.X:
+ this._value.x += deltaX;
+ break;
+ case EAxis.Y:
+ this._value.y += deltaX;
+ break;
+ case EAxis.Z:
+ this._value.z += deltaX;
+ break;
+ }
+
+ const elementXV = document.getElementById(this._id + '-vx') as HTMLDivElement;
+ const elementYV = document.getElementById(this._id + '-vy') as HTMLDivElement;
+ const elementZV = document.getElementById(this._id + '-vz') as HTMLDivElement;
+ elementXV.innerHTML = this._value.x.toString();
+ elementYV.innerHTML = this._value.y.toString();
+ elementZV.innerHTML = this._value.z.toString();
+ }
+
+ protected _onEnabledChanged() {
+ super._onEnabledChanged();
+
+ LOG(this._label, 'is now enabled', this._isEnabled);
+
+ const keyElements = [
+ document.getElementById(this._id + '-kx') as HTMLDivElement,
+ document.getElementById(this._id + '-ky') as HTMLDivElement,
+ document.getElementById(this._id + '-kz') as HTMLDivElement,
+ ];
+ const valueElements = [
+ document.getElementById(this._id + '-vx') as HTMLDivElement,
+ document.getElementById(this._id + '-vy') as HTMLDivElement,
+ document.getElementById(this._id + '-vz') as HTMLDivElement,
+ ];
+
+ if (this._isEnabled) {
+ for (const keyElement of keyElements) {
+ keyElement.classList.remove('spinbox-key-disabled');
+ }
+ for (const valueElement of valueElements) {
+ valueElement.classList.remove('spinbox-value-disabled');
+ }
+ } else {
+ for (const keyElement of keyElements) {
+ keyElement.classList.add('spinbox-key-disabled');
+ }
+ for (const valueElement of valueElements) {
+ valueElement.classList.add('spinbox-value-disabled');
+ }
+ }
+ }
+}
diff --git a/src/ui/layout.ts b/src/ui/layout.ts
index 3ae37de8..8d9a954b 100644
--- a/src/ui/layout.ts
+++ b/src/ui/layout.ts
@@ -1,564 +1,585 @@
-import { BaseUIElement } from './elements/base';
-import { SliderElement } from './elements/slider';
-import { ComboBoxElement, ComboBoxItem } from './elements/combobox';
-import { FileInputElement } from './elements/file_input';
-import { ButtonElement } from './elements/button';
-import { OutputElement } from './elements/output';
-import { EAction, AppContext } from '../app_context';
-import { ASSERT, ATLASES_DIR, LOG, PALETTES_DIR } from '../util';
-
-import fs from 'fs';
-import { ToolbarItemElement } from './elements/toolbar_item';
-import { EAppEvent } from '../event';
-import { MeshType, Renderer } from '../renderer';
-import { ArcballCamera } from '../camera';
-import { TVoxelisers } from '../voxelisers/voxelisers';
-import { TExporters } from '../exporters/exporters';
-import { TBlockAssigners } from '../block_assigner';
-import { TVoxelOverlapRule } from '../voxel_mesh';
-
-export interface Group {
- label: string;
- elements: { [key: string]: BaseUIElement };
- elementsOrder: string[];
- submitButton: ButtonElement;
- output: OutputElement;
- postElements?: { [key: string]: BaseUIElement };
- postElementsOrder?: string[];
-}
-
-export interface ToolbarGroup {
- elements: { [key: string]: ToolbarItemElement };
- elementsOrder: string[];
-}
-
-export class UI {
- public uiOrder = ['import', 'simplify', 'build', 'assign', 'export'];
- private _ui = {
- 'import': {
- label: 'Import',
- elements: {
- 'input': new FileInputElement('Wavefront .obj file', 'obj'),
- },
- elementsOrder: ['input'],
- submitButton: new ButtonElement('Load mesh', () => {
- this._appContext.do(EAction.Import);
- }),
- output: new OutputElement(),
- },
- 'simplify': {
- label: 'Simplify',
- elements: {
- 'ratio': new SliderElement('Ratio', 0.0, 1.0, 2, 0.5, 0.01),
- },
- elementsOrder: ['ratio'],
- submitButton: new ButtonElement('Simplify mesh', () => {
- this._appContext.do(EAction.Simplify);
- }),
- output: new OutputElement(),
- },
- 'build': {
- label: 'Build',
- elements: {
- 'height': new SliderElement('Desired height', 3, 380, 0, 80, 1),
- 'voxeliser': new ComboBoxElement('Algorithm', [
- {
- id: 'bvh-ray',
- displayText: 'BVH Ray-based',
- },
- {
- id: 'ncrb',
- displayText: 'NCRB',
- },
- {
- id: 'ray-based',
- displayText: 'Ray-based (legacy)',
- },
- ]),
- 'ambientOcclusion': new ComboBoxElement('Ambient occlusion', [
- {
- id: 'on',
- displayText: 'On (recommended)',
- },
- {
- id: 'off',
- displayText: 'Off (faster)',
- },
- ]),
- 'multisampleColouring': new ComboBoxElement('Multisample colouring', [
- {
- id: 'on',
- displayText: 'On (recommended)',
- },
- {
- id: 'off',
- displayText: 'Off (faster)',
- },
- ]),
- 'textureFiltering': new ComboBoxElement('Texture filtering', [
- {
- id: 'linear',
- displayText: 'Linear (recommended)',
- },
- {
- id: 'nearest',
- displayText: 'Nearest (faster)',
- },
- ]),
- 'voxelOverlapRule': new ComboBoxElement('Voxel overlap', [
- {
- id: 'average',
- displayText: 'Average (recommended)',
- tooltip: 'If multiple voxels are placed in the same location, take the average of their colours',
- },
- {
- id: 'first',
- displayText: 'First',
- tooltip: 'If multiple voxels are placed in the same location, use the first voxel\'s colour',
- },
- ]),
- },
- elementsOrder: ['height', 'voxeliser', 'ambientOcclusion', 'multisampleColouring', 'textureFiltering', 'voxelOverlapRule'],
- submitButton: new ButtonElement('Voxelise mesh', () => {
- this._appContext.do(EAction.Voxelise);
- }),
- output: new OutputElement(),
- },
- 'assign': {
- label: 'Assign',
- elements: {
- 'textureAtlas': new ComboBoxElement('Texture atlas', this._getTextureAtlases()),
- 'blockPalette': new ComboBoxElement('Block palette', this._getBlockPalettes()),
- 'dithering': new ComboBoxElement('Dithering', [
- { id: 'ordered-dithering', displayText: 'Ordered' },
- { id: 'random-dithering', displayText: 'Random' },
- { id: 'basic', displayText: 'Off' },
- ]),
- 'colourSpace': new ComboBoxElement('Colour space', [
- { id: 'rgb', displayText: 'RGB (faster)' },
- { id: 'lab', displayText: 'LAB (recommended, slow)' },
- ]),
- 'fallable': new ComboBoxElement('Fallable blocks', [
- {
- id: 'replace-falling',
- displayText: 'Replace falling with solid',
- tooltip: 'Replace all blocks that can fall with solid blocks',
- },
- {
- id: 'replace-fallable',
- displayText: 'Replace fallable with solid',
- tooltip: 'Replace all blocks that will fall with solid blocks',
- },
- /*
- {
- id: 'place-string',
- displayText: 'Place string under',
- tooltip: 'Place string blocks under all blocks that would fall otherwise',
- },
- */
- {
- id: 'do-nothing',
- displayText: 'Do nothing',
- tooltip: 'Let the block fall',
- },
- ]),
- },
- elementsOrder: ['textureAtlas', 'blockPalette', 'dithering', 'colourSpace', 'fallable'],
- submitButton: new ButtonElement('Assign blocks', () => {
- this._appContext.do(EAction.Assign);
- }),
- output: new OutputElement(),
- },
- 'export': {
- label: 'Export',
- elements: {
- 'export': new ComboBoxElement('File format', [
- { id: 'litematic', displayText: 'Litematic (.litematic)' },
- { id: 'schematic', displayText: 'Schematic (.schematic)' },
- { id: 'obj', displayText: 'Wavefront OBJ (.obj)' },
- { id: 'schem', displayText: 'Sponge Schematic (.schem)' },
- { id: 'nbt', displayText: 'Structure blocks (.nbt)' },
- ]),
- },
- elementsOrder: ['export'],
- submitButton: new ButtonElement('Export structure', () => {
- this._appContext.do(EAction.Export);
- }),
- output: new OutputElement(),
- },
- };
-
- private _toolbarLeft = {
- groups: {
- 'viewmode': {
- elements: {
- 'mesh': new ToolbarItemElement('mesh', () => {
- Renderer.Get.setModelToUse(MeshType.TriangleMesh);
- },
- EAppEvent.onModelActiveChanged, (...args: any[]) => {
- const modelUsed = args[0][0][0] as MeshType;
- return modelUsed === MeshType.TriangleMesh;
- },
- EAppEvent.onModelAvailableChanged, (...args: any[]) => {
- const modelType = args[0][0][0] as MeshType;
- const isCached = args[0][0][1] as boolean;
- return modelType >= MeshType.TriangleMesh && isCached;
- }),
-
- 'voxelMesh': new ToolbarItemElement('voxel', () => {
- Renderer.Get.setModelToUse(MeshType.VoxelMesh);
- }, EAppEvent.onModelActiveChanged, (...args: any[]) => {
- const modelUsed = args[0][0][0] as MeshType;
- return modelUsed === MeshType.VoxelMesh;
- }, EAppEvent.onModelAvailableChanged, (...args: any[]) => {
- const modelType = args[0][0][0] as MeshType;
- const isCached = args[0][0][1] as boolean;
- return modelType >= MeshType.VoxelMesh && isCached;
- }),
-
- 'blockMesh': new ToolbarItemElement('block', () => {
- Renderer.Get.setModelToUse(MeshType.BlockMesh);
- }, EAppEvent.onModelActiveChanged, (...args: any[]) => {
- const modelUsed = args[0][0][0] as MeshType;
- return modelUsed === MeshType.BlockMesh;
- }, EAppEvent.onModelAvailableChanged, (...args: any[]) => {
- const modelType = args[0][0][0] as MeshType;
- const isCached = args[0][0][1] as boolean;
- return modelType >= MeshType.BlockMesh && isCached;
- }),
- },
- elementsOrder: ['mesh', 'voxelMesh', 'blockMesh'],
- },
- 'zoom': {
- elements: {
- 'zoomOut': new ToolbarItemElement('minus', () => {
- ArcballCamera.Get.onZoomOut();
- }),
- 'zoomIn': new ToolbarItemElement('plus', () => {
- ArcballCamera.Get.onZoomIn();
- }),
- 'centre': new ToolbarItemElement('centre', () => {
- ArcballCamera.Get.reset();
- }),
- },
- elementsOrder: ['zoomOut', 'zoomIn', 'centre'],
- },
- 'debug': {
- elements: {
- 'grid': new ToolbarItemElement('grid', () => {
- Renderer.Get.toggleIsGridEnabled();
- }, EAppEvent.onGridEnabledChanged, (...args: any[]) => {
- const isEnabled = args[0][0][0] as boolean;
- return isEnabled;
- }, EAppEvent.onModelActiveChanged, (...args: any[]) => {
- return Renderer.Get.getActiveMeshType() !== MeshType.None;
- }),
- 'axes': new ToolbarItemElement('axes', () => {
- Renderer.Get.toggleIsAxesEnabled();
- }, EAppEvent.onAxesEnabledChanged, (...args: any[]) => {
- const isEnabled = args[0][0][0] as boolean;
- return isEnabled;
- }),
- },
- elementsOrder: ['grid', 'axes'],
- },
- },
- groupsOrder: ['viewmode', 'zoom', 'debug'],
- };
-
- private _toolbarRight = {
- groups: {
- 'debug': {
- elements: {
- /*
- 'wireframe': new ToolbarItemElement('wireframe', () => {
- Renderer.Get.toggleIsWireframeEnabled();
- }, EAppEvent.onWireframeEnabledChanged, (...args: any[]) => {
- const isEnabled = args[0][0][0] as boolean;
- return isEnabled;
- }, EAppEvent.onModelActiveChanged, (...args: any[]) => {
- const modelUsed = args[0][0][0] as MeshType;
- return modelUsed === MeshType.TriangleMesh || modelUsed === MeshType.VoxelMesh;
- }),
- 'normals': new ToolbarItemElement('normal', () => {
- Renderer.Get.toggleIsNormalsEnabled();
- }, EAppEvent.onNormalsEnabledChanged, (...args: any[]) => {
- const isEnabled = args[0][0][0] as boolean;
- return isEnabled;
- }, EAppEvent.onModelActiveChanged, (...args: any[]) => {
- const modelUsed = args[0][0][0] as MeshType;
- return modelUsed === MeshType.TriangleMesh;
- }),
- 'dev': new ToolbarItemElement('debug', () => {
- Renderer.Get.toggleIsDevDebugEnabled();
- }, EAppEvent.onDevViewEnabledChanged, (...args: any[]) => {
- const isEnabled = args[0][0][0] as boolean;
- return isEnabled;
- }, EAppEvent.onModelActiveChanged, (...args: any[]) => {
- const modelUsed = args[0][0][0] as MeshType;
- const devBufferAvailable = Renderer.Get.getModelsAvailable() >= 2;
- return modelUsed === MeshType.TriangleMesh && devBufferAvailable;
- }),
- */
- },
- elementsOrder: [], // ['wireframe', 'normals', 'dev'],
- },
- },
- groupsOrder: ['debug'],
- };
-
- private _uiDull: { [key: string]: Group } = this._ui;
- private _toolbarLeftDull: { [key: string]: ToolbarGroup } = this._toolbarLeft.groups;
- private _toolbarRightDull: { [key: string]: ToolbarGroup } = this._toolbarRight.groups;
-
- private _appContext: AppContext;
-
- constructor(appContext: AppContext) {
- this._appContext = appContext;
-
- this._ui.assign.elements.textureAtlas.addDescription('Textures to use and colour-match with');
- this._ui.assign.elements.fallable.addDescription('Read tooltips for more info');
- }
-
- public build() {
- const groupHTML: { [key: string]: string } = {};
- for (const groupName in this._ui) {
- const group = this._uiDull[groupName];
- groupHTML[groupName] = `
-
-
-
- ${group.label.toUpperCase()}
-
-
-
- `;
- groupHTML[groupName] += this._buildGroup(group);
- }
-
- let itemHTML = '';
- for (const groupName of this.uiOrder) {
- itemHTML += groupHTML[groupName];
- }
-
- document.getElementById('properties')!.innerHTML = `
- ` + itemHTML + `
`;
-
- // Build toolbar
- let toolbarHTML = '';
- // Left
- toolbarHTML += '';
- // Right
- toolbarHTML += '';
-
- document.getElementById('toolbar')!.innerHTML = toolbarHTML;
- }
-
- public cacheValues(action: EAction) {
- const group = this._getEActionGroup(action);
- for (const elementName of group.elementsOrder) {
- LOG(`Caching ${elementName}`);
- const element = group.elements[elementName];
- element.cacheValue();
- }
- }
-
- private _buildGroup(group: Group) {
- let groupHTML = '';
- for (const elementName of group.elementsOrder) {
- const element = group.elements[elementName];
- groupHTML += this._buildSubcomponent(element);
- }
-
- let postGroupHTML = '';
- if (group.postElements) {
- ASSERT(group.postElementsOrder, 'No post elements order');
- for (const elementName of group.postElementsOrder) {
- const element = group.postElements[elementName];
- postGroupHTML += this._buildSubcomponent(element);
- }
- }
-
- return `
- ${groupHTML}
-
-
- ${group.submitButton.generateHTML()}
-
-
-
-
- ${group.output.generateHTML()}
-
-
- ${postGroupHTML}
- `;
- }
-
- private _buildSubcomponent(element: BaseUIElement) {
- return `
-
- ${element.generateHTML()}
-
- `;
- }
-
- public registerEvents() {
- for (const groupName in this._ui) {
- const group = this._uiDull[groupName];
- for (const elementName in group.elements) {
- const element = group.elements[elementName];
- element.registerEvents();
- }
- group.submitButton.registerEvents();
- if (group.postElements) {
- ASSERT(group.postElementsOrder);
- for (const elementName in group.postElements) {
- const element = group.postElements[elementName];
- element.registerEvents();
- }
- }
- }
-
- // Register toolbar left
- for (const toolbarGroupName of this._toolbarLeft.groupsOrder) {
- const toolbarGroup = this._toolbarLeftDull[toolbarGroupName];
- for (const groupElementName of toolbarGroup.elementsOrder) {
- toolbarGroup.elements[groupElementName].registerEvents();
- }
- }
- // Register toolbar right
- for (const toolbarGroupName of this._toolbarRight.groupsOrder) {
- const toolbarGroup = this._toolbarRightDull[toolbarGroupName];
- for (const groupElementName of toolbarGroup.elementsOrder) {
- toolbarGroup.elements[groupElementName].registerEvents();
- }
- }
- }
-
- public get layout() {
- return this._ui;
- }
-
- public get layoutDull() {
- return this._uiDull;
- }
-
- public enable(action: EAction) {
- if (action >= EAction.MAX) {
- return;
- }
-
- LOG('enabling', action);
- // TODO: Remove once Simplify has been implemented
- if (action === EAction.Simplify) {
- action = EAction.Voxelise;
- }
- const group = this._getEActionGroup(action);
- for (const compName in group.elements) {
- group.elements[compName].setEnabled(true);
- }
- group.submitButton.setEnabled(true);
- // Enable the post elements of the previous group
- const prevGroup = this._getEActionGroup(action - 1);
- if (prevGroup && prevGroup.postElements) {
- ASSERT(prevGroup.postElementsOrder);
- for (const postElementName in prevGroup.postElements) {
- prevGroup.postElements[postElementName].setEnabled(true);
- }
- }
- }
-
- public disable(action: EAction) {
- if (action < 0) {
- return;
- }
-
- for (let i = action; i < EAction.MAX; ++i) {
- const group = this._getEActionGroup(i);
- LOG('disabling', group.label);
- for (const compName in group.elements) {
- group.elements[compName].setEnabled(false);
- }
- group.submitButton.setEnabled(false);
- group.output.clearMessage();
- if (group.postElements) {
- LOG(group.label, 'has post-element');
- ASSERT(group.postElementsOrder);
- for (const postElementName in group.postElements) {
- LOG('disabling post-element', postElementName, 'for', group.label);
- group.postElements[postElementName].setEnabled(false);
- }
- }
- }
- // Disable the post elements of the previous group
- const prevGroup = this._getEActionGroup(action - 1);
- if (prevGroup && prevGroup.postElements) {
- ASSERT(prevGroup.postElementsOrder);
- for (const postElementName in prevGroup.postElements) {
- prevGroup.postElements[postElementName].setEnabled(false);
- }
- }
- }
-
- private _getEActionGroup(action: EAction): Group {
- const key = this.uiOrder[action];
- return this._uiDull[key];
- }
-
- private _getTextureAtlases(): ComboBoxItem[] {
- const textureAtlases: ComboBoxItem[] = [];
-
- fs.readdirSync(ATLASES_DIR).forEach((file) => {
- if (file.endsWith('.atlas')) {
- const paletteID = file.split('.')[0];
- let paletteName = paletteID.replace('-', ' ').toLowerCase();
- paletteName = paletteName.charAt(0).toUpperCase() + paletteName.slice(1);
- textureAtlases.push({ id: paletteID, displayText: paletteName });
- }
- });
-
- return textureAtlases;
- }
-
- private _getBlockPalettes(): ComboBoxItem[] {
- const blockPalettes: ComboBoxItem[] = [];
-
- fs.readdirSync(PALETTES_DIR).forEach((file) => {
- if (file.endsWith('.palette')) {
- const paletteID = file.split('.')[0];
- let paletteName = paletteID.replace('-', ' ').toLowerCase();
- paletteName = paletteName.charAt(0).toUpperCase() + paletteName.slice(1);
- blockPalettes.push({ id: paletteID, displayText: paletteName });
- }
- });
-
- return blockPalettes;
- }
-}
+import fs from 'fs';
+
+import { AppContext } from '../app_context';
+import { TBlockAssigners } from '../assigners/assigners';
+import { ArcballCamera } from '../camera';
+import { TExporters } from '../exporters/exporters';
+import { PaletteManager } from '../palette';
+import { MeshType, Renderer } from '../renderer';
+import { EAction } from '../util';
+import { ASSERT } from '../util/error_util';
+import { LOG } from '../util/log_util';
+import { AppPaths } from '../util/path_util';
+import { TVoxelOverlapRule } from '../voxel_mesh';
+import { TVoxelisers } from '../voxelisers/voxelisers';
+import { BaseUIElement } from './elements/base';
+import { ButtonElement } from './elements/button';
+import { ComboBoxElement, ComboBoxItem } from './elements/combobox';
+import { FileInputElement } from './elements/file_input';
+import { OutputElement } from './elements/output';
+import { SliderElement } from './elements/slider';
+import { ToolbarItemElement } from './elements/toolbar_item';
+
+export interface Group {
+ label: string;
+ elements: { [key: string]: BaseUIElement };
+ elementsOrder: string[];
+ submitButton: ButtonElement;
+ output: OutputElement;
+ postElements?: { [key: string]: BaseUIElement };
+ postElementsOrder?: string[];
+}
+
+export interface ToolbarGroup {
+ elements: { [key: string]: ToolbarItemElement };
+ elementsOrder: string[];
+}
+
+export class UI {
+ public uiOrder = ['import', 'voxelise', 'assign', 'export'];
+ private _ui = {
+ 'import': {
+ label: 'Import',
+ elements: {
+ 'input': new FileInputElement('Wavefront .obj file', 'obj'),
+ },
+ elementsOrder: ['input'],
+ submitButton: new ButtonElement('Load mesh', () => {
+ this._appContext.do(EAction.Import);
+ }),
+ output: new OutputElement(),
+ },
+ 'voxelise': {
+ label: 'Voxelise',
+ elements: {
+ 'desiredHeight': new SliderElement('Desired height', 3, 380, 0, 80, 1),
+ 'voxeliser': new ComboBoxElement('Algorithm', [
+ {
+ id: 'bvh-ray',
+ displayText: 'BVH Ray-based',
+ },
+ {
+ id: 'ncrb',
+ displayText: 'NCRB',
+ },
+ {
+ id: 'ray-based',
+ displayText: 'Ray-based (legacy)',
+ },
+ ]),
+ 'ambientOcclusion': new ComboBoxElement('Ambient occlusion', [
+ {
+ id: 'on',
+ displayText: 'On (recommended)',
+ },
+ {
+ id: 'off',
+ displayText: 'Off (faster)',
+ },
+ ]),
+ 'multisampleColouring': new ComboBoxElement('Multisampling', [
+ {
+ id: 'on',
+ displayText: 'On (recommended)',
+ },
+ {
+ id: 'off',
+ displayText: 'Off (faster)',
+ },
+ ]),
+ 'textureFiltering': new ComboBoxElement('Texture filtering', [
+ {
+ id: 'linear',
+ displayText: 'Linear (recommended)',
+ },
+ {
+ id: 'nearest',
+ displayText: 'Nearest (faster)',
+ },
+ ]),
+ 'voxelOverlapRule': new ComboBoxElement('Voxel overlap', [
+ {
+ id: 'average',
+ displayText: 'Average (recommended)',
+ tooltip: 'If multiple voxels are placed in the same location, take the average of their colours',
+ },
+ {
+ id: 'first',
+ displayText: 'First',
+ tooltip: 'If multiple voxels are placed in the same location, use the first voxel\'s colour',
+ },
+ ]),
+ },
+ elementsOrder: ['desiredHeight', 'voxeliser', 'ambientOcclusion', 'multisampleColouring', 'textureFiltering', 'voxelOverlapRule'],
+ submitButton: new ButtonElement('Voxelise mesh', () => {
+ this._appContext.do(EAction.Voxelise);
+ }),
+ output: new OutputElement(),
+ },
+ 'assign': {
+ label: 'Assign',
+ elements: {
+ 'textureAtlas': new ComboBoxElement('Texture atlas', this._getTextureAtlases()),
+ 'blockPalette': new ComboBoxElement('Block palette', this._getBlockPalettes()),
+ 'dithering': new ComboBoxElement('Dithering', [
+ { id: 'ordered-dithering', displayText: 'Ordered' },
+ { id: 'random-dithering', displayText: 'Random' },
+ { id: 'basic', displayText: 'Off' },
+ ]),
+ 'fallable': new ComboBoxElement('Fallable blocks', [
+ {
+ id: 'replace-falling',
+ displayText: 'Replace falling with solid',
+ tooltip: 'Replace all blocks that can fall with solid blocks',
+ },
+ {
+ id: 'replace-fallable',
+ displayText: 'Replace fallable with solid',
+ tooltip: 'Replace all blocks that will fall with solid blocks',
+ },
+ /*
+ {
+ id: 'place-string',
+ displayText: 'Place string under',
+ tooltip: 'Place string blocks under all blocks that would fall otherwise',
+ },
+ */
+ {
+ id: 'do-nothing',
+ displayText: 'Do nothing',
+ tooltip: 'Let the block fall',
+ },
+ ]),
+ 'colourAccuracy': new SliderElement('Colour accuracy', 1, 8, 1, 5, 0.1),
+ },
+ elementsOrder: ['textureAtlas', 'blockPalette', 'dithering', 'fallable', 'colourAccuracy'],
+ submitButton: new ButtonElement('Assign blocks', () => {
+ this._appContext.do(EAction.Assign);
+ }),
+ output: new OutputElement(),
+ },
+ 'export': {
+ label: 'Export',
+ elements: {
+ 'export': new ComboBoxElement('File format', [
+ { id: 'litematic', displayText: 'Litematic (.litematic)' },
+ { id: 'schematic', displayText: 'Schematic (.schematic)' },
+ { id: 'obj', displayText: 'Wavefront OBJ (.obj)' },
+ { id: 'schem', displayText: 'Sponge Schematic (.schem)' },
+ { id: 'nbt', displayText: 'Structure blocks (.nbt)' },
+ ]),
+ },
+ elementsOrder: ['export'],
+ submitButton: new ButtonElement('Export structure', () => {
+ this._appContext.do(EAction.Export);
+ }),
+ output: new OutputElement(),
+ },
+ };
+
+ private _toolbarLeft = {
+ groups: {
+ 'viewmode': {
+ elements: {
+ 'mesh': new ToolbarItemElement({ icon: 'mesh' })
+ .onClick(() => {
+ Renderer.Get.setModelToUse(MeshType.TriangleMesh);
+ })
+ .isActive(() => {
+ return Renderer.Get.getActiveMeshType() === MeshType.TriangleMesh;
+ })
+ .isEnabled(() => {
+ return Renderer.Get.getModelsAvailable() >= MeshType.TriangleMesh;
+ }),
+ 'voxelMesh': new ToolbarItemElement({ icon: 'voxel' })
+ .onClick(() => {
+ Renderer.Get.setModelToUse(MeshType.VoxelMesh);
+ })
+ .isActive(() => {
+ return Renderer.Get.getActiveMeshType() === MeshType.VoxelMesh;
+ })
+ .isEnabled(() => {
+ return Renderer.Get.getModelsAvailable() >= MeshType.VoxelMesh;
+ }),
+ 'blockMesh': new ToolbarItemElement({ icon: 'block' })
+ .onClick(() => {
+ Renderer.Get.setModelToUse(MeshType.BlockMesh);
+ })
+ .isActive(() => {
+ return Renderer.Get.getActiveMeshType() === MeshType.BlockMesh;
+ })
+ .isEnabled(() => {
+ return Renderer.Get.getModelsAvailable() >= MeshType.BlockMesh;
+ }),
+ },
+ elementsOrder: ['mesh', 'voxelMesh', 'blockMesh'],
+ },
+ 'debug': {
+ elements: {
+ 'grid': new ToolbarItemElement({ icon: 'grid' })
+ .onClick(() => {
+ Renderer.Get.toggleIsGridEnabled();
+ })
+ .isActive(() => {
+ return Renderer.Get.isGridEnabled();
+ })
+ .isEnabled(() => {
+ return Renderer.Get.getActiveMeshType() !== MeshType.None;
+ }),
+ 'axes': new ToolbarItemElement({ icon: 'axes' })
+ .onClick(() => {
+ Renderer.Get.toggleIsAxesEnabled();
+ })
+ .isActive(() => {
+ return Renderer.Get.isAxesEnabled();
+ }),
+ },
+ elementsOrder: ['grid', 'axes'],
+ },
+
+ },
+ groupsOrder: ['viewmode', 'debug'],
+ };
+
+ private _toolbarRight = {
+ groups: {
+ 'zoom': {
+ elements: {
+ 'zoomOut': new ToolbarItemElement({ icon: 'minus' })
+ .onClick(() => {
+ ArcballCamera.Get.onZoomOut();
+ }),
+ 'zoomIn': new ToolbarItemElement({ icon: 'plus' })
+ .onClick(() => {
+ ArcballCamera.Get.onZoomIn();
+ }),
+ 'reset': new ToolbarItemElement({ icon: 'centre' })
+ .onClick(() => {
+ ArcballCamera.Get.reset();
+ }),
+ },
+ elementsOrder: ['zoomOut', 'zoomIn', 'reset'],
+ },
+ 'camera': {
+ elements: {
+ 'perspective': new ToolbarItemElement({ icon: 'perspective' })
+ .onClick(() => {
+ ArcballCamera.Get.setCameraMode('perspective');
+ })
+ .isActive(() => {
+ return ArcballCamera.Get.isPerspective();
+ }),
+ 'orthographic': new ToolbarItemElement({ icon: 'orthographic' })
+ .onClick(() => {
+ ArcballCamera.Get.setCameraMode('orthographic');
+ })
+ .isActive(() => {
+ return ArcballCamera.Get.isOrthographic();
+ }),
+ 'angleSnap': new ToolbarItemElement({ icon: 'magnet' })
+ .onClick(() => {
+ ArcballCamera.Get.toggleAngleSnap();
+ })
+ .isActive(() => {
+ return ArcballCamera.Get.isAngleSnapEnabled();
+ })
+ .isEnabled(() => {
+ return ArcballCamera.Get.isOrthographic();
+ }),
+
+ },
+ elementsOrder: ['perspective', 'orthographic', 'angleSnap'],
+ },
+ },
+ groupsOrder: ['camera', 'zoom'],
+ };
+
+ private _uiDull: { [key: string]: Group } = this._ui;
+ private _toolbarLeftDull: { [key: string]: ToolbarGroup } = this._toolbarLeft.groups;
+ private _toolbarRightDull: { [key: string]: ToolbarGroup } = this._toolbarRight.groups;
+
+ private _appContext: AppContext;
+
+ constructor(appContext: AppContext) {
+ this._appContext = appContext;
+
+ this._ui.assign.elements.textureAtlas.addDescription('Textures to use and colour-match with');
+ this._ui.assign.elements.fallable.addDescription('Read tooltips for more info');
+ }
+
+ public tick() {
+ for (const groupName in this._toolbarLeftDull) {
+ const toolbarGroup = this._toolbarLeftDull[groupName];
+ for (const toolbarItem of toolbarGroup.elementsOrder) {
+ toolbarGroup.elements[toolbarItem].tick();
+ }
+ }
+
+ for (const groupName in this._toolbarRightDull) {
+ const toolbarGroup = this._toolbarRightDull[groupName];
+ for (const toolbarItem of toolbarGroup.elementsOrder) {
+ toolbarGroup.elements[toolbarItem].tick();
+ }
+ }
+ }
+
+ public build() {
+ const groupHTML: { [key: string]: string } = {};
+ for (const groupName in this._ui) {
+ const group = this._uiDull[groupName];
+ groupHTML[groupName] = `
+
+
+
+ ${group.label.toUpperCase()}
+
+
+
+ `;
+ groupHTML[groupName] += this._buildGroup(group);
+ }
+
+ let itemHTML = '';
+ for (const groupName of this.uiOrder) {
+ itemHTML += groupHTML[groupName];
+ }
+
+ document.getElementById('properties')!.innerHTML = `
+ ` + itemHTML + `
`;
+
+ // Build toolbar
+ let toolbarHTML = '';
+ // Left
+ toolbarHTML += '';
+ // Right
+ toolbarHTML += '';
+
+ document.getElementById('toolbar')!.innerHTML = toolbarHTML;
+ }
+
+ public cacheValues(action: EAction) {
+ const group = this._getEActionGroup(action);
+ for (const elementName of group.elementsOrder) {
+ LOG(`[UI]: Caching ${elementName}`);
+ const element = group.elements[elementName];
+ element.cacheValue();
+ }
+ }
+
+ private _buildGroup(group: Group) {
+ let groupHTML = '';
+ for (const elementName of group.elementsOrder) {
+ const element = group.elements[elementName];
+ groupHTML += this._buildSubcomponent(element);
+ }
+
+ let postGroupHTML = '';
+ if (group.postElements) {
+ ASSERT(group.postElementsOrder, 'No post elements order');
+ for (const elementName of group.postElementsOrder) {
+ const element = group.postElements[elementName];
+ postGroupHTML += this._buildSubcomponent(element);
+ }
+ }
+
+ return `
+ ${groupHTML}
+
+
+ ${group.submitButton.generateHTML()}
+
+
+
+
+ ${group.output.generateHTML()}
+
+
+ ${postGroupHTML}
+ `;
+ }
+
+ private _buildSubcomponent(element: BaseUIElement) {
+ return `
+
+ ${element.generateHTML()}
+
+ `;
+ }
+
+ public getActionOutput(action: EAction) {
+ const group = this._getEActionGroup(action);
+ return group.output;
+ }
+
+ public getActionButton(action: EAction) {
+ const group = this._getEActionGroup(action);
+ return group.submitButton;
+ }
+
+ public registerEvents() {
+ for (const groupName in this._ui) {
+ const group = this._uiDull[groupName];
+ for (const elementName in group.elements) {
+ const element = group.elements[elementName];
+ element.registerEvents();
+ }
+ group.submitButton.registerEvents();
+ if (group.postElements) {
+ ASSERT(group.postElementsOrder);
+ for (const elementName in group.postElements) {
+ const element = group.postElements[elementName];
+ element.registerEvents();
+ }
+ }
+ }
+
+ // Register toolbar left
+ for (const toolbarGroupName of this._toolbarLeft.groupsOrder) {
+ const toolbarGroup = this._toolbarLeftDull[toolbarGroupName];
+ for (const groupElementName of toolbarGroup.elementsOrder) {
+ toolbarGroup.elements[groupElementName].registerEvents();
+ }
+ }
+ // Register toolbar right
+ for (const toolbarGroupName of this._toolbarRight.groupsOrder) {
+ const toolbarGroup = this._toolbarRightDull[toolbarGroupName];
+ for (const groupElementName of toolbarGroup.elementsOrder) {
+ toolbarGroup.elements[groupElementName].registerEvents();
+ }
+ }
+ }
+
+ public get layout() {
+ return this._ui;
+ }
+
+ public get layoutDull() {
+ return this._uiDull;
+ }
+
+ public enableTo(action: EAction) {
+ for (let i = 0; i <= action; ++i) {
+ this.enable(i);
+ }
+ }
+
+ public enable(action: EAction) {
+ if (action >= EAction.MAX) {
+ return;
+ }
+
+ LOG('[UI]: Enabling', action);
+ const group = this._getEActionGroup(action);
+ for (const compName in group.elements) {
+ group.elements[compName].setEnabled(true);
+ }
+ group.submitButton.setEnabled(true);
+ // Enable the post elements of the previous group
+ const prevGroup = this._getEActionGroup(action - 1);
+ if (prevGroup && prevGroup.postElements) {
+ ASSERT(prevGroup.postElementsOrder);
+ for (const postElementName in prevGroup.postElements) {
+ prevGroup.postElements[postElementName].setEnabled(true);
+ }
+ }
+ }
+
+ public disableAll() {
+ this.disable(EAction.Import, false);
+ }
+
+ public disable(action: EAction, clearOutput: boolean = true) {
+ if (action < 0) {
+ return;
+ }
+
+ for (let i = action; i < EAction.MAX; ++i) {
+ const group = this._getEActionGroup(i);
+ //LOG('[UI]: Disabling', group.label);
+ for (const compName in group.elements) {
+ group.elements[compName].setEnabled(false);
+ }
+ group.submitButton.setEnabled(false);
+ if (clearOutput) {
+ group.output.getMessage().clearAll();
+ group.output.updateMessage();
+ }
+ if (group.postElements) {
+ LOG(group.label, 'has post-element');
+ ASSERT(group.postElementsOrder);
+ for (const postElementName in group.postElements) {
+ LOG('disabling post-element', postElementName, 'for', group.label);
+ group.postElements[postElementName].setEnabled(false);
+ }
+ }
+ }
+ // Disable the post elements of the previous group
+ const prevGroup = this._getEActionGroup(action - 1);
+ if (prevGroup && prevGroup.postElements) {
+ ASSERT(prevGroup.postElementsOrder);
+ for (const postElementName in prevGroup.postElements) {
+ prevGroup.postElements[postElementName].setEnabled(false);
+ }
+ }
+ }
+
+ private _getEActionGroup(action: EAction): Group {
+ const key = this.uiOrder[action];
+ return this._uiDull[key];
+ }
+
+ private _getTextureAtlases(): ComboBoxItem[] {
+ const textureAtlases: ComboBoxItem[] = [];
+
+ fs.readdirSync(AppPaths.Get.atlases).forEach((file) => {
+ if (file.endsWith('.atlas')) {
+ const paletteID = file.split('.')[0];
+ let paletteName = paletteID.replace('-', ' ').toLowerCase();
+ paletteName = paletteName.charAt(0).toUpperCase() + paletteName.slice(1);
+ textureAtlases.push({ id: paletteID, displayText: paletteName });
+ }
+ });
+
+ return textureAtlases;
+ }
+
+ private _getBlockPalettes(): ComboBoxItem[] {
+ const blockPalettes: ComboBoxItem[] = [];
+
+ const palettes = PaletteManager.getPalettesInfo();
+ for (const palette of palettes) {
+ blockPalettes.push({
+ id: palette.paletteID,
+ displayText: palette.paletteDisplayName,
+ });
+ }
+
+ return blockPalettes;
+ }
+}
diff --git a/src/ui/misc.ts b/src/ui/misc.ts
index 23bf6028..0c4d1608 100644
--- a/src/ui/misc.ts
+++ b/src/ui/misc.ts
@@ -1,33 +1,102 @@
-export class UIMessageBuilder {
- private _messages: string[];
-
- public constructor() {
- this._messages = [];
- }
-
- public addHeading(message: string) {
- this.addBold(message + ':');
- }
-
- public addBold(...messages: string[]) {
- for (const message of messages) {
- this._messages.push(`${message} `);
- }
- }
-
- public add(...messages: string[]) {
- for (const message of messages) {
- this._messages.push(message);
- }
- }
-
- public addItem(...messages: string[]) {
- for (const message of messages) {
- this._messages.push('• ' + message);
- }
- }
-
- public toString(): string {
- return this._messages.join(' ');
- }
-}
+import { OutputStyle } from './elements/output';
+
+type TMessage = {
+ groupId: string,
+ body: string,
+}
+
+export class UIMessageBuilder {
+ private _messages: TMessage[];
+
+ public constructor() {
+ this._messages = [];
+ }
+
+ public static create() {
+ return new UIMessageBuilder();
+ }
+
+ public addHeading(groupId: string, message: string, style: OutputStyle) {
+ this.addBold(groupId, [message + ':'], style);
+ return this;
+ }
+
+ public addBold(groupId: string, messages: string[], style: OutputStyle) {
+ for (const message of messages) {
+ const cssColourClass = this._getStatusCSSClass(style);
+ this._messages.push({
+ groupId: groupId, body: `
+
+ `});
+ }
+ return this;
+ }
+
+ public addItem(groupId: string, messages: string[], style: OutputStyle) {
+ for (const message of messages) {
+ const cssColourClass = this._getStatusCSSClass(style);
+ this._messages.push({
+ groupId: groupId, body: `
+ - ${message}
+ `});
+ }
+ return this;
+ }
+
+ public addTask(groupId: string, message: string) {
+ this._messages.push({
+ groupId: groupId, body: `
+
+ `});
+ return this;
+ }
+
+ public clear(groupId: string) {
+ this._messages = this._messages.filter((x) => x.groupId !== groupId);
+ return this;
+ }
+
+ public clearAll() {
+ this._messages = [];
+ }
+
+ public toString(): string {
+ // Put together in a flexbox
+ const divs = this._messages
+ .map((x) => x.body)
+ .join('');
+
+ return `
+
+ ${divs}
+
+ `;
+ }
+
+ public static fromString(groupId: string, string: string, style: OutputStyle): UIMessageBuilder {
+ const builder = new UIMessageBuilder();
+ builder.addItem(groupId, [string], style);
+ return builder;
+ }
+
+ public join(builder: UIMessageBuilder) {
+ this._messages.push(...builder._messages);
+ }
+
+ private _getStatusCSSClass(status?: OutputStyle) {
+ switch (status) {
+ case 'success':
+ return 'status-success';
+ case 'warning':
+ return 'status-warning';
+ case 'error':
+ return 'status-error';
+ }
+ }
+}
diff --git a/src/util.ts b/src/util.ts
index 8e1ecaa1..5306b9ab 100644
--- a/src/util.ts
+++ b/src/util.ts
@@ -1,263 +1,57 @@
-import { AppConfig } from './config';
-import { Vector3 } from './vector';
-import { clamp } from './math';
-
-import path from 'path';
-import fs from 'fs';
-
-export class UV {
- public u: number;
- public v: number;
-
- constructor(u: number, v: number) {
- this.u = u;
- this.v = v;
- }
-
- public copy() {
- return new UV(this.u, this.v);
- }
-}
-
-/* eslint-disable */
-export enum ColourSpace {
- RGB,
- LAB
-}
-/* eslint-enable */
-
-export type TOptional = T | undefined;
-
-/**
- * A 3D cuboid volume defined by two opposing corners
- */
-export class Bounds {
- private _min: Vector3;
- private _max: Vector3;
-
- constructor(min: Vector3, max: Vector3) {
- this._min = min;
- this._max = max;
- }
-
- public extendByPoint(point: Vector3) {
- this._min = Vector3.min(this._min, point);
- this._max = Vector3.max(this._max, point);
- }
-
- public extendByVolume(volume: Bounds) {
- this._min = Vector3.min(this._min, volume._min);
- this._max = Vector3.max(this._max, volume._max);
- }
-
- public static getInfiniteBounds() {
- return new Bounds(
- new Vector3(Infinity, Infinity, Infinity),
- new Vector3(-Infinity, -Infinity, -Infinity),
- );
- }
-
- public get min() {
- return this._min;
- }
-
- public get max() {
- return this._max;
- }
-
- public getCentre() {
- const extents = Vector3.sub(this._max, this._min).divScalar(2);
- return Vector3.add(this.min, extents);
- }
-
- public getDimensions() {
- return Vector3.sub(this._max, this._min);
- }
-}
-
-export function ASSERT(condition: any, errorMessage = 'Assertion Failed'): asserts condition {
- if (AppConfig.ASSERTIONS_ENABLED && !condition) {
- throw Error(errorMessage);
- }
-}
-
-/* eslint-disable */
-export const LOG = console.log;
-export const LOG_WARN = console.warn;
-export const LOG_ERROR = console.error;
-export const TIME_START = console.time;
-export const TIME_END = console.timeEnd;
-/* eslint-enable */
-
-/** Regex for non-zero whitespace */
-export const REGEX_NZ_WS = /[ \t]+/;
-
-/** Regex for number */
-export const REGEX_NUMBER = /[0-9eE+\.\-]+/;
-
-export const REGEX_NZ_ANY = /.+/;
-
-export function regexCapture(identifier: string, regex: RegExp) {
- return new RegExp(`(?<${identifier}>${regex.source}`);
-}
-
-export function regexOptional(regex: RegExp) {
- return new RegExp(`(${regex})?`);
-}
-
-export function buildRegex(...args: (string | RegExp)[]) {
- return new RegExp(args.map((r) => {
- if (r instanceof RegExp) {
- return r.source;
- }
- return r;
- }).join(''));
-}
-
-export class AppError extends Error {
- constructor(msg: string) {
- super(msg);
- Object.setPrototypeOf(this, AppError.prototype);
- }
-}
-
-export function fileExists(absolutePath: string) {
- return fs.existsSync(absolutePath);
-}
-
-export class RegExpBuilder {
- private _components: string[];
-
- public constructor() {
- this._components = [];
- }
-
- public add(item: string | RegExp, capture?: string, optional: boolean = false): RegExpBuilder {
- let regex: string;
- if (item instanceof RegExp) {
- regex = item.source;
- } else {
- regex = item;
- }
- if (capture) {
- regex = `(?<${capture}>${regex})`;
- }
- if (optional) {
- regex = `(${regex})?`;
- }
- this._components.push(regex);
- return this;
- }
-
- public addMany(items: (string | RegExp)[], optional: boolean = false): RegExpBuilder {
- let toAdd: string = '';
- for (const item of items) {
- if (item instanceof RegExp) {
- toAdd += item.source;
- } else {
- toAdd += item;
- }
- }
- this._components.push(optional ? `(${toAdd})?` : toAdd);
- return this;
- }
-
- public addNonzeroWhitespace(): RegExpBuilder {
- this.add(REGEX_NZ_WS);
- return this;
- }
-
- public toRegExp(): RegExp {
- return new RegExp(this._components.join(''));
- }
-}
-
-export const BASE_DIR = path.join(__dirname, '/../../');
-export const RESOURCES_DIR = path.join(BASE_DIR, './res/');
-export const ATLASES_DIR = path.join(RESOURCES_DIR, './atlases');
-export const PALETTES_DIR = path.join(RESOURCES_DIR, './palettes/');
-export const STATIC_DIR = path.join(RESOURCES_DIR, './static/');
-export const SHADERS_DIR = path.join(RESOURCES_DIR, './shaders/');
-export const TOOLS_DIR = path.join(BASE_DIR, './tools/');
-export const TESTS_DATA_DIR = path.join(BASE_DIR, './tests/data/');
-
-export function getRandomID(): string {
- return (Math.random() + 1).toString(36).substring(7);
-}
-
-export class SmoothVariable {
- private _actual: number;
- private _target: number;
- private _smoothing: number;
- private _min: number;
- private _max: number;
-
- public constructor(value: number, smoothing: number) {
- this._actual = value;
- this._target = value;
- this._smoothing = smoothing;
- this._min = -Infinity;
- this._max = Infinity;
- }
-
- public setClamp(min: number, max: number) {
- this._min = min;
- this._max = max;
- }
-
- public addToTarget(delta: number) {
- this._target = clamp(this._target + delta, this._min, this._max);
- }
-
- public setTarget(target: number) {
- this._target = target;
- }
-
- public setActual(actual: number) {
- this._actual = actual;
- }
-
- public tick() {
- this._actual += (this._target - this._actual) * this._smoothing;
- }
-
- public getActual() {
- return this._actual;
- }
-
- public getTarget() {
- return this._target;
- }
-}
-
-export class SmoothVectorVariable {
- private _actual: Vector3;
- private _target: Vector3;
- private _smoothing: number;
-
- public constructor(value: Vector3, smoothing: number) {
- this._actual = value;
- this._target = value;
- this._smoothing = smoothing;
- }
-
- public addToTarget(delta: Vector3) {
- this._target = Vector3.add(this._target, delta);
- }
-
- public setTarget(target: Vector3) {
- this._target = target;
- }
-
- public tick() {
- this._actual.add(Vector3.sub(this._target, this._actual).mulScalar(this._smoothing));
- }
-
- public getActual() {
- return this._actual;
- }
-
- public getTarget() {
- return this._target;
- }
-}
+export namespace AppUtil {
+ export namespace Text {
+ export function capitaliseFirstLetter(text: string) {
+ return text.charAt(0).toUpperCase() + text.slice(1);
+ }
+
+ /**
+ * Namespaces a block name if it is not already namespaced
+ * For example `namespaceBlock('stone')` returns `'minecraft:stone'`
+ */
+ export function namespaceBlock(blockName: string): AppTypes.TNamespacedBlockName {
+ // https://minecraft.fandom.com/wiki/Resource_location#Namespaces
+ return blockName.includes(':') ? blockName : ('minecraft:' + blockName);
+ }
+ }
+}
+
+/* eslint-disable */
+export enum EAction {
+ Import = 0,
+ Voxelise = 1,
+ Assign = 2,
+ Export = 3,
+ MAX = 4,
+}
+/* eslint-enable */
+
+export namespace AppTypes {
+ export type TNamespacedBlockName = string;
+}
+
+export class UV {
+ public u: number;
+ public v: number;
+
+ constructor(u: number, v: number) {
+ this.u = u;
+ this.v = v;
+ }
+
+ public copy() {
+ return new UV(this.u, this.v);
+ }
+}
+
+/* eslint-disable */
+export enum ColourSpace {
+ RGB,
+ LAB
+}
+/* eslint-enable */
+
+export type TOptional = T | undefined;
+
+export function getRandomID(): string {
+ return (Math.random() + 1).toString(36).substring(7);
+}
diff --git a/src/util/error_util.ts b/src/util/error_util.ts
new file mode 100644
index 00000000..19038f48
--- /dev/null
+++ b/src/util/error_util.ts
@@ -0,0 +1,13 @@
+export class AppError extends Error {
+ constructor(msg: string) {
+ super(msg);
+ Object.setPrototypeOf(this, AppError.prototype);
+ }
+}
+
+export function ASSERT(condition: any, errorMessage = 'Assertion Failed'): asserts condition {
+ if (!condition) {
+ Error(errorMessage);
+ throw Error(errorMessage);
+ }
+}
diff --git a/src/util/file_util.ts b/src/util/file_util.ts
new file mode 100644
index 00000000..63229552
--- /dev/null
+++ b/src/util/file_util.ts
@@ -0,0 +1,13 @@
+import fs from 'fs';
+
+export namespace FileUtil {
+ export function fileExists(absolutePath: string) {
+ return fs.existsSync(absolutePath);
+ }
+
+ export function mkdirSyncIfNotExist(path: fs.PathLike) {
+ if (!fs.existsSync(path)) {
+ fs.mkdirSync(path);
+ }
+ }
+}
diff --git a/src/util/log_util.ts b/src/util/log_util.ts
new file mode 100644
index 00000000..68f2a4c3
--- /dev/null
+++ b/src/util/log_util.ts
@@ -0,0 +1,247 @@
+import fs from 'fs';
+import util from 'util';
+
+import { AppConfig } from '../config';
+import { FileUtil } from './file_util';
+import { AppPaths, PathUtil } from './path_util';
+
+/**
+ * Logs to console and file if logging `LOG` is enabled.
+ * This should be used for verbose logs.
+ * @see LOG_MAJOR
+ */
+export const LOG = (...data: any[]) => {
+ if (Logger.Get.isLOGEnabled()) {
+ // eslint-disable-next-line no-console
+ console.log(...data);
+ }
+ if (Logger.Get.logToFile) {
+ Logger.Get.logToFile(...data);
+ }
+};
+
+export const LOGF = (...data: any[]) => {
+ if (Logger.Get.logToFile) {
+ Logger.Get.logToFile(...data);
+ }
+};
+
+/**
+ * Logs to console and file if logging `LOG_MAJOR` is enabled.
+ * This is identical to `LOG` but can be enabled/disabled separately.
+ * This should be used for important logs.
+ * @see LOG
+ */
+export const LOG_MAJOR = (...data: any[]) => {
+ if (Logger.Get.isLOGMAJOREnabled()) {
+ // eslint-disable-next-line no-console
+ console.log(...data);
+ }
+ if (Logger.Get.logToFile) {
+ Logger.Get.logToFile(...data);
+ }
+};
+
+/**
+ * Logs a warning to the console and file if logging `LOG_WARN` is enabled.
+ */
+export const LOG_WARN = (...data: any[]) => {
+ if (Logger.Get.isLOGWARNEnabled()) {
+ // eslint-disable-next-line no-console
+ console.warn(...data);
+ }
+ if (Logger.Get.logToFile) {
+ Logger.Get.logToFile(...data);
+ }
+};
+
+/**
+ * Starts a timer.
+ * @see `TIME_END` To stop the timer.
+ * @param label The ID of this timer.
+ */
+export const TIME_START = (label: string) => {
+ if (Logger.Get.isLOGTIMEEnabled()) {
+ // eslint-disable-next-line no-console
+ console.time(label);
+ }
+};
+
+/**
+ * Stops a timer and prints the time elapsed. Not logged to file.
+ * @see `TIME_START` To start the timer.
+ * @param label The ID of this timer.
+ */
+export const TIME_END = (label: string) => {
+ if (Logger.Get.isLOGTIMEEnabled()) {
+ // eslint-disable-next-line no-console
+ console.timeEnd(label);
+ }
+};
+
+/**
+ * Logs an error to the console and file, always.
+ */
+export const LOG_ERROR = (...data: any[]) => {
+ // eslint-disable-next-line no-console
+ console.error(...data);
+ if (Logger.Get.logToFile) {
+ Logger.Get.logToFile(...data);
+ }
+};
+
+/**
+ * Logger controls enable/disabling the logging functions above.
+ */
+export class Logger {
+ /* Singleton */
+ private static _instance: Logger;
+ public static get Get() {
+ return this._instance || (this._instance = new this());
+ }
+
+ private _enabledLOG: boolean;
+ private _enabledLOGMAJOR: boolean;
+ private _enabledLOGWARN: boolean;
+ private _enabledLOGTIME: boolean;
+
+ private _enabledLogToFile?: boolean;
+
+ private _logStream?: fs.WriteStream;
+
+ private constructor() {
+ this._enabledLOG = false;
+ this._enabledLOGMAJOR = false;
+ this._enabledLOGWARN = false;
+ this._enabledLOGTIME = false;
+ }
+
+ /**
+ * Setup the log file.
+ * @param suffix The suffix to append to the end of the log file name.
+ */
+ public initLogFile(suffix: string) {
+ if (this._logStream === undefined && this._enabledLogToFile === true) {
+ FileUtil.mkdirSyncIfNotExist(AppPaths.Get.logs);
+ this._logStream = fs.createWriteStream(PathUtil.join(AppPaths.Get.logs, `./${Date.now()}-${suffix}.log`));
+ }
+ }
+
+ /**
+ * Logs to the log file if setup.
+ * @param data The data to print.
+ */
+ public logToFile(...data: any[]) {
+ if (this._logStream && this._enabledLogToFile) {
+ this._logStream.write(`[${(new Date()).toISOString()}] ${util.format(...data)}\n`);
+ }
+ }
+
+ /**
+ * Allow `LOG` calls to be printed to the console and to the log file if setup.
+ */
+ public enableLOG() {
+ this._enabledLOG = true;
+ }
+
+ /**
+ * Prevent `LOG` calls to be printed to the console and to the log file if setup.
+ */
+ public disableLOG() {
+ this._enabledLOG = false;
+ }
+
+ /**
+ * Allow `LOG_MAJOR` calls to be printed to the console and to the log file if setup.
+ */
+ public enableLOGMAJOR() {
+ this._enabledLOGMAJOR = true;
+ }
+
+ /**
+ * Prevent `LOG_MAJOR` calls to be printed to the console and to the log file if setup.
+ */
+ public disableLOGMAJOR() {
+ this._enabledLOGMAJOR = false;
+ }
+
+ /**
+ * Allow `LOG_WARN` calls to be printed to the console and to the log file if setup.
+ */
+ public enableLOGWARN() {
+ this._enabledLOGWARN = true;
+ }
+
+ /**
+ * Prevent `LOG_WARN` calls to be printed to the console and to the log file if setup.
+ */
+ public disableLOGWARN() {
+ this._enabledLOGWARN = false;
+ }
+
+ /**
+ * Allow `TIME_START`/`TIME_END` calls to be printed to the console and to the log file if setup.
+ */
+ public enableLOGTIME() {
+ this._enabledLOGTIME = true;
+ }
+
+ /**
+ * Prevent `TIME_START`/`TIME_END` calls to be printed to the console and to the log file if setup.
+ */
+ public disableLOGTIME() {
+ this._enabledLOGTIME = false;
+ }
+
+ /**
+ * Allow console log calls to logged to the log file if setup.
+ * Should be called before `initLogFile`
+ */
+ public enableLogToFile() {
+ if (AppConfig.Get.LOG_TO_FILE && this._enabledLogToFile === undefined) {
+ this._enabledLogToFile = true;
+ }
+ }
+
+ /**
+ * Prevent console log calls to logged to the log file if setup.
+ */
+ public disableLogToFile() {
+ this._enabledLogToFile = false;
+ }
+
+ /**
+ * Whether or not `LOG` calls should be printed to the console and log file.
+ */
+ public isLOGEnabled() {
+ return this._enabledLOG;
+ }
+
+ /**
+ * Whether or not `LOG_MAJOR` calls should be printed to the console and log file.
+ */
+ public isLOGMAJOREnabled() {
+ return this._enabledLOGMAJOR;
+ }
+
+ /**
+ * Whether or not `LOG_WARN` calls should be printed to the console and log file.
+ */
+ public isLOGWARNEnabled() {
+ return this._enabledLOGWARN;
+ }
+
+ /**
+ * Whether or not `TIME_START`/`TIME_END` calls should be printed to the console and log file.
+ */
+ public isLOGTIMEEnabled() {
+ return this._enabledLOGTIME;
+ }
+
+ /**
+ * Whether or not console log calls should be logged to the log file if setup.
+ */
+ public isLogToFileEnabled() {
+ return this.logToFile;
+ }
+}
diff --git a/src/util/math_util.ts b/src/util/math_util.ts
new file mode 100644
index 00000000..2bdc5223
--- /dev/null
+++ b/src/util/math_util.ts
@@ -0,0 +1,18 @@
+export namespace MathUtil {
+
+ export function uint8(x: number) {
+ return x & 0xFF;
+ }
+
+ export function int8(x: number) {
+ return uint8(x + 0x80) - 0x80;
+ }
+
+ export function uint32(x: number) {
+ return x >>> 0;
+ }
+
+ export function int32(x: number) {
+ return uint32(x + 0x80000000) - 0x80000000;
+ }
+}
diff --git a/src/util/nbt_util.ts b/src/util/nbt_util.ts
index 99d99673..2f3821f7 100644
--- a/src/util/nbt_util.ts
+++ b/src/util/nbt_util.ts
@@ -1,21 +1,14 @@
-import { ASSERT } from '../util';
-
-import path from 'path';
-import { NBT, writeUncompressed } from 'prismarine-nbt';
-import zlib from 'zlib';
-import fs from 'fs';
-
-export function saveNBT(nbt: NBT, filepath: string) {
- ASSERT(path.isAbsolute(filepath), '[saveNBT]: filepath is not absolute');
-
- const outBuffer = fs.createWriteStream(filepath);
- const newBuffer = writeUncompressed(nbt, 'big');
-
- zlib.gzip(newBuffer, (err, buffer) => {
- if (!err) {
- outBuffer.write(buffer);
- outBuffer.end();
- }
- return err;
- });
-}
+import fs from 'fs';
+import path from 'path';
+import { NBT, writeUncompressed } from 'prismarine-nbt';
+import zlib from 'zlib';
+
+import { ASSERT } from './error_util';
+
+export function saveNBT(nbt: NBT, filepath: string) {
+ ASSERT(path.isAbsolute(filepath), '[saveNBT]: filepath is not absolute');
+
+ const uncompressedBuffer = writeUncompressed(nbt, 'big');
+ const compressedBuffer = zlib.gzipSync(uncompressedBuffer);
+ fs.writeFileSync(filepath, compressedBuffer);
+}
diff --git a/src/util/path_util.ts b/src/util/path_util.ts
new file mode 100644
index 00000000..4918fa67
--- /dev/null
+++ b/src/util/path_util.ts
@@ -0,0 +1,67 @@
+import path from 'path';
+
+export namespace PathUtil {
+ export function join(...paths: string[]) {
+ return path.join(...paths);
+ }
+}
+
+export class AppPaths {
+ /* Singleton */
+ private static _instance: AppPaths;
+ public static get Get() {
+ return this._instance || (this._instance = new this());
+ }
+
+ private _base: string;
+
+ private constructor() {
+ this._base = PathUtil.join(__dirname, '../../..');
+ }
+
+ public setBaseDir(dir: string) {
+ this._base = dir;
+ //const parsed = path.parse(dir);
+ //ASSERT(parsed.base === 'ObjToSchematic', `AppPaths: Not correct base ${dir}`);
+ }
+
+ public get base() {
+ return this._base;
+ }
+
+ public get resources() {
+ return PathUtil.join(this._base, './res/');
+ }
+
+ public get tools() {
+ return PathUtil.join(this._base, './tools/');
+ }
+
+ public get tests() {
+ return PathUtil.join(this._base, './tests/');
+ }
+
+ public get testData() {
+ return PathUtil.join(this._base, './tests/data/');
+ }
+
+ public get atlases() {
+ return PathUtil.join(this.resources, './atlases/');
+ }
+
+ public get palettes() {
+ return PathUtil.join(this.resources, './palettes/');
+ }
+
+ public get static() {
+ return PathUtil.join(this.resources, './static/');
+ }
+
+ public get shaders() {
+ return PathUtil.join(this.resources, './shaders/');
+ }
+
+ public get logs() {
+ return PathUtil.join(this._base, './logs/');
+ }
+}
diff --git a/src/util/regex_util.ts b/src/util/regex_util.ts
new file mode 100644
index 00000000..eea9aeab
--- /dev/null
+++ b/src/util/regex_util.ts
@@ -0,0 +1,71 @@
+/** Regex for non-zero whitespace */
+export const REGEX_NZ_WS = /[ \t]+/;
+
+/** Regex for number */
+export const REGEX_NUMBER = /[0-9eE+\.\-]+/;
+
+export const REGEX_NZ_ANY = /.+/;
+
+export function regexCapture(identifier: string, regex: RegExp) {
+ return new RegExp(`(?<${identifier}>${regex.source}`);
+}
+
+export function regexOptional(regex: RegExp) {
+ return new RegExp(`(${regex})?`);
+}
+
+export function buildRegex(...args: (string | RegExp)[]) {
+ return new RegExp(args.map((r) => {
+ if (r instanceof RegExp) {
+ return r.source;
+ }
+ return r;
+ }).join(''));
+}
+
+export class RegExpBuilder {
+ private _components: string[];
+
+ public constructor() {
+ this._components = [];
+ }
+
+ public add(item: string | RegExp, capture?: string, optional: boolean = false): RegExpBuilder {
+ let regex: string;
+ if (item instanceof RegExp) {
+ regex = item.source;
+ } else {
+ regex = item;
+ }
+ if (capture) {
+ regex = `(?<${capture}>${regex})`;
+ }
+ if (optional) {
+ regex = `(${regex})?`;
+ }
+ this._components.push(regex);
+ return this;
+ }
+
+ public addMany(items: (string | RegExp)[], optional: boolean = false): RegExpBuilder {
+ let toAdd: string = '';
+ for (const item of items) {
+ if (item instanceof RegExp) {
+ toAdd += item.source;
+ } else {
+ toAdd += item;
+ }
+ }
+ this._components.push(optional ? `(${toAdd})?` : toAdd);
+ return this;
+ }
+
+ public addNonzeroWhitespace(): RegExpBuilder {
+ this.add(REGEX_NZ_WS);
+ return this;
+ }
+
+ public toRegExp(): RegExp {
+ return new RegExp(this._components.join(''));
+ }
+}
diff --git a/src/vector.ts b/src/vector.ts
index 7cc3337c..497ce630 100644
--- a/src/vector.ts
+++ b/src/vector.ts
@@ -1,254 +1,266 @@
-import { IHashable } from './hash_map';
-import { ASSERT } from './util';
-
-export class Vector3 implements IHashable {
- public x: number;
- public y: number;
- public z: number;
-
- constructor(x: number, y: number, z: number) {
- this.x = x;
- this.y = y;
- this.z = z;
- }
-
- public set(x: number, y: number, z: number) {
- this.x = x;
- this.y = y;
- this.z = z;
- }
-
- public setFrom(vec: Vector3) {
- this.x = vec.x;
- this.y = vec.y;
- this.z = vec.z;
- }
-
- static fromArray(arr: number[]) {
- ASSERT(arr.length === 3);
- return new Vector3(arr[0], arr[1], arr[2]);
- }
-
- toArray() {
- return [this.x, this.y, this.z];
- }
-
- static random() {
- return new Vector3(
- Math.random(),
- Math.random(),
- Math.random(),
- );
- }
-
- static parse(line: string) {
- const regex = /[+-]?\d+(\.\d+)?/g;
- const floats = line.match(regex)!.map(function(v) {
- return parseFloat(v);
- });
-
- return new Vector3(
- floats[0], floats[1], floats[2],
- );
- }
-
- public static copy(vec: Vector3) {
- return new Vector3(
- vec.x,
- vec.y,
- vec.z,
- );
- }
-
- public static add(vec: Vector3, toAdd: (Vector3 | number)) {
- return Vector3.copy(vec).add(toAdd);
- }
-
- public static sub(vec: Vector3, toAdd: (Vector3 | number)) {
- return Vector3.copy(vec).sub(toAdd);
- }
-
- public add(toAdd: (Vector3 | number)) {
- if (toAdd instanceof Vector3) {
- this.x += toAdd.x;
- this.y += toAdd.y;
- this.z += toAdd.z;
- return this;
- } else {
- this.x += toAdd;
- this.y += toAdd;
- this.z += toAdd;
- return this;
- }
- }
-
- public sub(toAdd: (Vector3 | number)) {
- if (toAdd instanceof Vector3) {
- this.x -= toAdd.x;
- this.y -= toAdd.y;
- this.z -= toAdd.z;
- return this;
- } else {
- this.x -= toAdd;
- this.y -= toAdd;
- this.z -= toAdd;
- return this;
- }
- }
-
- static dot(vecA: Vector3, vecB: Vector3) {
- return vecA.x * vecB.x + vecA.y * vecB.y + vecA.z * vecB.z;
- }
-
- public copy() {
- return Vector3.copy(this);
- }
-
- static mulScalar(vec: Vector3, scalar: number) {
- return new Vector3(
- scalar * vec.x,
- scalar * vec.y,
- scalar * vec.z,
- );
- }
-
- mulScalar(scalar: number) {
- this.x *= scalar;
- this.y *= scalar;
- this.z *= scalar;
- return this;
- }
-
- static divScalar(vec: Vector3, scalar: number) {
- return new Vector3(
- vec.x / scalar,
- vec.y / scalar,
- vec.z / scalar,
- );
- }
-
- divScalar(scalar: number) {
- this.x /= scalar;
- this.y /= scalar;
- this.z /= scalar;
- return this;
- }
-
- static lessThanEqualTo(vecA: Vector3, vecB: Vector3) {
- return vecA.x <= vecB.x && vecA.y <= vecB.y && vecA.z <= vecB.z;
- }
-
- static round(vec: Vector3) {
- return new Vector3(
- Math.round(vec.x),
- Math.round(vec.y),
- Math.round(vec.z),
- );
- }
-
- round() {
- this.x = Math.round(this.x);
- this.y = Math.round(this.y);
- this.z = Math.round(this.z);
- return this;
- }
-
- static abs(vec: Vector3) {
- return new Vector3(
- Math.abs(vec.x),
- Math.abs(vec.y),
- Math.abs(vec.z),
- );
- }
-
- static cross(vecA: Vector3, vecB: Vector3) {
- return new Vector3(
- vecA.y * vecB.z - vecA.z * vecB.y,
- vecA.z * vecB.x - vecA.x * vecB.z,
- vecA.x * vecB.y - vecA.y * vecB.x,
- );
- }
-
- static min(vecA: Vector3, vecB: Vector3) {
- return new Vector3(
- Math.min(vecA.x, vecB.x),
- Math.min(vecA.y, vecB.y),
- Math.min(vecA.z, vecB.z),
- );
- }
-
- static max(vecA: Vector3, vecB: Vector3) {
- return new Vector3(
- Math.max(vecA.x, vecB.x),
- Math.max(vecA.y, vecB.y),
- Math.max(vecA.z, vecB.z),
- );
- }
-
- magnitude() {
- return Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2) + Math.pow(this.z, 2));
- }
-
- normalise() {
- const mag = this.magnitude();
- this.x /= mag;
- this.y /= mag;
- this.z /= mag;
-
- return this;
- }
-
- public static get xAxis() {
- return new Vector3(1.0, 0.0, 0.0);
- }
-
- public static get yAxis() {
- return new Vector3(0.0, 1.0, 0.0);
- }
-
- public static get zAxis() {
- return new Vector3(0.0, 0.0, 1.0);
- }
-
- public isNumber() {
- return !isNaN(this.x) && !isNaN(this.y) && !isNaN(this.z);
- }
-
- public negate() {
- this.x = -this.x;
- this.y = -this.y;
- this.z = -this.z;
- return this;
- }
-
- public floor() {
- this.x = Math.floor(this.x);
- this.y = Math.floor(this.y);
- this.z = Math.floor(this.z);
- return this;
- }
-
- public ceil() {
- this.x = Math.ceil(this.x);
- this.y = Math.ceil(this.y);
- this.z = Math.ceil(this.z);
- return this;
- }
-
- // Begin IHashable interface
- public hash() {
- const p0 = 73856093;
- const p1 = 19349663;
- const p2 = 83492791;
- return (this.x * p0) ^ (this.y * p1) ^ (this.z * p2);
- }
-
- public equals(other: Vector3) {
- return this.x == other.x && this.y == other.y && this.z == other.z;
- }
- // End IHashable interface
-
- public stringify() {
- return `${this.x}_${this.y}_${this.z}`;
- }
-}
+import { IHashable } from './hash_map';
+import { ASSERT } from './util/error_util';
+
+export class Vector3 implements IHashable {
+ public x: number;
+ public y: number;
+ public z: number;
+
+ constructor(x: number, y: number, z: number) {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ public set(x: number, y: number, z: number) {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ public setFrom(vec: Vector3) {
+ this.x = vec.x;
+ this.y = vec.y;
+ this.z = vec.z;
+ }
+
+ static fromArray(arr: number[]) {
+ ASSERT(arr.length === 3);
+ return new Vector3(arr[0], arr[1], arr[2]);
+ }
+
+ toArray() {
+ return [this.x, this.y, this.z];
+ }
+
+ static random() {
+ return new Vector3(
+ Math.random(),
+ Math.random(),
+ Math.random(),
+ );
+ }
+
+ static parse(line: string) {
+ const regex = /[+-]?\d+(\.\d+)?/g;
+ const floats = line.match(regex)!.map(function(v) {
+ return parseFloat(v);
+ });
+
+ return new Vector3(
+ floats[0], floats[1], floats[2],
+ );
+ }
+
+ public static copy(vec: Vector3) {
+ return new Vector3(
+ vec.x,
+ vec.y,
+ vec.z,
+ );
+ }
+
+ public static add(vec: Vector3, toAdd: (Vector3 | number)) {
+ return Vector3.copy(vec).add(toAdd);
+ }
+
+ public static sub(vec: Vector3, toAdd: (Vector3 | number)) {
+ return Vector3.copy(vec).sub(toAdd);
+ }
+
+ public add(toAdd: (Vector3 | number)) {
+ if (toAdd instanceof Vector3) {
+ this.x += toAdd.x;
+ this.y += toAdd.y;
+ this.z += toAdd.z;
+ return this;
+ } else {
+ this.x += toAdd;
+ this.y += toAdd;
+ this.z += toAdd;
+ return this;
+ }
+ }
+
+ public sub(toAdd: (Vector3 | number)) {
+ if (toAdd instanceof Vector3) {
+ this.x -= toAdd.x;
+ this.y -= toAdd.y;
+ this.z -= toAdd.z;
+ return this;
+ } else {
+ this.x -= toAdd;
+ this.y -= toAdd;
+ this.z -= toAdd;
+ return this;
+ }
+ }
+
+ static dot(vecA: Vector3, vecB: Vector3) {
+ return vecA.x * vecB.x + vecA.y * vecB.y + vecA.z * vecB.z;
+ }
+
+ public copy() {
+ return Vector3.copy(this);
+ }
+
+ static mulScalar(vec: Vector3, scalar: number) {
+ return new Vector3(
+ scalar * vec.x,
+ scalar * vec.y,
+ scalar * vec.z,
+ );
+ }
+
+ mulScalar(scalar: number) {
+ this.x *= scalar;
+ this.y *= scalar;
+ this.z *= scalar;
+ return this;
+ }
+
+ static divScalar(vec: Vector3, scalar: number) {
+ return new Vector3(
+ vec.x / scalar,
+ vec.y / scalar,
+ vec.z / scalar,
+ );
+ }
+
+ divScalar(scalar: number) {
+ this.x /= scalar;
+ this.y /= scalar;
+ this.z /= scalar;
+ return this;
+ }
+
+ static lessThanEqualTo(vecA: Vector3, vecB: Vector3) {
+ return vecA.x <= vecB.x && vecA.y <= vecB.y && vecA.z <= vecB.z;
+ }
+
+ static round(vec: Vector3) {
+ return new Vector3(
+ Math.round(vec.x),
+ Math.round(vec.y),
+ Math.round(vec.z),
+ );
+ }
+
+ round() {
+ this.x = Math.round(this.x);
+ this.y = Math.round(this.y);
+ this.z = Math.round(this.z);
+ return this;
+ }
+
+ static abs(vec: Vector3) {
+ return new Vector3(
+ Math.abs(vec.x),
+ Math.abs(vec.y),
+ Math.abs(vec.z),
+ );
+ }
+
+ static cross(vecA: Vector3, vecB: Vector3) {
+ return new Vector3(
+ vecA.y * vecB.z - vecA.z * vecB.y,
+ vecA.z * vecB.x - vecA.x * vecB.z,
+ vecA.x * vecB.y - vecA.y * vecB.x,
+ );
+ }
+
+ static min(vecA: Vector3, vecB: Vector3) {
+ return new Vector3(
+ Math.min(vecA.x, vecB.x),
+ Math.min(vecA.y, vecB.y),
+ Math.min(vecA.z, vecB.z),
+ );
+ }
+
+ static max(vecA: Vector3, vecB: Vector3) {
+ return new Vector3(
+ Math.max(vecA.x, vecB.x),
+ Math.max(vecA.y, vecB.y),
+ Math.max(vecA.z, vecB.z),
+ );
+ }
+
+ magnitude() {
+ return Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2) + Math.pow(this.z, 2));
+ }
+
+ normalise() {
+ const mag = this.magnitude();
+ this.x /= mag;
+ this.y /= mag;
+ this.z /= mag;
+
+ return this;
+ }
+
+ public static get xAxis() {
+ return new Vector3(1.0, 0.0, 0.0);
+ }
+
+ public static get yAxis() {
+ return new Vector3(0.0, 1.0, 0.0);
+ }
+
+ public static get zAxis() {
+ return new Vector3(0.0, 0.0, 1.0);
+ }
+
+ public isNumber() {
+ return !isNaN(this.x) && !isNaN(this.y) && !isNaN(this.z);
+ }
+
+ public negate() {
+ this.x = -this.x;
+ this.y = -this.y;
+ this.z = -this.z;
+ return this;
+ }
+
+ public floor() {
+ this.x = Math.floor(this.x);
+ this.y = Math.floor(this.y);
+ this.z = Math.floor(this.z);
+ return this;
+ }
+
+ public ceil() {
+ this.x = Math.ceil(this.x);
+ this.y = Math.ceil(this.y);
+ this.z = Math.ceil(this.z);
+ return this;
+ }
+
+ // Begin IHashable interface
+ public hash() {
+ const p0 = 73856093;
+ const p1 = 19349663;
+ const p2 = 83492791;
+ return (this.x * p0) ^ (this.y * p1) ^ (this.z * p2);
+ }
+
+ public equals(other: Vector3) {
+ return this.x == other.x && this.y == other.y && this.z == other.z;
+ }
+ // End IHashable interface
+
+ public stringify() {
+ return `${this.x}_${this.y}_${this.z}`;
+ }
+}
+
+export const fastCrossXAxis = (vec: Vector3) => {
+ return new Vector3(0.0, -vec.z, vec.y);
+};
+
+export const fastCrossYAxis = (vec: Vector3) => {
+ return new Vector3(vec.z, 0.0, -vec.x);
+};
+
+export const fastCrossZAxis = (vec: Vector3) => {
+ return new Vector3(-vec.y, vec.x, 0.0);
+};
diff --git a/src/voxel_mesh.ts b/src/voxel_mesh.ts
index 52727e82..e31df278 100644
--- a/src/voxel_mesh.ts
+++ b/src/voxel_mesh.ts
@@ -1,221 +1,185 @@
-import { AttributeData } from './buffer';
-import { RGBA } from './colour';
-import { AppConstants } from './constants';
-import { GeometryTemplates } from './geometry';
-import { HashMap } from './hash_map';
-import { OcclusionManager } from './occlusion';
-import { ASSERT, Bounds, TOptional } from './util';
-import { Vector3 } from './vector';
-
-export interface Voxel {
- position: Vector3;
- colour: RGBA;
- collisions: number;
-}
-
-export type TVoxelOverlapRule = 'first' | 'average';
-
-/** These are the parameters required to create a Voxel Mesh */
-export type VoxelMeshParams = {
- voxelOverlapRule: TVoxelOverlapRule,
- calculateNeighbours: boolean,
-}
-
-export class VoxelMesh {
- private _voxels: (Voxel & { collisions: number })[];
- private _voxelsHash: HashMap;
- private _bounds: Bounds;
- private _neighbourMap: Map;
- private _voxelMeshParams: VoxelMeshParams;
-
- public constructor(voxelMeshParams: VoxelMeshParams) {
- this._voxels = [];
- this._voxelsHash = new HashMap(2048);
- this._neighbourMap = new Map();
- this._bounds = Bounds.getInfiniteBounds();
- this._voxelMeshParams = voxelMeshParams;
- }
-
- public getVoxels() {
- return this._voxels;
- }
-
- public isVoxelAt(pos: Vector3) {
- return this._voxelsHash.has(pos);
- }
-
- public getVoxelAt(pos: Vector3): TOptional {
- const voxelIndex = this._voxelsHash.get(pos);
- if (voxelIndex !== undefined) {
- return this._voxels[voxelIndex];
- }
- }
-
- public addVoxel(pos: Vector3, colour: RGBA) {
- if (colour.a === 0) {
- return;
- }
-
- pos.round();
-
- const voxelIndex = this._voxelsHash.get(pos);
- if (voxelIndex !== undefined) {
- // A voxel at this position already exists
- const voxel = this._voxels[voxelIndex];
- voxel.colour.r = ((voxel.colour.r * voxel.collisions) + colour.r) / (voxel.collisions + 1);
- voxel.colour.g = ((voxel.colour.g * voxel.collisions) + colour.g) / (voxel.collisions + 1);
- voxel.colour.b = ((voxel.colour.b * voxel.collisions) + colour.b) / (voxel.collisions + 1);
- voxel.colour.a = ((voxel.colour.a * voxel.collisions) + colour.a) / (voxel.collisions + 1);
- ++voxel.collisions;
- } else {
- // This is a new voxel
- this._voxels.push({
- position: pos,
- colour: colour,
- collisions: 1,
- });
- this._voxelsHash.add(pos, this._voxels.length - 1);
- this._bounds.extendByPoint(pos);
- this._updateNeighbours(pos);
- }
- }
-
- public getBounds() {
- return this._bounds;
- }
-
- public getVoxelCount() {
- return this._voxels.length;
- }
-
- private _neighbours = [
- new Vector3(1, 1, -1),
- new Vector3(0, 1, -1),
- new Vector3(-1, 1, -1),
- new Vector3(1, 0, -1),
- new Vector3(-1, 0, -1),
- new Vector3(1, -1, -1),
- new Vector3(0, -1, -1),
- new Vector3(-1, -1, -1),
- new Vector3(1, 1, 0),
- new Vector3(-1, 1, 0),
- new Vector3(1, -1, 0),
- new Vector3(-1, -1, 0),
- new Vector3(1, 1, 1),
- new Vector3(0, 1, 1),
- new Vector3(-1, 1, 1),
- new Vector3(1, 0, 1),
- new Vector3(-1, 0, 1),
- new Vector3(1, -1, 1),
- new Vector3(0, -1, 1),
- new Vector3(-1, -1, 1),
- ];
-
- private _updateNeighbours(pos: Vector3) {
- if (this._voxelMeshParams.calculateNeighbours) {
- for (const neighbourOffset of this._neighbours) {
- const neighbour = Vector3.add(pos, neighbourOffset);
- const inverseOffset = neighbourOffset.copy().negate();
- const inverseIndex = OcclusionManager.getNeighbourIndex(inverseOffset);
- // ASSERT(inverseIndex >= 0 && inverseIndex < 27);
- const neighbourData = this.getNeighbours(neighbour);
- neighbourData.value |= (1 << inverseIndex);
- // ASSERT((this.getNeighbours(neighbour).value & (1 << inverseIndex)) !== 0);
- }
- }
- }
-
- private _stringified: string = '';
- public getNeighbours(pos: Vector3) {
- ASSERT(this._voxelMeshParams.calculateNeighbours, 'Calculate neighbours is disabled');
-
- this._stringified = pos.stringify();
- const neighbours = this._neighbourMap.get(this._stringified);
- if (neighbours === undefined) {
- this._neighbourMap.set(this._stringified, { value: 0 });
- return this._neighbourMap.get(this._stringified)!;
- } else {
- return neighbours;
- }
- }
-
- public getNeighbourhoodMap() {
- return this._neighbourMap;
- }
-
- /*
- * Returns true if a voxel at position 'pos' has a neighbour with offset 'offset'
- * Offset must be a vector that exists within this._neighbours defined above
- */
- public hasNeighbour(pos: Vector3, offset: Vector3): boolean {
- return (this.getNeighbours(pos).value & (1 << OcclusionManager.getNeighbourIndex(offset))) > 0;
- }
-
- // //////////////////////////////////////////////////////////////////////////
-
- public createBuffer(enableAmbientOcclusion: boolean) {
- const numVoxels = this._voxels.length;
- const newBuffer = {
- position: {
- numComponents: AppConstants.ComponentSize.POSITION,
- data: new Float32Array(numVoxels * AppConstants.VoxelMeshBufferComponentOffsets.POSITION),
- },
- colour: {
- numComponents: AppConstants.ComponentSize.COLOUR,
- data: new Float32Array(numVoxels * AppConstants.VoxelMeshBufferComponentOffsets.COLOUR),
- },
- occlusion: {
- numComponents: AppConstants.ComponentSize.OCCLUSION,
- data: new Float32Array(numVoxels * AppConstants.VoxelMeshBufferComponentOffsets.OCCLUSION).fill(1.0),
- },
- texcoord: {
- numComponents: AppConstants.ComponentSize.TEXCOORD,
- data: new Float32Array(numVoxels * AppConstants.VoxelMeshBufferComponentOffsets.TEXCOORD),
- },
- normal: {
- numComponents: AppConstants.ComponentSize.NORMAL,
- data: new Float32Array(numVoxels * AppConstants.VoxelMeshBufferComponentOffsets.NORMAL),
- },
- indices: {
- numComponents: AppConstants.ComponentSize.INDICES,
- data: new Uint32Array(numVoxels * AppConstants.VoxelMeshBufferComponentOffsets.INDICES),
- },
- };
-
- const cube: AttributeData = GeometryTemplates.getBoxBufferData(new Vector3(0, 0, 0));
- for (let i = 0; i < numVoxels; ++i) {
- const voxel = this._voxels[i];
- const voxelColourArray = [voxel.colour.r, voxel.colour.g, voxel.colour.b, voxel.colour.a];
- const voxelPositionArray = voxel.position.toArray();
-
- for (let j = 0; j < AppConstants.VoxelMeshBufferComponentOffsets.POSITION; ++j) {
- newBuffer.position.data[i * AppConstants.VoxelMeshBufferComponentOffsets.POSITION + j] = cube.custom.position[j] + voxelPositionArray[j % 3];
- }
-
- for (let j = 0; j < AppConstants.VoxelMeshBufferComponentOffsets.COLOUR; ++j) {
- newBuffer.colour.data[i * AppConstants.VoxelMeshBufferComponentOffsets.COLOUR + j] = voxelColourArray[j % 4];
- }
-
- for (let j = 0; j < AppConstants.VoxelMeshBufferComponentOffsets.NORMAL; ++j) {
- newBuffer.normal.data[i * AppConstants.VoxelMeshBufferComponentOffsets.NORMAL + j] = cube.custom.normal[j];
- }
-
- for (let j = 0; j < AppConstants.VoxelMeshBufferComponentOffsets.TEXCOORD; ++j) {
- newBuffer.texcoord.data[i * AppConstants.VoxelMeshBufferComponentOffsets.TEXCOORD + j] = cube.custom.texcoord[j];
- }
-
- for (let j = 0; j < AppConstants.VoxelMeshBufferComponentOffsets.INDICES; ++j) {
- newBuffer.indices.data[i * AppConstants.VoxelMeshBufferComponentOffsets.INDICES + j] = cube.indices[j] + (i * AppConstants.INDICES_PER_VOXEL);
- }
-
- if (enableAmbientOcclusion) {
- const voxelOcclusionArray = OcclusionManager.Get.getOcclusions(voxel.position, this);
- for (let j = 0; j < AppConstants.VoxelMeshBufferComponentOffsets.OCCLUSION; ++j) {
- newBuffer.occlusion.data[i * AppConstants.VoxelMeshBufferComponentOffsets.OCCLUSION + j] = voxelOcclusionArray[j];
- }
- }
- }
-
- return newBuffer;
- }
-}
+import { Bounds } from './bounds';
+import { ChunkedBufferGenerator, TVoxelMeshBufferDescription } from './buffer';
+import { RGBA } from './colour';
+import { OcclusionManager } from './occlusion';
+import { TOptional } from './util';
+import { ASSERT } from './util/error_util';
+import { LOGF } from './util/log_util';
+import { Vector3 } from './vector';
+import { RenderNextVoxelMeshChunkParams, VoxeliseParams } from './worker_types';
+
+export interface Voxel {
+ position: Vector3;
+ colour: RGBA;
+ collisions: number;
+}
+
+export type TVoxelOverlapRule = 'first' | 'average';
+
+export type TVoxelMeshParams = Pick;
+
+export class VoxelMesh {
+ private _voxels: (Voxel & { collisions: number })[];
+ private _voxelsHash: Map;
+ private _bounds: Bounds;
+ private _neighbourMap: Map;
+ private _voxelMeshParams: TVoxelMeshParams;
+
+ public constructor(voxelMeshParams: TVoxelMeshParams) {
+ this._voxels = [];
+ this._voxelsHash = new Map();
+ this._neighbourMap = new Map();
+ this._bounds = Bounds.getInfiniteBounds();
+ this._voxelMeshParams = voxelMeshParams;
+ this._recreateBuffer = true;
+ }
+
+ public getVoxels() {
+ return this._voxels;
+ }
+
+ public isVoxelAt(pos: Vector3) {
+ return this._voxelsHash.has(pos.stringify());
+ }
+
+ public getVoxelAt(pos: Vector3): TOptional {
+ const voxelIndex = this._voxelsHash.get(pos.stringify());
+ if (voxelIndex !== undefined) {
+ const voxel = this._voxels[voxelIndex];
+ ASSERT(voxel !== undefined);
+ return voxel;
+ }
+ }
+
+ public addVoxel(pos: Vector3, colour: RGBA) {
+ if (colour.a === 0) {
+ return;
+ }
+
+ pos.round();
+
+ const voxelIndex = this._voxelsHash.get(pos.stringify());
+ if (voxelIndex !== undefined) {
+ // A voxel at this position already exists
+ const voxel = this._voxels[voxelIndex];
+ voxel.colour.r = ((voxel.colour.r * voxel.collisions) + colour.r) / (voxel.collisions + 1);
+ voxel.colour.g = ((voxel.colour.g * voxel.collisions) + colour.g) / (voxel.collisions + 1);
+ voxel.colour.b = ((voxel.colour.b * voxel.collisions) + colour.b) / (voxel.collisions + 1);
+ voxel.colour.a = ((voxel.colour.a * voxel.collisions) + colour.a) / (voxel.collisions + 1);
+ ++voxel.collisions;
+ } else {
+ // This is a new voxel
+ this._voxels.push({
+ position: pos,
+ colour: colour,
+ collisions: 1,
+ });
+ this._voxelsHash.set(pos.stringify(), this._voxels.length - 1);
+ this._bounds.extendByPoint(pos);
+ this._updateNeighbours(pos);
+ }
+ }
+
+ public getBounds() {
+ return this._bounds;
+ }
+
+ public getVoxelCount() {
+ return this._voxels.length;
+ }
+
+ private _neighbours = [
+ new Vector3(1, 1, -1),
+ new Vector3(0, 1, -1),
+ new Vector3(-1, 1, -1),
+ new Vector3(1, 0, -1),
+ new Vector3(-1, 0, -1),
+ new Vector3(1, -1, -1),
+ new Vector3(0, -1, -1),
+ new Vector3(-1, -1, -1),
+ new Vector3(1, 1, 0),
+ new Vector3(-1, 1, 0),
+ new Vector3(1, -1, 0),
+ new Vector3(-1, -1, 0),
+ new Vector3(1, 1, 1),
+ new Vector3(0, 1, 1),
+ new Vector3(-1, 1, 1),
+ new Vector3(1, 0, 1),
+ new Vector3(-1, 0, 1),
+ new Vector3(1, -1, 1),
+ new Vector3(0, -1, 1),
+ new Vector3(-1, -1, 1),
+ ];
+
+ private _updateNeighbours(pos: Vector3) {
+ if (this._voxelMeshParams.enableAmbientOcclusion) {
+ for (const neighbourOffset of this._neighbours) {
+ const neighbour = Vector3.add(pos, neighbourOffset);
+ const inverseOffset = neighbourOffset.copy().negate();
+ const inverseIndex = OcclusionManager.getNeighbourIndex(inverseOffset);
+ // ASSERT(inverseIndex >= 0 && inverseIndex < 27);
+ const neighbourData = this.getNeighbours(neighbour);
+ neighbourData.value |= (1 << inverseIndex);
+ // ASSERT((this.getNeighbours(neighbour).value & (1 << inverseIndex)) !== 0);
+ }
+ }
+ }
+
+ private _stringified: string = '';
+ public getNeighbours(pos: Vector3) {
+ ASSERT(this._voxelMeshParams.enableAmbientOcclusion, 'Ambient occlusion is disabled');
+
+ this._stringified = pos.stringify();
+ const neighbours = this._neighbourMap.get(this._stringified);
+ if (neighbours === undefined) {
+ this._neighbourMap.set(this._stringified, { value: 0 });
+ return this._neighbourMap.get(this._stringified)!;
+ } else {
+ return neighbours;
+ }
+ }
+
+ public getNeighbourhoodMap() {
+ return this._neighbourMap;
+ }
+
+ /*
+ * Returns true if a voxel at position 'pos' has a neighbour with offset 'offset'
+ * Offset must be a vector that exists within this._neighbours defined above
+ */
+ public hasNeighbour(pos: Vector3, offset: Vector3): boolean {
+ return (this.getNeighbours(pos).value & (1 << OcclusionManager.getNeighbourIndex(offset))) > 0;
+ }
+
+ private _renderParams?: RenderNextVoxelMeshChunkParams.Input;
+ private _recreateBuffer: boolean;
+ public setRenderParams(params: RenderNextVoxelMeshChunkParams.Input) {
+ this._renderParams = params;
+ this._recreateBuffer = true;
+ this._bufferChunks = [];
+ }
+
+ /*
+ private _buffer?: TVoxelMeshBufferDescription;
+ public getBuffer(): TVoxelMeshBufferDescription {
+ ASSERT(this._renderParams, 'Called VoxelMesh.getBuffer() without setting render params');
+ if (this._buffer === undefined || this._recreateBuffer) {
+ this._buffer = BufferGenerator.fromVoxelMesh(this, this._renderParams);
+ this._recreateBuffer = false;
+ }
+ return this._buffer;
+ }
+ */
+
+ private _bufferChunks: Array = [];
+ public getChunkedBuffer(chunkIndex: number): TVoxelMeshBufferDescription & { moreVoxelsToBuffer: boolean, progress: number } {
+ ASSERT(this._renderParams, 'Called VoxelMesh.getChunkedBuffer() without setting render params');
+ if (this._bufferChunks[chunkIndex] === undefined) {
+ LOGF(`[VoxelMesh]: getChunkedBuffer: ci: ${chunkIndex} not cached`);
+ this._bufferChunks[chunkIndex] = ChunkedBufferGenerator.fromVoxelMesh(this, this._renderParams, chunkIndex);
+ } else {
+ LOGF(`[VoxelMesh]: getChunkedBuffer: ci: ${chunkIndex} cached`);
+ }
+ return this._bufferChunks[chunkIndex];
+ }
+}
diff --git a/src/voxelisers/base-voxeliser.ts b/src/voxelisers/base-voxeliser.ts
index b4fee3fd..773b8a41 100644
--- a/src/voxelisers/base-voxeliser.ts
+++ b/src/voxelisers/base-voxeliser.ts
@@ -1,46 +1,46 @@
-import { UVTriangle, Triangle } from '../triangle';
-import { UV } from '../util';
-import { Vector3 } from '../vector';
-import { Mesh } from '../mesh';
-import { VoxelMesh } from '../voxel_mesh';
-import { TextureFiltering } from '../texture';
-import { StatusHandler } from '../status';
-import { RGBA } from '../colour';
-import { VoxeliseParams } from './voxelisers';
-
-export abstract class IVoxeliser {
- public voxelise(mesh: Mesh, voxeliseParams: VoxeliseParams): VoxelMesh {
- const voxelMesh = this._voxelise(mesh, voxeliseParams);
-
- StatusHandler.Get.add('info', `Voxel mesh has ${voxelMesh.getVoxelCount().toLocaleString()} voxels`);
-
- const dim = voxelMesh.getBounds().getDimensions().add(1);
- StatusHandler.Get.add('info', `Dimensions are ${dim.x.toLocaleString()}x${dim.y.toLocaleString()}x${dim.z.toLocaleString()} voxels`);
-
- return voxelMesh;
- }
-
- protected abstract _voxelise(mesh: Mesh, voxeliseParams: VoxeliseParams): VoxelMesh;
-
- protected _getVoxelColour(mesh: Mesh, triangle: UVTriangle, materialName: string, location: Vector3, filtering: TextureFiltering): (RGBA | undefined) {
- const area01 = new Triangle(triangle.v0, triangle.v1, location).getArea();
- const area12 = new Triangle(triangle.v1, triangle.v2, location).getArea();
- const area20 = new Triangle(triangle.v2, triangle.v0, location).getArea();
- const total = area01 + area12 + area20;
-
- const w0 = area12 / total;
- const w1 = area20 / total;
- const w2 = area01 / total;
-
- const uv = new UV(
- triangle.uv0.u * w0 + triangle.uv1.u * w1 + triangle.uv2.u * w2,
- triangle.uv0.v * w0 + triangle.uv1.v * w1 + triangle.uv2.v * w2,
- );
-
- if (isNaN(uv.u) || isNaN(uv.v)) {
- return undefined;
- }
-
- return mesh.sampleMaterial(materialName, uv, filtering);
- }
-}
+import { RGBA } from '../colour';
+import { Mesh } from '../mesh';
+import { StatusHandler } from '../status';
+import { TextureFiltering } from '../texture';
+import { Triangle, UVTriangle } from '../triangle';
+import { UV } from '../util';
+import { Vector3 } from '../vector';
+import { VoxelMesh } from '../voxel_mesh';
+import { VoxeliseParams } from '../worker_types';
+
+export abstract class IVoxeliser {
+ public voxelise(mesh: Mesh, voxeliseParams: VoxeliseParams.Input): VoxelMesh {
+ const voxelMesh = this._voxelise(mesh, voxeliseParams);
+
+ StatusHandler.Get.add('info', `Voxel mesh has ${voxelMesh.getVoxelCount().toLocaleString()} voxels`);
+
+ const dim = voxelMesh.getBounds().getDimensions().add(1);
+ StatusHandler.Get.add('info', `Dimensions are ${dim.x.toLocaleString()}x${dim.y.toLocaleString()}x${dim.z.toLocaleString()} voxels`);
+
+ return voxelMesh;
+ }
+
+ protected abstract _voxelise(mesh: Mesh, voxeliseParams: VoxeliseParams.Input): VoxelMesh;
+
+ protected _getVoxelColour(mesh: Mesh, triangle: UVTriangle, materialName: string, location: Vector3, filtering: TextureFiltering): (RGBA | undefined) {
+ const area01 = new Triangle(triangle.v0, triangle.v1, location).getArea();
+ const area12 = new Triangle(triangle.v1, triangle.v2, location).getArea();
+ const area20 = new Triangle(triangle.v2, triangle.v0, location).getArea();
+ const total = area01 + area12 + area20;
+
+ const w0 = area12 / total;
+ const w1 = area20 / total;
+ const w2 = area01 / total;
+
+ const uv = new UV(
+ triangle.uv0.u * w0 + triangle.uv1.u * w1 + triangle.uv2.u * w2,
+ triangle.uv0.v * w0 + triangle.uv1.v * w1 + triangle.uv2.v * w2,
+ );
+
+ if (isNaN(uv.u) || isNaN(uv.v)) {
+ return undefined;
+ }
+
+ return mesh.sampleMaterial(materialName, uv, filtering);
+ }
+}
diff --git a/src/voxelisers/bvh-ray-voxeliser.ts b/src/voxelisers/bvh-ray-voxeliser.ts
index fd6c0889..28237ba0 100644
--- a/src/voxelisers/bvh-ray-voxeliser.ts
+++ b/src/voxelisers/bvh-ray-voxeliser.ts
@@ -1,103 +1,111 @@
-import { VoxelMesh } from '../voxel_mesh';
-import { Mesh } from '../mesh';
-import { Axes, axesToDirection, Ray } from '../ray';
-import { ASSERT, LOG } from '../util';
-import { Vector3 } from '../vector';
-import { IVoxeliser } from './base-voxeliser';
-import { VoxeliseParams } from './voxelisers';
-
-const bvhtree = require('bvh-tree');
-
-/**
- * This voxeliser works by projecting rays onto each triangle
- * on each of the principle angles and testing for intersections
- */
-export class BVHRayVoxeliser extends IVoxeliser {
- protected override _voxelise(mesh: Mesh, voxeliseParams: VoxeliseParams): VoxelMesh {
- const voxelMesh = new VoxelMesh(voxeliseParams);
- const scale = (voxeliseParams.desiredHeight - 1) / Mesh.desiredHeight;
- const offset = (voxeliseParams.desiredHeight % 2 === 0) ? new Vector3(0.0, 0.5, 0.0) : new Vector3(0.0, 0.0, 0.0);
- const useMesh = mesh.copy(); // TODO: Voxelise without copying mesh, too expensive for dense meshes
-
- useMesh.scaleMesh(scale);
- useMesh.translateMesh(offset);
-
- // Build BVH
- const triangles = Array<{x: Number, y: Number, z: Number}[]>(useMesh._tris.length);
- for (let triIndex = 0; triIndex < useMesh.getTriangleCount(); ++triIndex) {
- const positionData = useMesh.getVertices(triIndex);
- triangles[triIndex] = [positionData.v0, positionData.v1, positionData.v2];
- }
-
- const MAX_TRIANGLES_PER_NODE = 8;
- LOG('Creating BVH...');
- const bvh = new bvhtree.BVH(triangles, MAX_TRIANGLES_PER_NODE);
- LOG('BVH created...');
-
- // Generate rays
- const bounds = useMesh.getBounds();
- bounds.min.floor();
- bounds.max.ceil();
-
- const planeDims = Vector3.sub(bounds.max, bounds.min).add(1);
- const numRays = (planeDims.x * planeDims.y) + (planeDims.x * planeDims.z) + (planeDims.y * planeDims.z);
- const rays = new Array(numRays);
- let rayIndex = 0;
- {
- // Generate x-plane rays
- for (let y = bounds.min.y; y <= bounds.max.y; ++y) {
- for (let z = bounds.min.z; z <= bounds.max.z; ++z) {
- rays[rayIndex++] = {
- origin: new Vector3(bounds.min.x - 1, y, z),
- axis: Axes.x,
- };
- }
- }
- // Generate y-plane rays
- for (let x = bounds.min.x; x <= bounds.max.x; ++x) {
- for (let z = bounds.min.z; z <= bounds.max.z; ++z) {
- rays[rayIndex++] = {
- origin: new Vector3(x, bounds.min.y - 1, z),
- axis: Axes.y,
- };
- }
- }
- // Generate z-plane rays
- for (let x = bounds.min.x; x <= bounds.max.x; ++x) {
- for (let y = bounds.min.y; y <= bounds.max.y; ++y) {
- rays[rayIndex++] = {
- origin: new Vector3(x, y, bounds.min.z - 1),
- axis: Axes.z,
- };
- }
- }
- }
- ASSERT(rays.length === rayIndex);
- LOG('Rays created...');
-
- // Ray test BVH
- for (rayIndex = 0; rayIndex < rays.length; ++rayIndex) {
- const ray = rays[rayIndex];
- const intersections = bvh.intersectRay(ray.origin, axesToDirection(ray.axis), false);
- for (const intersection of intersections) {
- const point = intersection.intersectionPoint;
- const position = new Vector3(point.x, point.y, point.z);
- position.round();
-
- const voxelColour = this._getVoxelColour(
- mesh,
- useMesh.getUVTriangle(intersection.triangleIndex),
- useMesh.getMaterialByTriangle(intersection.triangleIndex),
- position,
- voxeliseParams.textureFiltering,
- );
-
- if (voxelColour) {
- voxelMesh.addVoxel(position, voxelColour);
- }
- }
- }
-
- return voxelMesh;
- }
-}
+import { Mesh } from '../mesh';
+import { ProgressManager } from '../progress';
+import { Axes, axesToDirection, Ray } from '../ray';
+import { ASSERT } from '../util/error_util';
+import { LOG } from '../util/log_util';
+import { Vector3 } from '../vector';
+import { VoxelMesh } from '../voxel_mesh';
+import { VoxeliseParams } from '../worker_types';
+import { IVoxeliser } from './base-voxeliser';
+
+const bvhtree = require('bvh-tree');
+
+/**
+ * This voxeliser works by projecting rays onto each triangle
+ * on each of the principle angles and testing for intersections
+ */
+export class BVHRayVoxeliser extends IVoxeliser {
+ protected override _voxelise(mesh: Mesh, voxeliseParams: VoxeliseParams.Input): VoxelMesh {
+ const voxelMesh = new VoxelMesh(voxeliseParams);
+ const scale = (voxeliseParams.desiredHeight - 1) / Mesh.desiredHeight;
+ const offset = (voxeliseParams.desiredHeight % 2 === 0) ? new Vector3(0.0, 0.5, 0.0) : new Vector3(0.0, 0.0, 0.0);
+
+ mesh.setTransform((vertex: Vector3) => {
+ return vertex.copy().mulScalar(scale).add(offset);
+ });
+
+ // Build BVH
+ const triangles = Array<{ x: Number, y: Number, z: Number }[]>(mesh._tris.length);
+ for (let triIndex = 0; triIndex < mesh.getTriangleCount(); ++triIndex) {
+ const positionData = mesh.getVertices(triIndex);
+ triangles[triIndex] = [positionData.v0, positionData.v1, positionData.v2];
+ }
+
+ const MAX_TRIANGLES_PER_NODE = 8;
+ LOG('Creating BVH...');
+ const bvh = new bvhtree.BVH(triangles, MAX_TRIANGLES_PER_NODE);
+ LOG('BVH created...');
+
+ // Generate rays
+ const bounds = mesh.getBounds();
+ bounds.min.floor();
+ bounds.max.ceil();
+
+ const planeDims = Vector3.sub(bounds.max, bounds.min).add(1);
+ const numRays = (planeDims.x * planeDims.y) + (planeDims.x * planeDims.z) + (planeDims.y * planeDims.z);
+ const rays = new Array(numRays);
+ let rayIndex = 0;
+ {
+ // Generate x-plane rays
+ for (let y = bounds.min.y; y <= bounds.max.y; ++y) {
+ for (let z = bounds.min.z; z <= bounds.max.z; ++z) {
+ rays[rayIndex++] = {
+ origin: new Vector3(bounds.min.x - 1, y, z),
+ axis: Axes.x,
+ };
+ }
+ }
+ // Generate y-plane rays
+ for (let x = bounds.min.x; x <= bounds.max.x; ++x) {
+ for (let z = bounds.min.z; z <= bounds.max.z; ++z) {
+ rays[rayIndex++] = {
+ origin: new Vector3(x, bounds.min.y - 1, z),
+ axis: Axes.y,
+ };
+ }
+ }
+ // Generate z-plane rays
+ for (let x = bounds.min.x; x <= bounds.max.x; ++x) {
+ for (let y = bounds.min.y; y <= bounds.max.y; ++y) {
+ rays[rayIndex++] = {
+ origin: new Vector3(x, y, bounds.min.z - 1),
+ axis: Axes.z,
+ };
+ }
+ }
+ }
+ ASSERT(rays.length === rayIndex);
+ LOG('Rays created...');
+
+ // Ray test BVH
+ const taskHandle = ProgressManager.Get.start('Voxelising');
+ for (rayIndex = 0; rayIndex < rays.length; ++rayIndex) {
+ ProgressManager.Get.progress(taskHandle, rayIndex / rays.length);
+
+ const ray = rays[rayIndex];
+ const intersections = bvh.intersectRay(ray.origin, axesToDirection(ray.axis), false);
+ for (const intersection of intersections) {
+ const point = intersection.intersectionPoint;
+ const position = new Vector3(point.x, point.y, point.z);
+ position.round();
+
+ const voxelColour = this._getVoxelColour(
+ mesh,
+ mesh.getUVTriangle(intersection.triangleIndex),
+ mesh.getMaterialByTriangle(intersection.triangleIndex),
+ position,
+ voxeliseParams.textureFiltering,
+ );
+
+ if (voxelColour) {
+ voxelMesh.addVoxel(position, voxelColour);
+ }
+ }
+ }
+ ProgressManager.Get.end(taskHandle);
+
+ mesh.clearTransform();
+
+ return voxelMesh;
+ }
+}
diff --git a/src/voxelisers/normal-corrected-ray-voxeliser.ts b/src/voxelisers/normal-corrected-ray-voxeliser.ts
index 27cc206a..139eccbc 100644
--- a/src/voxelisers/normal-corrected-ray-voxeliser.ts
+++ b/src/voxelisers/normal-corrected-ray-voxeliser.ts
@@ -1,168 +1,177 @@
-import { VoxelMesh } from '../voxel_mesh';
-import { AppConfig } from '../config';
-import { Mesh } from '../mesh';
-import { Axes, Ray, rayIntersectTriangle } from '../ray';
-import { Triangle, UVTriangle } from '../triangle';
-import { Bounds, UV } from '../util';
-import { Vector3 } from '../vector';
-import { IVoxeliser } from './base-voxeliser';
-import { RGBA, RGBAUtil } from '../colour';
-import { VoxeliseParams } from './voxelisers';
-
-/**
- * This voxeliser works by projecting rays onto each triangle
- * on each of the principle angles and testing for intersections
- */
-export class NormalCorrectedRayVoxeliser extends IVoxeliser {
- private _mesh?: Mesh;
- private _voxelMesh?: VoxelMesh;
- private _voxeliseParams?: VoxeliseParams;
- private _scale!: number;
- private _size!: Vector3;
- private _offset!: Vector3;
-
- protected override _voxelise(mesh: Mesh, voxeliseParams: VoxeliseParams): VoxelMesh {
- this._mesh = mesh;
- this._voxelMesh = new VoxelMesh(voxeliseParams);
- this._voxeliseParams = voxeliseParams;
-
- this._scale = (voxeliseParams.desiredHeight) / Mesh.desiredHeight;
- const useMesh = mesh.copy(); // TODO: Voxelise without copying mesh, too expensive for dense meshes
-
- useMesh.scaleMesh(this._scale);
- const bounds = useMesh.getBounds();
- this._size = Vector3.sub(bounds.max, bounds.min);
- this._offset =new Vector3(
- this._size.x % 2 < 0.001 ? 0.5 : 0.0,
- this._size.y % 2 < 0.001 ? 0.5 : 0.0,
- this._size.z % 2 < 0.001 ? 0.5 : 0.0,
- );
-
- for (let triIndex = 0; triIndex < useMesh.getTriangleCount(); ++triIndex) {
- const uvTriangle = useMesh.getUVTriangle(triIndex);
- const normals = useMesh.getNormals(triIndex);
- const material = useMesh.getMaterialByTriangle(triIndex);
- this._voxeliseTri(uvTriangle, material, normals);
- }
-
- return this._voxelMesh;
- }
-
- private _voxeliseTri(triangle: UVTriangle, materialName: string, normals: { v0: Vector3, v1: Vector3, v2: Vector3}) {
- const rayList = this._generateRays(triangle.v0, triangle.v1, triangle.v2,
- this._offset,
- );
-
- rayList.forEach((ray) => {
- const intersection = rayIntersectTriangle(ray, triangle.v0, triangle.v1, triangle.v2);
- if (intersection) {
- // Move transition away from normal
- const norm = normals.v0.normalise();
- intersection.sub(Vector3.mulScalar(norm, 0.5));
- // Correct size parity
- intersection.add(this._offset);
-
- let voxelPosition: Vector3;
- switch (ray.axis) {
- case Axes.x:
- voxelPosition = new Vector3(Math.round(intersection.x), intersection.y, intersection.z);
- break;
- case Axes.y:
- voxelPosition = new Vector3(intersection.x, Math.round(intersection.y), intersection.z);
- break;
- case Axes.z:
- voxelPosition = new Vector3(intersection.x, intersection.y, Math.round(intersection.z));
- break;
- }
- voxelPosition.round();
-
- let voxelColour: RGBA;
- if (this._voxeliseParams!.useMultisampleColouring) {
- const samples: RGBA[] = [];
- for (let i = 0; i < AppConfig.MULTISAMPLE_COUNT; ++i) {
- const samplePosition = Vector3.add(voxelPosition, Vector3.random().add(-0.5));
- samples.push(this.__getVoxelColour(triangle, materialName, samplePosition));
- }
- voxelColour = RGBAUtil.average(...samples);
- } else {
- voxelColour = this.__getVoxelColour(triangle, materialName, voxelPosition);
- }
-
- this._voxelMesh!.addVoxel(voxelPosition, voxelColour);
- }
- });
- }
-
- // TODO: Remove
- private __getVoxelColour(triangle: UVTriangle, materialName: string, location: Vector3): RGBA {
- const area01 = new Triangle(triangle.v0, triangle.v1, location).getArea();
- const area12 = new Triangle(triangle.v1, triangle.v2, location).getArea();
- const area20 = new Triangle(triangle.v2, triangle.v0, location).getArea();
- const total = area01 + area12 + area20;
-
- const w0 = area12 / total;
- const w1 = area20 / total;
- const w2 = area01 / total;
-
- const uv = new UV(
- triangle.uv0.u * w0 + triangle.uv1.u * w1 + triangle.uv2.u * w2,
- triangle.uv0.v * w0 + triangle.uv1.v * w1 + triangle.uv2.v * w2,
- );
-
- return this._mesh!.sampleMaterial(materialName, uv, this._voxeliseParams!.textureFiltering);
- }
-
- private _generateRays(v0: Vector3, v1: Vector3, v2: Vector3, offset: Vector3): Array {
- const bounds: Bounds = new Bounds(
- new Vector3(
- Math.ceil(Math.min(v0.x, v1.x, v2.x)),
- Math.ceil(Math.min(v0.y, v1.y, v2.y)),
- Math.ceil(Math.min(v0.z, v1.z, v2.z)),
- ),
- new Vector3(
- Math.floor(Math.max(v0.x, v1.x, v2.x)),
- Math.floor(Math.max(v0.y, v1.y, v2.y)),
- Math.floor(Math.max(v0.z, v1.z, v2.z)),
- ),
- );
-
- const rayList: Array = [];
- this._traverseX(rayList, bounds, offset);
- this._traverseY(rayList, bounds, offset);
- this._traverseZ(rayList, bounds, offset);
- return rayList;
- }
-
- private _traverseX(rayList: Array, bounds: Bounds, offset: Vector3) {
- for (let y = bounds.min.y - offset.y; y <= bounds.max.y + offset.y; ++y) {
- for (let z = bounds.min.z - offset.z; z <= bounds.max.z + offset.z; ++z) {
- rayList.push({
- origin: new Vector3(bounds.min.x - 1, y, z),
- axis: Axes.x,
- });
- }
- }
- }
-
- private _traverseY(rayList: Array, bounds: Bounds, offset: Vector3) {
- for (let x = bounds.min.x - offset.x; x <= bounds.max.x + offset.x; ++x) {
- for (let z = bounds.min.z - offset.z; z <= bounds.max.z + offset.z; ++z) {
- rayList.push({
- origin: new Vector3(x, bounds.min.y - 1, z),
- axis: Axes.y,
- });
- }
- }
- }
-
- private _traverseZ(rayList: Array, bounds: Bounds, offset: Vector3) {
- for (let x = bounds.min.x - offset.x; x <= bounds.max.x + offset.x; ++x) {
- for (let y = bounds.min.y - offset.y; y <= bounds.max.y + offset.y; ++y) {
- rayList.push({
- origin: new Vector3(x, y, bounds.min.z - 1),
- axis: Axes.z,
- });
- }
- }
- }
-}
+import { Bounds } from '../bounds';
+import { RGBA, RGBAUtil } from '../colour';
+import { AppConfig } from '../config';
+import { MaterialType, Mesh } from '../mesh';
+import { ProgressManager } from '../progress';
+import { Axes, Ray, rayIntersectTriangle } from '../ray';
+import { Triangle, UVTriangle } from '../triangle';
+import { UV } from '../util';
+import { Vector3 } from '../vector';
+import { VoxelMesh } from '../voxel_mesh';
+import { VoxeliseParams } from '../worker_types';
+import { IVoxeliser } from './base-voxeliser';
+
+/**
+ * This voxeliser works by projecting rays onto each triangle
+ * on each of the principle angles and testing for intersections
+ */
+export class NormalCorrectedRayVoxeliser extends IVoxeliser {
+ private _mesh?: Mesh;
+ private _voxelMesh?: VoxelMesh;
+ private _voxeliseParams?: VoxeliseParams.Input;
+ private _size!: Vector3;
+ private _offset!: Vector3;
+
+ protected override _voxelise(mesh: Mesh, voxeliseParams: VoxeliseParams.Input): VoxelMesh {
+ this._mesh = mesh;
+ this._voxelMesh = new VoxelMesh(voxeliseParams);
+ this._voxeliseParams = voxeliseParams;
+
+ const scale = (voxeliseParams.desiredHeight) / Mesh.desiredHeight;
+ mesh.setTransform((vertex: Vector3) => {
+ return vertex.copy().mulScalar(scale);
+ });
+
+ const bounds = mesh.getBounds();
+ this._size = Vector3.sub(bounds.max, bounds.min);
+ this._offset = new Vector3(
+ this._size.x % 2 < 0.001 ? 0.5 : 0.0,
+ this._size.y % 2 < 0.001 ? 0.5 : 0.0,
+ this._size.z % 2 < 0.001 ? 0.5 : 0.0,
+ );
+
+ const numTris = mesh.getTriangleCount();
+
+ const taskHandle = ProgressManager.Get.start('Voxelising');
+ for (let triIndex = 0; triIndex < numTris; ++triIndex) {
+ ProgressManager.Get.progress(taskHandle, triIndex / numTris);
+ const uvTriangle = mesh.getUVTriangle(triIndex);
+ const normals = mesh.getNormals(triIndex);
+ const material = mesh.getMaterialByTriangle(triIndex);
+ this._voxeliseTri(uvTriangle, material, normals);
+ }
+ ProgressManager.Get.end(taskHandle);
+
+ mesh.clearTransform();
+
+ return this._voxelMesh;
+ }
+
+ private _voxeliseTri(triangle: UVTriangle, materialName: string, normals: { v0: Vector3, v1: Vector3, v2: Vector3 }) {
+ const rayList = this._generateRays(triangle.v0, triangle.v1, triangle.v2,
+ this._offset,
+ );
+
+ rayList.forEach((ray) => {
+ const intersection = rayIntersectTriangle(ray, triangle.v0, triangle.v1, triangle.v2);
+ if (intersection) {
+ // Move transition away from normal
+ const norm = normals.v0.normalise();
+ intersection.sub(Vector3.mulScalar(norm, 0.5));
+ // Correct size parity
+ intersection.add(this._offset);
+
+ let voxelPosition: Vector3;
+ switch (ray.axis) {
+ case Axes.x:
+ voxelPosition = new Vector3(Math.round(intersection.x), intersection.y, intersection.z);
+ break;
+ case Axes.y:
+ voxelPosition = new Vector3(intersection.x, Math.round(intersection.y), intersection.z);
+ break;
+ case Axes.z:
+ voxelPosition = new Vector3(intersection.x, intersection.y, Math.round(intersection.z));
+ break;
+ }
+ voxelPosition.round();
+
+ let voxelColour: RGBA;
+ if (this._voxeliseParams!.useMultisampleColouring && this._mesh!.getMaterialByName(materialName).type === MaterialType.textured) {
+ const samples: RGBA[] = [];
+ for (let i = 0; i < AppConfig.Get.MULTISAMPLE_COUNT; ++i) {
+ const samplePosition = Vector3.add(voxelPosition, Vector3.random().add(-0.5));
+ samples.push(this.__getVoxelColour(triangle, materialName, samplePosition));
+ }
+ voxelColour = RGBAUtil.average(...samples);
+ } else {
+ voxelColour = this.__getVoxelColour(triangle, materialName, voxelPosition);
+ }
+
+ this._voxelMesh!.addVoxel(voxelPosition, voxelColour);
+ }
+ });
+ }
+
+ // TODO: Remove
+ private __getVoxelColour(triangle: UVTriangle, materialName: string, location: Vector3): RGBA {
+ const area01 = new Triangle(triangle.v0, triangle.v1, location).getArea();
+ const area12 = new Triangle(triangle.v1, triangle.v2, location).getArea();
+ const area20 = new Triangle(triangle.v2, triangle.v0, location).getArea();
+ const total = area01 + area12 + area20;
+
+ const w0 = area12 / total;
+ const w1 = area20 / total;
+ const w2 = area01 / total;
+
+ const uv = new UV(
+ triangle.uv0.u * w0 + triangle.uv1.u * w1 + triangle.uv2.u * w2,
+ triangle.uv0.v * w0 + triangle.uv1.v * w1 + triangle.uv2.v * w2,
+ );
+
+ return this._mesh!.sampleMaterial(materialName, uv, this._voxeliseParams!.textureFiltering);
+ }
+
+ private _generateRays(v0: Vector3, v1: Vector3, v2: Vector3, offset: Vector3): Array {
+ const bounds: Bounds = new Bounds(
+ new Vector3(
+ Math.ceil(Math.min(v0.x, v1.x, v2.x)),
+ Math.ceil(Math.min(v0.y, v1.y, v2.y)),
+ Math.ceil(Math.min(v0.z, v1.z, v2.z)),
+ ),
+ new Vector3(
+ Math.floor(Math.max(v0.x, v1.x, v2.x)),
+ Math.floor(Math.max(v0.y, v1.y, v2.y)),
+ Math.floor(Math.max(v0.z, v1.z, v2.z)),
+ ),
+ );
+
+ const rayList: Array = [];
+ this._traverseX(rayList, bounds, offset);
+ this._traverseY(rayList, bounds, offset);
+ this._traverseZ(rayList, bounds, offset);
+ return rayList;
+ }
+
+ private _traverseX(rayList: Array, bounds: Bounds, offset: Vector3) {
+ for (let y = bounds.min.y - offset.y; y <= bounds.max.y + offset.y; ++y) {
+ for (let z = bounds.min.z - offset.z; z <= bounds.max.z + offset.z; ++z) {
+ rayList.push({
+ origin: new Vector3(bounds.min.x - 1, y, z),
+ axis: Axes.x,
+ });
+ }
+ }
+ }
+
+ private _traverseY(rayList: Array, bounds: Bounds, offset: Vector3) {
+ for (let x = bounds.min.x - offset.x; x <= bounds.max.x + offset.x; ++x) {
+ for (let z = bounds.min.z - offset.z; z <= bounds.max.z + offset.z; ++z) {
+ rayList.push({
+ origin: new Vector3(x, bounds.min.y - 1, z),
+ axis: Axes.y,
+ });
+ }
+ }
+ }
+
+ private _traverseZ(rayList: Array, bounds: Bounds, offset: Vector3) {
+ for (let x = bounds.min.x - offset.x; x <= bounds.max.x + offset.x; ++x) {
+ for (let y = bounds.min.y - offset.y; y <= bounds.max.y + offset.y; ++y) {
+ rayList.push({
+ origin: new Vector3(x, y, bounds.min.z - 1),
+ axis: Axes.z,
+ });
+ }
+ }
+ }
+}
diff --git a/src/voxelisers/ray-voxeliser.ts b/src/voxelisers/ray-voxeliser.ts
index ffa7c7b6..40c95459 100644
--- a/src/voxelisers/ray-voxeliser.ts
+++ b/src/voxelisers/ray-voxeliser.ts
@@ -1,152 +1,159 @@
-import { VoxelMesh } from '../voxel_mesh';
-import { AppConfig } from '../config';
-import { Mesh } from '../mesh';
-import { Axes, Ray, rayIntersectTriangle } from '../ray';
-import { Triangle, UVTriangle } from '../triangle';
-import { Bounds, UV } from '../util';
-import { Vector3 } from '../vector';
-import { IVoxeliser } from './base-voxeliser';
-import { RGBA, RGBAUtil } from '../colour';
-import { VoxeliseParams } from './voxelisers';
-
-/**
- * This voxeliser works by projecting rays onto each triangle
- * on each of the principle angles and testing for intersections
- */
-export class RayVoxeliser extends IVoxeliser {
- private _mesh?: Mesh;
- private _voxelMesh?: VoxelMesh;
- private _voxeliseParams?: VoxeliseParams;
- private _scale!: number;
- private _offset!: Vector3;
-
- protected override _voxelise(mesh: Mesh, voxeliseParams: VoxeliseParams): VoxelMesh {
- this._mesh = mesh;
- this._voxelMesh = new VoxelMesh(voxeliseParams);
- this._voxeliseParams = voxeliseParams;
-
- this._scale = (voxeliseParams.desiredHeight - 1) / Mesh.desiredHeight;
- this._offset = (voxeliseParams.desiredHeight % 2 === 0) ? new Vector3(0.0, 0.5, 0.0) : new Vector3(0.0, 0.0, 0.0);
- const useMesh = mesh.copy(); // TODO: Voxelise without copying mesh, too expensive for dense meshes
-
- useMesh.scaleMesh(this._scale);
- useMesh.translateMesh(this._offset);
-
- for (let triIndex = 0; triIndex < useMesh.getTriangleCount(); ++triIndex) {
- const uvTriangle = useMesh.getUVTriangle(triIndex);
- const material = useMesh.getMaterialByTriangle(triIndex);
- this._voxeliseTri(uvTriangle, material);
- }
-
- return this._voxelMesh;
- }
-
- private _voxeliseTri(triangle: UVTriangle, materialName: string) {
- const rayList = this._generateRays(triangle.v0, triangle.v1, triangle.v2);
-
- rayList.forEach((ray) => {
- const intersection = rayIntersectTriangle(ray, triangle.v0, triangle.v1, triangle.v2);
- if (intersection) {
- let voxelPosition: Vector3;
- switch (ray.axis) {
- case Axes.x:
- voxelPosition = new Vector3(Math.round(intersection.x), intersection.y, intersection.z);
- break;
- case Axes.y:
- voxelPosition = new Vector3(intersection.x, Math.round(intersection.y), intersection.z);
- break;
- case Axes.z:
- voxelPosition = new Vector3(intersection.x, intersection.y, Math.round(intersection.z));
- break;
- }
-
- let voxelColour: RGBA;
- if (this._voxeliseParams!.useMultisampleColouring) {
- const samples: RGBA[] = [];
- for (let i = 0; i < AppConfig.MULTISAMPLE_COUNT; ++i) {
- const samplePosition = Vector3.add(voxelPosition, Vector3.random().add(-0.5));
- samples.push(this.__getVoxelColour(triangle, materialName, samplePosition));
- }
- voxelColour = RGBAUtil.average(...samples);
- } else {
- voxelColour = this.__getVoxelColour(triangle, materialName, voxelPosition);
- }
-
- this._voxelMesh!.addVoxel(voxelPosition, voxelColour);
- }
- });
- }
-
- // TODO: Remove
- private __getVoxelColour(triangle: UVTriangle, materialName: string, location: Vector3): RGBA {
- const area01 = new Triangle(triangle.v0, triangle.v1, location).getArea();
- const area12 = new Triangle(triangle.v1, triangle.v2, location).getArea();
- const area20 = new Triangle(triangle.v2, triangle.v0, location).getArea();
- const total = area01 + area12 + area20;
-
- const w0 = area12 / total;
- const w1 = area20 / total;
- const w2 = area01 / total;
-
- const uv = new UV(
- triangle.uv0.u * w0 + triangle.uv1.u * w1 + triangle.uv2.u * w2,
- triangle.uv0.v * w0 + triangle.uv1.v * w1 + triangle.uv2.v * w2,
- );
-
- return this._mesh!.sampleMaterial(materialName, uv, this._voxeliseParams!.textureFiltering);
- }
-
- private _generateRays(v0: Vector3, v1: Vector3, v2: Vector3): Array {
- const bounds: Bounds = new Bounds(
- new Vector3(
- Math.floor(Math.min(v0.x, v1.x, v2.x)),
- Math.floor(Math.min(v0.y, v1.y, v2.y)),
- Math.floor(Math.min(v0.z, v1.z, v2.z)),
- ),
- new Vector3(
- Math.ceil(Math.max(v0.x, v1.x, v2.x)),
- Math.ceil(Math.max(v0.y, v1.y, v2.y)),
- Math.ceil(Math.max(v0.z, v1.z, v2.z)),
- ),
- );
-
- const rayList: Array = [];
- this._traverseX(rayList, bounds);
- this._traverseY(rayList, bounds);
- this._traverseZ(rayList, bounds);
- return rayList;
- }
-
- private _traverseX(rayList: Array, bounds: Bounds) {
- for (let y = bounds.min.y; y <= bounds.max.y; ++y) {
- for (let z = bounds.min.z; z <= bounds.max.z; ++z) {
- rayList.push({
- origin: new Vector3(bounds.min.x - 1, y, z),
- axis: Axes.x,
- });
- }
- }
- }
-
- private _traverseY(rayList: Array, bounds: Bounds) {
- for (let x = bounds.min.x; x <= bounds.max.x; ++x) {
- for (let z = bounds.min.z; z <= bounds.max.z; ++z) {
- rayList.push({
- origin: new Vector3(x, bounds.min.y - 1, z),
- axis: Axes.y,
- });
- }
- }
- }
-
- private _traverseZ(rayList: Array, bounds: Bounds) {
- for (let x = bounds.min.x; x <= bounds.max.x; ++x) {
- for (let y = bounds.min.y; y <= bounds.max.y; ++y) {
- rayList.push({
- origin: new Vector3(x, y, bounds.min.z - 1),
- axis: Axes.z,
- });
- }
- }
- }
-}
+import { Bounds } from '../bounds';
+import { RGBA, RGBAUtil } from '../colour';
+import { AppConfig } from '../config';
+import { MaterialType, Mesh } from '../mesh';
+import { ProgressManager } from '../progress';
+import { Axes, Ray, rayIntersectTriangle } from '../ray';
+import { Triangle, UVTriangle } from '../triangle';
+import { UV } from '../util';
+import { Vector3 } from '../vector';
+import { VoxelMesh } from '../voxel_mesh';
+import { VoxeliseParams } from '../worker_types';
+import { IVoxeliser } from './base-voxeliser';
+
+/**
+ * This voxeliser works by projecting rays onto each triangle
+ * on each of the principle angles and testing for intersections
+ */
+export class RayVoxeliser extends IVoxeliser {
+ private _mesh?: Mesh;
+ private _voxelMesh?: VoxelMesh;
+ private _voxeliseParams?: VoxeliseParams.Input;
+
+ protected override _voxelise(mesh: Mesh, voxeliseParams: VoxeliseParams.Input): VoxelMesh {
+ this._mesh = mesh;
+ this._voxelMesh = new VoxelMesh(voxeliseParams);
+ this._voxeliseParams = voxeliseParams;
+
+ const scale = (voxeliseParams.desiredHeight - 1) / Mesh.desiredHeight;
+ const offset = (voxeliseParams.desiredHeight % 2 === 0) ? new Vector3(0.0, 0.5, 0.0) : new Vector3(0.0, 0.0, 0.0);
+
+ mesh.setTransform((vertex: Vector3) => {
+ return vertex.copy().mulScalar(scale).add(offset);
+ });
+
+ const numTris = mesh.getTriangleCount();
+
+ const taskHandle = ProgressManager.Get.start('Voxelising');
+ for (let triIndex = 0; triIndex < numTris; ++triIndex) {
+ ProgressManager.Get.progress(taskHandle, triIndex / numTris);
+ const uvTriangle = mesh.getUVTriangle(triIndex);
+ const material = mesh.getMaterialByTriangle(triIndex);
+ this._voxeliseTri(uvTriangle, material);
+ }
+ ProgressManager.Get.end(taskHandle);
+
+ mesh.clearTransform();
+
+ return this._voxelMesh;
+ }
+
+ private _voxeliseTri(triangle: UVTriangle, materialName: string) {
+ const rayList = this._generateRays(triangle.v0, triangle.v1, triangle.v2);
+
+ rayList.forEach((ray) => {
+ const intersection = rayIntersectTriangle(ray, triangle.v0, triangle.v1, triangle.v2);
+ if (intersection) {
+ let voxelPosition: Vector3;
+ switch (ray.axis) {
+ case Axes.x:
+ voxelPosition = new Vector3(Math.round(intersection.x), intersection.y, intersection.z);
+ break;
+ case Axes.y:
+ voxelPosition = new Vector3(intersection.x, Math.round(intersection.y), intersection.z);
+ break;
+ case Axes.z:
+ voxelPosition = new Vector3(intersection.x, intersection.y, Math.round(intersection.z));
+ break;
+ }
+
+ let voxelColour: RGBA;
+ if (this._voxeliseParams!.useMultisampleColouring && this._mesh!.getMaterialByName(materialName).type === MaterialType.textured) {
+ const samples: RGBA[] = [];
+ for (let i = 0; i < AppConfig.Get.MULTISAMPLE_COUNT; ++i) {
+ const samplePosition = Vector3.add(voxelPosition, Vector3.random().add(-0.5));
+ samples.push(this.__getVoxelColour(triangle, materialName, samplePosition));
+ }
+ voxelColour = RGBAUtil.average(...samples);
+ } else {
+ voxelColour = this.__getVoxelColour(triangle, materialName, voxelPosition);
+ }
+
+ this._voxelMesh!.addVoxel(voxelPosition, voxelColour);
+ }
+ });
+ }
+
+ // TODO: Remove
+ private __getVoxelColour(triangle: UVTriangle, materialName: string, location: Vector3): RGBA {
+ const area01 = new Triangle(triangle.v0, triangle.v1, location).getArea();
+ const area12 = new Triangle(triangle.v1, triangle.v2, location).getArea();
+ const area20 = new Triangle(triangle.v2, triangle.v0, location).getArea();
+ const total = area01 + area12 + area20;
+
+ const w0 = area12 / total;
+ const w1 = area20 / total;
+ const w2 = area01 / total;
+
+ const uv = new UV(
+ triangle.uv0.u * w0 + triangle.uv1.u * w1 + triangle.uv2.u * w2,
+ triangle.uv0.v * w0 + triangle.uv1.v * w1 + triangle.uv2.v * w2,
+ );
+
+ return this._mesh!.sampleMaterial(materialName, uv, this._voxeliseParams!.textureFiltering);
+ }
+
+ private _generateRays(v0: Vector3, v1: Vector3, v2: Vector3): Array {
+ const bounds: Bounds = new Bounds(
+ new Vector3(
+ Math.floor(Math.min(v0.x, v1.x, v2.x)),
+ Math.floor(Math.min(v0.y, v1.y, v2.y)),
+ Math.floor(Math.min(v0.z, v1.z, v2.z)),
+ ),
+ new Vector3(
+ Math.ceil(Math.max(v0.x, v1.x, v2.x)),
+ Math.ceil(Math.max(v0.y, v1.y, v2.y)),
+ Math.ceil(Math.max(v0.z, v1.z, v2.z)),
+ ),
+ );
+
+ const rayList: Array = [];
+ this._traverseX(rayList, bounds);
+ this._traverseY(rayList, bounds);
+ this._traverseZ(rayList, bounds);
+ return rayList;
+ }
+
+ private _traverseX(rayList: Array, bounds: Bounds) {
+ for (let y = bounds.min.y; y <= bounds.max.y; ++y) {
+ for (let z = bounds.min.z; z <= bounds.max.z; ++z) {
+ rayList.push({
+ origin: new Vector3(bounds.min.x - 1, y, z),
+ axis: Axes.x,
+ });
+ }
+ }
+ }
+
+ private _traverseY(rayList: Array, bounds: Bounds) {
+ for (let x = bounds.min.x; x <= bounds.max.x; ++x) {
+ for (let z = bounds.min.z; z <= bounds.max.z; ++z) {
+ rayList.push({
+ origin: new Vector3(x, bounds.min.y - 1, z),
+ axis: Axes.y,
+ });
+ }
+ }
+ }
+
+ private _traverseZ(rayList: Array, bounds: Bounds) {
+ for (let x = bounds.min.x; x <= bounds.max.x; ++x) {
+ for (let y = bounds.min.y; y <= bounds.max.y; ++y) {
+ rayList.push({
+ origin: new Vector3(x, y, bounds.min.z - 1),
+ axis: Axes.z,
+ });
+ }
+ }
+ }
+}
diff --git a/src/voxelisers/voxelisers.ts b/src/voxelisers/voxelisers.ts
index 06fb8419..f7f8408e 100644
--- a/src/voxelisers/voxelisers.ts
+++ b/src/voxelisers/voxelisers.ts
@@ -1,32 +1,22 @@
-import { IVoxeliser } from './base-voxeliser';
-import { BVHRayVoxeliser } from './bvh-ray-voxeliser';
-import { NormalCorrectedRayVoxeliser } from './normal-corrected-ray-voxeliser';
-import { RayVoxeliser } from './ray-voxeliser';
-import { ASSERT } from '../util';
-import { TextureFiltering } from '../texture';
-import { VoxelMeshParams } from '../voxel_mesh';
-
-export type TVoxelisers = 'bvh-ray' | 'ncrb' | 'ray-based';
-
-/** These are the parameters required by voxelisers */
-export type VoxeliseParams = VoxelMeshParams & {
- desiredHeight: number,
- useMultisampleColouring: boolean,
- textureFiltering: TextureFiltering,
- enableAmbientOcclusion: boolean,
-}
-
-export class VoxeliserFactory {
- public static GetVoxeliser(voxeliser: TVoxelisers): IVoxeliser {
- switch (voxeliser) {
- case 'bvh-ray':
- return new BVHRayVoxeliser();
- case 'ncrb':
- return new NormalCorrectedRayVoxeliser();
- case 'ray-based':
- return new RayVoxeliser();
- default:
- ASSERT(false, 'Unreachable');
- }
- }
-}
+import { ASSERT } from '../util/error_util';
+import { IVoxeliser } from './base-voxeliser';
+import { BVHRayVoxeliser } from './bvh-ray-voxeliser';
+import { NormalCorrectedRayVoxeliser } from './normal-corrected-ray-voxeliser';
+import { RayVoxeliser } from './ray-voxeliser';
+
+export type TVoxelisers = 'bvh-ray' | 'ncrb' | 'ray-based';
+
+export class VoxeliserFactory {
+ public static GetVoxeliser(voxeliser: TVoxelisers): IVoxeliser {
+ switch (voxeliser) {
+ case 'bvh-ray':
+ return new BVHRayVoxeliser();
+ case 'ncrb':
+ return new NormalCorrectedRayVoxeliser();
+ case 'ray-based':
+ return new RayVoxeliser();
+ default:
+ ASSERT(false, 'Unreachable');
+ }
+ }
+}
diff --git a/src/worker.ts b/src/worker.ts
new file mode 100644
index 00000000..6bc0cb0d
--- /dev/null
+++ b/src/worker.ts
@@ -0,0 +1,85 @@
+import { ProgressManager } from './progress';
+import { StatusHandler } from './status';
+import { AppError } from './util/error_util';
+import { WorkerClient } from './worker_client';
+import { TFromWorkerMessage, TToWorkerMessage } from './worker_types';
+
+export function doWork(message: TToWorkerMessage): TFromWorkerMessage {
+ StatusHandler.Get.clear();
+
+ if (message.action !== 'RenderNextVoxelMeshChunk' && message.action !== 'RenderNextBlockMeshChunk') {
+ ProgressManager.Get.clear();
+ }
+
+ try {
+ switch (message.action) {
+ case 'Init':
+ return {
+ action: 'Init',
+ result: WorkerClient.Get.init(message.params),
+ statusMessages: StatusHandler.Get.getAllStatusMessages(),
+ };
+ case 'Import':
+ return {
+ action: 'Import',
+ result: WorkerClient.Get.import(message.params),
+ statusMessages: StatusHandler.Get.getAllStatusMessages(),
+ };
+ case 'RenderMesh':
+ return {
+ action: 'RenderMesh',
+ result: WorkerClient.Get.renderMesh(message.params),
+ statusMessages: StatusHandler.Get.getAllStatusMessages(),
+ };
+ case 'Voxelise':
+ return {
+ action: 'Voxelise',
+ result: WorkerClient.Get.voxelise(message.params),
+ statusMessages: StatusHandler.Get.getAllStatusMessages(),
+ };
+ /*
+ case 'RenderVoxelMesh':
+ return {
+ action: 'RenderVoxelMesh',
+ result: WorkerClient.Get.renderVoxelMesh(message.params),
+ statusMessages: StatusHandler.Get.getAllStatusMessages(),
+ };
+ */
+ case 'RenderNextVoxelMeshChunk':
+ return {
+ action: 'RenderNextVoxelMeshChunk',
+ result: WorkerClient.Get.renderChunkedVoxelMesh(message.params),
+ statusMessages: StatusHandler.Get.getAllStatusMessages(),
+ };
+ case 'Assign':
+ return {
+ action: 'Assign',
+ result: WorkerClient.Get.assign(message.params),
+ statusMessages: StatusHandler.Get.getAllStatusMessages(),
+ };
+ /*
+ case 'RenderBlockMesh':
+ return {
+ action: 'RenderBlockMesh',
+ result: WorkerClient.Get.renderBlockMesh(message.params),
+ statusMessages: StatusHandler.Get.getAllStatusMessages(),
+ };
+ */
+ case 'RenderNextBlockMeshChunk':
+ return {
+ action: 'RenderNextBlockMeshChunk',
+ result: WorkerClient.Get.renderChunkedBlockMesh(message.params),
+ statusMessages: StatusHandler.Get.getAllStatusMessages(),
+ };
+ case 'Export':
+ return {
+ action: 'Export',
+ result: WorkerClient.Get.export(message.params),
+ statusMessages: StatusHandler.Get.getAllStatusMessages(),
+ };
+ }
+ } catch (e: any) {
+ return { action: e instanceof AppError ? 'KnownError' : 'UnknownError', error: e as Error };
+ }
+}
+
diff --git a/src/worker_client.ts b/src/worker_client.ts
new file mode 100644
index 00000000..50e6c4bc
--- /dev/null
+++ b/src/worker_client.ts
@@ -0,0 +1,215 @@
+import { Atlas } from './atlas';
+import { BlockMesh } from './block_mesh';
+import { BufferGenerator } from './buffer';
+import { EAppEvent, EventManager } from './event';
+import { IExporter } from './exporters/base_exporter';
+import { ExporterFactory } from './exporters/exporters';
+import { ObjImporter } from './importers/obj_importer';
+import { Mesh } from './mesh';
+import { ProgressManager, TTaskHandle } from './progress';
+import { ASSERT } from './util/error_util';
+import { Logger } from './util/log_util';
+import { VoxelMesh } from './voxel_mesh';
+import { IVoxeliser } from './voxelisers/base-voxeliser';
+import { VoxeliserFactory } from './voxelisers/voxelisers';
+import { AssignParams, ExportParams, ImportParams, InitParams, RenderMeshParams, RenderNextBlockMeshChunkParams, RenderNextVoxelMeshChunkParams, TFromWorkerMessage, VoxeliseParams } from './worker_types';
+
+export class WorkerClient {
+ private static _instance: WorkerClient;
+ public static get Get() {
+ return this._instance || (this._instance = new this());
+ }
+
+ private constructor() {
+ Logger.Get.enableLogToFile();
+ Logger.Get.initLogFile('worker');
+ }
+
+ private _loadedMesh?: Mesh;
+ private _loadedVoxelMesh?: VoxelMesh;
+ private _loadedBlockMesh?: BlockMesh;
+
+ /**
+ * This function should only be called if the client is using the worker.
+ */
+ public init(params: InitParams.Input): InitParams.Output {
+ EventManager.Get.add(EAppEvent.onTaskStart, (e: any) => {
+ const message: TFromWorkerMessage = {
+ action: 'Progress',
+ payload: {
+ type: 'Started',
+ taskId: e[0],
+ },
+ };
+ postMessage(message);
+ });
+
+ EventManager.Get.add(EAppEvent.onTaskProgress, (e: any) => {
+ const message: TFromWorkerMessage = {
+ action: 'Progress',
+ payload: {
+ type: 'Progress',
+ taskId: e[0],
+ percentage: e[1],
+ },
+ };
+ postMessage(message);
+ });
+
+ EventManager.Get.add(EAppEvent.onTaskEnd, (e: any) => {
+ const message: TFromWorkerMessage = {
+ action: 'Progress',
+ payload: {
+ type: 'Finished',
+ taskId: e[0],
+ },
+ };
+ postMessage(message);
+ });
+
+ return {};
+ }
+
+ public import(params: ImportParams.Input): ImportParams.Output {
+ const importer = new ObjImporter();
+ importer.parseFile(params.filepath);
+ this._loadedMesh = importer.toMesh();
+ this._loadedMesh.processMesh();
+
+ return {
+ triangleCount: this._loadedMesh.getTriangleCount(),
+ };
+ }
+
+ public renderMesh(params: RenderMeshParams.Input): RenderMeshParams.Output {
+ ASSERT(this._loadedMesh !== undefined);
+
+ return {
+ buffers: BufferGenerator.fromMesh(this._loadedMesh),
+ dimensions: this._loadedMesh.getBounds().getDimensions(),
+ };
+ }
+
+
+ public voxelise(params: VoxeliseParams.Input): VoxeliseParams.Output {
+ ASSERT(this._loadedMesh !== undefined);
+
+ const voxeliser: IVoxeliser = VoxeliserFactory.GetVoxeliser(params.voxeliser);
+ this._loadedVoxelMesh = voxeliser.voxelise(this._loadedMesh, params);
+
+ this._voxelMeshChunkIndex = 0;
+
+ return {
+ };
+ }
+
+ private _voxelMeshChunkIndex = 0;
+ private _voxelMeshProgressHandle?: TTaskHandle;
+ public renderChunkedVoxelMesh(params: RenderNextVoxelMeshChunkParams.Input): RenderNextVoxelMeshChunkParams.Output {
+ ASSERT(this._loadedVoxelMesh !== undefined);
+
+ const isFirstChunk = this._voxelMeshChunkIndex === 0;
+ if (isFirstChunk) {
+ this._voxelMeshProgressHandle = ProgressManager.Get.start('VoxelMeshBuffer');
+ this._loadedVoxelMesh.setRenderParams(params);
+ }
+
+ const buffer = this._loadedVoxelMesh.getChunkedBuffer(this._voxelMeshChunkIndex);
+ ++this._voxelMeshChunkIndex;
+
+ if (this._voxelMeshProgressHandle !== undefined) {
+ if (buffer.moreVoxelsToBuffer) {
+ ProgressManager.Get.progress(this._voxelMeshProgressHandle, buffer.progress);
+ } else {
+ ProgressManager.Get.end(this._voxelMeshProgressHandle);
+ this._voxelMeshProgressHandle = undefined;
+ }
+ }
+
+ return {
+ buffer: buffer,
+ dimensions: this._loadedVoxelMesh.getBounds().getDimensions(),
+ voxelSize: 8.0 / params.desiredHeight,
+ moreVoxelsToBuffer: buffer.moreVoxelsToBuffer,
+ isFirstChunk: isFirstChunk,
+ };
+ }
+
+ public assign(params: AssignParams.Input): AssignParams.Output {
+ ASSERT(this._loadedVoxelMesh !== undefined);
+
+ this._loadedBlockMesh = BlockMesh.createFromVoxelMesh(this._loadedVoxelMesh, params);
+
+ this._blockMeshChunkIndex = 0;
+
+ return {
+ };
+ }
+
+ private _blockMeshChunkIndex = 0;
+ //private _blockMeshProgressHandle?: TTaskHandle;
+ public renderChunkedBlockMesh(params: RenderNextBlockMeshChunkParams.Input): RenderNextBlockMeshChunkParams.Output {
+ ASSERT(this._loadedBlockMesh !== undefined);
+
+ const isFirstChunk = this._blockMeshChunkIndex === 0;
+ if (isFirstChunk) {
+ //this._blockMeshProgressHandle = ProgressManager.Get.start('BlockMeshBuffer');
+ }
+
+ const buffer = this._loadedBlockMesh.getChunkedBuffer(this._blockMeshChunkIndex);
+ ++this._blockMeshChunkIndex;
+
+ /*
+ if (this._blockMeshProgressHandle !== undefined) {
+ if (buffer.moreBlocksToBuffer) {
+ ProgressManager.Get.progress(this._blockMeshProgressHandle, buffer.progress);
+ } else {
+ ProgressManager.Get.end(this._blockMeshProgressHandle);
+ this._blockMeshProgressHandle = undefined;
+ }
+ }
+ */
+
+ const atlas = Atlas.load(params.textureAtlas);
+ ASSERT(atlas !== undefined);
+
+ return {
+ buffer: buffer,
+ dimensions: this._loadedBlockMesh.getVoxelMesh().getBounds().getDimensions(),
+ atlasTexturePath: atlas.getAtlasTexturePath(),
+ atlasSize: atlas.getAtlasSize(),
+ moreBlocksToBuffer: buffer.moreBlocksToBuffer,
+ isFirstChunk: isFirstChunk,
+ };
+ }
+
+ /*
+ public renderBlockMesh(params: RenderBlockMeshParams.Input): RenderBlockMeshParams.Output {
+ ASSERT(this._loadedBlockMesh !== undefined);
+
+ const atlas = Atlas.load(params.textureAtlas);
+ ASSERT(atlas !== undefined);
+
+ return {
+ buffer: this._loadedBlockMesh.getBuffer(),
+ dimensions: this._loadedBlockMesh.getVoxelMesh().getBounds().getDimensions(),
+ atlasTexturePath: atlas.getAtlasTexturePath(),
+ atlasSize: atlas.getAtlasSize(),
+ };
+ }
+ */
+
+ public export(params: ExportParams.Input): ExportParams.Output {
+ ASSERT(this._loadedBlockMesh !== undefined);
+
+ const exporter: IExporter = ExporterFactory.GetExporter(params.exporter);
+ const fileExtension = '.' + exporter.getFileExtension();
+ if (!params.filepath.endsWith(fileExtension)) {
+ params.filepath += fileExtension;
+ }
+ exporter.export(this._loadedBlockMesh, params.filepath);
+
+ return {
+ };
+ }
+}
diff --git a/src/worker_controller.ts b/src/worker_controller.ts
new file mode 100644
index 00000000..231c7176
--- /dev/null
+++ b/src/worker_controller.ts
@@ -0,0 +1,116 @@
+import { AppConfig } from './config';
+import { EAppEvent, EventManager } from './event';
+import { ASSERT } from './util/error_util';
+import { LOG } from './util/log_util';
+import { doWork } from './worker';
+import { TFromWorkerMessage, TToWorkerMessage } from './worker_types';
+
+export type TWorkerJob = {
+ id: string,
+ payload: TToWorkerMessage,
+ callback?: (payload: TFromWorkerMessage) => void, // Called with the payload of the next message received by the worker
+}
+
+export class WorkerController {
+ private _worker: Worker;
+ private _jobQueue: TWorkerJob[];
+ private _jobPending: TWorkerJob | undefined;
+ private _jobStartTime: number;
+ private _timerOn: boolean;
+
+ public constructor(scriptURL: string, options?: WorkerOptions) {
+ this._worker = new Worker(scriptURL, options);
+ this._worker.onmessage = this._onWorkerMessage.bind(this);
+
+ this._jobQueue = [];
+ this._jobStartTime = 0;
+ this._timerOn = false;
+ }
+
+ public addJob(newJob: TWorkerJob): boolean {
+ const isJobAlreadyQueued = this._jobQueue.some((queuedJob) => { return queuedJob.id === newJob.id; });
+ if (isJobAlreadyQueued) {
+ LOG('[WorkerController]: Job already queued with ID', newJob.id);
+ return false;
+ }
+
+ this._jobQueue.push(newJob);
+ this._tryStartNextJob();
+
+ return true;
+ }
+
+ public isBusy() {
+ return this._jobPending !== undefined;
+ }
+
+ private _onWorkerMessage(payload: MessageEvent) {
+ ASSERT(this._jobPending !== undefined, `Received worker message when no job is pending`);
+
+ if (payload.data.action === 'Progress') {
+ switch (payload.data.payload.type) {
+ case 'Started':
+ EventManager.Get.broadcast(EAppEvent.onTaskStart, payload.data.payload.taskId);
+ break;
+ case 'Progress':
+ EventManager.Get.broadcast(EAppEvent.onTaskProgress, payload.data.payload.taskId, payload.data.payload.percentage);
+ break;
+ case 'Finished':
+ EventManager.Get.broadcast(EAppEvent.onTaskEnd, payload.data.payload.taskId);
+ break;
+ }
+ return;
+ }
+
+ let endTimer = true;
+ if (payload.data.action === 'RenderNextVoxelMeshChunk') {
+ if (payload.data.result.moreVoxelsToBuffer) {
+ endTimer = false;
+ }
+ } else if (payload.data.action === 'RenderNextBlockMeshChunk') {
+ if (payload.data.result.moreBlocksToBuffer) {
+ endTimer = false;
+ }
+ }
+
+ if (endTimer) {
+ const deltaTime = Date.now() - this._jobStartTime;
+ LOG(`[WorkerController]: '${this._jobPending.id}' completed in ${deltaTime}ms`);
+ this._timerOn = false;
+ }
+
+ if (this._jobPending.callback) {
+ this._jobPending.callback(payload.data);
+ }
+ this._jobPending = undefined;
+
+ this._tryStartNextJob();
+ }
+
+ private _tryStartNextJob() {
+ if (this.isBusy() && AppConfig.Get.USE_WORKER_THREAD) {
+ return;
+ }
+
+ this._jobPending = this._jobQueue.shift();
+ if (this._jobPending === undefined) {
+ return;
+ }
+
+ if (!this._timerOn) {
+ LOG(`[WorkerController]: Starting Job '${this._jobPending.id}' (${this._jobQueue.length} remaining)`);
+ LOG(`[WorkerController]: ${JSON.stringify(this._jobPending.payload, null, 4)}`);
+ this._jobStartTime = Date.now();
+ this._timerOn = true;
+ }
+
+ if (AppConfig.Get.USE_WORKER_THREAD) {
+ this._worker.postMessage(this._jobPending.payload);
+ } else {
+ const result = doWork(this._jobPending.payload);
+ if (this._jobPending.callback) {
+ this._jobPending.callback(result);
+ }
+ }
+ }
+}
diff --git a/src/worker_interface.ts b/src/worker_interface.ts
new file mode 100644
index 00000000..373b67ef
--- /dev/null
+++ b/src/worker_interface.ts
@@ -0,0 +1,5 @@
+const workerInstance = require('./worker');
+
+addEventListener('message', (e) => {
+ postMessage(workerInstance.doWork(e.data));
+});
diff --git a/src/worker_types.ts b/src/worker_types.ts
new file mode 100644
index 00000000..48a7f16e
--- /dev/null
+++ b/src/worker_types.ts
@@ -0,0 +1,182 @@
+import { TBlockAssigners } from './assigners/assigners';
+import { FallableBehaviour } from './block_mesh';
+import { TBlockMeshBufferDescription, TMeshBufferDescription, TVoxelMeshBufferDescription } from './buffer';
+import { RGBAUtil } from './colour';
+import { TExporters } from './exporters/exporters';
+import { StatusMessage } from './status';
+import { TextureFiltering } from './texture';
+import { ColourSpace } from './util';
+import { AppError } from './util/error_util';
+import { Vector3 } from './vector';
+import { TVoxelOverlapRule } from './voxel_mesh';
+import { TVoxelisers } from './voxelisers/voxelisers';
+
+export namespace InitParams {
+ export type Input = {
+ }
+
+ export type Output = {
+ }
+}
+
+export namespace ImportParams {
+ export type Input = {
+ filepath: string,
+ }
+
+ export type Output = {
+ triangleCount: number,
+ }
+}
+
+export namespace RenderMeshParams {
+ export type Input = {
+
+ }
+
+ export type Output = {
+ buffers: TMeshBufferDescription[],
+ dimensions: Vector3
+ }
+}
+
+export namespace VoxeliseParams {
+ export type Input = {
+ voxeliser: TVoxelisers,
+ desiredHeight: number,
+ useMultisampleColouring: boolean,
+ textureFiltering: TextureFiltering,
+ enableAmbientOcclusion: boolean,
+ voxelOverlapRule: TVoxelOverlapRule,
+ }
+
+ export type Output = {
+
+ }
+}
+
+/*
+export namespace RenderVoxelMeshParams {
+ export type Input = {
+ desiredHeight: number,
+ enableAmbientOcclusion: boolean,
+ }
+
+ export type Output = {
+ buffer: TVoxelMeshBufferDescription,
+ dimensions: Vector3,
+ voxelSize: number,
+ }
+}
+*/
+
+export namespace RenderNextVoxelMeshChunkParams {
+ export type Input = {
+ desiredHeight: number,
+ enableAmbientOcclusion: boolean,
+ }
+
+ export type Output = {
+ buffer: TVoxelMeshBufferDescription,
+ dimensions: Vector3,
+ voxelSize: number,
+ moreVoxelsToBuffer: boolean,
+ isFirstChunk: boolean,
+ }
+}
+
+export type TAtlasId = string;
+export type TPaletteId = string;
+
+export namespace AssignParams {
+ export type Input = {
+ textureAtlas: TAtlasId,
+ blockPalette: TPaletteId,
+ blockAssigner: TBlockAssigners,
+ colourSpace: ColourSpace,
+ fallable: FallableBehaviour,
+ resolution: RGBAUtil.TColourAccuracy,
+ }
+
+ export type Output = {
+
+ }
+}
+
+export namespace RenderNextBlockMeshChunkParams {
+ export type Input = {
+ textureAtlas: TAtlasId,
+ }
+
+ export type Output = {
+ buffer: TBlockMeshBufferDescription,
+ dimensions: Vector3,
+ atlasTexturePath: string,
+ atlasSize: number,
+ moreBlocksToBuffer: boolean,
+ isFirstChunk: boolean,
+ }
+}
+
+/*
+export namespace RenderBlockMeshParams {
+ export type Input = {
+ textureAtlas: TAtlasId,
+ }
+
+ export type Output = {
+ buffer: TBlockMeshBufferDescription,
+ dimensions: Vector3,
+ atlasTexturePath: string,
+ atlasSize: number,
+ }
+}
+*/
+
+export namespace ExportParams {
+ export type Input = {
+ filepath: string,
+ exporter: TExporters,
+ }
+
+ export type Output = {
+
+ }
+}
+
+export type TStatus = {
+ statusMessages: StatusMessage[],
+}
+
+export type TaskParams =
+ | { type: 'Started', taskId: string }
+ | { type: 'Progress', taskId: string, percentage: number }
+ | { type: 'Finished', taskId: string }
+
+export type TToWorkerMessage =
+ | { action: 'Init', params: InitParams.Input }
+ | { action: 'Import', params: ImportParams.Input }
+ | { action: 'RenderMesh', params: RenderMeshParams.Input }
+ | { action: 'Voxelise', params: VoxeliseParams.Input }
+ //| { action: 'RenderVoxelMesh', params: RenderVoxelMeshParams.Input }
+ | { action: 'RenderNextVoxelMeshChunk', params: RenderNextVoxelMeshChunkParams.Input }
+ | { action: 'Assign', params: AssignParams.Input }
+ //| { action: 'RenderBlockMesh', params: RenderBlockMeshParams.Input }
+ | { action: 'RenderNextBlockMeshChunk', params: RenderNextBlockMeshChunkParams.Input }
+ | { action: 'Export', params: ExportParams.Input }
+
+export type TFromWorkerMessage =
+ | { action: 'KnownError', error: AppError }
+ | { action: 'UnknownError', error: Error }
+ | { action: 'Progress', payload: TaskParams }
+ | (TStatus & (
+ | { action: 'Init', result: InitParams.Output }
+ | { action: 'Import', result: ImportParams.Output }
+ | { action: 'RenderMesh', result: RenderMeshParams.Output }
+ | { action: 'Voxelise', result: VoxeliseParams.Output }
+ //| { action: 'RenderVoxelMesh', result: RenderVoxelMeshParams.Output }
+ | { action: 'RenderNextVoxelMeshChunk', result: RenderNextVoxelMeshChunkParams.Output }
+ | { action: 'Assign', result: AssignParams.Output }
+ //| { action: 'RenderBlockMesh', result: RenderBlockMeshParams.Output }
+ | { action: 'RenderNextBlockMeshChunk', result: RenderNextBlockMeshChunkParams.Output }
+ | { action: 'Export', result: ExportParams.Output }));
diff --git a/styles.css b/styles.css
index ac391616..cf9207b2 100644
--- a/styles.css
+++ b/styles.css
@@ -80,6 +80,7 @@ canvas {
padding: 0px 10px;
width: 125px;
}
+
.prop-left-disabled {
color: var(--text-disabled) !important;
}
@@ -96,6 +97,7 @@ canvas {
min-height: 30px;
padding: 5px 0px;
}
+
.item-body-sunken {
background: var(--prop-sunken);
box-shadow: rgba(0, 0, 0, 0.2) 0px 3px 10px 0px inset;
@@ -143,11 +145,13 @@ select {
border: 1px solid rgb(255, 255, 255, 0.0);
max-width: 100%;
}
+
select:hover:enabled {
color: #C6C6C6;
background: var(--prop-hovered);
border: 1px solid rgb(255, 255, 255, 0.1);
}
+
select:disabled {
background: #282828 !important;
color: var(--text-disabled);
@@ -177,6 +181,7 @@ select:disabled {
width: 20px;
text-align: center;
}
+
.slider-value-disabled {
color: var(--text-disabled);
}
@@ -193,10 +198,12 @@ select:disabled {
font-size: 90%;
border: 1px solid var(--prop-bg);
}
+
.new-slider-hover {
border: 1px solid rgba(255, 255, 255, 0.1) !important;
background: var(--prop-hovered) !important;
}
+
.new-slider-disabled {
background: var(--prop-disabled) !important;
cursor: default !important;
@@ -210,10 +217,12 @@ select:disabled {
background: var(--prop-accent-standard);
border: 1px solid rgb(255, 255, 255, 0.0);
}
+
.new-slider-bar-hover {
border: 1px solid rgb(255, 255, 255, 0.2) !important;
background: var(--prop-accent-hovered) !important;
}
+
.new-slider-bar-disabled {
background: var(--prop-accent-disabled) !important;
cursor: default !important;
@@ -230,13 +239,32 @@ select:disabled {
text-align: center;
padding: 5px 0px 0px 0px;
border: 1px solid rgb(255, 255, 255, 0);
+ position: relative;
cursor: pointer;
+ display: inline-block;
+ width: 100%;
}
+
.button:hover {
border: 1px solid rgb(255, 255, 255, 0.2);
background: var(--prop-accent-hovered);
cursor: pointer;
}
+
+.progress {
+ z-index: 5;
+ background: white;
+ opacity: 0.1;
+ border-radius: 5px;
+ position: absolute;
+ left: 0;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ width: 0%;
+ transition: width 0.2s;
+}
+
.button-disabled {
cursor: default !important;
background: var(--prop-accent-disabled) !important;
@@ -252,13 +280,16 @@ select:disabled {
padding: 6px 0px 0px 10px;
border: 1px solid rgb(255, 255, 255, 0);
}
-.input-text:hover {
+
+.input-text-hover {
border: 1px solid rgb(255, 255, 255, 0.2);
background: var(--prop-hovered);
cursor: pointer;
}
+
.input-text-disabled {
- background: rgb(156, 27, 27) !important;
+ background: var(--prop-disabled) !important;
+ color: var(--text-disabled) !important;
}
.h-div {
@@ -300,21 +331,18 @@ select:disabled {
background: rgba(255, 255, 255, 0.2);
}
-.border-warning {
- border: 1.5px solid orange;
- transition-duration: 1s;
+.status-warning {
+ transition-duration: 0.5s;
color: orange;
}
-.border-success {
- border: 1.5px solid green;
- transition-duration: 1s;
- color: green;
+.status-success {
+ transition-duration: 0.5s;
+ color: var(--prop-accent-standard);
}
-.border-error {
- border: 1.5px solid rgb(156, 27, 27);
- transition-duration: 1s;
+.status-error {
+ transition-duration: 0.5s;
color: rgb(156, 27, 27);
}
@@ -329,11 +357,13 @@ select:disabled {
border-style: solid;
border: rgba(255, 255, 255, 0.0);
}
+
.spinbox-key-hover {
border: rgba(255, 255, 255, 0.2) !important;
filter: brightness(1.5);
cursor: ew-resize;
}
+
.spinbox-key-disabled {
filter: brightness(0.4);
}
@@ -348,16 +378,18 @@ select:disabled {
border-width: 1px 1px 1px 0px;
border-style: solid;
border: rgba(255, 255, 255, 0.0);
-
+
color: var(--text-disabled);
align-self: center;
text-align: center;
}
+
.spinbox-value-hover {
border: rgba(255, 255, 255, 0.2) !important;
background: var(--prop-hovered) !important;
cursor: ew-resize;
}
+
.spinbox-value-disabled {
color: var(--text-disabled);
background: var(--prop-disabled) !important;
@@ -380,6 +412,7 @@ select:disabled {
flex-direction: row;
margin: 20px 10px;
}
+
.toolbar-column:last-child {
flex-direction: row-reverse !important;
}
@@ -402,33 +435,44 @@ select:disabled {
background-color: var(--prop-standard);
border: 1px solid var(--prop-standard);
}
+
.toolbar-item-hover {
background-color: var(--prop-hovered) !important;
border: 1px solid var(--prop-border-hovered) !important;
cursor: pointer;
}
+
.toolbar-item-active-hover {
background-color: var(--prop-accent-hovered) !important;
border: 1px solid var(--prop-accent-border-hovered) !important;
}
+
.toolbar-item-disabled {
background-color: var(--prop-disabled) !important;
border: 1px solid var(--prop-disabled) !important;
}
+
.toolbar-item-active {
background-color: var(--prop-accent-standard) !important;
border-color: var(--prop-accent-border-hovered) !important;
}
+
.toolbar-item:first-child {
border-top-left-radius: 5px;
border-bottom-left-radius: 5px;
}
+
.toolbar-item:last-child {
border-top-right-radius: 5px;
border-bottom-right-radius: 5px;
}
-svg { width: 16px; height: 16px; padding-top: 7.5px; stroke: var(--text-standard); }
+svg {
+ width: 16px;
+ height: 16px;
+ padding-top: 7.5px;
+ stroke: var(--text-standard);
+}
.icon-active {
stroke: white !important;
@@ -436,4 +480,129 @@ svg { width: 16px; height: 16px; padding-top: 7.5px; stroke: var(--text-standard
.icon-disabled {
stroke: var(--text-disabled) !important;
+}
+
+.palette-container {
+ width: 100%;
+ height: 200px;
+ display: flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+ align-items: flex-start;
+ align-content: flex-start;
+ overflow: auto;
+ gap: 4px;
+}
+
+.palette-item {
+ display: flex;
+ background: var(--prop-disabled);
+ width: 32px;
+ height: 32px;
+ border-radius: 8px;
+}
+
+
+.interactable-base {
+ display: flex;
+ border-radius: 8px;
+ padding: 5px;
+ border-width: 1px;
+ border-style: solid;
+}
+
+
+.interactable {
+ border-color: rgb(255, 255, 255, 0.0);
+ background-color: var(--prop-standard);
+}
+
+.interactable-hover {
+ border-color: rgb(255, 255, 255, 0.2);
+ background-color: var(--prop-standard);
+}
+
+.interactable-disabled {
+ border-color: rgb(255, 255, 255, 0.0);
+ background-color: var(--prop-disabled);
+}
+
+
+.interactable-active {
+ border-color: var(----prop-accent-standard);
+ background-color: var(--prop-accent-standard);
+}
+
+.interactable-active-hover {
+ border-color: var(--prop-accent-border-hovered);
+ background-color: var(--prop-accent-hovered);
+}
+
+.interactable-active-disabled {
+ border-color: var(--prop-accent-disabled);
+ background-color: var(--prop-accent-disabled);
+}
+
+
+
+.toggleable-icon {
+ filter: drop-shadow(0px 0px 4px rgba(0, 0, 0, 0.125));
+}
+
+
+.button-loading {
+ box-shadow: 0 0 0 0 rgba(0, 0, 0, 1);
+ animation: pulse 2s infinite;
+}
+
+@keyframes pulse {
+ 0% {
+ box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.5);
+ }
+
+ 70% {
+ box-shadow: 0 0 0 6px rgba(255, 255, 255, 0);
+ }
+
+ 100% {
+ box-shadow: 0 0 0 0 rgba(255, 255, 255, 0);
+ }
+}
+
+
+
+.loader-circle {
+ width: 6px;
+ height: 6px;
+ border-radius: 50%;
+ background-color: currentColor;
+}
+
+.spin {
+ animation: blinker 0.75s ease-in-out infinite;
+}
+
+@keyframes blinker {
+ 0% {
+ opacity: 100%;
+ }
+ 50% {
+ opacity: 50%;
+ }
+ 100% {
+ opacity: 100%;
+ }
+}
+
+
+
+.progress-bar-container {
+ width: 100%;
+ height: 2px;
+}
+
+.progress-bar {
+ background-color: var(--prop-accent-standard);
+ height: 100%;
+ transition: width 0.1s;
}
\ No newline at end of file
diff --git a/tests/buffer.test.ts b/tests/buffer.test.ts
index f17e4999..89072730 100644
--- a/tests/buffer.test.ts
+++ b/tests/buffer.test.ts
@@ -1,6 +1,9 @@
-import { AttributeData, MergeAttributeData } from '../src/buffer';
+import { AttributeData, MergeAttributeData } from '../src/render_buffer';
+import { TEST_PREAMBLE } from './preamble';
test('MergeAttributeData #1', () => {
+ TEST_PREAMBLE();
+
const a: AttributeData = {
indices: new Uint32Array([0, 1, 2]),
custom: {
@@ -13,6 +16,8 @@ test('MergeAttributeData #1', () => {
});
test('MergeAttributeData #2', () => {
+ TEST_PREAMBLE();
+
const a: AttributeData = {
indices: new Uint32Array([0, 1, 2]),
custom: {
@@ -32,7 +37,7 @@ test('MergeAttributeData #2', () => {
indices: new Uint32Array([0, 1, 2, 3, 4, 5]),
custom: {
position: [
- 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 18,
],
colour: [
@@ -45,6 +50,8 @@ test('MergeAttributeData #2', () => {
});
test('MergeAttributeData #3', () => {
+ TEST_PREAMBLE();
+
const a: AttributeData = {
indices: new Uint32Array([0, 1]),
custom: {
diff --git a/tests/normal-corrected-ray-voxeliser.test.ts b/tests/normal-corrected-ray-voxeliser.test.ts
index 6d0313bb..defb78e4 100644
--- a/tests/normal-corrected-ray-voxeliser.test.ts
+++ b/tests/normal-corrected-ray-voxeliser.test.ts
@@ -1,13 +1,16 @@
-import { NormalCorrectedRayVoxeliser } from '../src/voxelisers/normal-corrected-ray-voxeliser';
+import path from 'path';
+
+import { RGBAColours } from '../src/colour';
import { ObjImporter } from '../src/importers/obj_importer';
import { TextureFiltering } from '../src/texture';
-import { ASSERT } from '../src/util';
+import { ASSERT } from '../src/util/error_util';
import { Vector3 } from '../src/vector';
-
-import path from 'path';
-import { RGBAColours } from '../src/colour';
+import { NormalCorrectedRayVoxeliser } from '../src/voxelisers/normal-corrected-ray-voxeliser';
+import { TEST_PREAMBLE } from './preamble';
test('Voxelise solid 2x2 cube', () => {
+ TEST_PREAMBLE();
+
const importer = new ObjImporter();
importer.parseFile(path.join(__dirname, './data/cube.obj'));
const mesh = importer.toMesh();
@@ -20,7 +23,7 @@ test('Voxelise solid 2x2 cube', () => {
textureFiltering: TextureFiltering.Nearest,
enableAmbientOcclusion: false,
voxelOverlapRule: 'average',
- calculateNeighbours: false,
+ voxeliser: 'ncrb',
});
const expectedVoxels = [
diff --git a/tests/obj_importer.test.ts b/tests/obj_importer.test.ts
index b8887a9b..5dd13d9a 100644
--- a/tests/obj_importer.test.ts
+++ b/tests/obj_importer.test.ts
@@ -1,8 +1,11 @@
import { ObjImporter } from '../src/importers/obj_importer';
-import { ASSERT } from '../src/util';
+import { ASSERT } from '../src/util/error_util';
import { Vector3 } from '../src/vector';
+import { TEST_PREAMBLE } from './preamble';
test('Parse vertex #1', () => {
+ TEST_PREAMBLE();
+
const importer = new ObjImporter();
importer.parseOBJLine('v 1.0 -2.0 3.0');
const mesh = importer.toMesh();
@@ -11,6 +14,8 @@ test('Parse vertex #1', () => {
});
test('Parse vertex #2', () => {
+ TEST_PREAMBLE();
+
const importer = new ObjImporter();
importer.parseOBJLine('v 4.467e+000 9.243e+000 9.869e+000');
const mesh = importer.toMesh();
@@ -19,6 +24,8 @@ test('Parse vertex #2', () => {
});
test('Parse normal #1', () => {
+ TEST_PREAMBLE();
+
const importer = new ObjImporter();
importer.parseOBJLine('vn -1.0 -0.5 0.0');
const mesh = importer.toMesh();
@@ -27,6 +34,8 @@ test('Parse normal #1', () => {
});
test('Parse texcoord #1', () => {
+ TEST_PREAMBLE();
+
const importer = new ObjImporter();
importer.parseOBJLine('vt 0.5 -0.8');
const mesh = importer.toMesh();
@@ -35,6 +44,8 @@ test('Parse texcoord #1', () => {
});
test('Parse face #1', () => {
+ TEST_PREAMBLE();
+
const importer = new ObjImporter();
importer.parseOBJLine('f 12 24 36');
const mesh = importer.toMesh();
@@ -44,10 +55,12 @@ test('Parse face #1', () => {
expect(tri.normalIndices).toBeDefined(); ASSERT(tri.normalIndices);
expect(tri.positionIndices.x === 12 - 1 && tri.positionIndices.y === 24 - 1 && tri.positionIndices.z === 36 - 1).toBe(true);
expect(tri.texcoordIndices.x === 12 - 1 && tri.texcoordIndices.y === 24 - 1 && tri.texcoordIndices.z === 36 - 1).toBe(true);
- expect(tri.normalIndices.x === 12 - 1 && tri.normalIndices.y === 24 - 1 && tri.normalIndices.z === 36 - 1).toBe(true);
+ expect(tri.normalIndices.x === 12 - 1 && tri.normalIndices.y === 24 - 1 && tri.normalIndices.z === 36 - 1).toBe(true);
});
test('Parse face #2', () => {
+ TEST_PREAMBLE();
+
const importer = new ObjImporter();
importer.parseOBJLine('f 1/2 3/4 5/6');
const mesh = importer.toMesh();
@@ -60,6 +73,8 @@ test('Parse face #2', () => {
});
test('Parse face #3', () => {
+ TEST_PREAMBLE();
+
const importer = new ObjImporter();
importer.parseOBJLine('f 11/2/3 4/55/6 7/8/99');
const mesh = importer.toMesh();
@@ -67,12 +82,14 @@ test('Parse face #3', () => {
const tri = mesh._tris[0];
expect(tri.texcoordIndices).toBeDefined(); ASSERT(tri.texcoordIndices);
expect(tri.normalIndices).toBeDefined(); ASSERT(tri.normalIndices);
- expect(tri.positionIndices.x === 11 - 1 && tri.positionIndices.y === 4 - 1&& tri.positionIndices.z === 7 - 1).toBe(true);
+ expect(tri.positionIndices.x === 11 - 1 && tri.positionIndices.y === 4 - 1 && tri.positionIndices.z === 7 - 1).toBe(true);
expect(tri.texcoordIndices.x === 2 - 1 && tri.texcoordIndices.y === 55 - 1 && tri.texcoordIndices.z === 8 - 1).toBe(true);
expect(tri.normalIndices.x === 3 - 1 && tri.normalIndices.y === 6 - 1 && tri.normalIndices.z === 99 - 1).toBe(true);
});
test('Parse mini #1', () => {
+ TEST_PREAMBLE();
+
const importer = new ObjImporter();
importer.parseOBJLine('v -1 2 3');
importer.parseOBJLine('v 4 -5 6');
@@ -95,7 +112,7 @@ test('Parse mini #1', () => {
expect(vertexData.v0.equals(new Vector3(-1, 2, 3))).toBe(true);
expect(vertexData.v1.equals(new Vector3(4, -5, 6))).toBe(true);
expect(vertexData.v2.equals(new Vector3(7, 8, -9))).toBe(true);
-
+
const texcoordData = mesh.getUVs(0);
expect(texcoordData.uv0.u === 0.0 && texcoordData.uv0.v === 0.5).toBe(true);
expect(texcoordData.uv1.u === 0.5 && texcoordData.uv1.v === 1.0).toBe(true);
@@ -109,6 +126,8 @@ test('Parse mini #1', () => {
test('Parse mini #2', () => {
+ TEST_PREAMBLE();
+
const importer = new ObjImporter();
importer.parseOBJLine('v -1 2 3');
importer.parseOBJLine('v 4 -5 6');
@@ -131,7 +150,7 @@ test('Parse mini #2', () => {
expect(vertexData.v0.equals(new Vector3(7, 8, -9))).toBe(true);
expect(vertexData.v1.equals(new Vector3(-1, 2, 3))).toBe(true);
expect(vertexData.v2.equals(new Vector3(4, -5, 6))).toBe(true);
-
+
const texcoordData = mesh.getUVs(0);
expect(texcoordData.uv0.u === 0.0 && texcoordData.uv0.v === 0.5).toBe(true);
expect(texcoordData.uv1.u === 0.5 && texcoordData.uv1.v === 1.0).toBe(true);
@@ -144,6 +163,8 @@ test('Parse mini #2', () => {
});
test('Parse mini #3', () => {
+ TEST_PREAMBLE();
+
const importer = new ObjImporter();
importer.parseOBJLine('v 0 0 0');
importer.parseOBJLine('v 1 0 0');
@@ -168,6 +189,8 @@ test('Parse mini #3', () => {
});
test('Parse comments', () => {
+ TEST_PREAMBLE();
+
const importer = new ObjImporter();
importer.parseOBJLine('# v -1 2 3');
importer.parseOBJLine('# vn 0.0 0.1 0.2');
diff --git a/tests/objlitematic.test.ts b/tests/objlitematic.test.ts
new file mode 100644
index 00000000..6791d4e3
--- /dev/null
+++ b/tests/objlitematic.test.ts
@@ -0,0 +1,48 @@
+import { TextureFiltering } from '../src/texture';
+import { ColourSpace } from '../src/util';
+import { AppPaths, PathUtil } from '../src/util/path_util';
+import { runHeadless, THeadlessConfig } from '../tools/headless';
+import { TEST_PREAMBLE } from './preamble';
+
+const baseConfig: THeadlessConfig = {
+ import: {
+ filepath: '', // Must be an absolute path
+ },
+ voxelise: {
+ voxeliser: 'bvh-ray',
+ desiredHeight: 80,
+ useMultisampleColouring: false,
+ textureFiltering: TextureFiltering.Linear,
+ voxelOverlapRule: 'average',
+ enableAmbientOcclusion: false, // Only want true if exporting to .obj
+ },
+ assign: {
+ textureAtlas: 'vanilla', // Must be an atlas name that exists in /resources/atlases
+ blockPalette: 'all-snapshot', // Must be a palette name that exists in /resources/palettes
+ blockAssigner: 'ordered-dithering',
+ colourSpace: ColourSpace.RGB,
+ fallable: 'replace-falling',
+ resolution: 32,
+ },
+ export: {
+ filepath: '', // Must be an absolute path to the file (can be anywhere)
+ exporter: 'obj', // 'schematic' / 'litematic',
+ },
+ debug: {
+ showLogs: false,
+ showWarnings: false,
+ showTimings: false,
+ },
+};
+
+test('FULL Obj->Obj', () => {
+ TEST_PREAMBLE();
+
+ const config: THeadlessConfig = baseConfig;
+
+ config.import.filepath = PathUtil.join(AppPaths.Get.resources, './samples/skull.obj');
+ config.export.exporter = 'litematic';
+ config.export.filepath = PathUtil.join(AppPaths.Get.testData, '../out/out.litematic');
+
+ runHeadless(config);
+});
diff --git a/tests/objobj.test.ts b/tests/objobj.test.ts
new file mode 100644
index 00000000..537e67eb
--- /dev/null
+++ b/tests/objobj.test.ts
@@ -0,0 +1,48 @@
+import { TextureFiltering } from '../src/texture';
+import { ColourSpace } from '../src/util';
+import { AppPaths, PathUtil } from '../src/util/path_util';
+import { runHeadless, THeadlessConfig } from '../tools/headless';
+import { TEST_PREAMBLE } from './preamble';
+
+const baseConfig: THeadlessConfig = {
+ import: {
+ filepath: '', // Must be an absolute path
+ },
+ voxelise: {
+ voxeliser: 'bvh-ray',
+ desiredHeight: 80,
+ useMultisampleColouring: false,
+ textureFiltering: TextureFiltering.Linear,
+ voxelOverlapRule: 'average',
+ enableAmbientOcclusion: false, // Only want true if exporting to .obj
+ },
+ assign: {
+ textureAtlas: 'vanilla', // Must be an atlas name that exists in /resources/atlases
+ blockPalette: 'all-snapshot', // Must be a palette name that exists in /resources/palettes
+ blockAssigner: 'ordered-dithering',
+ colourSpace: ColourSpace.RGB,
+ fallable: 'replace-falling',
+ resolution: 32,
+ },
+ export: {
+ filepath: '', // Must be an absolute path to the file (can be anywhere)
+ exporter: 'obj', // 'schematic' / 'litematic',
+ },
+ debug: {
+ showLogs: false,
+ showWarnings: false,
+ showTimings: false,
+ },
+};
+
+test('FULL Obj->Obj', () => {
+ TEST_PREAMBLE();
+
+ const config: THeadlessConfig = baseConfig;
+
+ config.import.filepath = PathUtil.join(AppPaths.Get.resources, './samples/skull.obj');
+ config.export.exporter = 'obj';
+ config.export.filepath = PathUtil.join(AppPaths.Get.testData, '../out/out.obj');
+
+ runHeadless(config);
+});
diff --git a/tests/objschem.test.ts b/tests/objschem.test.ts
new file mode 100644
index 00000000..a9a9340d
--- /dev/null
+++ b/tests/objschem.test.ts
@@ -0,0 +1,48 @@
+import { TextureFiltering } from '../src/texture';
+import { ColourSpace } from '../src/util';
+import { AppPaths, PathUtil } from '../src/util/path_util';
+import { runHeadless, THeadlessConfig } from '../tools/headless';
+import { TEST_PREAMBLE } from './preamble';
+
+const baseConfig: THeadlessConfig = {
+ import: {
+ filepath: '', // Must be an absolute path
+ },
+ voxelise: {
+ voxeliser: 'bvh-ray',
+ desiredHeight: 80,
+ useMultisampleColouring: false,
+ textureFiltering: TextureFiltering.Linear,
+ voxelOverlapRule: 'average',
+ enableAmbientOcclusion: false, // Only want true if exporting to .obj
+ },
+ assign: {
+ textureAtlas: 'vanilla', // Must be an atlas name that exists in /resources/atlases
+ blockPalette: 'all-snapshot', // Must be a palette name that exists in /resources/palettes
+ blockAssigner: 'ordered-dithering',
+ colourSpace: ColourSpace.RGB,
+ fallable: 'replace-falling',
+ resolution: 32,
+ },
+ export: {
+ filepath: '', // Must be an absolute path to the file (can be anywhere)
+ exporter: 'obj', // 'schematic' / 'litematic',
+ },
+ debug: {
+ showLogs: false,
+ showWarnings: false,
+ showTimings: false,
+ },
+};
+
+test('FULL Obj->Obj', () => {
+ TEST_PREAMBLE();
+
+ const config: THeadlessConfig = baseConfig;
+
+ config.import.filepath = PathUtil.join(AppPaths.Get.resources, './samples/skull.obj');
+ config.export.exporter = 'schem';
+ config.export.filepath = PathUtil.join(AppPaths.Get.testData, '../out/out.schem');
+
+ runHeadless(config);
+});
diff --git a/tests/objschematic.test.ts b/tests/objschematic.test.ts
new file mode 100644
index 00000000..44995133
--- /dev/null
+++ b/tests/objschematic.test.ts
@@ -0,0 +1,48 @@
+import { TextureFiltering } from '../src/texture';
+import { ColourSpace } from '../src/util';
+import { AppPaths, PathUtil } from '../src/util/path_util';
+import { runHeadless, THeadlessConfig } from '../tools/headless';
+import { TEST_PREAMBLE } from './preamble';
+
+const baseConfig: THeadlessConfig = {
+ import: {
+ filepath: '', // Must be an absolute path
+ },
+ voxelise: {
+ voxeliser: 'bvh-ray',
+ desiredHeight: 80,
+ useMultisampleColouring: false,
+ textureFiltering: TextureFiltering.Linear,
+ voxelOverlapRule: 'average',
+ enableAmbientOcclusion: false, // Only want true if exporting to .obj
+ },
+ assign: {
+ textureAtlas: 'vanilla', // Must be an atlas name that exists in /resources/atlases
+ blockPalette: 'all-snapshot', // Must be a palette name that exists in /resources/palettes
+ blockAssigner: 'ordered-dithering',
+ colourSpace: ColourSpace.RGB,
+ fallable: 'replace-falling',
+ resolution: 32,
+ },
+ export: {
+ filepath: '', // Must be an absolute path to the file (can be anywhere)
+ exporter: 'obj', // 'schematic' / 'litematic',
+ },
+ debug: {
+ showLogs: false,
+ showWarnings: false,
+ showTimings: false,
+ },
+};
+
+test('FULL Obj->Schematic', () => {
+ TEST_PREAMBLE();
+
+ const config: THeadlessConfig = baseConfig;
+
+ config.import.filepath = PathUtil.join(AppPaths.Get.resources, './samples/skull.obj');
+ config.export.exporter = 'schematic';
+ config.export.filepath = PathUtil.join(AppPaths.Get.testData, '../out/out.schematic');
+
+ runHeadless(config);
+});
diff --git a/tests/palette.test.ts b/tests/palette.test.ts
new file mode 100644
index 00000000..bf3d67fe
--- /dev/null
+++ b/tests/palette.test.ts
@@ -0,0 +1,9 @@
+import { Palette } from '../src/palette';
+
+test('Palette', () => {
+ const myPalette = Palette.create();
+ myPalette.add('minecraft:stone');
+ expect(myPalette.count()).toBe(1);
+ myPalette.remove('minecraft:stone');
+ expect(myPalette.count()).toBe(0);
+});
diff --git a/tests/preamble.ts b/tests/preamble.ts
new file mode 100644
index 00000000..f6edd245
--- /dev/null
+++ b/tests/preamble.ts
@@ -0,0 +1,9 @@
+import { FileUtil } from '../src/util/file_util';
+import { Logger } from '../src/util/log_util';
+import { AppPaths, PathUtil } from '../src/util/path_util';
+
+export const TEST_PREAMBLE = () => {
+ Logger.Get.disableLogToFile();
+ AppPaths.Get.setBaseDir(PathUtil.join(__dirname, '..'));
+ FileUtil.mkdirSyncIfNotExist(PathUtil.join(AppPaths.Get.tests, './out/'));
+};
diff --git a/tests/random-dither.test.ts b/tests/random-dither.test.ts
new file mode 100644
index 00000000..48de85cf
--- /dev/null
+++ b/tests/random-dither.test.ts
@@ -0,0 +1,21 @@
+import { StatusHandler, StatusID } from '../src/status';
+import { AppPaths, PathUtil } from '../src/util/path_util';
+import { WorkerClient } from '../src/worker_client';
+import { headlessConfig } from '../tools/headless-config';
+import { TEST_PREAMBLE } from './preamble';
+
+test('Random-dither', () => {
+ TEST_PREAMBLE();
+
+ const config = headlessConfig;
+
+ config.import.filepath = PathUtil.join(AppPaths.Get.resources, './samples/skull.obj');
+ config.assign.blockAssigner = 'random-dithering';
+
+ const worker = WorkerClient.Get;
+ worker.import(headlessConfig.import);
+ worker.voxelise(headlessConfig.voxelise);
+ worker.assign(headlessConfig.assign);
+
+ expect(StatusHandler.Get.hasId(StatusID.SchematicUnsupportedBlocks)).toBe(false);
+});
diff --git a/tests/ray.test.ts b/tests/ray.test.ts
index 198c355f..2f5708a2 100644
--- a/tests/ray.test.ts
+++ b/tests/ray.test.ts
@@ -1,17 +1,20 @@
-import { Ray, Axes, rayIntersectTriangle } from '../src/ray';
-import { Vector3 } from '../src/vector';
+import { Axes, Ray, rayIntersectTriangle } from '../src/ray';
import { Triangle } from '../src/triangle';
-import { ASSERT } from '../src/util';
+import { ASSERT } from '../src/util/error_util';
+import { Vector3 } from '../src/vector';
+import { TEST_PREAMBLE } from './preamble';
test('rayIntersectTriangle x-axis #1', () => {
+ TEST_PREAMBLE();
+
const ray: Ray = {
origin: new Vector3(-1, 0, 0),
axis: Axes.x,
};
const tri = new Triangle(
new Vector3(5, -1, -1),
- new Vector3(5, 0, 1),
- new Vector3(5, 1, -1),
+ new Vector3(5, 0, 1),
+ new Vector3(5, 1, -1),
);
const intersects = rayIntersectTriangle(ray, tri.v0, tri.v1, tri.v2);
expect(intersects).toBeDefined();
@@ -20,28 +23,32 @@ test('rayIntersectTriangle x-axis #1', () => {
});
test('rayIntersectTriangle x-axis #2', () => {
+ TEST_PREAMBLE();
+
const ray: Ray = {
origin: new Vector3(1, 0, 0),
axis: Axes.x,
};
const tri = new Triangle(
new Vector3(0, -1, -1),
- new Vector3(0, 0, 1),
- new Vector3(0, 1, -1),
+ new Vector3(0, 0, 1),
+ new Vector3(0, 1, -1),
);
const intersects = rayIntersectTriangle(ray, tri.v0, tri.v1, tri.v2);
expect(intersects).toBeUndefined();
});
test('rayIntersectTriangle y-axis #1', () => {
+ TEST_PREAMBLE();
+
const ray: Ray = {
origin: new Vector3(0, -1, 0),
axis: Axes.y,
};
const tri = new Triangle(
new Vector3(-1, 6, -1),
- new Vector3( 0, 6, 1),
- new Vector3( 1, 6, -1),
+ new Vector3(0, 6, 1),
+ new Vector3(1, 6, -1),
);
const intersects = rayIntersectTriangle(ray, tri.v0, tri.v1, tri.v2);
expect(intersects).toBeDefined();
@@ -50,28 +57,32 @@ test('rayIntersectTriangle y-axis #1', () => {
});
test('rayIntersectTriangle y-axis #2', () => {
+ TEST_PREAMBLE();
+
const ray: Ray = {
origin: new Vector3(0, 1, 0),
axis: Axes.y,
};
const tri = new Triangle(
new Vector3(-1, 0, -1),
- new Vector3( 0, 0, 1),
- new Vector3( 1, 0, -1),
+ new Vector3(0, 0, 1),
+ new Vector3(1, 0, -1),
);
const intersects = rayIntersectTriangle(ray, tri.v0, tri.v1, tri.v2);
expect(intersects).toBeUndefined();
});
test('rayIntersectTriangle z-axis #1', () => {
+ TEST_PREAMBLE();
+
const ray: Ray = {
origin: new Vector3(0, 0, -1),
axis: Axes.z,
};
const tri = new Triangle(
new Vector3(-1, -1, 7),
- new Vector3( 0, 1, 7),
- new Vector3( 1, -1, 7),
+ new Vector3(0, 1, 7),
+ new Vector3(1, -1, 7),
);
const intersects = rayIntersectTriangle(ray, tri.v0, tri.v1, tri.v2);
expect(intersects).toBeDefined();
@@ -80,14 +91,16 @@ test('rayIntersectTriangle z-axis #1', () => {
});
test('rayIntersectTriangle z-axis #2', () => {
+ TEST_PREAMBLE();
+
const ray: Ray = {
origin: new Vector3(0, 0, 1),
axis: Axes.z,
};
const tri = new Triangle(
new Vector3(-1, -1, 0),
- new Vector3( 0, 1, 0),
- new Vector3( 1, -1, 0),
+ new Vector3(0, 1, 0),
+ new Vector3(1, -1, 0),
);
const intersects = rayIntersectTriangle(ray, tri.v0, tri.v1, tri.v2);
expect(intersects).toBeUndefined();
diff --git a/tests/schematic-friendly.test.ts b/tests/schematic-friendly.test.ts
new file mode 100644
index 00000000..cc7f6f63
--- /dev/null
+++ b/tests/schematic-friendly.test.ts
@@ -0,0 +1,24 @@
+import { StatusHandler, StatusID } from '../src/status';
+import { AppPaths, PathUtil } from '../src/util/path_util';
+import { WorkerClient } from '../src/worker_client';
+import { headlessConfig } from '../tools/headless-config';
+import { TEST_PREAMBLE } from './preamble';
+
+test('Schematic-friendly Palette', () => {
+ TEST_PREAMBLE();
+
+ const config = headlessConfig;
+
+ config.import.filepath = PathUtil.join(AppPaths.Get.resources, './samples/skull.obj');
+ config.assign.blockPalette = 'schematic-friendly';
+ config.export.exporter = 'schematic';
+ config.export.filepath = PathUtil.join(AppPaths.Get.testData, '../out/friendly.schematic');
+
+ const worker = WorkerClient.Get;
+ worker.import(headlessConfig.import);
+ worker.voxelise(headlessConfig.voxelise);
+ worker.assign(headlessConfig.assign);
+ worker.export(headlessConfig.export);
+
+ expect(StatusHandler.Get.hasId(StatusID.SchematicUnsupportedBlocks)).toBe(false);
+});
diff --git a/tests/status.test.ts b/tests/status.test.ts
index ff938c4d..6b20349b 100644
--- a/tests/status.test.ts
+++ b/tests/status.test.ts
@@ -1,6 +1,9 @@
import { StatusHandler } from '../src/status';
+import { TEST_PREAMBLE } from './preamble';
test('Status', () => {
+ TEST_PREAMBLE();
+
StatusHandler.Get.add(
'warning',
'This is a warning',
@@ -11,6 +14,8 @@ test('Status', () => {
});
test('Status', () => {
+ TEST_PREAMBLE();
+
StatusHandler.Get.add(
'warning',
'This is a warning',
@@ -23,9 +28,9 @@ test('Status', () => {
'info',
'This is some more info',
);
- expect(StatusHandler.Get.getStatusMessages( 'info').length).toBe(2);
- expect(StatusHandler.Get.getStatusMessages( 'warning').length).toBe(1);
+ expect(StatusHandler.Get.getStatusMessages('info').length).toBe(2);
+ expect(StatusHandler.Get.getStatusMessages('warning').length).toBe(1);
StatusHandler.Get.clear();
- expect(StatusHandler.Get.getStatusMessages( 'info').length).toBe(0);
- expect(StatusHandler.Get.getStatusMessages( 'warning').length).toBe(0);
+ expect(StatusHandler.Get.getStatusMessages('info').length).toBe(0);
+ expect(StatusHandler.Get.getStatusMessages('warning').length).toBe(0);
});
diff --git a/tests/util.test.ts b/tests/util.test.ts
index cf954e46..f3f9262d 100644
--- a/tests/util.test.ts
+++ b/tests/util.test.ts
@@ -1,6 +1,11 @@
-import { ASSERT, RegExpBuilder, REGEX_NUMBER, REGEX_NZ_ANY } from '../src/util';
+import { AppUtil } from '../src/util';
+import { ASSERT } from '../src/util/error_util';
+import { REGEX_NUMBER, REGEX_NZ_ANY, RegExpBuilder } from '../src/util/regex_util';
+import { TEST_PREAMBLE } from './preamble';
test('RegExpBuilder', () => {
+ TEST_PREAMBLE();
+
const regex = new RegExpBuilder()
.add(/hello/)
.toRegExp();
@@ -9,6 +14,8 @@ test('RegExpBuilder', () => {
});
test('RegExpBuilder REGEX_NUMBER', () => {
+ TEST_PREAMBLE();
+
const tests = [
{ f: '0', s: 0 },
{ f: '0.0', s: 0.0 },
@@ -25,6 +32,8 @@ test('RegExpBuilder REGEX_NUMBER', () => {
});
test('RegExpBuilder Required-whitespace', () => {
+ TEST_PREAMBLE();
+
const regex = new RegExpBuilder()
.add(/hello/)
.addNonzeroWhitespace()
@@ -36,6 +45,8 @@ test('RegExpBuilder Required-whitespace', () => {
});
test('RegExpBuilder Optional', () => {
+ TEST_PREAMBLE();
+
const regex = new RegExpBuilder()
.add(/hello/)
.addNonzeroWhitespace()
@@ -48,6 +59,8 @@ test('RegExpBuilder Optional', () => {
});
test('RegExpBuilder Capture', () => {
+ TEST_PREAMBLE();
+
const regex = new RegExpBuilder()
.add(/[0-9]+/, 'myNumber')
.toRegExp();
@@ -60,6 +73,8 @@ test('RegExpBuilder Capture', () => {
});
test('RegExpBuilder Capture-multiple', () => {
+ TEST_PREAMBLE();
+
const regex = new RegExpBuilder()
.add(/[0-9]+/, 'x')
.addNonzeroWhitespace()
@@ -81,6 +96,8 @@ test('RegExpBuilder Capture-multiple', () => {
});
test('RegExpBuilder Capture-multiple', () => {
+ TEST_PREAMBLE();
+
const regex = new RegExpBuilder()
.add(/f/)
.addNonzeroWhitespace()
@@ -123,6 +140,8 @@ test('RegExpBuilder Capture-multiple', () => {
});
test('RegExpBuilder Capture-multiple', () => {
+ TEST_PREAMBLE();
+
const regex = new RegExpBuilder()
.add(/usemtl/)
.add(/ /)
@@ -135,3 +154,11 @@ test('RegExpBuilder Capture-multiple', () => {
expect(exec.groups['path']).toBe('hellothere.txt');
}
});
+
+test('Namespace block', () => {
+ expect(AppUtil.Text.namespaceBlock('stone')).toBe('minecraft:stone');
+});
+
+test('Namespace already namespaced block', () => {
+ expect(AppUtil.Text.namespaceBlock('minecraft:stone')).toBe('minecraft:stone');
+});
diff --git a/tests/voxel_mesh.test.ts b/tests/voxel_mesh.test.ts
index 41df4e02..75f3b729 100644
--- a/tests/voxel_mesh.test.ts
+++ b/tests/voxel_mesh.test.ts
@@ -1,12 +1,16 @@
+import { RGBAColours } from '../src/colour';
+import { ASSERT } from '../src/util/error_util';
import { Vector3 } from '../src/vector';
import { VoxelMesh } from '../src/voxel_mesh';
-import { RGBAColours } from '../src/colour';
-import { ASSERT } from '../src/util';
+import { TEST_PREAMBLE } from './preamble';
test('Voxel neighbours', () => {
+ TEST_PREAMBLE();
+
const voxelMesh = new VoxelMesh({
voxelOverlapRule: 'first',
- calculateNeighbours: true,
+ enableAmbientOcclusion: true,
+
});
voxelMesh.addVoxel(new Vector3(1, 2, 3), RGBAColours.WHITE);
@@ -25,7 +29,7 @@ test('Voxel neighbours', () => {
test('Add voxel', () => {
const voxelMesh = new VoxelMesh({
voxelOverlapRule: 'first',
- calculateNeighbours: true,
+ enableAmbientOcclusion: true,
});
voxelMesh.addVoxel(new Vector3(1, 2, 3), RGBAColours.RED);
@@ -41,7 +45,7 @@ test('Add voxel', () => {
test('Voxel overlap first', () => {
const voxelMesh = new VoxelMesh({
voxelOverlapRule: 'first',
- calculateNeighbours: false,
+ enableAmbientOcclusion: false,
});
voxelMesh.addVoxel(new Vector3(1, 2, 3), RGBAColours.RED);
@@ -53,11 +57,11 @@ test('Voxel overlap first', () => {
test('Voxel overlap average', () => {
const voxelMesh = new VoxelMesh({
voxelOverlapRule: 'average',
- calculateNeighbours: false,
+ enableAmbientOcclusion: false,
});
voxelMesh.addVoxel(new Vector3(1, 2, 3), { r: 1.0, g: 0.5, b: 0.25, a: 1.0 });
voxelMesh.addVoxel(new Vector3(1, 2, 3), { r: 0.0, g: 0.5, b: 0.75, a: 1.0 });
- expect(voxelMesh.getVoxelAt(new Vector3(1, 2, 3))?.colour).toEqual({ r: 0.5, g: 0.5, b: 0.5, a: 1.0});
+ expect(voxelMesh.getVoxelAt(new Vector3(1, 2, 3))?.colour).toEqual({ r: 0.5, g: 0.5, b: 0.5, a: 1.0 });
});
diff --git a/tools/all-supported-blocks.txt b/tools/all-supported-blocks.txt
index bcc20776..0137eccf 100644
--- a/tools/all-supported-blocks.txt
+++ b/tools/all-supported-blocks.txt
@@ -238,7 +238,6 @@ smooth_quartz
smooth_red_sandstone
smooth_sandstone
smooth_stone
-smooth_stone_slab_double
snow_block
soul_sand
soul_soil
diff --git a/tools/build-atlas.ts b/tools/build-atlas.ts
index 3954dd4b..d47611bd 100644
--- a/tools/build-atlas.ts
+++ b/tools/build-atlas.ts
@@ -1,18 +1,24 @@
-import { ATLASES_DIR, TOOLS_DIR, UV } from '../src/util';
-import { log, LogStyle } from './logging';
-import { isDirSetup, ASSERT, getAverageColour, getPermission, getMinecraftDir } from './misc';
-
+import AdmZip from 'adm-zip';
+import chalk from 'chalk';
import fs from 'fs';
import path from 'path';
-import images from 'images';
import { PNG } from 'pngjs';
-import chalk from 'chalk';
import prompt from 'prompt';
-import { RGBA } from '../src/colour';
-const AdmZip = require('adm-zip');
+import * as sharp from 'sharp';
const copydir = require('copy-dir');
+import { RGBA } from '../src/colour';
+import { UV } from '../src/util';
+import { AppPaths, PathUtil } from '../src/util/path_util';
+import { log, LogStyle } from './logging';
+import { ASSERT, getAverageColour, getMinecraftDir, getPermission, isDirSetup } from './misc'; ;
+
+const BLOCKS_DIR = PathUtil.join(AppPaths.Get.tools, '/blocks');
+const MODELS_DIR = PathUtil.join(AppPaths.Get.tools, '/models');
+
void async function main() {
+ AppPaths.Get.setBaseDir(PathUtil.join(__dirname, '../..'));
+
await getPermission();
checkMinecraftInstallation();
cleanupDirectories();
@@ -33,8 +39,8 @@ function checkMinecraftInstallation() {
}
function cleanupDirectories() {
- fs.rmSync(path.join(TOOLS_DIR, '/blocks'), { recursive: true, force: true });
- fs.rmSync(path.join(TOOLS_DIR, '/models'), { recursive: true, force: true });
+ fs.rmSync(BLOCKS_DIR, { recursive: true, force: true });
+ fs.rmSync(MODELS_DIR, { recursive: true, force: true });
}
async function getResourcePack() {
@@ -48,14 +54,14 @@ async function getResourcePack() {
const resourcePacks = fs.readdirSync(resourcePacksDir);
log(LogStyle.None, `1) Vanilla`);
for (let i = 0; i < resourcePacks.length; ++i) {
- log(LogStyle.None, `${i+2}) ${resourcePacks[i]}`);
+ log(LogStyle.None, `${i + 2}) ${resourcePacks[i]}`);
}
const { packChoice } = await prompt.get({
properties: {
packChoice: {
- description: `Which resource pack do you want to build an atlas for? (1-${resourcePacks.length+1})`,
- message: `Response must be between 1 and ${resourcePacks.length+1}`,
+ description: `Which resource pack do you want to build an atlas for? (1-${resourcePacks.length + 1})`,
+ message: `Response must be between 1 and ${resourcePacks.length + 1}`,
required: true,
conform: (value) => {
return value >= 1 && value <= resourcePacks.length + 1;
@@ -97,9 +103,9 @@ function fetchVanillModelsAndTextures(fetchTextures: boolean) {
const zipEntries = zip.getEntries();
zipEntries.forEach((zipEntry: any) => {
if (fetchTextures && zipEntry.entryName.startsWith('assets/minecraft/textures/block')) {
- zip.extractEntryTo(zipEntry.entryName, path.join(TOOLS_DIR, './blocks'), false, true);
+ zip.extractEntryTo(zipEntry.entryName, BLOCKS_DIR, false, true);
} else if (zipEntry.entryName.startsWith('assets/minecraft/models/block')) {
- zip.extractEntryTo(zipEntry.entryName, path.join(TOOLS_DIR, './models'), false, true);
+ zip.extractEntryTo(zipEntry.entryName, MODELS_DIR, false, true);
}
});
log(LogStyle.Success, `Extracted textures and models successfully\n`);
@@ -120,7 +126,7 @@ async function fetchModelsAndTextures() {
if (fs.lstatSync(resourcePackDir).isDirectory()) {
log(LogStyle.Info, `Resource pack '${resourcePack}' is a directory`);
const blockTexturesSrc = path.join(resourcePackDir, 'assets/minecraft/textures/block');
- const blockTexturesDst = path.join(TOOLS_DIR, './blocks');
+ const blockTexturesDst = BLOCKS_DIR;
log(LogStyle.Info, `Copying ${blockTexturesSrc} to ${blockTexturesDst}`);
copydir(blockTexturesSrc, blockTexturesDst, {
utimes: true,
@@ -130,12 +136,12 @@ async function fetchModelsAndTextures() {
log(LogStyle.Success, `Copied block textures successfully`);
} else {
log(LogStyle.Info, `Resource pack '${resourcePack}' is not a directory, expecting to be a .zip`);
-
+
const zip = new AdmZip(resourcePackDir);
const zipEntries = zip.getEntries();
zipEntries.forEach((zipEntry: any) => {
if (zipEntry.entryName.startsWith('assets/minecraft/textures/block')) {
- zip.extractEntryTo(zipEntry.entryName, path.join(TOOLS_DIR, './blocks'), false, true);
+ zip.extractEntryTo(zipEntry.entryName, BLOCKS_DIR, false, true);
}
});
log(LogStyle.Success, `Copied block textures successfully`);
@@ -145,20 +151,20 @@ async function fetchModelsAndTextures() {
async function buildAtlas() {
// Check /blocks and /models is setup correctly
- log(LogStyle.Info, 'Checking assets are provided...');
-
+ log(LogStyle.Info, 'Checking assets are provided...');
+
const texturesDirSetup = isDirSetup('./blocks', 'assets/minecraft/textures/block');
ASSERT(texturesDirSetup, '/blocks is not setup correctly');
- log(LogStyle.Success, '/tools/blocks/ setup correctly');
-
+ log(LogStyle.Success, '/tools/blocks/ setup correctly');
+
const modelsDirSetup = isDirSetup('./models', 'assets/minecraft/models/block');
ASSERT(modelsDirSetup, '/models is not setup correctly');
- log(LogStyle.Success, '/tools/models/ setup correctly');
+ log(LogStyle.Success, '/tools/models/ setup correctly');
// Load the ignore list
log(LogStyle.Info, 'Loading ignore list...');
let ignoreList: Array = [];
- const ignoreListPath = path.join(TOOLS_DIR, './ignore-list.txt');
+ const ignoreListPath = path.join(AppPaths.Get.tools, './ignore-list.txt');
if (fs.existsSync(ignoreListPath)) {
log(LogStyle.Success, 'Found ignore list');
ignoreList = fs.readFileSync(ignoreListPath, 'utf-8').replace(/\r/g, '').split('\n');
@@ -179,7 +185,7 @@ async function buildAtlas() {
Leaves = 'minecraft:block/leaves',
}
/* eslint-enable */
-
+
interface Model {
name: string,
colour?: RGBA,
@@ -187,24 +193,24 @@ async function buildAtlas() {
[face: string]: Texture
}
}
-
+
interface Texture {
name: string,
texcoord?: UV,
colour?: RGBA
}
-
+
log(LogStyle.Info, 'Loading block models...');
const faces = ['north', 'south', 'up', 'down', 'east', 'west'];
const allModels: Array = [];
const allBlockNames: Set = new Set();
const usedTextures: Set = new Set();
- fs.readdirSync(path.join(TOOLS_DIR, './models')).forEach((filename) => {
+ fs.readdirSync(MODELS_DIR).forEach((filename) => {
if (path.extname(filename) !== '.json') {
return;
};
- const filePath = path.join(TOOLS_DIR, './models', filename);
+ const filePath = path.join(MODELS_DIR, filename);
const fileData = fs.readFileSync(filePath, 'utf8');
const modelData = JSON.parse(fileData);
const parsedPath = path.parse(filePath);
@@ -307,11 +313,10 @@ async function buildAtlas() {
log(LogStyle.Success, `${allModels.length} blocks loaded\n`);
const atlasSize = Math.ceil(Math.sqrt(usedTextures.size));
- const atlasWidth = atlasSize * 16;
+ const atlasWidthPixels = atlasSize * 16 * 3;
let offsetX = 0;
let offsetY = 0;
- const outputImage = images(atlasWidth * 3, atlasWidth * 3);
const textureDetails: { [textureName: string]: { texcoord: UV, colour: RGBA } } = {};
@@ -326,27 +331,43 @@ async function buildAtlas() {
},
});
+ //const tiles: mergeImages.ImageSource[] = [];
+ let outputImage = sharp.default({
+ create: {
+ width: atlasWidthPixels,
+ height: atlasWidthPixels,
+ channels: 4,
+ background: { r: 255, g: 255, b: 255, alpha: 0.0 },
+ },
+ });
+
+ const composites: sharp.OverlayOptions[] = [];
+
log(LogStyle.Info, `Building ${atlasName}.png...`);
usedTextures.forEach((textureName) => {
const shortName = textureName.split('/')[1]; // Eww
- const absolutePath = path.join(TOOLS_DIR, './blocks', shortName + '.png');
- const fileData = fs.readFileSync(absolutePath);
- const pngData = PNG.sync.read(fileData);
- const image = images(absolutePath);
+ const absolutePath = path.join(BLOCKS_DIR, shortName + '.png');
for (let x = 0; x < 3; ++x) {
for (let y = 0; y < 3; ++y) {
- outputImage.draw(image, 16 * (3 * offsetX + x), 16 * (3 * offsetY + y));
+ composites.push({
+ input: absolutePath,
+ left: 16 * (3 * offsetX + x),
+ top: 16 * (3 * offsetY + y),
+ });
}
}
+ const fileData = fs.readFileSync(absolutePath);
+ const pngData = PNG.sync.read(fileData);
+
textureDetails[textureName] = {
texcoord: new UV(
- 16 * (3 * offsetX + 1) / (atlasWidth * 3),
- 16 * (3 * offsetY + 1) / (atlasWidth * 3),
+ 16 * (3 * offsetX + 1) / atlasWidthPixels,
+ 16 * (3 * offsetY + 1) / atlasWidthPixels,
),
colour: getAverageColour(pngData),
- },
+ };
++offsetX;
if (offsetX >= atlasSize) {
@@ -355,6 +376,8 @@ async function buildAtlas() {
}
});
+ outputImage = outputImage.composite(composites);
+
// Build up the output JSON
log(LogStyle.Info, `Building ${atlasName}.atlas...\n`);
@@ -380,15 +403,17 @@ async function buildAtlas() {
log(LogStyle.Info, 'Exporting...');
- const atlasDir = path.join(ATLASES_DIR, `./${atlasName}.png`);
- outputImage.save(atlasDir);
+ const atlasTextureDir = path.join(AppPaths.Get.atlases, `./${atlasName}.png`);
+ await outputImage.toFile(atlasTextureDir);
+ //ASSERT(success, 'Unsuccess save');
+
log(LogStyle.Success, `${atlasName}.png exported to /resources/atlases/`);
const outputJSON = {
atlasSize: atlasSize,
blocks: allModels,
supportedBlockNames: Array.from(allBlockNames),
};
- fs.writeFileSync(path.join(ATLASES_DIR, `./${atlasName}.atlas`), JSON.stringify(outputJSON, null, 4));
+ fs.writeFileSync(path.join(AppPaths.Get.atlases, `./${atlasName}.atlas`), JSON.stringify(outputJSON, null, 4));
log(LogStyle.Success, `${atlasName}.atlas exported to /resources/atlases/\n`);
/* eslint-disable */
diff --git a/tools/build-palette.ts b/tools/build-palette.ts
index cd8131d7..93903567 100644
--- a/tools/build-palette.ts
+++ b/tools/build-palette.ts
@@ -1,20 +1,25 @@
-import { log, LogStyle } from './logging';
-import { TOOLS_DIR, PALETTES_DIR } from '../src/util';
-
import fs from 'fs';
import path from 'path';
import prompt from 'prompt';
+import { Palette } from '../src/palette';
+import { AppPaths, PathUtil } from '../src/util/path_util';
+import { log, LogStyle } from './logging';
+
+const PALETTE_NAME_REGEX = /^[a-zA-Z\-]+$/;
+
void async function main() {
+ AppPaths.Get.setBaseDir(PathUtil.join(__dirname, '../..'));
+
log(LogStyle.Info, 'Creating a new palette...');
-
- const paletteBlocksDir = path.join(TOOLS_DIR, './new-palette-blocks.txt');
+
+ const paletteBlocksDir = path.join(AppPaths.Get.tools, './new-palette-blocks.txt');
if (!fs.existsSync(paletteBlocksDir)) {
log(LogStyle.Failure, 'Could not find /tools/new-palette-blocks.txt');
return;
}
log(LogStyle.Success, 'Found list of blocks to use in /tools/new-palette-blocks.txt');
-
+
let blocksToUse: string[] = fs.readFileSync(paletteBlocksDir, 'utf8').replace(/\r/g, '').split('\n');
blocksToUse = blocksToUse.filter((block) => {
return block.length !== 0;
@@ -25,11 +30,11 @@ void async function main() {
return;
}
log(LogStyle.Info, `Found ${blocksToUse.length} blocks to use`);
-
+
const schema: prompt.Schema = {
properties: {
paletteName: {
- pattern: /^[a-zA-Z\-]+$/,
+ pattern: PALETTE_NAME_REGEX,
description: 'What do you want to call this block palette? (e.g. my-block-palette)',
message: 'Must be only letters or dash',
required: true,
@@ -39,10 +44,24 @@ void async function main() {
const promptUser = await prompt.get(schema);
- const paletteJSON = {
- blocks: blocksToUse,
- };
+ log(LogStyle.Info, 'Creating palette...');
+ const palette = Palette.create();
+ if (palette === undefined) {
+ log(LogStyle.Failure, 'Invalid palette name');
+ return;
+ }
- fs.writeFileSync(path.join(PALETTES_DIR, `./${promptUser.paletteName}.palette`), JSON.stringify(paletteJSON, null, 4));
- log(LogStyle.Success, `Successfully created ${promptUser.paletteName}.palette in /resources/palettes/`);
+ log(LogStyle.Info, 'Adding blocks to palette...');
+ for (const blockNames of blocksToUse) {
+ palette.add(blockNames);
+ }
+
+ log(LogStyle.Info, 'Saving palette...');
+ const success = palette.save(promptUser.paletteName as string);
+
+ if (success) {
+ log(LogStyle.Success, 'Palette saved.');
+ } else {
+ log(LogStyle.Failure, 'Could not save palette.');
+ }
}();
diff --git a/tools/headless-config.ts b/tools/headless-config.ts
index 52e5d672..d210ea25 100644
--- a/tools/headless-config.ts
+++ b/tools/headless-config.ts
@@ -1,31 +1,34 @@
-import { THeadlessConfig } from './headless';
import { TextureFiltering } from '../src/texture';
import { ColourSpace } from '../src/util';
+import { THeadlessConfig } from './headless';
export const headlessConfig: THeadlessConfig = {
import: {
- absoluteFilePathLoad: 'C:/Users//Desktop/my_model.obj', // Must be an absolute path to the file (can be anywhere)
+ filepath: '/Users/lucasdower/ObjToSchematic/res/samples/skull.obj', // Must be an absolute path
},
voxelise: {
voxeliser: 'bvh-ray',
- voxelMeshParams: {
- desiredHeight: 80, // 5-320 inclusive
- useMultisampleColouring: false,
- textureFiltering: TextureFiltering.Linear,
- voxelOverlapRule: 'average',
- },
+ desiredHeight: 80,
+ useMultisampleColouring: false,
+ textureFiltering: TextureFiltering.Linear,
+ voxelOverlapRule: 'average',
+ enableAmbientOcclusion: false, // Only want true if exporting to .obj
},
- palette: {
- blockMeshParams: {
- textureAtlas: 'vanilla', // Must be an atlas name that exists in /resources/atlases
- blockPalette: 'all-snapshot', // Must be a palette name that exists in /resources/palettes
- blockAssigner: 'ordered-dithering',
- colourSpace: ColourSpace.RGB,
- fallable: 'replace-falling',
- },
+ assign: {
+ textureAtlas: 'vanilla', // Must be an atlas name that exists in /resources/atlases
+ blockPalette: 'all-snapshot', // Must be a palette name that exists in /resources/palettes
+ blockAssigner: 'ordered-dithering',
+ colourSpace: ColourSpace.RGB,
+ fallable: 'replace-falling',
+ resolution: 32,
},
export: {
- absoluteFilePathSave: 'C:/Users/Lucas/Desktop/my_structure.schematic', // Must be an absolute path to the file (can be anywhere)
- exporter: 'schematic', // 'schematic' / 'litematic',
+ filepath: '/Users/lucasdower/Documents/out.obj', // Must be an absolute path to the file (can be anywhere)
+ exporter: 'obj', // 'schematic' / 'litematic',
+ },
+ debug: {
+ showLogs: true,
+ showWarnings: true,
+ showTimings: true,
},
};
diff --git a/tools/headless.ts b/tools/headless.ts
index e59b0247..1553fc2d 100644
--- a/tools/headless.ts
+++ b/tools/headless.ts
@@ -1,120 +1,74 @@
-import { Mesh } from '../src/mesh';
-import { ObjImporter } from '../src/importers/obj_importer';
-import { IVoxeliser } from '../src/voxelisers/base-voxeliser';
-import { TVoxelOverlapRule, VoxelMesh } from '../src/voxel_mesh';
-import { BlockMesh, BlockMeshParams, FallableBehaviour } from '../src/block_mesh';
-import { IExporter} from '../src/exporters/base_exporter';
-import { TextureFiltering } from '../src/texture';
-import { ColourSpace } from '../src/util';
-import { log, LogStyle } from './logging';
-import { headlessConfig } from './headless-config';
-import { TBlockAssigners } from '../src/block_assigner';
-import { TVoxelisers, VoxeliserFactory } from '../src/voxelisers/voxelisers';
-import { VoxeliseParams } from '../src/voxelisers/voxelisers';
-import { ExporterFactory, TExporters } from '../src/exporters/exporters';
+import { StatusHandler } from '../src/status';
+import { LOG_MAJOR, Logger, TIME_END, TIME_START } from '../src/util/log_util';
+import { WorkerClient } from '../src/worker_client';
+import { AssignParams, ExportParams, ImportParams, VoxeliseParams } from '../src/worker_types';
export type THeadlessConfig = {
- import: {
- absoluteFilePathLoad: string,
- },
- voxelise: {
- voxeliser: TVoxelisers,
- voxelMeshParams: {
- desiredHeight: number
- useMultisampleColouring: boolean,
- textureFiltering: TextureFiltering,
- voxelOverlapRule: TVoxelOverlapRule,
- },
- },
- palette: {
- blockMeshParams: {
- textureAtlas: string,
- blockPalette: string,
- blockAssigner: TBlockAssigners,
- colourSpace: ColourSpace,
- fallable: FallableBehaviour,
- },
- },
- export: {
- absoluteFilePathSave: string,
- exporter: TExporters,
- },
+ import: ImportParams.Input,
+ voxelise: VoxeliseParams.Input,
+ assign: AssignParams.Input,
+ export: ExportParams.Input,
+ debug: {
+ showLogs: boolean,
+ showWarnings: boolean,
+ showTimings: boolean,
+ }
}
-void async function main() {
- const mesh = _import({
- absoluteFilePathLoad: headlessConfig.import.absoluteFilePathLoad,
- });
- const voxelMesh = _voxelise(mesh, {
- voxeliser: VoxeliserFactory.GetVoxeliser(headlessConfig.voxelise.voxeliser),
- voxeliseParams: {
- desiredHeight: headlessConfig.voxelise.voxelMeshParams.desiredHeight,
- useMultisampleColouring: headlessConfig.voxelise.voxelMeshParams.useMultisampleColouring,
- textureFiltering: headlessConfig.voxelise.voxelMeshParams.textureFiltering,
- enableAmbientOcclusion: false,
- voxelOverlapRule: headlessConfig.voxelise.voxelMeshParams.voxelOverlapRule,
- calculateNeighbours: false,
- },
- });
- const blockMesh = _palette(voxelMesh, {
- blockMeshParams: {
- textureAtlas: headlessConfig.palette.blockMeshParams.textureAtlas,
- blockPalette: headlessConfig.palette.blockMeshParams.blockPalette,
- blockAssigner: headlessConfig.palette.blockMeshParams.blockAssigner as TBlockAssigners,
- colourSpace: headlessConfig.palette.blockMeshParams.colourSpace,
- fallable: headlessConfig.palette.blockMeshParams.fallable as FallableBehaviour,
- },
- });
- _export(blockMesh, {
- absoluteFilePathSave: headlessConfig.export.absoluteFilePathSave,
- exporter: ExporterFactory.GetExporter(headlessConfig.export.exporter),
- });
- log(LogStyle.Success, 'Finished!');
-}();
+export function runHeadless(headlessConfig: THeadlessConfig) {
+ if (headlessConfig.debug.showLogs) {
+ Logger.Get.enableLOGMAJOR();
+ }
+ if (headlessConfig.debug.showWarnings) {
+ Logger.Get.enableLOGWARN();
+ }
+ if (headlessConfig.debug.showTimings) {
+ Logger.Get.enableLOGTIME();
+ }
-interface ImportParams {
- absoluteFilePathLoad: string;
-}
-
-interface ActionVoxeliseParams {
- voxeliser: IVoxeliser;
- voxeliseParams: VoxeliseParams;
-}
-
-interface PaletteParams {
- blockMeshParams: BlockMeshParams;
-}
-
-interface ExportParams {
- absoluteFilePathSave: string;
- exporter: IExporter;
-}
-
-// TODO: Log status messages
-function _import(params: ImportParams): Mesh {
- log(LogStyle.Info, 'Importing...');
- const importer = new ObjImporter();
- importer.parseFile(params.absoluteFilePathLoad);
- const mesh = importer.toMesh();
- mesh.processMesh();
- return mesh;
-}
-
-// TODO: Log status messages
-function _voxelise(mesh: Mesh, params: ActionVoxeliseParams): VoxelMesh {
- log(LogStyle.Info, 'Voxelising...');
- const voxeliser: IVoxeliser = params.voxeliser;
- return voxeliser.voxelise(mesh, params.voxeliseParams);
-}
-
-// TODO: Log status messages
-function _palette(voxelMesh: VoxelMesh, params: PaletteParams): BlockMesh {
- log(LogStyle.Info, 'Assigning blocks...');
- return BlockMesh.createFromVoxelMesh(voxelMesh, params.blockMeshParams);
-}
+ const worker = WorkerClient.Get;
+ {
+ TIME_START('[TIMER] Importer');
+ LOG_MAJOR('\nImporting...');
+ worker.import(headlessConfig.import);
+ StatusHandler.Get.dump().clear();
+ TIME_END('[TIMER] Importer');
+ }
+ {
+ TIME_START('[TIMER] Voxeliser');
+ LOG_MAJOR('\nVoxelising...');
+ worker.voxelise(headlessConfig.voxelise);
+ StatusHandler.Get.dump().clear();
+ TIME_END('[TIMER] Voxeliser');
+ }
+ {
+ TIME_START('[TIMER] Assigner');
+ LOG_MAJOR('\nAssigning...');
+ worker.assign(headlessConfig.assign);
+ StatusHandler.Get.dump().clear();
+ TIME_END('[TIMER] Assigner');
+ }
+ {
+ TIME_START('[TIMER] Exporter');
+ LOG_MAJOR('\nExporting...');
+
+ /**
+ * The OBJExporter is unique in that it uses the actual render buffer used by WebGL
+ * to create its data, in headless mode this render buffer is not created so we must
+ * generate it manually
+ */
+ {
+ let result;
+ do {
+ result = worker.renderChunkedVoxelMesh({
+ enableAmbientOcclusion: headlessConfig.voxelise.enableAmbientOcclusion,
+ desiredHeight: headlessConfig.voxelise.desiredHeight,
+ });
+ } while (result.moreVoxelsToBuffer);
+ }
-// TODO: Log status messages
-function _export(blockMesh: BlockMesh, params: ExportParams) {
- log(LogStyle.Info, 'Exporting...');
- params.exporter.export(blockMesh, params.absoluteFilePathSave);
+ worker.export(headlessConfig.export);
+ StatusHandler.Get.dump().clear();
+ TIME_END('[TIMER] Exporter');
+ }
}
diff --git a/tools/misc.ts b/tools/misc.ts
index 0085b871..6b205b2e 100644
--- a/tools/misc.ts
+++ b/tools/misc.ts
@@ -1,11 +1,11 @@
-import { log, LogStyle } from './logging';
-import { TOOLS_DIR } from '../src/util';
-
import fs from 'fs';
import path from 'path';
import { PNG } from 'pngjs';
import prompt from 'prompt';
+
import { RGBA } from '../src/colour';
+import { AppPaths } from '../src/util/path_util';
+import { log, LogStyle } from './logging';
export const ASSERT = (condition: boolean, onFailMessage: string) => {
if (!condition) {
@@ -15,7 +15,7 @@ export const ASSERT = (condition: boolean, onFailMessage: string) => {
};
export function isDirSetup(relativePath: string, jarAssetDir: string) {
- const dir = path.join(TOOLS_DIR, relativePath);
+ const dir = path.join(AppPaths.Get.tools, relativePath);
if (fs.existsSync(dir)) {
if (fs.readdirSync(dir).length > 0) {
return true;
diff --git a/tools/run-headless.ts b/tools/run-headless.ts
new file mode 100644
index 00000000..be35506c
--- /dev/null
+++ b/tools/run-headless.ts
@@ -0,0 +1,14 @@
+import { LOG_MAJOR, Logger } from '../src/util/log_util';
+import { AppPaths, PathUtil } from '../src/util/path_util';
+import { runHeadless } from './headless';
+import { headlessConfig } from './headless-config';
+
+void async function main() {
+ AppPaths.Get.setBaseDir(PathUtil.join(__dirname, '../..'));
+ Logger.Get.enableLogToFile();
+ Logger.Get.initLogFile('headless');
+
+ runHeadless(headlessConfig);
+
+ LOG_MAJOR('\nFinished!');
+}();
diff --git a/tsconfig.json b/tsconfig.json
index 057b49cb..b6fbdbc5 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -3,7 +3,7 @@
/* Visit https://aka.ms/tsconfig.json to read more about this file */
/* Basic Options */
- // "incremental": true, /* Enable incremental compilation */
+ "incremental": true, /* Enable incremental compilation */
"target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', 'ES2021', or 'ESNEXT'. */
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
//"resolveJsonModule": true,
@@ -65,7 +65,7 @@
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
/* Experimental Options */
- // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
+ "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
/* Advanced Options */