Compare commits

...

62 Commits

Author SHA1 Message Date
Yeicor
3b394d5325 Automatically update version to 0.8.10 2024-05-12 11:29:44 +00:00
Yeicor
1d4e9efc5c dev 2024-05-12 13:26:20 +02:00
Yeicor
097b17386b Fix missing merge function after update 2024-05-12 13:24:22 +02:00
dependabot[bot]
c65b871404 Bump @gltf-transform/core from 3.10.1 to 4.0.0 (#69)
Bumps [@gltf-transform/core](https://github.com/donmccurdy/glTF-Transform) from 3.10.1 to 4.0.0.
- [Changelog](https://github.com/donmccurdy/glTF-Transform/blob/main/CHANGELOG.md)
- [Commits](https://github.com/donmccurdy/glTF-Transform/compare/v3.10.1...v4.0.0)

---
updated-dependencies:
- dependency-name: "@gltf-transform/core"
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-11 09:17:16 +00:00
dependabot[bot]
64a2c9e630 Bump vuetify from 3.6.3 to 3.6.5 (#68)
Bumps [vuetify](https://github.com/vuetifyjs/vuetify/tree/HEAD/packages/vuetify) from 3.6.3 to 3.6.5.
- [Release notes](https://github.com/vuetifyjs/vuetify/releases)
- [Commits](https://github.com/vuetifyjs/vuetify/commits/v3.6.5/packages/vuetify)

---
updated-dependencies:
- dependency-name: vuetify
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-11 09:16:46 +00:00
dependabot[bot]
62aa53be27 Bump @gltf-transform/functions from 3.10.1 to 4.0.0 (#66)
Bumps [@gltf-transform/functions](https://github.com/donmccurdy/glTF-Transform) from 3.10.1 to 4.0.0.
- [Changelog](https://github.com/donmccurdy/glTF-Transform/blob/main/CHANGELOG.md)
- [Commits](https://github.com/donmccurdy/glTF-Transform/compare/v3.10.1...v4.0.0)

---
updated-dependencies:
- dependency-name: "@gltf-transform/functions"
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-11 09:16:23 +00:00
dependabot[bot]
6c9cba552e Bump @types/node from 20.12.8 to 20.12.11 (#70)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 20.12.8 to 20.12.11.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-11 09:16:02 +00:00
dependabot[bot]
624fcb6fcf Bump vue-tsc from 2.0.16 to 2.0.17 (#67)
Bumps [vue-tsc](https://github.com/vuejs/language-tools/tree/HEAD/packages/tsc) from 2.0.16 to 2.0.17.
- [Release notes](https://github.com/vuejs/language-tools/releases)
- [Changelog](https://github.com/vuejs/language-tools/blob/master/CHANGELOG.md)
- [Commits](https://github.com/vuejs/language-tools/commits/v2.0.17/packages/tsc)

---
updated-dependencies:
- dependency-name: vue-tsc
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-11 09:15:34 +00:00
dependabot[bot]
835d72d6dc Bump @gltf-transform/extensions from 3.10.1 to 4.0.0 (#65)
Bumps [@gltf-transform/extensions](https://github.com/donmccurdy/glTF-Transform) from 3.10.1 to 4.0.0.
- [Changelog](https://github.com/donmccurdy/glTF-Transform/blob/main/CHANGELOG.md)
- [Commits](https://github.com/donmccurdy/glTF-Transform/compare/v3.10.1...v4.0.0)

---
updated-dependencies:
- dependency-name: "@gltf-transform/extensions"
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-11 09:15:11 +00:00
dependabot[bot]
4c0a752b3b Bump vue from 3.4.26 to 3.4.27 (#64)
Bumps [vue](https://github.com/vuejs/core) from 3.4.26 to 3.4.27.
- [Release notes](https://github.com/vuejs/core/releases)
- [Changelog](https://github.com/vuejs/core/blob/main/CHANGELOG.md)
- [Commits](https://github.com/vuejs/core/compare/v3.4.26...v3.4.27)

---
updated-dependencies:
- dependency-name: vue
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-11 09:15:02 +00:00
dependabot[bot]
f6b6039c5f Bump vite from 5.2.10 to 5.2.11 (#63)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.2.10 to 5.2.11.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.2.11/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-04 09:18:23 +00:00
dependabot[bot]
ad7caae417 Bump vuetify from 3.5.17 to 3.6.3 (#59)
Bumps [vuetify](https://github.com/vuetifyjs/vuetify/tree/HEAD/packages/vuetify) from 3.5.17 to 3.6.3.
- [Release notes](https://github.com/vuetifyjs/vuetify/releases)
- [Commits](https://github.com/vuetifyjs/vuetify/commits/v3.6.3/packages/vuetify)

---
updated-dependencies:
- dependency-name: vuetify
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-04 09:16:57 +00:00
dependabot[bot]
c96b910f5e Bump vue from 3.4.25 to 3.4.26 (#62)
Bumps [vue](https://github.com/vuejs/core) from 3.4.25 to 3.4.26.
- [Release notes](https://github.com/vuejs/core/releases)
- [Changelog](https://github.com/vuejs/core/blob/main/CHANGELOG.md)
- [Commits](https://github.com/vuejs/core/compare/v3.4.25...v3.4.26)

---
updated-dependencies:
- dependency-name: vue
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-04 09:15:41 +00:00
dependabot[bot]
8c5dc4fefd Bump vue-tsc from 2.0.14 to 2.0.16 (#61)
Bumps [vue-tsc](https://github.com/vuejs/language-tools/tree/HEAD/packages/tsc) from 2.0.14 to 2.0.16.
- [Release notes](https://github.com/vuejs/language-tools/releases)
- [Changelog](https://github.com/vuejs/language-tools/blob/master/CHANGELOG.md)
- [Commits](https://github.com/vuejs/language-tools/commits/v2.0.16/packages/tsc)

---
updated-dependencies:
- dependency-name: vue-tsc
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-04 09:15:27 +00:00
dependabot[bot]
fd824f611f Bump terser from 5.30.4 to 5.31.0 (#60)
Bumps [terser](https://github.com/terser/terser) from 5.30.4 to 5.31.0.
- [Changelog](https://github.com/terser/terser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/terser/terser/compare/v5.30.4...v5.31.0)

---
updated-dependencies:
- dependency-name: terser
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-04 09:15:17 +00:00
dependabot[bot]
66fd1d88c7 Bump @types/node from 20.12.7 to 20.12.8 (#58)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 20.12.7 to 20.12.8.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-04 09:15:00 +00:00
Yeicor
3539918b12 Fix example instructions 2024-04-28 13:31:37 +02:00
dependabot[bot]
a385ff9cb5 Bump vue from 3.4.23 to 3.4.25 (#56)
Bumps [vue](https://github.com/vuejs/core) from 3.4.23 to 3.4.25.
- [Release notes](https://github.com/vuejs/core/releases)
- [Changelog](https://github.com/vuejs/core/blob/main/CHANGELOG.md)
- [Commits](https://github.com/vuejs/core/compare/v3.4.23...v3.4.25)

---
updated-dependencies:
- dependency-name: vue
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-27 10:02:51 +00:00
dependabot[bot]
a80cfffcda Bump vue-tsc from 2.0.13 to 2.0.14 (#55)
Bumps [vue-tsc](https://github.com/vuejs/language-tools/tree/HEAD/packages/tsc) from 2.0.13 to 2.0.14.
- [Release notes](https://github.com/vuejs/language-tools/releases)
- [Changelog](https://github.com/vuejs/language-tools/blob/master/CHANGELOG.md)
- [Commits](https://github.com/vuejs/language-tools/commits/v2.0.14/packages/tsc)

---
updated-dependencies:
- dependency-name: vue-tsc
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-27 10:01:38 +00:00
dependabot[bot]
4f0da2bee1 Bump vite from 5.2.9 to 5.2.10 (#54)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.2.9 to 5.2.10.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.2.10/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-27 10:00:26 +00:00
dependabot[bot]
62808e3e52 Bump vuetify from 3.5.16 to 3.5.17 (#53)
Bumps [vuetify](https://github.com/vuetifyjs/vuetify/tree/HEAD/packages/vuetify) from 3.5.16 to 3.5.17.
- [Release notes](https://github.com/vuetifyjs/vuetify/releases)
- [Commits](https://github.com/vuetifyjs/vuetify/commits/v3.5.17/packages/vuetify)

---
updated-dependencies:
- dependency-name: vuetify
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-27 10:00:13 +00:00
dependabot[bot]
2f901f78c1 Bump generate-license-file from 3.3.0 to 3.4.0 (#52)
Bumps [generate-license-file](https://github.com/TobyAndToby/generate-license-file/tree/HEAD/src/packages/generate-license-file) from 3.3.0 to 3.4.0.
- [Release notes](https://github.com/TobyAndToby/generate-license-file/releases)
- [Commits](https://github.com/TobyAndToby/generate-license-file/commits/v3.4.0/src/packages/generate-license-file)

---
updated-dependencies:
- dependency-name: generate-license-file
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-27 09:59:58 +00:00
dependabot[bot]
9fa15f1a49 Bump terser from 5.30.3 to 5.30.4 (#51)
Bumps [terser](https://github.com/terser/terser) from 5.30.3 to 5.30.4.
- [Changelog](https://github.com/terser/terser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/terser/terser/compare/v5.30.3...v5.30.4)

---
updated-dependencies:
- dependency-name: terser
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-27 09:59:38 +00:00
dependabot[bot]
01431bc46c Bump vue from 3.4.21 to 3.4.23 (#49)
Bumps [vue](https://github.com/vuejs/core) from 3.4.21 to 3.4.23.
- [Release notes](https://github.com/vuejs/core/releases)
- [Changelog](https://github.com/vuejs/core/blob/main/CHANGELOG.md)
- [Commits](https://github.com/vuejs/core/compare/v3.4.21...v3.4.23)

---
updated-dependencies:
- dependency-name: vue
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-20 09:31:03 +00:00
dependabot[bot]
073f9086e0 Bump vite from 5.2.8 to 5.2.9 (#50)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.2.8 to 5.2.9.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.2.9/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-20 09:30:37 +00:00
dependabot[bot]
36f9b09bd7 Bump generate-license-file from 3.2.0 to 3.3.0 (#48)
Bumps [generate-license-file](https://github.com/TobyAndToby/generate-license-file/tree/HEAD/src/packages/generate-license-file) from 3.2.0 to 3.3.0.
- [Release notes](https://github.com/TobyAndToby/generate-license-file/releases)
- [Commits](https://github.com/TobyAndToby/generate-license-file/commits/v3.3.0/src/packages/generate-license-file)

---
updated-dependencies:
- dependency-name: generate-license-file
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-20 09:30:11 +00:00
dependabot[bot]
135023c950 Bump three, @google/model-viewer and @types/three (#47)
Bumps [three](https://github.com/mrdoob/three.js), [@google/model-viewer](https://github.com/google/model-viewer) and [@types/three](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/three). These dependencies needed to be updated together.

Updates `three` from 0.160.1 to 0.163.0
- [Release notes](https://github.com/mrdoob/three.js/releases)
- [Commits](https://github.com/mrdoob/three.js/commits)

Updates `@google/model-viewer` from 3.4.0 to 3.5.0
- [Release notes](https://github.com/google/model-viewer/releases)
- [Commits](https://github.com/google/model-viewer/compare/v3.4.0...v3.5.0)

Updates `@types/three` from 0.160.0 to 0.163.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/three)

---
updated-dependencies:
- dependency-name: three
  dependency-type: direct:production
  update-type: version-update:semver-minor
- dependency-name: "@google/model-viewer"
  dependency-type: direct:production
  update-type: version-update:semver-minor
- dependency-name: "@types/three"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-20 09:30:01 +00:00
dependabot[bot]
dcc206ec78 Bump vuetify from 3.5.15 to 3.5.16 (#46)
Bumps [vuetify](https://github.com/vuetifyjs/vuetify/tree/HEAD/packages/vuetify) from 3.5.15 to 3.5.16.
- [Release notes](https://github.com/vuetifyjs/vuetify/releases)
- [Commits](https://github.com/vuetifyjs/vuetify/commits/v3.5.16/packages/vuetify)

---
updated-dependencies:
- dependency-name: vuetify
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-20 09:29:33 +00:00
dependabot[bot]
e8a23f2ef1 Bump tar from 6.2.0 to 6.2.1 (#45)
Bumps [tar](https://github.com/isaacs/node-tar) from 6.2.0 to 6.2.1.
- [Release notes](https://github.com/isaacs/node-tar/releases)
- [Changelog](https://github.com/isaacs/node-tar/blob/main/CHANGELOG.md)
- [Commits](https://github.com/isaacs/node-tar/compare/v6.2.0...v6.2.1)

---
updated-dependencies:
- dependency-name: tar
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-13 11:10:38 +00:00
dependabot[bot]
35f8c047df Bump @types/node from 20.12.5 to 20.12.7 (#44)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 20.12.5 to 20.12.7.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-13 10:31:23 +00:00
dependabot[bot]
0b670896f4 Bump three-mesh-bvh from 0.7.3 to 0.7.4 (#43)
Bumps [three-mesh-bvh](https://github.com/gkjohnson/three-mesh-bvh) from 0.7.3 to 0.7.4.
- [Release notes](https://github.com/gkjohnson/three-mesh-bvh/releases)
- [Changelog](https://github.com/gkjohnson/three-mesh-bvh/blob/master/CHANGELOG.md)
- [Commits](https://github.com/gkjohnson/three-mesh-bvh/compare/v0.7.3...v0.7.4)

---
updated-dependencies:
- dependency-name: three-mesh-bvh
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-13 09:35:30 +00:00
dependabot[bot]
d5a9f6a1f5 Bump vue-tsc from 2.0.10 to 2.0.13 (#42)
Bumps [vue-tsc](https://github.com/vuejs/language-tools/tree/HEAD/packages/tsc) from 2.0.10 to 2.0.13.
- [Release notes](https://github.com/vuejs/language-tools/releases)
- [Changelog](https://github.com/vuejs/language-tools/blob/master/CHANGELOG.md)
- [Commits](https://github.com/vuejs/language-tools/commits/v2.0.13/packages/tsc)

---
updated-dependencies:
- dependency-name: vue-tsc
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-13 09:35:21 +00:00
dependabot[bot]
258bd831b3 Bump generate-license-file from 3.0.1 to 3.2.0 (#41)
Bumps [generate-license-file](https://github.com/TobyAndToby/generate-license-file/tree/HEAD/src/packages/generate-license-file) from 3.0.1 to 3.2.0.
- [Release notes](https://github.com/TobyAndToby/generate-license-file/releases)
- [Commits](https://github.com/TobyAndToby/generate-license-file/commits/v3.2.0/src/packages/generate-license-file)

---
updated-dependencies:
- dependency-name: generate-license-file
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-13 09:35:08 +00:00
dependabot[bot]
507f5141df Bump typescript from 5.4.4 to 5.4.5 (#40)
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 5.4.4 to 5.4.5.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release.yml)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v5.4.4...v5.4.5)

---
updated-dependencies:
- dependency-name: typescript
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-13 09:34:56 +00:00
dependabot[bot]
31bd324d0f Bump vuetify from 3.5.14 to 3.5.15 (#39)
Bumps [vuetify](https://github.com/vuetifyjs/vuetify/tree/HEAD/packages/vuetify) from 3.5.14 to 3.5.15.
- [Release notes](https://github.com/vuetifyjs/vuetify/releases)
- [Commits](https://github.com/vuetifyjs/vuetify/commits/v3.5.15/packages/vuetify)

---
updated-dependencies:
- dependency-name: vuetify
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-13 09:34:40 +00:00
dependabot[bot]
a1bd159a84 Bump vue-tsc from 2.0.7 to 2.0.10 (#38)
Bumps [vue-tsc](https://github.com/vuejs/language-tools/tree/HEAD/packages/tsc) from 2.0.7 to 2.0.10.
- [Release notes](https://github.com/vuejs/language-tools/releases)
- [Changelog](https://github.com/vuejs/language-tools/blob/master/CHANGELOG.md)
- [Commits](https://github.com/vuejs/language-tools/commits/v2.0.10/packages/tsc)

---
updated-dependencies:
- dependency-name: vue-tsc
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-06 09:44:32 +00:00
dependabot[bot]
b472f1adfb Bump typescript from 5.4.3 to 5.4.4 (#35)
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 5.4.3 to 5.4.4.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release.yml)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v5.4.3...v5.4.4)

---
updated-dependencies:
- dependency-name: typescript
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-06 09:44:16 +00:00
dependabot[bot]
9fd6a81d98 Bump terser from 5.30.0 to 5.30.3 (#37)
Bumps [terser](https://github.com/terser/terser) from 5.30.0 to 5.30.3.
- [Changelog](https://github.com/terser/terser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/terser/terser/compare/v5.30.0...v5.30.3)

---
updated-dependencies:
- dependency-name: terser
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-06 09:42:59 +00:00
dependabot[bot]
14d51a4cb0 Bump @types/node from 20.12.2 to 20.12.5 (#36)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 20.12.2 to 20.12.5.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-06 09:42:50 +00:00
dependabot[bot]
456b593ad0 Bump vuetify from 3.5.13 to 3.5.14 (#34)
Bumps [vuetify](https://github.com/vuetifyjs/vuetify/tree/HEAD/packages/vuetify) from 3.5.13 to 3.5.14.
- [Release notes](https://github.com/vuetifyjs/vuetify/releases)
- [Commits](https://github.com/vuetifyjs/vuetify/commits/v3.5.14/packages/vuetify)

---
updated-dependencies:
- dependency-name: vuetify
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-06 09:42:23 +00:00
dependabot[bot]
9af50dccd6 Bump vite from 5.2.7 to 5.2.8 (#33)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.2.7 to 5.2.8.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.2.8/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-06 09:42:15 +00:00
dependabot[bot]
21e85b1ce6 Bump pillow from 10.2.0 to 10.3.0 (#32)
Bumps [pillow](https://github.com/python-pillow/Pillow) from 10.2.0 to 10.3.0.
- [Release notes](https://github.com/python-pillow/Pillow/releases)
- [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst)
- [Commits](https://github.com/python-pillow/Pillow/compare/10.2.0...10.3.0)

---
updated-dependencies:
- dependency-name: pillow
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-06 09:06:50 +00:00
Yeicor
1f30c2fd0a Automatically update version to 0.8.9 2024-04-03 18:05:59 +00:00
Yeicor
ba05a8072b Minor frontend fix for long object names 2024-04-03 20:01:46 +02:00
Yeicor
27f540be23 Automatically update version to 0.8.8 2024-03-31 18:24:32 +00:00
Yeicor
e8c0f683c5 Lots of frontend improvements like keeping camera position on changes, avoid flickering on live updates, smooth gizmo animations, proper ortho camera movement, and enabling move by tap when not selecting. 2024-03-31 20:20:53 +02:00
Yeicor
345636e478 Automatically update version to 0.8.7 2024-03-30 17:02:20 +00:00
Yeicor
9a0fb03526 Merge remote-tracking branch 'origin/master' 2024-03-30 18:00:50 +01:00
Yeicor
2037621afc Fix frontend style issues 2024-03-30 18:00:37 +01:00
Yeicor
2ba0e18479 Automatically update version to 0.8.6 2024-03-30 16:31:40 +00:00
Yeicor
eca2bbfa7c Fix python import bug 2024-03-30 17:28:49 +01:00
Yeicor
86180c424e Keep selected enabled features on model updates instead of resetting them, better list of objects support and recover/disable previous selection on scene reloads. 2024-03-30 17:26:06 +01:00
dependabot[bot]
e42d6be074 Bump @tsconfig/node20 from 20.1.3 to 20.1.4 (#30)
Bumps [@tsconfig/node20](https://github.com/tsconfig/bases/tree/HEAD/bases) from 20.1.3 to 20.1.4.
- [Commits](https://github.com/tsconfig/bases/commits/HEAD/bases)

---
updated-dependencies:
- dependency-name: "@tsconfig/node20"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-30 10:57:52 +00:00
dependabot[bot]
e2d6a3cb00 Bump actions/configure-pages from 4 to 5 in /.github/workflows (#31)
Bumps [actions/configure-pages](https://github.com/actions/configure-pages) from 4 to 5.
- [Release notes](https://github.com/actions/configure-pages/releases)
- [Commits](https://github.com/actions/configure-pages/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/configure-pages
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-30 09:15:41 +00:00
dependabot[bot]
9e453b7890 Bump vuetify from 3.5.11 to 3.5.13 (#29)
Bumps [vuetify](https://github.com/vuetifyjs/vuetify/tree/HEAD/packages/vuetify) from 3.5.11 to 3.5.13.
- [Release notes](https://github.com/vuetifyjs/vuetify/releases)
- [Commits](https://github.com/vuetifyjs/vuetify/commits/v3.5.13/packages/vuetify)

---
updated-dependencies:
- dependency-name: vuetify
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-30 09:14:06 +00:00
dependabot[bot]
0b8faa9e8b Bump vite from 5.2.6 to 5.2.7 (#28)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.2.6 to 5.2.7.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.2.7/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-30 09:13:56 +00:00
dependabot[bot]
00bc2a15e0 Bump @types/node from 20.11.30 to 20.12.2 (#27)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 20.11.30 to 20.12.2.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-30 09:13:29 +00:00
dependabot[bot]
432abcf85c Bump terser from 5.29.2 to 5.30.0 (#26)
Bumps [terser](https://github.com/terser/terser) from 5.29.2 to 5.30.0.
- [Changelog](https://github.com/terser/terser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/terser/terser/compare/v5.29.2...v5.30.0)

---
updated-dependencies:
- dependency-name: terser
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-30 09:13:17 +00:00
Yeicor
4b6d3f6266 Automatically update version to 0.8.5 2024-03-29 11:26:06 +00:00
Yeicor
255ae72ed2 Count features again after changes to model and support for sending arbitrary lists of shapes as a single model. 2024-03-29 12:23:16 +01:00
Yeicor
77dd9fb43e Merge remote-tracking branch 'origin/master' 2024-03-28 23:32:28 +01:00
Yeicor
5dc2ae2f8d Remove debug check 2024-03-28 23:32:20 +01:00
28 changed files with 690 additions and 576 deletions

View File

@@ -25,7 +25,6 @@ jobs:
with:
cache: "yarn"
- run: "yarn install"
- run: "git diff" # Check if there are changes
- run: "yarn build"
- uses: "actions/upload-artifact@v4"
with:

View File

@@ -40,7 +40,7 @@ jobs:
mv "$dir/"* public/
rmdir "$dir"
done
- uses: "actions/configure-pages@v4"
- uses: "actions/configure-pages@v5"
- uses: "actions/upload-pages-artifact@v3"
with:
path: 'public'

View File

@@ -2439,7 +2439,7 @@ THE SOFTWARE.
The following npm package may be included in this product:
- vuetify@3.5.11
- vuetify@3.5.13
This package contains the following license and notice below:

View File

@@ -3,13 +3,12 @@
## Installation
1. Download the contents of this folder.
2. Assuming you have a recent version of Python installed, install the required packages:
2. Assuming you have a recent version of Python 3 installed, install the required packages:
```bash
python -m venv venv
. venv/bin/activate # Execute this line every time you change the terminal
pip install -r requirements.txt
# Do this every time you change the terminal:
. venv/bin/activate
```
## Usage

View File

@@ -1,13 +1,13 @@
<!--suppress SillyAssignmentJS -->
<script setup lang="ts">
import {defineAsyncComponent, provide, type Ref, ref, shallowRef, triggerRef} from "vue";
<script lang="ts" setup>
import {defineAsyncComponent, provide, type Ref, ref, shallowRef, triggerRef, watch} from "vue";
import Sidebar from "./misc/Sidebar.vue";
import Loading from "./misc/Loading.vue";
import Tools from "./tools/Tools.vue";
import Models from "./models/Models.vue";
import {VBtn, VLayout, VMain, VToolbarTitle} from "vuetify/lib/components/index.mjs";
import {settings} from "./misc/settings";
import {NetworkManager, NetworkUpdateEvent} from "./misc/network";
import {NetworkManager, NetworkUpdateEvent, NetworkUpdateEventModel} from "./misc/network";
import {SceneMgr} from "./misc/scene";
import {Document} from "@gltf-transform/core";
import type ModelViewerWrapperT from "./viewer/ModelViewerWrapper.vue";
@@ -28,6 +28,7 @@ const viewer: Ref<InstanceType<typeof ModelViewerWrapperT> | null> = ref(null);
const sceneDocument = shallowRef(new Document());
provide('sceneDocument', {sceneDocument});
const models: Ref<InstanceType<typeof Models> | null> = ref(null)
const tools: Ref<InstanceType<typeof Tools> | null> = ref(null)
const disableTap = ref(false);
const setDisableTap = (val: boolean) => disableTap.value = val;
provide('disableTap', {disableTap, setDisableTap});
@@ -49,6 +50,7 @@ async function onModelUpdateRequest(event: NetworkUpdateEvent) {
for (let modelIndex in event.models) {
let isLast = parseInt(modelIndex) === event.models.length - 1;
let model = event.models[modelIndex];
tools.value?.removeObjectSelections(model.name);
try {
if (!model.isRemove) {
doc = await SceneMgr.loadModel(sceneUrl, doc, model.name, model.url, isLast && settings.loadHelpers, isLast);
@@ -68,8 +70,8 @@ async function onModelUpdateRequest(event: NetworkUpdateEvent) {
}
async function onModelRemoveRequest(name: string) {
sceneDocument.value = await SceneMgr.removeModel(sceneUrl, sceneDocument.value, name);
triggerRef(sceneDocument); // Why not triggered automatically?
await onModelUpdateRequest(new NetworkUpdateEvent([new NetworkUpdateEventModel(name, "", null, true)], () => {
}));
}
// Set up the load model event listener
@@ -81,6 +83,12 @@ networkMgr.addEventListener('update', (e) => onModelUpdateRequest(e as NetworkUp
for (let model of settings.preload) {
networkMgr.load(model);
}
watch(viewer, (newViewer) => {
if (newViewer) {
newViewer.setPosterText('<tspan x="50%" dy="1.2em">Trying to load' +
' models from:</tspan>' + settings.preload.map((url) => '<tspan x="50%" dy="1.2em">- ' + url + '</tspan>').join(""));
}
});
async function loadModelManual() {
const modelUrl = prompt("For an improved experience in viewing CAD/GLTF models with automatic updates, it's recommended to use the official yacv_server Python package. This ensures seamless serving of models and automatic updates.\n\nOtherwise, enter the URL of the model to load:");
@@ -97,24 +105,24 @@ async function loadModelManual() {
</v-main>
<!-- The left collapsible sidebar has the list of models -->
<sidebar :opened-init="openSidebarsByDefault" side="left" :width="300">
<sidebar :opened-init="openSidebarsByDefault" :width="300" side="left">
<template #toolbar>
<v-toolbar-title>Models</v-toolbar-title>
</template>
<template #toolbar-items>
<v-btn icon="" @click="loadModelManual">
<svg-icon type="mdi" :path="mdiPlus"/>
<svg-icon :path="mdiPlus" type="mdi"/>
</v-btn>
</template>
<models ref="models" :viewer="viewer" @remove="onModelRemoveRequest"/>
</sidebar>
<!-- The right collapsible sidebar has the list of tools -->
<sidebar :opened-init="openSidebarsByDefault" side="right" :width="48 * 3 /* buttons */ + 1 /* border? */">
<sidebar :opened-init="openSidebarsByDefault" :width="48 * 3 /* buttons */ + 1 /* border? */" side="right">
<template #toolbar>
<v-toolbar-title>Tools</v-toolbar-title>
</template>
<tools :viewer="viewer" @findModel="(name) => models?.findModel(name)"/>
<tools ref="tools" :viewer="viewer" @findModel="(name) => models?.findModel(name)"/>
</sidebar>
</v-layout>

View File

@@ -1,5 +1,5 @@
<script setup lang="ts">
import {VContainer, VRow, VCol, VProgressCircular} from "vuetify/lib/components/index.mjs";
<script lang="ts" setup>
import {VCol, VContainer, VProgressCircular, VRow} from "vuetify/lib/components/index.mjs";
</script>
<template>

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script lang="ts" setup>
import {ref} from "vue";
import {VBtn, VNavigationDrawer, VToolbar, VToolbarItems} from "vuetify/lib/components/index.mjs";
import {mdiChevronLeft, mdiChevronRight, mdiClose} from '@mdi/js'
@@ -16,22 +16,22 @@ const openIcon = props.side === 'left' ? mdiChevronRight : mdiChevronLeft;
</script>
<template>
<v-btn icon @click="opened = !opened" class="open-button" :class="side">
<svg-icon type="mdi" :path="openIcon"/>
<v-btn :class="side" class="open-button" icon @click="opened = !opened">
<svg-icon :path="openIcon" type="mdi"/>
</v-btn>
<v-navigation-drawer v-model="opened" permanent :location="side" :width="props.width">
<v-navigation-drawer v-model="opened" :location="side" :width="props.width" permanent>
<v-toolbar density="compact">
<v-toolbar-items v-if="side == 'right'">
<slot name="toolbar-items"></slot>
<v-btn icon @click="opened = !opened">
<svg-icon type="mdi" :path="mdiClose"/>
<svg-icon :path="mdiClose" type="mdi"/>
</v-btn>
</v-toolbar-items>
<slot name="toolbar"></slot>
<v-toolbar-items v-if="side == 'left'">
<slot name="toolbar-items"></slot>
<v-btn icon @click="opened = !opened">
<svg-icon type="mdi" :path="mdiClose"/>
<svg-icon :path="mdiClose" type="mdi"/>
</v-btn>
</v-toolbar-items>
</v-toolbar>

View File

@@ -8,7 +8,6 @@ function getCenterAndVertexList(selInfo: SelectionInfo, scene: ModelScene): {
center: Vector3,
vertices: Array<Vector3>
} {
selInfo.object.updateMatrixWorld();
let pos: BufferAttribute | InterleavedBufferAttribute = selInfo.object.geometry.getAttribute('position');
let ind: BufferAttribute | null = selInfo.object.geometry.index;
if (ind === null) {

View File

@@ -1,5 +1,5 @@
import {Buffer, Document, Scene, type Transform, WebIO} from "@gltf-transform/core";
import {unpartition} from "@gltf-transform/functions";
import {unpartition, mergeDocuments} from "@gltf-transform/functions";
let io = new WebIO();
export let extrasNameKey = "__yacv_name";
@@ -56,7 +56,8 @@ export async function mergePartial(url: string, name: string, document: Document
await newDoc.transform(setNames(name));
// Merge the new document into the current one
return document.merge(newDoc);
mergeDocuments(document, newDoc);
return document;
}
export async function mergeFinalize(document: Document): Promise<Document> {

View File

@@ -2,7 +2,7 @@ import {settings} from "./settings";
const batchTimeout = 250; // ms
class NetworkUpdateEventModel {
export class NetworkUpdateEventModel {
name: string;
url: string;
// TODO: Detect and manage instances of the same object (same hash, different name)

View File

@@ -37,19 +37,6 @@ export class SceneMgr {
return document;
}
private static async reloadHelpers(sceneUrl: Ref<string>, document: Document, reloadScene: boolean): Promise<Document> {
let bb = SceneMgr.getBoundingBox(document);
if (!bb) return document;
// Create the helper axes and grid box
let helpersDoc = new Document();
let transform = (new Matrix4()).makeTranslation(bb.getCenter(new Vector3()));
newAxes(helpersDoc, bb.getSize(new Vector3()).multiplyScalar(0.5), transform);
newGridBox(helpersDoc, bb.getSize(new Vector3()), transform);
let helpersUrl = URL.createObjectURL(new Blob([await toBuffer(helpersDoc)]));
return await SceneMgr.loadModel(sceneUrl, document, extrasNameValueHelpers, helpersUrl, false, reloadScene);
}
static getBoundingBox(document: Document): Box3 | null {
if (document.getRoot().listNodes().length === 0) return null;
// Get bounding box of the model and use it to set the size of the helpers
@@ -91,6 +78,19 @@ export class SceneMgr {
return document;
}
private static async reloadHelpers(sceneUrl: Ref<string>, document: Document, reloadScene: boolean): Promise<Document> {
let bb = SceneMgr.getBoundingBox(document);
if (!bb) return document;
// Create the helper axes and grid box
let helpersDoc = new Document();
let transform = (new Matrix4()).makeTranslation(bb.getCenter(new Vector3()));
newAxes(helpersDoc, bb.getSize(new Vector3()).multiplyScalar(0.5), transform);
newGridBox(helpersDoc, bb.getSize(new Vector3()), transform);
let helpersUrl = URL.createObjectURL(new Blob([await toBuffer(helpersDoc)]));
return await SceneMgr.loadModel(sceneUrl, document, extrasNameValueHelpers, helpersUrl, false, reloadScene);
}
/** Serializes the current document into a GLB and updates the viewerSrc */
private static async showCurrentDoc(sceneUrl: Ref<string>, document: Document): Promise<Document> {
// Make sure the document is fully loaded and ready to be shown

View File

@@ -18,8 +18,11 @@ export const settings = {
monitorEveryMs: 100,
monitorOpenTimeoutMs: 1000,
// ModelViewer settings
autoplay: true,
autoplay: true, // Global animation toggle
arModes: 'webxr scene-viewer quick-look',
zoomSensitivity: 0.25,
orbitSensitivity: 1,
panSensitivity: 1,
exposure: 1,
shadowIntensity: 0,
background: '',

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script lang="ts" setup>
import {
VBtn,
VBtnToggle,
@@ -12,8 +12,8 @@ import {
VTooltip,
} from "vuetify/lib/components/index.mjs";
import {extrasNameKey, extrasNameValueHelpers} from "../misc/gltf";
import {Document, Mesh} from "@gltf-transform/core";
import {inject, ref, type ShallowRef, watch} from "vue";
import {Mesh} from "@gltf-transform/core";
import {ref, watch} from "vue";
import type ModelViewerWrapper from "../viewer/ModelViewerWrapper.vue";
import {
mdiCircleOpacity,
@@ -33,7 +33,7 @@ import {Plane} from "three/src/math/Plane.js";
import {Vector3} from "three/src/math/Vector3.js";
import type {MObject3D} from "../tools/Selection.vue";
import {toLineSegments} from "../misc/lines.js";
import {settings} from "../misc/settings.js";
import {settings} from "../misc/settings.js"
const props = defineProps<{
meshes: Array<Mesh>,
@@ -43,10 +43,11 @@ const emit = defineEmits<{ remove: [] }>()
let modelName = props.meshes[0].getExtras()[extrasNameKey] // + " blah blah blah blah blag blah blah blah"
// Reactive properties
const enabledFeatures = defineModel<Array<number>>("enabledFeatures", {default: [0, 1, 2]});
const opacity = defineModel<number>("opacity", {default: 1});
const wireframe = ref(false);
// Count the number of faces, edges and vertices
let faceCount = ref(-1);
let edgeCount = ref(-1);
let vertexCount = ref(-1);
// Clipping planes are handled in y-up space (swapped on interface, Z inverted later)
const clipPlaneX = ref(1);
const clipPlaneSwappedX = ref(false);
@@ -56,24 +57,10 @@ const clipPlaneZ = ref(1);
const clipPlaneSwappedZ = ref(false);
const edgeWidth = ref(settings.edgeWidth);
// Count the number of faces, edges and vertices
let faceCount = props.meshes
.flatMap((m) => m.listPrimitives().filter(p => p.getMode() === WebGL2RenderingContext.TRIANGLES))
.map(p => (p.getExtras()?.face_triangles_end as any)?.length ?? 1)
.reduce((a, b) => a + b, 0)
let edgeCount = props.meshes
.flatMap((m) => m.listPrimitives().filter(p => p.getMode() in [WebGL2RenderingContext.LINE_STRIP, WebGL2RenderingContext.LINES]))
.map(p => (p.getExtras()?.edge_points_end as any)?.length ?? 0)
.reduce((a, b) => a + b, 0)
let vertexCount = props.meshes
.flatMap((m) => m.listPrimitives().filter(p => p.getMode() === WebGL2RenderingContext.POINTS))
.map(p => (p.getAttribute("POSITION")?.getCount() ?? 0))
.reduce((a, b) => a + b, 0)
// Set initial defaults for the enabled features
if (faceCount === 0) enabledFeatures.value = enabledFeatures.value.filter((f) => f !== 0)
if (edgeCount === 0) enabledFeatures.value = enabledFeatures.value.filter((f) => f !== 1)
if (vertexCount === 0) enabledFeatures.value = enabledFeatures.value.filter((f) => f !== 2)
// Misc properties
const enabledFeatures = defineModel<Array<number>>("enabledFeatures", {default: [0, 1, 2]});
const opacity = defineModel<number>("opacity", {default: 1});
const wireframe = ref(false);
// Listeners for changes in the properties (or viewer reloads)
function onEnabledFeaturesChange(newEnabledFeatures: Array<number>) {
@@ -81,9 +68,6 @@ function onEnabledFeaturesChange(newEnabledFeatures: Array<number>) {
let scene = props.viewer?.scene;
let sceneModel = (scene as any)?._model;
if (!scene || !sceneModel) return;
// Iterate all primitives of the mesh and set their visibility based on the enabled features
// Use the scene graph instead of the document to avoid reloading the same model, at the cost
// of not actually removing the primitives from the scene graph
sceneModel.traverse((child: MObject3D) => {
if (child.userData[extrasNameKey] === modelName) {
let childIsFace = child.type == 'Mesh' || child.type == 'SkinnedMesh'
@@ -101,16 +85,12 @@ function onEnabledFeaturesChange(newEnabledFeatures: Array<number>) {
scene.queueRender()
}
watch(enabledFeatures, onEnabledFeaturesChange);
watch(enabledFeatures, onEnabledFeaturesChange, {deep: true});
function onOpacityChange(newOpacity: number) {
let scene = props.viewer?.scene;
let sceneModel = (scene as any)?._model;
if (!scene || !sceneModel) return;
// Iterate all primitives of the mesh and set their opacity based on the enabled features
// Use the scene graph instead of the document to avoid reloading the same model, at the cost
// of not actually removing the primitives from the scene graph
// console.log('Opacity may have changed', newOpacity)
sceneModel.traverse((child: MObject3D) => {
if (child.userData[extrasNameKey] === modelName) {
if (child.material && child.material.opacity !== newOpacity) {
@@ -129,10 +109,6 @@ function onWireframeChange(newWireframe: boolean) {
let scene = props.viewer?.scene;
let sceneModel = (scene as any)?._model;
if (!scene || !sceneModel) return;
// Iterate all primitives of the mesh and set their wireframe based on the enabled features
// Use the scene graph instead of the document to avoid reloading the same model, at the cost
// of not actually removing the primitives from the scene graph
// console.log('Wireframe may have changed', newWireframe)
sceneModel.traverse((child: MObject3D) => {
if (child.userData[extrasNameKey] === modelName) {
if (child.material && child.material.wireframe !== newWireframe) {
@@ -146,8 +122,6 @@ function onWireframeChange(newWireframe: boolean) {
watch(wireframe, onWireframeChange);
let {sceneDocument} = inject<{ sceneDocument: ShallowRef<Document> }>('sceneDocument')!!;
function onClipPlanesChange() {
let scene = props.viewer?.scene;
let sceneModel = (scene as any)?._model;
@@ -204,8 +178,6 @@ watch(clipPlaneZ, onClipPlanesChange);
watch(clipPlaneSwappedX, onClipPlanesChange);
watch(clipPlaneSwappedY, onClipPlanesChange);
watch(clipPlaneSwappedZ, onClipPlanesChange);
// Clip planes are also affected by the camera position, so we need to listen to camera changes
props.viewer!!.onElemReady((elem) => elem.addEventListener('camera-change', onClipPlanesChange))
let edgeWidthChangeCleanup = [] as Array<() => void>;
@@ -268,11 +240,36 @@ function onModelLoad() {
let scene = props.viewer?.scene;
let sceneModel = (scene as any)?._model;
if (!scene || !sceneModel) return;
// Iterate all primitives of the mesh and set their visibility based on the enabled features
// Use the scene graph instead of the document to avoid reloading the same model, at the cost
// of not actually removing the primitives from the scene graph
// Count the number of faces, edges and vertices
const isFirstLoad = faceCount.value === -1;
faceCount.value = props.meshes
.flatMap((m) => m.listPrimitives().filter(p => p.getMode() === WebGL2RenderingContext.TRIANGLES))
.map(p => (p.getExtras()?.face_triangles_end as any)?.length ?? 1)
.reduce((a, b) => a + b, 0)
edgeCount.value = props.meshes
.flatMap((m) => m.listPrimitives().filter(p => p.getMode() in [WebGL2RenderingContext.LINE_STRIP, WebGL2RenderingContext.LINES]))
.map(p => (p.getExtras()?.edge_points_end as any)?.length ?? 0)
.reduce((a, b) => a + b, 0)
vertexCount.value = props.meshes
.flatMap((m) => m.listPrimitives().filter(p => p.getMode() === WebGL2RenderingContext.POINTS))
.map(p => (p.getAttribute("POSITION")?.getCount() ?? 0))
.reduce((a, b) => a + b, 0)
// First time: set the enabled features to all provided features
if (isFirstLoad) {
if (faceCount.value === 0) enabledFeatures.value = enabledFeatures.value.filter((f) => f !== 0)
else if (!enabledFeatures.value.includes(0)) enabledFeatures.value.push(0)
if (edgeCount.value === 0) enabledFeatures.value = enabledFeatures.value.filter((f) => f !== 1)
else if (!enabledFeatures.value.includes(1)) enabledFeatures.value.push(1)
if (vertexCount.value === 0) enabledFeatures.value = enabledFeatures.value.filter((f) => f !== 2)
else if (!enabledFeatures.value.includes(2)) enabledFeatures.value.push(2)
}
// Add darkened back faces for all face objects to improve cutting planes
let childrenToAdd: Array<MObject3D> = [];
sceneModel.traverse((child: MObject3D) => {
child.updateMatrixWorld(); // Objects are mostly static, so ensure updated matrices
if (child.userData[extrasNameKey] === modelName) {
if (child.type == 'Mesh' || child.type == 'SkinnedMesh') {
// Compute a BVH for faster raycasting (MUCH faster selection)
@@ -319,95 +316,101 @@ function onModelLoad() {
}
// props.viewer.elem may not yet be available, so we need to wait for it
props.viewer!!.onElemReady((elem) => elem.addEventListener('load', onModelLoad))
const onViewerReady = (viewer: InstanceType<typeof ModelViewerWrapper>) => {
viewer?.onElemReady((elem: HTMLElement) => {
elem.addEventListener('before-render', onModelLoad);
elem.addEventListener('camera-change', onClipPlanesChange);
});
};
if (props.viewer) onViewerReady(props.viewer); else watch((() => props.viewer) as any, onViewerReady);
</script>
<template>
<v-expansion-panel :value="modelName">
<v-expansion-panel-title expand-icon="hide-this-icon" collapse-icon="hide-this-icon">
<v-btn-toggle v-model="enabledFeatures" multiple @click.stop color="surface-light">
<v-expansion-panel-title collapse-icon="hide-this-icon" expand-icon="hide-this-icon">
<v-btn-toggle v-model="enabledFeatures" color="surface-light" multiple @click.stop>
<v-btn icon>
<v-tooltip activator="parent">Toggle Faces ({{ faceCount }})</v-tooltip>
<svg-icon type="mdi" :path="mdiRectangle" :rotate="90"></svg-icon>
<svg-icon :path="mdiRectangle" :rotate="90" type="mdi"></svg-icon>
</v-btn>
<v-btn icon>
<v-tooltip activator="parent">Toggle Edges ({{ edgeCount }})</v-tooltip>
<svg-icon type="mdi" :path="mdiRectangleOutline" :rotate="90"></svg-icon>
<svg-icon :path="mdiRectangleOutline" :rotate="90" type="mdi"></svg-icon>
</v-btn>
<v-btn icon>
<v-tooltip activator="parent">Toggle Vertices ({{ vertexCount }})</v-tooltip>
<svg-icon type="mdi" :path="mdiVectorRectangle" :rotate="90"></svg-icon>
<svg-icon :path="mdiVectorRectangle" :rotate="90" type="mdi"></svg-icon>
</v-btn>
</v-btn-toggle>
<div class="model-name">{{ modelName }}</div>
<v-spacer></v-spacer>
<v-btn icon @click.stop="emit('remove')">
<v-tooltip activator="parent">Remove</v-tooltip>
<svg-icon type="mdi" :path="mdiDelete"></svg-icon>
<svg-icon :path="mdiDelete" type="mdi"></svg-icon>
</v-btn>
</v-expansion-panel-title>
<v-expansion-panel-text>
<v-slider v-model="opacity" hide-details min="0" max="1" :step="0.1">
<v-slider v-model="opacity" :step="0.1" hide-details max="1" min="0">
<template v-slot:prepend>
<v-tooltip activator="parent">Change opacity</v-tooltip>
<svg-icon type="mdi" :path="mdiCircleOpacity"></svg-icon>
<svg-icon :path="mdiCircleOpacity" type="mdi"></svg-icon>
</template>
<template v-slot:append>
<v-tooltip activator="parent">Wireframe</v-tooltip>
<v-checkbox-btn trueIcon="mdi-triangle-outline" falseIcon="mdi-triangle" v-model="wireframe"></v-checkbox-btn>
<v-checkbox-btn v-model="wireframe" falseIcon="mdi-triangle" trueIcon="mdi-triangle-outline"></v-checkbox-btn>
</template>
</v-slider>
<v-slider v-if="edgeCount > 0 || vertexCount > 0" v-model="edgeWidth" hide-details min="0" max="1">
<v-slider v-if="edgeCount > 0 || vertexCount > 0" v-model="edgeWidth" hide-details max="1" min="0">
<template v-slot:prepend>
<v-tooltip activator="parent">Edge and vertex sizes</v-tooltip>
<svg-icon type="mdi" :path="mdiVectorLine"></svg-icon>
<svg-icon :path="mdiVectorLine" type="mdi"></svg-icon>
</template>
</v-slider>
<v-divider></v-divider>
<v-slider v-model="clipPlaneX" hide-details min="0" max="1">
<v-slider v-model="clipPlaneX" hide-details max="1" min="0">
<template v-slot:prepend>
<v-tooltip activator="parent">Clip plane X</v-tooltip>
<svg-icon type="mdi" :path="mdiCube" :rotate="120"></svg-icon>
<svg-icon :path="mdiCube" :rotate="120" type="mdi"></svg-icon>
X
</template>
<template v-slot:append>
<v-tooltip activator="parent">Swap clip plane X</v-tooltip>
<v-checkbox-btn trueIcon="mdi-checkbox-marked-outline" falseIcon="mdi-checkbox-blank-outline"
v-model="clipPlaneSwappedX">
<v-checkbox-btn v-model="clipPlaneSwappedX" falseIcon="mdi-checkbox-blank-outline"
trueIcon="mdi-checkbox-marked-outline">
<template v-slot:label>
<svg-icon type="mdi" :path="mdiSwapHorizontal"></svg-icon>
<svg-icon :path="mdiSwapHorizontal" type="mdi"></svg-icon>
</template>
</v-checkbox-btn>
</template>
</v-slider>
<v-slider v-model="clipPlaneZ" hide-details min="0" max="1">
<v-slider v-model="clipPlaneZ" hide-details max="1" min="0">
<template v-slot:prepend>
<v-tooltip activator="parent">Clip plane Y</v-tooltip>
<svg-icon type="mdi" :path="mdiCube" :rotate="-120"></svg-icon>
<svg-icon :path="mdiCube" :rotate="-120" type="mdi"></svg-icon>
Y
</template>
<template v-slot:append>
<v-tooltip activator="parent">Swap clip plane Y</v-tooltip>
<v-checkbox-btn trueIcon="mdi-checkbox-marked-outline" falseIcon="mdi-checkbox-blank-outline"
v-model="clipPlaneSwappedZ">
<v-checkbox-btn v-model="clipPlaneSwappedZ" falseIcon="mdi-checkbox-blank-outline"
trueIcon="mdi-checkbox-marked-outline">
<template v-slot:label>
<svg-icon type="mdi" :path="mdiSwapHorizontal"></svg-icon>
<svg-icon :path="mdiSwapHorizontal" type="mdi"></svg-icon>
</template>
</v-checkbox-btn>
</template>
</v-slider>
<v-slider v-model="clipPlaneY" hide-details min="0" max="1">
<v-slider v-model="clipPlaneY" hide-details max="1" min="0">
<template v-slot:prepend>
<v-tooltip activator="parent">Clip plane Z</v-tooltip>
<svg-icon type="mdi" :path="mdiCube"></svg-icon>
<svg-icon :path="mdiCube" type="mdi"></svg-icon>
Z
</template>
<template v-slot:append>
<v-tooltip activator="parent">Swap clip plane Z</v-tooltip>
<v-checkbox-btn trueIcon="mdi-checkbox-marked-outline" falseIcon="mdi-checkbox-blank-outline"
v-model="clipPlaneSwappedY">
<v-checkbox-btn v-model="clipPlaneSwappedY" falseIcon="mdi-checkbox-blank-outline"
trueIcon="mdi-checkbox-marked-outline">
<template v-slot:label>
<svg-icon type="mdi" :path="mdiSwapHorizontal"></svg-icon>
<svg-icon :path="mdiSwapHorizontal" type="mdi"></svg-icon>
</template>
</v-checkbox-btn>
</template>
@@ -441,11 +444,12 @@ props.viewer!!.onElemReady((elem) => elem.addEventListener('load', onModelLoad))
}
.model-name {
width: 130px;
min-height: 1.15em; /* HACK: Avoid eating the bottom of the text when using 1 line */
max-height: 2em;
width: 179px;
font-size: 110%;
overflow-x: clip;
overflow-y: visible; /* HACK: bottom of text is lost otherwise (due to buggy -webkit-box bounds?) */
word-wrap: break-word;
text-overflow: ellipsis;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2; /* https://caniuse.com/?search=line-clamp */
-webkit-box-orient: vertical;

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script lang="ts" setup>
import {VExpansionPanels} from "vuetify/lib/components/index.mjs";
import type ModelViewerWrapper from "../viewer/ModelViewerWrapper.vue";
import {Document, Mesh} from "@gltf-transform/core";

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script lang="ts" setup>
// License text for all dependencies, only downloaded when/if needed
// @ts-ignore
import licenseText from "../../assets/licenses.txt?raw";

View File

@@ -1,18 +1,16 @@
<script setup lang="ts">
<script lang="ts" setup>
import {onMounted, onUpdated, ref} from "vue";
import type {ModelScene} from "@google/model-viewer/lib/three-components/ModelScene";
import * as OrientationGizmoRaw from "three-orientation-gizmo/src/OrientationGizmo";
import type {ModelViewerElement} from '@google/model-viewer';
// Optimized minimal dependencies from three
import {Vector3} from "three/src/math/Vector3.js";
import {Matrix4} from "three/src/math/Matrix4.js";
import type ModelViewerWrapper from "../viewer/ModelViewerWrapper.vue";
(globalThis as any).THREE = {Vector3, Matrix4} as any // HACK: Required for the gizmo to work
const OrientationGizmo = OrientationGizmoRaw.default;
const props = defineProps<{ elem: ModelViewerElement | null, scene: ModelScene }>();
const props = defineProps<{ viewer: InstanceType<typeof ModelViewerWrapper> }>();
function createGizmo(expectedParent: HTMLElement, scene: ModelScene): HTMLElement {
// noinspection SpellCheckingInspection
@@ -33,21 +31,26 @@ function createGizmo(expectedParent: HTMLElement, scene: ModelScene): HTMLElemen
}
// Append and listen for events
gizmo.onAxisSelected = (axis: { direction: { x: any; y: any; z: any; }; }) => {
let lookFrom = scene.getCamera().position.clone();
let lookAt = scene.getTarget().clone().add(scene.target.position);
let magnitude = lookFrom.clone().sub(lookAt).length()
let direction = new Vector3(axis.direction.x, axis.direction.y, axis.direction.z);
let newLookFrom = lookAt.clone().add(direction.clone().multiplyScalar(magnitude));
//console.log("New camera position", newLookFrom)
scene.getCamera().position.copy(newLookFrom);
scene.getCamera().lookAt(lookAt);
if ((scene as any).__perspectiveCamera) { // HACK: Make the hacky ortho also work
(scene as any).__perspectiveCamera.position.copy(newLookFrom);
(scene as any).__perspectiveCamera.lookAt(lookAt);
if (!props.viewer.elem || !props.viewer.controls) return;
// Animate the controls to the new wanted angle
const controls = props.viewer.controls;
const {theta: curTheta/*, phi: curPhi*/} = (controls as any).goalSpherical;
let wantedTheta = NaN;
let wantedPhi = NaN;
let attempt = 0
while ((attempt == 0 || curTheta == wantedTheta) && attempt < 2) {
if (attempt > 0) { // Flip the camera if the user clicks on the same axis
axis.direction.x = -axis.direction.x;
axis.direction.y = -axis.direction.y;
axis.direction.z = -axis.direction.z;
}
wantedTheta = Math.atan2(axis.direction.x, axis.direction.z);
wantedPhi = Math.asin(-axis.direction.y) + Math.PI / 2;
attempt++;
}
controls.setOrbit(wantedTheta, wantedPhi);
props.viewer.elem?.dispatchEvent(new CustomEvent('camera-change', {detail: {source: 'none'}}))
scene.queueRender();
requestIdleCallback(() => props.elem?.dispatchEvent(
new CustomEvent('camera-change', {detail: {source: 'none'}})), {timeout: 100})
}
return gizmo;
}
@@ -65,9 +68,9 @@ function updateGizmo() {
}
let reinstall = () => {
if(!container.value) return;
if (!container.value) return;
if (gizmo) container.value.removeChild(gizmo);
gizmo = createGizmo(container.value, props.scene as ModelScene) as typeof gizmo;
gizmo = createGizmo(container.value, props.viewer.scene!! as any) as typeof gizmo;
container.value.appendChild(gizmo);
requestIdleCallback(updateGizmo, {timeout: 250}); // Low priority updates
}

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script lang="ts" setup>
import {defineModel, inject, ref, type ShallowRef, watch} from "vue";
import {VBtn, VSelect, VTooltip} from "vuetify/lib/components/index.mjs";
import SvgIcon from '@jamescoyle/vue-icon';
@@ -33,21 +33,23 @@ let showBoundingBox = ref<Boolean>(false); // Enabled automatically on start
let showDistances = ref<Boolean>(true);
let mouseDownAt: [number, number] | null = null;
let mouseDownTime = 0;
let selectFilter = ref('Any (S)');
const raycaster = new Raycaster();
let selectionMoveListener = (event: MouseEvent) => {
let mouseDownListener = (event: MouseEvent) => {
mouseDownAt = [event.clientX, event.clientY];
mouseDownTime = performance.now();
if (!selectionEnabled.value) return;
};
let selectionListener = (event: MouseEvent) => {
let mouseUpListener = (event: MouseEvent) => {
// If the mouse moved while clicked (dragging), avoid selection logic
if (mouseDownAt) {
let [x, y] = mouseDownAt;
mouseDownAt = null;
if (Math.abs(event.clientX - x) > 5 || Math.abs(event.clientY - y) > 5) {
if (Math.abs(event.clientX - x) > 5 || Math.abs(event.clientY - y) > 5 || performance.now() - mouseDownTime > 500) {
return;
}
}
@@ -254,14 +256,29 @@ let onViewerReady = (viewer: typeof ModelViewerWrapperT) => {
viewer.onElemReady((elem: ModelViewerElement) => {
if (hasListeners) return;
hasListeners = true;
elem.addEventListener('mouseup', selectionListener);
elem.addEventListener('mousedown', selectionMoveListener); // Avoid clicking when dragging
elem.addEventListener('load', () => {
elem.addEventListener('mousedown', mouseDownListener); // Avoid clicking when dragging
elem.addEventListener('mouseup', mouseUpListener);
elem.addEventListener('before-render', () => {
// After a reload of the scene, we need to recover object references and highlight them again
for (let sel of selected.value) {
let scene = props.viewer?.scene;
if (!scene) continue;
let foundObject = null;
scene.traverse((obj: MObject3D) => {
if (sel.matches(obj)) {
foundObject = obj as MObject3D;
}
});
if (foundObject) {
sel.object = foundObject;
highlight(sel);
} else {
selected.value = selected.value.filter((m) => m.getKey() !== sel.getKey());
}
}
if (firstLoad) {
toggleShowBoundingBox();
firstLoad = false;
} else {
updateBoundingBox();
}
});
elem.addEventListener('camera-change', onCameraChange);
@@ -406,6 +423,8 @@ function updateDistances() {
return;
}
defineExpose({deselect, updateBoundingBox, updateDistances});
// Add keyboard shortcuts
window.addEventListener('keydown', (event) => {
if (event.key === 's') {
@@ -443,52 +462,41 @@ window.addEventListener('keydown', (event) => {
</script>
<template>
<div class="select-parent">
<v-btn icon @click="toggleSelection" :color="selectionEnabled ? 'surface-light' : ''">
<v-tooltip activator="parent">{{ selectionEnabled ? 'Disable (s)election mode' : 'Enable (s)election mode' }}
</v-tooltip>
<svg-icon type="mdi" :path="mdiCursorDefaultClick"/>
</v-btn>
<v-tooltip :text="'Select only ' + selectFilter.toString().toLocaleLowerCase()" :open-on-click="false">
<template v-slot:activator="{ props }">
<v-select v-bind="props" class="select-only" variant="underlined"
:items="['Any (S)', '(F)aces', '(E)dges', '(V)ertices']"
v-model="selectFilter"/>
</template>
<v-btn :color="selectionEnabled ? 'surface-light' : ''" icon @click="toggleSelection">
<v-tooltip activator="parent">{{ selectionEnabled ? 'Disable (s)election mode' : 'Enable (s)election mode' }}
</v-tooltip>
</div>
<v-btn icon @click="toggleHighlightNextSelection" :color="highlightNextSelection[0] ? 'surface-light' : ''">
<v-tooltip activator="parent">(H)ighlight the next clicked element in the models list</v-tooltip>
<svg-icon type="mdi" :path="mdiFeatureSearch"/>
<svg-icon :path="mdiCursorDefaultClick" type="mdi"/>
</v-btn>
<v-btn icon @click="toggleShowBoundingBox" :color="showBoundingBox ? 'surface-light' : ''">
<v-tooltip :open-on-click="false" :text="'Select only ' + selectFilter.toString().toLocaleLowerCase()">
<template v-slot:activator="{ props }">
<v-select v-model="selectFilter" :items="['Any (S)', '(F)aces', '(E)dges', '(V)ertices']" class="select-only"
v-bind="props"
variant="underlined"/>
</template>
</v-tooltip>
<v-btn :color="highlightNextSelection[0] ? 'surface-light' : ''" icon @click="toggleHighlightNextSelection">
<v-tooltip activator="parent">(H)ighlight the next clicked element in the models list</v-tooltip>
<svg-icon :path="mdiFeatureSearch" type="mdi"/>
</v-btn>
<v-btn :color="showBoundingBox ? 'surface-light' : ''" icon @click="toggleShowBoundingBox">
<v-tooltip activator="parent">{{ showBoundingBox ? 'Hide selection (b)ounds' : 'Show selection (b)ounds' }}
</v-tooltip>
<svg-icon type="mdi" :path="mdiCubeOutline"/>
<svg-icon :path="mdiCubeOutline" type="mdi"/>
</v-btn>
<v-btn icon @click="toggleShowDistances" :color="showDistances ? 'surface-light' : ''">
<v-btn :color="showDistances ? 'surface-light' : ''" icon @click="toggleShowDistances">
<v-tooltip activator="parent">
{{ showDistances ? 'Hide selection (d)istances' : 'Show (d)istances (when a pair of features is selected)' }}
</v-tooltip>
<svg-icon type="mdi" :path="mdiRuler"/>
<svg-icon :path="mdiRuler" type="mdi"/>
</v-btn>
</template>
<style scoped>
/* Very hacky styling... */
.select-parent {
height: 48px;
}
.select-parent .v-btn {
position: relative;
top: -20px;
}
.select-only {
display: inline-block;
width: calc(100% - 48px);
float: right;
height: 36px;
position: relative;
top: -12px;
width: calc(100% - 48px);
}
</style>

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script lang="ts" setup>
import {
VBtn,
VCard,
@@ -16,10 +16,9 @@ import {OrthographicCamera} from "three/src/cameras/OrthographicCamera.js";
import {mdiClose, mdiCrosshairsGps, mdiDownload, mdiGithub, mdiLicense, mdiProjector} from '@mdi/js'
import SvgIcon from '@jamescoyle/vue-icon';
import type {ModelViewerElement} from '@google/model-viewer';
import type {MObject3D} from "./Selection.vue";
import Loading from "../misc/Loading.vue";
import type ModelViewerWrapper from "../viewer/ModelViewerWrapper.vue";
import {defineAsyncComponent, type Ref, ref} from "vue";
import {defineAsyncComponent, ref, type Ref} from "vue";
import type {SelectionInfo} from "./selection";
const SelectionComponent = defineAsyncComponent({
@@ -57,14 +56,14 @@ function syncOrthoCamera(force: boolean) {
let h = perspectiveWidthAtCenter / scene.aspect;
(scene as any).camera = new OrthographicCamera(-w, w, h, -h, perspectiveCam.near, perspectiveCam.far);
scene.camera.position.copy(perspectiveCam.position);
scene.camera.lookAt(lookAtCenter);
scene.camera.rotation.copy(perspectiveCam.rotation);
if (force) scene.queueRender() // Force rerender of model-viewer
requestAnimationFrame(() => syncOrthoCamera(false));
}
}
let toggleProjectionText = ref('PERSP'); // Default to perspective camera
function toggleProjection() {
async function toggleProjection() {
let scene = props.viewer?.scene;
if (!scene) return;
let prevCam = scene.camera;
@@ -79,16 +78,16 @@ function toggleProjection() {
scene.queueRender() // Force rerender of model-viewer
}
toggleProjectionText.value = wasPerspectiveCamera ? 'ORTHO' : 'PERSP';
// The camera change may take a few frames to take effect, dispatch the event after a delay
requestIdleCallback(() => props.viewer?.elem?.dispatchEvent(
new CustomEvent('camera-change', {detail: {source: 'none'}})), {timeout: 100})
// The camera change may take a frame to take effect, dispatch the event after a delay
await new Promise((resolve) => requestAnimationFrame(resolve));
props.viewer?.elem?.dispatchEvent(new CustomEvent('camera-change', {detail: {source: 'none'}}));
}
async function centerCamera() {
let viewerEl: ModelViewerElement | null | undefined = props.viewer?.elem;
if (!viewerEl) return;
await viewerEl.updateFraming();
viewerEl.zoom(3);
props.viewer?.scene?.setTarget(0, 0, 0); // Center the target
viewerEl.zoom(-1000000); // Max zoom out
}
@@ -107,6 +106,15 @@ async function openGithub() {
window.open('https://github.com/yeicor-3d/yet-another-cad-viewer', '_blank')
}
function removeObjectSelections(objName: string) {
for (let selInfo of selection.value.filter((s) => s.getObjectName() === objName)) {
selectionComp.value?.deselect(selInfo);
}
selectionComp.value?.updateBoundingBox();
selectionComp.value?.updateDistances();
}
defineExpose({removeObjectSelections});
// Add keyboard shortcuts
window.addEventListener('keydown', (event) => {
@@ -118,35 +126,35 @@ window.addEventListener('keydown', (event) => {
</script>
<template>
<orientation-gizmo :scene="props.viewer.scene as any" :elem="props.viewer.elem" v-if="props.viewer?.scene"/>
<orientation-gizmo v-if="props.viewer?.scene" :viewer="props.viewer"/>
<v-divider/>
<h5>Camera</h5>
<v-btn icon @click="toggleProjection"><span class="icon-detail">{{ toggleProjectionText }}</span>
<v-tooltip activator="parent">Toggle (P)rojection<br/>(currently
{{ toggleProjectionText === 'PERSP' ? 'perspective' : 'orthographic' }})
</v-tooltip>
<svg-icon type="mdi" :path="mdiProjector"></svg-icon>
<svg-icon :path="mdiProjector" type="mdi"></svg-icon>
</v-btn>
<v-btn icon @click="centerCamera">
<v-tooltip activator="parent">Re(c)enter Camera</v-tooltip>
<svg-icon type="mdi" :path="mdiCrosshairsGps"/>
<svg-icon :path="mdiCrosshairsGps" type="mdi"/>
</v-btn>
<v-divider/>
<h5>Selection ({{ selectionFaceCount() }}F {{ selectionEdgeCount() }}E {{ selectionVertexCount() }}V)</h5>
<selection-component :ref="selectionComp as any" :viewer="props.viewer as any" v-model="selection"
<selection-component ref="selectionComp" v-model="selection" :viewer="props.viewer as any"
@findModel="(name) => emit('findModel', name)"/>
<v-divider/>
<v-spacer></v-spacer>
<h5>Extras</h5>
<v-btn icon @click="downloadSceneGlb">
<v-tooltip activator="parent">(D)ownload Scene</v-tooltip>
<svg-icon type="mdi" :path="mdiDownload"/>
<svg-icon :path="mdiDownload" type="mdi"/>
</v-btn>
<v-dialog id="licenses-dialog" fullscreen>
<template v-slot:activator="{ props }">
<v-btn icon v-bind="props">
<v-tooltip activator="parent">Show Licenses</v-tooltip>
<svg-icon type="mdi" :path="mdiLicense"/>
<svg-icon :path="mdiLicense" type="mdi"/>
</v-btn>
</template>
<template v-slot:default="{ isActive }">
@@ -156,7 +164,7 @@ window.addEventListener('keydown', (event) => {
<v-spacer>
</v-spacer>
<v-btn icon @click="isActive.value = false">
<svg-icon type="mdi" :path="mdiClose"/>
<svg-icon :path="mdiClose" type="mdi"/>
</v-btn>
</v-toolbar>
<v-card-text>
@@ -167,7 +175,7 @@ window.addEventListener('keydown', (event) => {
</v-dialog>
<v-btn icon @click="openGithub">
<v-tooltip activator="parent">Open (G)itHub</v-tooltip>
<svg-icon type="mdi" :path="mdiGithub"/>
<svg-icon :path="mdiGithub" type="mdi"/>
</v-btn>
<div ref="statsHolder"></div>
</template>
@@ -187,4 +195,8 @@ window.addEventListener('keydown', (event) => {
position: relative;
top: 5px;
}
h5 {
font-size: 14px;
}
</style>

View File

@@ -3,6 +3,7 @@
import type {MObject3D} from "./Selection.vue";
import type {Intersection} from "three";
import {Box3} from "three";
import {extrasNameKey} from "../misc/gltf";
/** Information about a single item in the selection */
export class SelectionInfo {
@@ -19,6 +20,17 @@ export class SelectionInfo {
this.indices = indices;
}
public getObjectName() {
return this.object.userData[extrasNameKey];
}
public matches(object: MObject3D) {
return this.getObjectName() === object.userData[extrasNameKey] &&
(this.kind === 'face' && (object.type === 'Mesh' || object.type === 'SkinnedMesh') ||
this.kind === 'edge' && (object.type === 'Line' || object.type === 'LineSegments') ||
this.kind === 'vertex' && object.type === 'Points')
}
public getKey() {
return this.object.uuid + this.kind + this.indices[0].toFixed() + this.indices[1].toFixed();
}

View File

@@ -1,8 +1,9 @@
<script setup lang="ts">
<script lang="ts" setup>
import {settings} from "../misc/settings";
import {inject, onMounted, type Ref, ref, watch} from "vue";
import {VList, VListItem} from "vuetify/lib/components/index.mjs";
import {$renderer, $scene} from "@google/model-viewer/lib/model-viewer-base";
import {$controls} from '@google/model-viewer/lib/features/controls.js';
import {type SmoothControls} from '@google/model-viewer/lib/three-components/SmoothControls';
import {ModelViewerElement} from '@google/model-viewer';
import type {ModelScene} from "@google/model-viewer/lib/three-components/ModelScene";
import {Hotspot} from "@google/model-viewer/lib/three-components/Hotspot";
@@ -19,31 +20,63 @@ BufferGeometry.prototype.disposeBoundsTree = disposeBoundsTree;
//@ts-ignore
Mesh.prototype.raycast = acceleratedRaycast;
const emit = defineEmits<{ load: [] }>()
const props = defineProps<{ src: string }>();
const elem = ref<ModelViewerElement | null>(null);
const scene = ref<ModelScene | null>(null);
const renderer = ref<Renderer | null>(null);
const controls = ref<SmoothControls | null>(null);
let lastCameraTargetPosition: Vector3 | undefined = undefined;
let lastCameraZoom: number | undefined = undefined;
let lastCameraUrl = props.src.toString();
onMounted(() => {
if (!elem.value) return;
elem.value.addEventListener('load', async () => {
elem.value.addEventListener('before-render', () => {
if (!elem.value) return;
// Delete the initial load banner
let banner = elem.value.querySelector('.initial-load-banner');
if (banner) banner.remove();
// Set the scene and renderer
// Extract internals of model-viewer in order to hack unsupported features
scene.value = elem.value[$scene] as ModelScene;
renderer.value = elem.value[$renderer] as Renderer;
// Emit the load event
emit('load')
controls.value = (elem.value as any)[$controls] as SmoothControls;
// Recover the camera position if it was set before
if (lastCameraTargetPosition) {
// console.log("RESTORING camera position?", lastCameraTargetPosition);
scene.value.setTarget(-lastCameraTargetPosition.x, -lastCameraTargetPosition.y, -lastCameraTargetPosition.z);
scene.value.jumpToGoal(); // Avoid move animation
}
(async () => {
let tries = 0
while (tries++ < 25) {
if (!lastCameraZoom || !elem.value?.getCameraOrbit()?.radius) break;
let change = lastCameraZoom - elem.value.getCameraOrbit().radius;
//console.log("Zooming to", lastCameraZoom, "from", elem.value.getCameraOrbit().radius, "change", change);
if (Math.abs(change) < 0.001) break;
elem.value.zoom(-Math.sign(change) * (Math.pow(Math.abs(change) + 1, 0.9) - 1)); // Arbitrary, experimental
elem.value.jumpCameraToGoal();
await elem.value.updateComplete;
}
//console.log("Ready to save!")
lastCameraUrl = props.src.toString();
})();
});
elem.value.addEventListener('camera-change', onCameraChange);
elem.value.addEventListener('progress', (ev) => onProgress((ev as any).detail.totalProgress));
});
function onCameraChange() {
// Remember the camera position to keep it in case of scene changes
if (scene.value && props.src.toString() == lastCameraUrl) { // Don't overwrite with initial unwanted positions
lastCameraTargetPosition = scene.value.target.position.clone();
lastCameraZoom = elem.value?.getCameraOrbit()?.radius;
//console.log("Saving camera?", lastCameraTargetPosition, lastCameraZoom);
}
// Also need to update the SVG overlay
for (let lineId in lines.value) {
onCameraChangeLine(lineId as any);
}
}
// Handles loading the events for <model-viewer>'s slotted progress bar
const progressBar = ref<HTMLElement | null>(null);
const updateBar = ref<HTMLElement | null>(null);
@@ -66,6 +99,17 @@ const onProgress = (totalProgress: number) => {
}, 1000);
};
const poster = ref<string>("")
const setPosterText = (newText: string) => {
poster.value = "data:image/svg+xml;charset=utf-8;base64," + btoa(
'<svg width="800" height="600" xmlns="http://www.w3.org/2000/svg" fill="gray">' +
'<text x="50%" y="0%" dominant-baseline="middle" text-anchor="middle" font-size="48px">' +
newText +
'</text>' +
'</svg>')
}
setPosterText("Loading...")
class Line3DData {
startHotspot: HTMLElement = document.body
endHotspot: HTMLElement = document.body
@@ -118,13 +162,6 @@ function removeLine3D(id: number): boolean {
return true;
}
function onCameraChange() {
// Need to update the SVG overlay
for (let lineId in lines.value) {
onCameraChangeLine(lineId as any);
}
}
let svg = ref<SVGElement | null>(null);
function onCameraChangeLine(lineId: number) {
@@ -160,54 +197,47 @@ function entries(lines: { [id: number]: Line3DData }): [string, Line3DData][] {
return Object.entries(lines);
}
defineExpose({elem, onElemReady, scene, renderer, addLine3D, removeLine3D, onProgress});
defineExpose({elem, onElemReady, scene, renderer, controls, addLine3D, removeLine3D, onProgress, setPosterText});
let {disableTap} = inject<{ disableTap: Ref<boolean> }>('disableTap')!!;
watch(disableTap, (value) => {
// Rerender not auto triggered? This works anyway...
if (value) elem.value?.setAttribute('disable-tap', '');
else elem.value?.removeAttribute('disable-tap');
watch(disableTap, (newDisableTap) => {
if (elem.value) elem.value.disableTap = newDisableTap;
});
</script>
<template>
<!-- The main 3D model viewer -->
<model-viewer ref="elem" style="width: 100%; height: 100%" :src="props.src" alt="The 3D model(s)" camera-controls
camera-orbit="30deg 75deg auto" max-camera-orbit="Infinity 180deg auto"
min-camera-orbit="-Infinity 0deg 5%" :disable-tap="disableTap" :exposure="settings.exposure"
:shadow-intensity="settings.shadowIntensity" interaction-prompt="none" :autoplay="settings.autoplay"
:ar="settings.arModes.length > 0" :ar-modes="settings.arModes" :skybox-image="settings.background"
:environment-image="settings.background">
<model-viewer ref="elem" :ar="settings.arModes.length > 0" :ar-modes="settings.arModes" :autoplay="settings.autoplay"
:environment-image="settings.background" :exposure="settings.exposure"
:orbit-sensitivity="settings.orbitSensitivity" :pan-sensitivity="settings.panSensitivity"
:poster="poster" :shadow-intensity="settings.shadowIntensity" :skybox-image="settings.background"
:src="props.src" :zoom-sensitivity="settings.zoomSensitivity" alt="The 3D model(s)" camera-controls
camera-orbit="30deg 75deg auto" interaction-prompt="none" max-camera-orbit="Infinity 180deg auto"
min-camera-orbit="-Infinity 0deg 5%" style="width: 100%; height: 100%">
<slot></slot>
<!-- Display some information during initial load -->
<div class="annotation initial-load-banner">
Trying to load models from...
<v-list v-for="src in settings.preload" :key="src">
<v-list-item>{{ src }}</v-list-item>
</v-list>
<!-- Too much idle CPU usage: <loading></loading> -->
</div>
<!-- Customize the progress bar -->
<div class="progress-bar" slot="progress-bar" ref="progressBar">
<div class="update-bar" ref="updateBar"/>
<!-- Add a progress bar to the top of the model viewer -->
<div ref="progressBar" slot="progress-bar" class="progress-bar">
<div ref="updateBar" class="update-bar"/>
</div>
</model-viewer>
<!-- The SVG overlay for fake 3D lines attached to the model -->
<div class="overlay-svg-wrapper">
<svg ref="svg" class="overlay-svg" width="100%" height="100%" xmlns="http://www.w3.org/2000/svg">
<svg ref="svg" class="overlay-svg" height="100%" width="100%" xmlns="http://www.w3.org/2000/svg">
<g v-for="[lineId, line] in entries(lines)" :key="lineId">
<line :x1="line.start2D[0]" :y1="line.start2D[1]" :x2="line.end2D[0]"
<line :x1="line.start2D[0]" :x2="line.end2D[0]" :y1="line.start2D[1]"
:y2="line.end2D[1]" v-bind="line.lineAttrs"/>
<g v-if="line.centerText !== undefined">
<rect :x="(line.start2D[0] + line.end2D[0]) / 2 - line.centerTextSize[0]/2 - 4"
:y="(line.start2D[1] + line.end2D[1]) / 2 - line.centerTextSize[1]/2 - 2"
:width="line.centerTextSize[0] + 8" :height="line.centerTextSize[1] + 4"
fill="gray" fill-opacity="0.75" rx="4" ry="4" stroke="black" v-if="line.centerText"/>
<text :x="(line.start2D[0] + line.end2D[0]) / 2" :y="(line.start2D[1] + line.end2D[1]) / 2"
text-anchor="middle" dominant-baseline="middle" font-size="16" fill="black"
:class="'line' + lineId + '_text'" v-if="line.centerText">
<rect v-if="line.centerText"
:height="line.centerTextSize[1] + 4"
:width="line.centerTextSize[0] + 8"
:x="(line.start2D[0] + line.end2D[0]) / 2 - line.centerTextSize[0]/2 - 4"
:y="(line.start2D[1] + line.end2D[1]) / 2 - line.centerTextSize[1]/2 - 2" fill="gray"
fill-opacity="0.75" rx="4" ry="4" stroke="black"/>
<text v-if="line.centerText" :class="'line' + lineId + '_text'"
:x="(line.start2D[0] + line.end2D[0]) / 2" :y="(line.start2D[1] + line.end2D[1]) / 2"
dominant-baseline="middle" fill="black"
font-size="16" text-anchor="middle">
{{ line.centerText }}
</text>
</g>
@@ -242,17 +272,6 @@ watch(disableTap, (value) => {
pointer-events: none;
}
.initial-load-banner {
width: 300px;
margin: auto;
margin-top: 3em;
overflow: hidden;
}
.initial-load-banner .v-list-item {
overflow: hidden;
}
.progress-bar {
display: block;
pointer-events: none;

View File

@@ -1,6 +1,6 @@
{
"name": "yet-another-cad-viewer",
"version": "0.8.4",
"version": "0.8.10",
"description": "",
"license": "MIT",
"private": true,
@@ -15,33 +15,33 @@
"update-licenses": "generate-license-file --input package.json --output assets/licenses.txt --overwrite"
},
"dependencies": {
"@gltf-transform/core": "^3.10.1",
"@gltf-transform/extensions": "^3.10.1",
"@gltf-transform/functions": "^3.10.1",
"@google/model-viewer": "^3.4.0",
"@gltf-transform/core": "^4.0.0",
"@gltf-transform/extensions": "^4.0.0",
"@gltf-transform/functions": "^4.0.0",
"@google/model-viewer": "^3.5.0",
"@jamescoyle/vue-icon": "^0.1.2",
"@mdi/js": "^7.4.47",
"@mdi/svg": "^7.4.47",
"three": "^0.160.1",
"three-mesh-bvh": "^0.7.3",
"three": "^0.163.0",
"three-mesh-bvh": "^0.7.4",
"three-orientation-gizmo": "https://github.com/jrj2211/three-orientation-gizmo",
"vue": "^3.4.21",
"vuetify": "^3.5.11"
"vue": "^3.4.27",
"vuetify": "^3.6.5"
},
"devDependencies": {
"@tsconfig/node20": "^20.1.3",
"@types/node": "^20.11.30",
"@types/three": "^0.160.0",
"@tsconfig/node20": "^20.1.4",
"@types/node": "^20.12.11",
"@types/three": "^0.163.0",
"@vitejs/plugin-vue": "^5.0.3",
"@vitejs/plugin-vue-jsx": "^3.1.0",
"@vue/tsconfig": "^0.5.1",
"buffer": "^5.5.0||^6.0.0",
"commander": "^12.0.0",
"generate-license-file": "^3.0.1",
"generate-license-file": "^3.4.0",
"npm-run-all2": "^6.1.1",
"terser": "^5.29.2",
"typescript": "~5.4.3",
"vite": "^5.2.6",
"vue-tsc": "^2.0.7"
"terser": "^5.31.0",
"typescript": "~5.4.5",
"vite": "^5.2.11",
"vue-tsc": "^2.0.17"
}
}

139
poetry.lock generated
View File

@@ -502,79 +502,80 @@ ptyprocess = ">=0.5"
[[package]]
name = "pillow"
version = "10.2.0"
version = "10.3.0"
description = "Python Imaging Library (Fork)"
optional = false
python-versions = ">=3.8"
files = [
{file = "pillow-10.2.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:7823bdd049099efa16e4246bdf15e5a13dbb18a51b68fa06d6c1d4d8b99a796e"},
{file = "pillow-10.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:83b2021f2ade7d1ed556bc50a399127d7fb245e725aa0113ebd05cfe88aaf588"},
{file = "pillow-10.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fad5ff2f13d69b7e74ce5b4ecd12cc0ec530fcee76356cac6742785ff71c452"},
{file = "pillow-10.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da2b52b37dad6d9ec64e653637a096905b258d2fc2b984c41ae7d08b938a67e4"},
{file = "pillow-10.2.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:47c0995fc4e7f79b5cfcab1fc437ff2890b770440f7696a3ba065ee0fd496563"},
{file = "pillow-10.2.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:322bdf3c9b556e9ffb18f93462e5f749d3444ce081290352c6070d014c93feb2"},
{file = "pillow-10.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:51f1a1bffc50e2e9492e87d8e09a17c5eea8409cda8d3f277eb6edc82813c17c"},
{file = "pillow-10.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:69ffdd6120a4737710a9eee73e1d2e37db89b620f702754b8f6e62594471dee0"},
{file = "pillow-10.2.0-cp310-cp310-win32.whl", hash = "sha256:c6dafac9e0f2b3c78df97e79af707cdc5ef8e88208d686a4847bab8266870023"},
{file = "pillow-10.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:aebb6044806f2e16ecc07b2a2637ee1ef67a11840a66752751714a0d924adf72"},
{file = "pillow-10.2.0-cp310-cp310-win_arm64.whl", hash = "sha256:7049e301399273a0136ff39b84c3678e314f2158f50f517bc50285fb5ec847ad"},
{file = "pillow-10.2.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:35bb52c37f256f662abdfa49d2dfa6ce5d93281d323a9af377a120e89a9eafb5"},
{file = "pillow-10.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9c23f307202661071d94b5e384e1e1dc7dfb972a28a2310e4ee16103e66ddb67"},
{file = "pillow-10.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:773efe0603db30c281521a7c0214cad7836c03b8ccff897beae9b47c0b657d61"},
{file = "pillow-10.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11fa2e5984b949b0dd6d7a94d967743d87c577ff0b83392f17cb3990d0d2fd6e"},
{file = "pillow-10.2.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:716d30ed977be8b37d3ef185fecb9e5a1d62d110dfbdcd1e2a122ab46fddb03f"},
{file = "pillow-10.2.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:a086c2af425c5f62a65e12fbf385f7c9fcb8f107d0849dba5839461a129cf311"},
{file = "pillow-10.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c8de2789052ed501dd829e9cae8d3dcce7acb4777ea4a479c14521c942d395b1"},
{file = "pillow-10.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:609448742444d9290fd687940ac0b57fb35e6fd92bdb65386e08e99af60bf757"},
{file = "pillow-10.2.0-cp311-cp311-win32.whl", hash = "sha256:823ef7a27cf86df6597fa0671066c1b596f69eba53efa3d1e1cb8b30f3533068"},
{file = "pillow-10.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:1da3b2703afd040cf65ec97efea81cfba59cdbed9c11d8efc5ab09df9509fc56"},
{file = "pillow-10.2.0-cp311-cp311-win_arm64.whl", hash = "sha256:edca80cbfb2b68d7b56930b84a0e45ae1694aeba0541f798e908a49d66b837f1"},
{file = "pillow-10.2.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:1b5e1b74d1bd1b78bc3477528919414874748dd363e6272efd5abf7654e68bef"},
{file = "pillow-10.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0eae2073305f451d8ecacb5474997c08569fb4eb4ac231ffa4ad7d342fdc25ac"},
{file = "pillow-10.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7c2286c23cd350b80d2fc9d424fc797575fb16f854b831d16fd47ceec078f2c"},
{file = "pillow-10.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e23412b5c41e58cec602f1135c57dfcf15482013ce6e5f093a86db69646a5aa"},
{file = "pillow-10.2.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:52a50aa3fb3acb9cf7213573ef55d31d6eca37f5709c69e6858fe3bc04a5c2a2"},
{file = "pillow-10.2.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:127cee571038f252a552760076407f9cff79761c3d436a12af6000cd182a9d04"},
{file = "pillow-10.2.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:8d12251f02d69d8310b046e82572ed486685c38f02176bd08baf216746eb947f"},
{file = "pillow-10.2.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:54f1852cd531aa981bc0965b7d609f5f6cc8ce8c41b1139f6ed6b3c54ab82bfb"},
{file = "pillow-10.2.0-cp312-cp312-win32.whl", hash = "sha256:257d8788df5ca62c980314053197f4d46eefedf4e6175bc9412f14412ec4ea2f"},
{file = "pillow-10.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:154e939c5f0053a383de4fd3d3da48d9427a7e985f58af8e94d0b3c9fcfcf4f9"},
{file = "pillow-10.2.0-cp312-cp312-win_arm64.whl", hash = "sha256:f379abd2f1e3dddb2b61bc67977a6b5a0a3f7485538bcc6f39ec76163891ee48"},
{file = "pillow-10.2.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:8373c6c251f7ef8bda6675dd6d2b3a0fcc31edf1201266b5cf608b62a37407f9"},
{file = "pillow-10.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:870ea1ada0899fd0b79643990809323b389d4d1d46c192f97342eeb6ee0b8483"},
{file = "pillow-10.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4b6b1e20608493548b1f32bce8cca185bf0480983890403d3b8753e44077129"},
{file = "pillow-10.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3031709084b6e7852d00479fd1d310b07d0ba82765f973b543c8af5061cf990e"},
{file = "pillow-10.2.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:3ff074fc97dd4e80543a3e91f69d58889baf2002b6be64347ea8cf5533188213"},
{file = "pillow-10.2.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:cb4c38abeef13c61d6916f264d4845fab99d7b711be96c326b84df9e3e0ff62d"},
{file = "pillow-10.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b1b3020d90c2d8e1dae29cf3ce54f8094f7938460fb5ce8bc5c01450b01fbaf6"},
{file = "pillow-10.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:170aeb00224ab3dc54230c797f8404507240dd868cf52066f66a41b33169bdbe"},
{file = "pillow-10.2.0-cp38-cp38-win32.whl", hash = "sha256:c4225f5220f46b2fde568c74fca27ae9771536c2e29d7c04f4fb62c83275ac4e"},
{file = "pillow-10.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:0689b5a8c5288bc0504d9fcee48f61a6a586b9b98514d7d29b840143d6734f39"},
{file = "pillow-10.2.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:b792a349405fbc0163190fde0dc7b3fef3c9268292586cf5645598b48e63dc67"},
{file = "pillow-10.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c570f24be1e468e3f0ce7ef56a89a60f0e05b30a3669a459e419c6eac2c35364"},
{file = "pillow-10.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8ecd059fdaf60c1963c58ceb8997b32e9dc1b911f5da5307aab614f1ce5c2fb"},
{file = "pillow-10.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c365fd1703040de1ec284b176d6af5abe21b427cb3a5ff68e0759e1e313a5e7e"},
{file = "pillow-10.2.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:70c61d4c475835a19b3a5aa42492409878bbca7438554a1f89d20d58a7c75c01"},
{file = "pillow-10.2.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:b6f491cdf80ae540738859d9766783e3b3c8e5bd37f5dfa0b76abdecc5081f13"},
{file = "pillow-10.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9d189550615b4948f45252d7f005e53c2040cea1af5b60d6f79491a6e147eef7"},
{file = "pillow-10.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:49d9ba1ed0ef3e061088cd1e7538a0759aab559e2e0a80a36f9fd9d8c0c21591"},
{file = "pillow-10.2.0-cp39-cp39-win32.whl", hash = "sha256:babf5acfede515f176833ed6028754cbcd0d206f7f614ea3447d67c33be12516"},
{file = "pillow-10.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:0304004f8067386b477d20a518b50f3fa658a28d44e4116970abfcd94fac34a8"},
{file = "pillow-10.2.0-cp39-cp39-win_arm64.whl", hash = "sha256:0fb3e7fc88a14eacd303e90481ad983fd5b69c761e9e6ef94c983f91025da869"},
{file = "pillow-10.2.0-pp310-pypy310_pp73-macosx_10_10_x86_64.whl", hash = "sha256:322209c642aabdd6207517e9739c704dc9f9db943015535783239022002f054a"},
{file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3eedd52442c0a5ff4f887fab0c1c0bb164d8635b32c894bc1faf4c618dd89df2"},
{file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb28c753fd5eb3dd859b4ee95de66cc62af91bcff5db5f2571d32a520baf1f04"},
{file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:33870dc4653c5017bf4c8873e5488d8f8d5f8935e2f1fb9a2208c47cdd66efd2"},
{file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:3c31822339516fb3c82d03f30e22b1d038da87ef27b6a78c9549888f8ceda39a"},
{file = "pillow-10.2.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a2b56ba36e05f973d450582fb015594aaa78834fefe8dfb8fcd79b93e64ba4c6"},
{file = "pillow-10.2.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:d8e6aeb9201e655354b3ad049cb77d19813ad4ece0df1249d3c793de3774f8c7"},
{file = "pillow-10.2.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:2247178effb34a77c11c0e8ac355c7a741ceca0a732b27bf11e747bbc950722f"},
{file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:15587643b9e5eb26c48e49a7b33659790d28f190fc514a322d55da2fb5c2950e"},
{file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753cd8f2086b2b80180d9b3010dd4ed147efc167c90d3bf593fe2af21265e5a5"},
{file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:7c8f97e8e7a9009bcacbe3766a36175056c12f9a44e6e6f2d5caad06dcfbf03b"},
{file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:d1b35bcd6c5543b9cb547dee3150c93008f8dd0f1fef78fc0cd2b141c5baf58a"},
{file = "pillow-10.2.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:fe4c15f6c9285dc54ce6553a3ce908ed37c8f3825b5a51a15c91442bb955b868"},
{file = "pillow-10.2.0.tar.gz", hash = "sha256:e87f0b2c78157e12d7686b27d63c070fd65d994e8ddae6f328e0dcf4a0cd007e"},
{file = "pillow-10.3.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:90b9e29824800e90c84e4022dd5cc16eb2d9605ee13f05d47641eb183cd73d45"},
{file = "pillow-10.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a2c405445c79c3f5a124573a051062300936b0281fee57637e706453e452746c"},
{file = "pillow-10.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78618cdbccaa74d3f88d0ad6cb8ac3007f1a6fa5c6f19af64b55ca170bfa1edf"},
{file = "pillow-10.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:261ddb7ca91fcf71757979534fb4c128448b5b4c55cb6152d280312062f69599"},
{file = "pillow-10.3.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:ce49c67f4ea0609933d01c0731b34b8695a7a748d6c8d186f95e7d085d2fe475"},
{file = "pillow-10.3.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:b14f16f94cbc61215115b9b1236f9c18403c15dd3c52cf629072afa9d54c1cbf"},
{file = "pillow-10.3.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d33891be6df59d93df4d846640f0e46f1a807339f09e79a8040bc887bdcd7ed3"},
{file = "pillow-10.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b50811d664d392f02f7761621303eba9d1b056fb1868c8cdf4231279645c25f5"},
{file = "pillow-10.3.0-cp310-cp310-win32.whl", hash = "sha256:ca2870d5d10d8726a27396d3ca4cf7976cec0f3cb706debe88e3a5bd4610f7d2"},
{file = "pillow-10.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:f0d0591a0aeaefdaf9a5e545e7485f89910c977087e7de2b6c388aec32011e9f"},
{file = "pillow-10.3.0-cp310-cp310-win_arm64.whl", hash = "sha256:ccce24b7ad89adb5a1e34a6ba96ac2530046763912806ad4c247356a8f33a67b"},
{file = "pillow-10.3.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:5f77cf66e96ae734717d341c145c5949c63180842a545c47a0ce7ae52ca83795"},
{file = "pillow-10.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e4b878386c4bf293578b48fc570b84ecfe477d3b77ba39a6e87150af77f40c57"},
{file = "pillow-10.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fdcbb4068117dfd9ce0138d068ac512843c52295ed996ae6dd1faf537b6dbc27"},
{file = "pillow-10.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9797a6c8fe16f25749b371c02e2ade0efb51155e767a971c61734b1bf6293994"},
{file = "pillow-10.3.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:9e91179a242bbc99be65e139e30690e081fe6cb91a8e77faf4c409653de39451"},
{file = "pillow-10.3.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:1b87bd9d81d179bd8ab871603bd80d8645729939f90b71e62914e816a76fc6bd"},
{file = "pillow-10.3.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:81d09caa7b27ef4e61cb7d8fbf1714f5aec1c6b6c5270ee53504981e6e9121ad"},
{file = "pillow-10.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:048ad577748b9fa4a99a0548c64f2cb8d672d5bf2e643a739ac8faff1164238c"},
{file = "pillow-10.3.0-cp311-cp311-win32.whl", hash = "sha256:7161ec49ef0800947dc5570f86568a7bb36fa97dd09e9827dc02b718c5643f09"},
{file = "pillow-10.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:8eb0908e954d093b02a543dc963984d6e99ad2b5e36503d8a0aaf040505f747d"},
{file = "pillow-10.3.0-cp311-cp311-win_arm64.whl", hash = "sha256:4e6f7d1c414191c1199f8996d3f2282b9ebea0945693fb67392c75a3a320941f"},
{file = "pillow-10.3.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:e46f38133e5a060d46bd630faa4d9fa0202377495df1f068a8299fd78c84de84"},
{file = "pillow-10.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:50b8eae8f7334ec826d6eeffaeeb00e36b5e24aa0b9df322c247539714c6df19"},
{file = "pillow-10.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9d3bea1c75f8c53ee4d505c3e67d8c158ad4df0d83170605b50b64025917f338"},
{file = "pillow-10.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:19aeb96d43902f0a783946a0a87dbdad5c84c936025b8419da0a0cd7724356b1"},
{file = "pillow-10.3.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:74d28c17412d9caa1066f7a31df8403ec23d5268ba46cd0ad2c50fb82ae40462"},
{file = "pillow-10.3.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:ff61bfd9253c3915e6d41c651d5f962da23eda633cf02262990094a18a55371a"},
{file = "pillow-10.3.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d886f5d353333b4771d21267c7ecc75b710f1a73d72d03ca06df49b09015a9ef"},
{file = "pillow-10.3.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4b5ec25d8b17217d635f8935dbc1b9aa5907962fae29dff220f2659487891cd3"},
{file = "pillow-10.3.0-cp312-cp312-win32.whl", hash = "sha256:51243f1ed5161b9945011a7360e997729776f6e5d7005ba0c6879267d4c5139d"},
{file = "pillow-10.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:412444afb8c4c7a6cc11a47dade32982439925537e483be7c0ae0cf96c4f6a0b"},
{file = "pillow-10.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:798232c92e7665fe82ac085f9d8e8ca98826f8e27859d9a96b41d519ecd2e49a"},
{file = "pillow-10.3.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:4eaa22f0d22b1a7e93ff0a596d57fdede2e550aecffb5a1ef1106aaece48e96b"},
{file = "pillow-10.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cd5e14fbf22a87321b24c88669aad3a51ec052eb145315b3da3b7e3cc105b9a2"},
{file = "pillow-10.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1530e8f3a4b965eb6a7785cf17a426c779333eb62c9a7d1bbcf3ffd5bf77a4aa"},
{file = "pillow-10.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d512aafa1d32efa014fa041d38868fda85028e3f930a96f85d49c7d8ddc0383"},
{file = "pillow-10.3.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:339894035d0ede518b16073bdc2feef4c991ee991a29774b33e515f1d308e08d"},
{file = "pillow-10.3.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:aa7e402ce11f0885305bfb6afb3434b3cd8f53b563ac065452d9d5654c7b86fd"},
{file = "pillow-10.3.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:0ea2a783a2bdf2a561808fe4a7a12e9aa3799b701ba305de596bc48b8bdfce9d"},
{file = "pillow-10.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c78e1b00a87ce43bb37642c0812315b411e856a905d58d597750eb79802aaaa3"},
{file = "pillow-10.3.0-cp38-cp38-win32.whl", hash = "sha256:72d622d262e463dfb7595202d229f5f3ab4b852289a1cd09650362db23b9eb0b"},
{file = "pillow-10.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:2034f6759a722da3a3dbd91a81148cf884e91d1b747992ca288ab88c1de15999"},
{file = "pillow-10.3.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:2ed854e716a89b1afcedea551cd85f2eb2a807613752ab997b9974aaa0d56936"},
{file = "pillow-10.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:dc1a390a82755a8c26c9964d457d4c9cbec5405896cba94cf51f36ea0d855002"},
{file = "pillow-10.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4203efca580f0dd6f882ca211f923168548f7ba334c189e9eab1178ab840bf60"},
{file = "pillow-10.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3102045a10945173d38336f6e71a8dc71bcaeed55c3123ad4af82c52807b9375"},
{file = "pillow-10.3.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:6fb1b30043271ec92dc65f6d9f0b7a830c210b8a96423074b15c7bc999975f57"},
{file = "pillow-10.3.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:1dfc94946bc60ea375cc39cff0b8da6c7e5f8fcdc1d946beb8da5c216156ddd8"},
{file = "pillow-10.3.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b09b86b27a064c9624d0a6c54da01c1beaf5b6cadfa609cf63789b1d08a797b9"},
{file = "pillow-10.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d3b2348a78bc939b4fed6552abfd2e7988e0f81443ef3911a4b8498ca084f6eb"},
{file = "pillow-10.3.0-cp39-cp39-win32.whl", hash = "sha256:45ebc7b45406febf07fef35d856f0293a92e7417ae7933207e90bf9090b70572"},
{file = "pillow-10.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:0ba26351b137ca4e0db0342d5d00d2e355eb29372c05afd544ebf47c0956ffeb"},
{file = "pillow-10.3.0-cp39-cp39-win_arm64.whl", hash = "sha256:50fd3f6b26e3441ae07b7c979309638b72abc1a25da31a81a7fbd9495713ef4f"},
{file = "pillow-10.3.0-pp310-pypy310_pp73-macosx_10_10_x86_64.whl", hash = "sha256:6b02471b72526ab8a18c39cb7967b72d194ec53c1fd0a70b050565a0f366d355"},
{file = "pillow-10.3.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:8ab74c06ffdab957d7670c2a5a6e1a70181cd10b727cd788c4dd9005b6a8acd9"},
{file = "pillow-10.3.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:048eeade4c33fdf7e08da40ef402e748df113fd0b4584e32c4af74fe78baaeb2"},
{file = "pillow-10.3.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e2ec1e921fd07c7cda7962bad283acc2f2a9ccc1b971ee4b216b75fad6f0463"},
{file = "pillow-10.3.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:4c8e73e99da7db1b4cad7f8d682cf6abad7844da39834c288fbfa394a47bbced"},
{file = "pillow-10.3.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:16563993329b79513f59142a6b02055e10514c1a8e86dca8b48a893e33cf91e3"},
{file = "pillow-10.3.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:dd78700f5788ae180b5ee8902c6aea5a5726bac7c364b202b4b3e3ba2d293170"},
{file = "pillow-10.3.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:aff76a55a8aa8364d25400a210a65ff59d0168e0b4285ba6bf2bd83cf675ba32"},
{file = "pillow-10.3.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:b7bc2176354defba3edc2b9a777744462da2f8e921fbaf61e52acb95bafa9828"},
{file = "pillow-10.3.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:793b4e24db2e8742ca6423d3fde8396db336698c55cd34b660663ee9e45ed37f"},
{file = "pillow-10.3.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d93480005693d247f8346bc8ee28c72a2191bdf1f6b5db469c096c0c867ac015"},
{file = "pillow-10.3.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c83341b89884e2b2e55886e8fbbf37c3fa5efd6c8907124aeb72f285ae5696e5"},
{file = "pillow-10.3.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:1a1d1915db1a4fdb2754b9de292642a39a7fb28f1736699527bb649484fb966a"},
{file = "pillow-10.3.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a0eaa93d054751ee9964afa21c06247779b90440ca41d184aeb5d410f20ff591"},
{file = "pillow-10.3.0.tar.gz", hash = "sha256:9d2455fbf44c914840c793e89aa82d0e1763a14253a000743719ae5946814b2d"},
]
[package.extras]

View File

@@ -1,6 +1,6 @@
[tool.poetry]
name = "yacv-server"
version = "0.8.4"
version = "0.8.10"
description = "Yet Another CAD Viewer (server)"
authors = ["Yeicor <4929005+Yeicor@users.noreply.github.com>"]
license = "MIT"

View File

@@ -26,9 +26,10 @@ export default defineConfig({
}
},
build: {
assetsDir: '.',
assetsDir: '.', // Support deploying to a subdirectory using relative URLs
cssCodeSplit: false, // Small enough to inline
chunkSizeWarningLimit: 550, // Three.js is big. Draco is even bigger but not likely to be used.
sourcemap: true, // For debugging production
},
define: {
__APP_NAME__: JSON.stringify(name),

View File

@@ -2,10 +2,15 @@
Utilities to work with CAD objects
"""
import hashlib
from typing import Optional, Union, List, Tuple
import io
import re
from typing import Optional, Union, Tuple
from OCP.TopExp import TopExp
from OCP.TopLoc import TopLoc_Location
from OCP.TopTools import TopTools_IndexedMapOfShape
from OCP.TopoDS import TopoDS_Shape
from build123d import Compound, Shape
from yacv_server.gltf import GLTFMgr
@@ -40,6 +45,26 @@ def get_shape(obj: CADLike, error: bool = True) -> Optional[CADCoreLike]:
if isinstance(obj, TopoDS_Shape):
return obj
# Handle iterables like Build123d ShapeList by extracting all sub-shapes and making a compound
if isinstance(obj, list) or isinstance(obj, tuple) or isinstance(obj, set) or isinstance(obj, dict):
try:
if isinstance(obj, dict):
obj_iter = iter(obj.values())
else:
obj_iter = iter(obj)
# print(obj, ' -> ', obj_iter)
shapes_raw = [get_shape(sub_obj, error=False) for sub_obj in obj_iter]
# Silently drop non-shapes
shapes_raw_filtered = [shape for shape in shapes_raw if shape is not None]
if len(shapes_raw_filtered) > 0: # Continue if we found at least one shape
# Sorting is required to improve hashcode consistency
shapes_raw_filtered_sorted = sorted(shapes_raw_filtered, key=lambda x: _hashcode(x))
# Build a single compound shape
shapes_bd = [Shape(shape) for shape in shapes_raw_filtered_sorted if shape is not None]
return get_shape(Compound(shapes_bd), error)
except TypeError:
pass
if error:
raise ValueError(f'Cannot show object of type {type(obj)} (submit issue?)')
else:
@@ -137,3 +162,32 @@ def image_to_gltf(source: str | bytes, center: any, width: Optional[float] = Non
# Return the GLTF binary blob and the suggested name of the image
return b''.join(mgr.build().save_to_bytes()), name
def _hashcode(obj: Union[bytes, CADCoreLike], **extras) -> str:
"""Utility to compute the STABLE hash code of a shape"""
# NOTE: obj.HashCode(MAX_HASH_CODE) is not stable across different runs of the same program
# This is best-effort and not guaranteed to be unique
hasher = hashlib.md5(usedforsecurity=False)
for k, v in extras.items():
hasher.update(str(k).encode())
hasher.update(str(v).encode())
if isinstance(obj, bytes):
hasher.update(obj)
elif isinstance(obj, TopLoc_Location):
sub_data = io.BytesIO()
obj.DumpJson(sub_data)
hasher.update(sub_data.getvalue())
elif isinstance(obj, TopoDS_Shape):
map_of_shapes = TopTools_IndexedMapOfShape()
TopExp.MapShapes_s(obj, map_of_shapes)
for i in range(1, map_of_shapes.Extent() + 1):
sub_shape = map_of_shapes.FindKey(i)
sub_data = io.BytesIO()
TopoDS_Shape.DumpJson(sub_shape, sub_data)
val = sub_data.getvalue()
val = re.sub(b'"this": "[^"]*"', b'', val) # Remove memory address
hasher.update(val)
else:
raise ValueError(f'Cannot hash object of type {type(obj)}')
return hasher.hexdigest()

View File

@@ -1,14 +1,9 @@
import hashlib
import io
import re
from typing import List, Dict, Tuple, Union
from typing import List, Dict, Tuple
from OCP.BRep import BRep_Tool
from OCP.BRepAdaptor import BRepAdaptor_Curve
from OCP.GCPnts import GCPnts_TangentialDeflection
from OCP.TopExp import TopExp
from OCP.TopLoc import TopLoc_Location
from OCP.TopTools import TopTools_IndexedMapOfShape
from OCP.TopoDS import TopoDS_Face, TopoDS_Edge, TopoDS_Shape, TopoDS_Vertex
from build123d import Shape, Vertex, Face, Location
from pygltflib import GLTF2
@@ -130,30 +125,3 @@ def _tessellate_vertex(mgr: GLTFMgr, ocp_vertex: TopoDS_Vertex, faces: List[Topo
mgr.add_vertex(_push_point((c.X, c.Y, c.Z), faces))
def _hashcode(obj: Union[bytes, TopoDS_Shape], **extras) -> str:
"""Utility to compute the hash code of a shape recursively without the need to tessellate it"""
# NOTE: obj.HashCode(MAX_HASH_CODE) is not stable across different runs of the same program
# This is best-effort and not guaranteed to be unique
hasher = hashlib.md5(usedforsecurity=False)
for k, v in extras.items():
hasher.update(str(k).encode())
hasher.update(str(v).encode())
if isinstance(obj, bytes):
hasher.update(obj)
elif isinstance(obj, TopLoc_Location):
sub_data = io.BytesIO()
obj.DumpJson(sub_data)
hasher.update(sub_data.getvalue())
elif isinstance(obj, TopoDS_Shape):
map_of_shapes = TopTools_IndexedMapOfShape()
TopExp.MapShapes_s(obj, map_of_shapes)
for i in range(1, map_of_shapes.Extent() + 1):
sub_shape = map_of_shapes.FindKey(i)
sub_data = io.BytesIO()
TopoDS_Shape.DumpJson(sub_shape, sub_data)
val = sub_data.getvalue()
val = re.sub(b'"this": "[^"]*"', b'', val) # Remove memory address
hasher.update(val)
else:
raise ValueError(f'Cannot hash object of type {type(obj)}')
return hasher.hexdigest()

View File

@@ -23,7 +23,8 @@ from yacv_server.myhttp import HTTPHandler
from yacv_server.mylogger import logger
from yacv_server.pubsub import BufferedPubSub
from yacv_server.rwlock import RWLock
from yacv_server.tessellate import _hashcode, tessellate
from yacv_server.tessellate import tessellate
from yacv_server.cad import _hashcode
@dataclass_json

410
yarn.lock
View File

@@ -207,11 +207,16 @@
chalk "^2.4.2"
js-tokens "^4.0.0"
"@babel/parser@^7.23.6", "@babel/parser@^7.23.9", "@babel/parser@^7.24.0":
"@babel/parser@^7.23.6", "@babel/parser@^7.24.0":
version "7.24.0"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.0.tgz#26a3d1ff49031c53a97d03b604375f028746a9ac"
integrity sha512-QuP/FxEAzMSjXygs8v4N9dvdXzEHN4W1oF3PxuWAtPo08UdM17u89RDMgjLn/mlc56iM0HlLmVkO/wgR+rDgHg==
"@babel/parser@^7.24.4":
version "7.24.4"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.4.tgz#234487a110d89ad5a3ed4a8a566c36b9453e8c88"
integrity sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg==
"@babel/plugin-syntax-jsx@^7.23.3":
version "7.23.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz#8f2e4f8a9b5f9aa16067e142c1ac9cd9f810f473"
@@ -270,10 +275,10 @@
"@babel/helper-validator-identifier" "^7.22.20"
to-fast-properties "^2.0.0"
"@commander-js/extra-typings@^11.0.0":
version "11.1.0"
resolved "https://registry.yarnpkg.com/@commander-js/extra-typings/-/extra-typings-11.1.0.tgz#dd19fcb8cc6e33ede237fc1b7af96c70833d8f93"
integrity sha512-GuvZ38d23H+7Tz2C9DhzCepivsOsky03s5NI+KCy7ke1FNUvsJ2oO47scQ9YaGGhgjgNW5OYYNSADmbjcSoIhw==
"@commander-js/extra-typings@^12.0.0":
version "12.0.1"
resolved "https://registry.yarnpkg.com/@commander-js/extra-typings/-/extra-typings-12.0.1.tgz#4a74a9ccf1d19ef24e71df59359c6d90a605a469"
integrity sha512-OvkMobb1eMqOCuJdbuSin/KJkkZr7n24/UNV+Lcz/0Dhepf3r2p9PaGwpRpAWej7A+gQnny4h8mGhpFl4giKkg==
"@esbuild/aix-ppc64@0.20.2":
version "0.20.2"
@@ -390,37 +395,37 @@
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz#9c907b21e30a52db959ba4f80bb01a0cc403d5cc"
integrity sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==
"@gltf-transform/core@^3.10.1":
version "3.10.1"
resolved "https://registry.yarnpkg.com/@gltf-transform/core/-/core-3.10.1.tgz#d99c060b499482ed2c3304466405bf4c10939831"
integrity sha512-50OYemknGNxjBmiOM6iJp04JAu0bl9jvXJfN/gFt9QdJO02cPDcoXlTfSPJG6TVWDcfl0xPlsx1vybcbPVGFcQ==
"@gltf-transform/core@^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/@gltf-transform/core/-/core-4.0.0.tgz#4977ab4c7b714713f68d78cec80c088941e9c234"
integrity sha512-EVu2832Lb7sqsAfllEHNUUC89AYXXLGjEoWPzpO7WWE7hpuOLh1Aps8z/jZbVFatu2MxWu5/lFZwODkmZ2uevQ==
dependencies:
property-graph "^1.3.1"
property-graph "^2.0.0"
"@gltf-transform/extensions@^3.10.1":
version "3.10.1"
resolved "https://registry.yarnpkg.com/@gltf-transform/extensions/-/extensions-3.10.1.tgz#71664389cae46fb12eb97dc71eb96d86a0d7801f"
integrity sha512-xUS9K5fMvW2dkYN4VzxHg2aBPG54M2WqgIjQ7RoSyybMoD7DsPUyMyVgRja+aiTVt/Bxza2ve7zJBD3+tN+aTA==
"@gltf-transform/extensions@^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/@gltf-transform/extensions/-/extensions-4.0.0.tgz#36f1b64dd7ec11b86b16d8f4fd0fd0ca2c5bbfdf"
integrity sha512-RL6n1UmMITvuHurDdQuvR7a3i3CcXeS54C4+HHeuhIQo17iqADMJBtf9/DurXCB0DX/cZePb9tXHyUHolxc4Ig==
dependencies:
"@gltf-transform/core" "^3.10.1"
ktx-parse "^0.6.0"
"@gltf-transform/core" "^4.0.0"
ktx-parse "^0.7.0"
"@gltf-transform/functions@^3.10.1":
version "3.10.1"
resolved "https://registry.yarnpkg.com/@gltf-transform/functions/-/functions-3.10.1.tgz#c40817740241c0ee770f4d1210ccc766e46d8ab2"
integrity sha512-Zs6+1qvTD9w40R5qv70E4wJXXacNQ46ZxjKKW6dmfGIyjT8bsSJmV3Tdj+WJ8R6lWXXZ8e2p3ZvAUfPDEG73bQ==
"@gltf-transform/functions@^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/@gltf-transform/functions/-/functions-4.0.0.tgz#57d4c5f7dc8707cc6f686185025b15513664d67d"
integrity sha512-z47qqTf/h2y9Q4jQywVeuQDNJ2sQja0Riaf09db0yUusAjpLYQPyJekjtQLcnCi86Px96s2cHEWCK0mSIf0cUQ==
dependencies:
"@gltf-transform/core" "^3.10.1"
"@gltf-transform/extensions" "^3.10.1"
ktx-parse "^0.6.0"
"@gltf-transform/core" "^4.0.0"
"@gltf-transform/extensions" "^4.0.0"
ktx-parse "^0.7.0"
ndarray "^1.0.19"
ndarray-lanczos "^0.3.0"
ndarray-pixels "^3.0.4"
ndarray-pixels "^4.0.0"
"@google/model-viewer@^3.4.0":
version "3.4.0"
resolved "https://registry.yarnpkg.com/@google/model-viewer/-/model-viewer-3.4.0.tgz#dd3fd098b85ae5953a93f8eeef0e62434a0e7cc0"
integrity sha512-ZGZktE+uy7CiNOSrFdR1bTZDe9nfel2h8gWiRY6D5Eit77RAzIRYnPlkdQBoLSo8nnYS0faL/Z1tKP7nntvoGg==
"@google/model-viewer@^3.5.0":
version "3.5.0"
resolved "https://registry.yarnpkg.com/@google/model-viewer/-/model-viewer-3.5.0.tgz#7ca78b4af7e306e84ad1cb0bb22fcecb6f0086bd"
integrity sha512-wyrJ0yi+9XHaGg4OMDG7odbzI3/Lkn55VjIZ6siw3uM0NdPlWIYY8ZQbysbwS6f6jC7GiScax5KaxQxLLk4eQw==
dependencies:
"@monogrid/gainmap-js" "^3.0.1"
lit "^2.7.2"
@@ -777,10 +782,10 @@
"@sigstore/core" "^1.0.0"
"@sigstore/protobuf-specs" "^0.3.0"
"@tsconfig/node20@^20.1.3":
version "20.1.3"
resolved "https://registry.yarnpkg.com/@tsconfig/node20/-/node20-20.1.3.tgz#b3b4cf785e1b390a6ab48a68aa594a25960d2fe8"
integrity sha512-XeWn6Gms5MaQWdj+C4fuxuo/Icy8ckh+BwAIijhX2LKRHHt1OuctLLLlB0F4EPi55m2IUJNTnv8FH9kSBI7Ogw==
"@tsconfig/node20@^20.1.4":
version "20.1.4"
resolved "https://registry.yarnpkg.com/@tsconfig/node20/-/node20-20.1.4.tgz#3457d42eddf12d3bde3976186ab0cd22b85df928"
integrity sha512-sqgsT69YFeLWf5NtJ4Xq/xAF8p4ZQHlmGW74Nu2tD4+g5fAsposc4ZfaaPixVu4y01BEiDCWLRDCvDM5JOsRxg==
"@tufjs/canonical-json@2.0.0":
version "2.0.0"
@@ -795,6 +800,11 @@
"@tufjs/canonical-json" "2.0.0"
minimatch "^9.0.3"
"@tweenjs/tween.js@~23.1.1":
version "23.1.1"
resolved "https://registry.yarnpkg.com/@tweenjs/tween.js/-/tween.js-23.1.1.tgz#0ae28ed9c635805557f78c2626464018d5f1b5e2"
integrity sha512-ZpboH7pCPPeyBWKf8c7TJswtCEQObFo3bOBYalm99NzZarATALYCo5OhbCa/n4RQyJyHfhkdx+hNrdL5ByFYDw==
"@types/estree@1.0.5":
version "1.0.5"
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4"
@@ -805,10 +815,10 @@
resolved "https://registry.yarnpkg.com/@types/ndarray/-/ndarray-1.0.14.tgz#96b28c09a3587a76de380243f87bb7a2d63b4b23"
integrity sha512-oANmFZMnFQvb219SSBIhI1Ih/r4CvHDOzkWyJS/XRqkMrGH5/kaPSA1hQhdIBzouaE+5KpE/f5ylI9cujmckQg==
"@types/node@^20.11.30":
version "20.11.30"
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.30.tgz#9c33467fc23167a347e73834f788f4b9f399d66f"
integrity sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==
"@types/node@^20.12.11":
version "20.12.11"
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.12.11.tgz#c4ef00d3507000d17690643278a60dc55a9dc9be"
integrity sha512-vDg9PZ/zi+Nqp6boSOT7plNuthRugEKixDv5sFTIpkE89MmNtEArAShI4mxuX2+UrLEe9pxC1vm2cjm9YlWbJw==
dependencies:
undici-types "~5.26.4"
@@ -817,14 +827,15 @@
resolved "https://registry.yarnpkg.com/@types/stats.js/-/stats.js-0.17.3.tgz#705446e12ce0fad618557dd88236f51148b7a935"
integrity sha512-pXNfAD3KHOdif9EQXZ9deK82HVNaXP5ZIF5RP2QG6OQFNTaY2YIetfrE9t528vEreGQvEPRDDc8muaoYeK0SxQ==
"@types/three@^0.160.0":
version "0.160.0"
resolved "https://registry.yarnpkg.com/@types/three/-/three-0.160.0.tgz#7915a97e0a14ccaa9ccbb9f190c5730b04a23075"
integrity sha512-jWlbUBovicUKaOYxzgkLlhkiEQJkhCVvg4W2IYD2trqD2om3VK4DGLpHH5zQHNr7RweZK/5re/4IVhbhvxbV9w==
"@types/three@^0.163.0":
version "0.163.0"
resolved "https://registry.yarnpkg.com/@types/three/-/three-0.163.0.tgz#96f5440fcd39452d2c84dfe0c9b7a9cf0247b9e6"
integrity sha512-uIdDhsXRpQiBUkflBS/i1l3JX14fW6Ot9csed60nfbZNXHDTRsnV2xnTVwXcgbvTiboAR4IW+t+lTL5f1rqIqA==
dependencies:
"@tweenjs/tween.js" "~23.1.1"
"@types/stats.js" "*"
"@types/webxr" "*"
fflate "~0.6.10"
fflate "~0.8.2"
meshoptimizer "~0.18.1"
"@types/trusted-types@^2.0.2":
@@ -851,26 +862,26 @@
resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-5.0.4.tgz#508d6a0f2440f86945835d903fcc0d95d1bb8a37"
integrity sha512-WS3hevEszI6CEVEx28F8RjTX97k3KsrcY6kvTg7+Whm5y3oYvcqzVeGCU3hxSAn4uY2CLCkeokkGKpoctccilQ==
"@volar/language-core@2.1.5", "@volar/language-core@~2.1.3":
version "2.1.5"
resolved "https://registry.yarnpkg.com/@volar/language-core/-/language-core-2.1.5.tgz#78803531562ca423a3b4fa1b3a90d33537aab928"
integrity sha512-u1OHmVkCFsJqNdaM2GKuMhE67TxcEnOqJNF+VtYv2Ji8DnrUaF4FAFSNxY+MRGICl+873CsSJVKas9TQtW14LA==
"@volar/language-core@2.2.2", "@volar/language-core@~2.2.2":
version "2.2.2"
resolved "https://registry.yarnpkg.com/@volar/language-core/-/language-core-2.2.2.tgz#3c0e745a6d279e6f1872ad3de406683e2e92002b"
integrity sha512-GuvEL4JdxbnLVhPLICncCGT+tVW4cIz9GxXNeDofNnJ4iNTKhr5suGVsA1GLOne9PbraSjn8PlLt+pvLxuRVeQ==
dependencies:
"@volar/source-map" "2.1.5"
"@volar/source-map" "2.2.2"
"@volar/source-map@2.1.5":
version "2.1.5"
resolved "https://registry.yarnpkg.com/@volar/source-map/-/source-map-2.1.5.tgz#c073549368d399365f0024ed89aea93de0807328"
integrity sha512-GIkAM6fHgDcTXcdH4i10fAiAZzO0HLIer8/pt3oZ9A0n7n4R5d1b2F8Xxzh/pgmgNoL+SrHX3MFxs35CKgfmtA==
"@volar/source-map@2.2.2":
version "2.2.2"
resolved "https://registry.yarnpkg.com/@volar/source-map/-/source-map-2.2.2.tgz#ec25e8366297b1e9bbd3abcb1636330010d59d59"
integrity sha512-vUwvZuSW6iN4JI9QRinh9EjFasx1TUtnaWMKwgWx08xz1PyYuNkLlWlrZXBZ5GGBhML0u230M/7X+AHY2h9yKg==
dependencies:
muggle-string "^0.4.0"
"@volar/typescript@~2.1.3":
version "2.1.5"
resolved "https://registry.yarnpkg.com/@volar/typescript/-/typescript-2.1.5.tgz#756a8626af1c5ce3c9d8df3e79d49bfdd0adf39e"
integrity sha512-zo9a3NrNMSkufIvHuExDGTfYv+zO7C5p2wg8fyP7vcqF/Qo0ztjb0ZfOgq/A85EO/MBc1Kj2Iu7PaOBtP++NMw==
"@volar/typescript@~2.2.2":
version "2.2.2"
resolved "https://registry.yarnpkg.com/@volar/typescript/-/typescript-2.2.2.tgz#b133919b5d1ef99f882916ddb62297766500843c"
integrity sha512-WcwOREz7+uOrpjUrKhOMaOKKmyPdtqF95HWX7SE0d9hhBB1KkfahxhaAex5U9Bn43LfINHlycLoYCNEtfeKm0g==
dependencies:
"@volar/language-core" "2.1.5"
"@volar/language-core" "2.2.2"
path-browserify "^1.0.1"
"@vue/babel-helper-vue-transform-on@1.2.1":
@@ -906,54 +917,54 @@
"@babel/parser" "^7.23.6"
"@vue/compiler-sfc" "^3.4.15"
"@vue/compiler-core@3.4.21":
version "3.4.21"
resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.4.21.tgz#868b7085378fc24e58c9aed14c8d62110a62be1a"
integrity sha512-MjXawxZf2SbZszLPYxaFCjxfibYrzr3eYbKxwpLR9EQN+oaziSu3qKVbwBERj1IFIB8OLUewxB5m/BFzi613og==
"@vue/compiler-core@3.4.27":
version "3.4.27"
resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.4.27.tgz#e69060f4b61429fe57976aa5872cfa21389e4d91"
integrity sha512-E+RyqY24KnyDXsCuQrI+mlcdW3ALND6U7Gqa/+bVwbcpcR3BRRIckFoz7Qyd4TTlnugtwuI7YgjbvsLmxb+yvg==
dependencies:
"@babel/parser" "^7.23.9"
"@vue/shared" "3.4.21"
"@babel/parser" "^7.24.4"
"@vue/shared" "3.4.27"
entities "^4.5.0"
estree-walker "^2.0.2"
source-map-js "^1.0.2"
source-map-js "^1.2.0"
"@vue/compiler-dom@3.4.21", "@vue/compiler-dom@^3.4.0":
version "3.4.21"
resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.4.21.tgz#0077c355e2008207283a5a87d510330d22546803"
integrity sha512-IZC6FKowtT1sl0CR5DpXSiEB5ayw75oT2bma1BEhV7RRR1+cfwLrxc2Z8Zq/RGFzJ8w5r9QtCOvTjQgdn0IKmA==
"@vue/compiler-dom@3.4.27", "@vue/compiler-dom@^3.4.0":
version "3.4.27"
resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.4.27.tgz#d51d35f40d00ce235d7afc6ad8b09dfd92b1cc1c"
integrity sha512-kUTvochG/oVgE1w5ViSr3KUBh9X7CWirebA3bezTbB5ZKBQZwR2Mwj9uoSKRMFcz4gSMzzLXBPD6KpCLb9nvWw==
dependencies:
"@vue/compiler-core" "3.4.21"
"@vue/shared" "3.4.21"
"@vue/compiler-core" "3.4.27"
"@vue/shared" "3.4.27"
"@vue/compiler-sfc@3.4.21", "@vue/compiler-sfc@^3.4.15":
version "3.4.21"
resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.4.21.tgz#4af920dc31ab99e1ff5d152b5fe0ad12181145b2"
integrity sha512-me7epoTxYlY+2CUM7hy9PCDdpMPfIwrOvAXud2Upk10g4YLv9UBW7kL798TvMeDhPthkZ0CONNrK2GoeI1ODiQ==
"@vue/compiler-sfc@3.4.27", "@vue/compiler-sfc@^3.4.15":
version "3.4.27"
resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.4.27.tgz#399cac1b75c6737bf5440dc9cf3c385bb2959701"
integrity sha512-nDwntUEADssW8e0rrmE0+OrONwmRlegDA1pD6QhVeXxjIytV03yDqTey9SBDiALsvAd5U4ZrEKbMyVXhX6mCGA==
dependencies:
"@babel/parser" "^7.23.9"
"@vue/compiler-core" "3.4.21"
"@vue/compiler-dom" "3.4.21"
"@vue/compiler-ssr" "3.4.21"
"@vue/shared" "3.4.21"
"@babel/parser" "^7.24.4"
"@vue/compiler-core" "3.4.27"
"@vue/compiler-dom" "3.4.27"
"@vue/compiler-ssr" "3.4.27"
"@vue/shared" "3.4.27"
estree-walker "^2.0.2"
magic-string "^0.30.7"
postcss "^8.4.35"
source-map-js "^1.0.2"
magic-string "^0.30.10"
postcss "^8.4.38"
source-map-js "^1.2.0"
"@vue/compiler-ssr@3.4.21":
version "3.4.21"
resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.4.21.tgz#b84ae64fb9c265df21fc67f7624587673d324fef"
integrity sha512-M5+9nI2lPpAsgXOGQobnIueVqc9sisBFexh5yMIMRAPYLa7+5wEJs8iqOZc1WAa9WQbx9GR2twgznU8LTIiZ4Q==
"@vue/compiler-ssr@3.4.27":
version "3.4.27"
resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.4.27.tgz#2a8ecfef1cf448b09be633901a9c020360472e3d"
integrity sha512-CVRzSJIltzMG5FcidsW0jKNQnNRYC8bT21VegyMMtHmhW3UOI7knmUehzswXLrExDLE6lQCZdrhD4ogI7c+vuw==
dependencies:
"@vue/compiler-dom" "3.4.21"
"@vue/shared" "3.4.21"
"@vue/compiler-dom" "3.4.27"
"@vue/shared" "3.4.27"
"@vue/language-core@2.0.7":
version "2.0.7"
resolved "https://registry.yarnpkg.com/@vue/language-core/-/language-core-2.0.7.tgz#af12f752a93c4d2498626fca33f5d1ddc8c5ceb9"
integrity sha512-Vh1yZX3XmYjn9yYLkjU8DN6L0ceBtEcapqiyclHne8guG84IaTzqtvizZB1Yfxm3h6m7EIvjerLO5fvOZO6IIQ==
"@vue/language-core@2.0.17":
version "2.0.17"
resolved "https://registry.yarnpkg.com/@vue/language-core/-/language-core-2.0.17.tgz#25ba5c7f4450790cc6cfaccf9805a6b91ada1bd7"
integrity sha512-tHw2J6G9yL4kn3jN5MftOHEq86Y6qnuohBQ1OHkJ73fAv3OYgwDI1cfX7ds0OEJEycOMG64BA3ql5bDgDa41zw==
dependencies:
"@volar/language-core" "~2.1.3"
"@volar/language-core" "~2.2.2"
"@vue/compiler-dom" "^3.4.0"
"@vue/shared" "^3.4.0"
computeds "^0.0.1"
@@ -961,42 +972,42 @@
path-browserify "^1.0.1"
vue-template-compiler "^2.7.14"
"@vue/reactivity@3.4.21":
version "3.4.21"
resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.4.21.tgz#affd3415115b8ebf4927c8d2a0d6a24bccfa9f02"
integrity sha512-UhenImdc0L0/4ahGCyEzc/pZNwVgcglGy9HVzJ1Bq2Mm9qXOpP8RyNTjookw/gOCUlXSEtuZ2fUg5nrHcoqJcw==
"@vue/reactivity@3.4.27":
version "3.4.27"
resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.4.27.tgz#6ece72331bf719953f5eaa95ec60b2b8d49e3791"
integrity sha512-kK0g4NknW6JX2yySLpsm2jlunZJl2/RJGZ0H9ddHdfBVHcNzxmQ0sS0b09ipmBoQpY8JM2KmUw+a6sO8Zo+zIA==
dependencies:
"@vue/shared" "3.4.21"
"@vue/shared" "3.4.27"
"@vue/runtime-core@3.4.21":
version "3.4.21"
resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.4.21.tgz#3749c3f024a64c4c27ecd75aea4ca35634db0062"
integrity sha512-pQthsuYzE1XcGZznTKn73G0s14eCJcjaLvp3/DKeYWoFacD9glJoqlNBxt3W2c5S40t6CCcpPf+jG01N3ULyrA==
"@vue/runtime-core@3.4.27":
version "3.4.27"
resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.4.27.tgz#1b6e1d71e4604ba7442dd25ed22e4a1fc6adbbda"
integrity sha512-7aYA9GEbOOdviqVvcuweTLe5Za4qBZkUY7SvET6vE8kyypxVgaT1ixHLg4urtOlrApdgcdgHoTZCUuTGap/5WA==
dependencies:
"@vue/reactivity" "3.4.21"
"@vue/shared" "3.4.21"
"@vue/reactivity" "3.4.27"
"@vue/shared" "3.4.27"
"@vue/runtime-dom@3.4.21":
version "3.4.21"
resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.4.21.tgz#91f867ef64eff232cac45095ab28ebc93ac74588"
integrity sha512-gvf+C9cFpevsQxbkRBS1NpU8CqxKw0ebqMvLwcGQrNpx6gqRDodqKqA+A2VZZpQ9RpK2f9yfg8VbW/EpdFUOJw==
"@vue/runtime-dom@3.4.27":
version "3.4.27"
resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.4.27.tgz#fe8d1ce9bbe8921d5dd0ad5c10df0e04ef7a5ee7"
integrity sha512-ScOmP70/3NPM+TW9hvVAz6VWWtZJqkbdf7w6ySsws+EsqtHvkhxaWLecrTorFxsawelM5Ys9FnDEMt6BPBDS0Q==
dependencies:
"@vue/runtime-core" "3.4.21"
"@vue/shared" "3.4.21"
"@vue/runtime-core" "3.4.27"
"@vue/shared" "3.4.27"
csstype "^3.1.3"
"@vue/server-renderer@3.4.21":
version "3.4.21"
resolved "https://registry.yarnpkg.com/@vue/server-renderer/-/server-renderer-3.4.21.tgz#150751579d26661ee3ed26a28604667fa4222a97"
integrity sha512-aV1gXyKSN6Rz+6kZ6kr5+Ll14YzmIbeuWe7ryJl5muJ4uwSwY/aStXTixx76TwkZFJLm1aAlA/HSWEJ4EyiMkg==
"@vue/server-renderer@3.4.27":
version "3.4.27"
resolved "https://registry.yarnpkg.com/@vue/server-renderer/-/server-renderer-3.4.27.tgz#3306176f37e648ba665f97dda3ce705687be63d2"
integrity sha512-dlAMEuvmeA3rJsOMJ2J1kXU7o7pOxgsNHVr9K8hB3ImIkSuBrIdy0vF66h8gf8Tuinf1TK3mPAz2+2sqyf3KzA==
dependencies:
"@vue/compiler-ssr" "3.4.21"
"@vue/shared" "3.4.21"
"@vue/compiler-ssr" "3.4.27"
"@vue/shared" "3.4.27"
"@vue/shared@3.4.21", "@vue/shared@^3.4.0":
version "3.4.21"
resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.4.21.tgz#de526a9059d0a599f0b429af7037cd0c3ed7d5a1"
integrity sha512-PuJe7vDIi6VYSinuEbUIQgMIRZGgM8e4R+G+/dQTk0X1NEdvgvvgv7m+rfmDH1gZzyA1OjjoWskvHlfRNfQf3g==
"@vue/shared@3.4.27", "@vue/shared@^3.4.0":
version "3.4.27"
resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.4.27.tgz#f05e3cd107d157354bb4ae7a7b5fc9cf73c63b50"
integrity sha512-DL3NmY2OFlqmYYrzp39yi3LDkKxa5vZVwxWdQ3rG0ekuWscHraeIbnI8t+aZK7qhYqEqWKTUdijadunb9pnrgA==
"@vue/tsconfig@^0.5.1":
version "0.5.1"
@@ -1540,10 +1551,10 @@ fast-fifo@^1.1.0, fast-fifo@^1.2.0:
resolved "https://registry.yarnpkg.com/fast-fifo/-/fast-fifo-1.3.2.tgz#286e31de96eb96d38a97899815740ba2a4f3640c"
integrity sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==
fflate@~0.6.10:
version "0.6.10"
resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.6.10.tgz#5f40f9659205936a2d18abf88b2e7781662b6d43"
integrity sha512-IQrh3lEPM93wVCEczc9SaAOvkmcoQn/G8Bo1e8ZPlY3X3bnAxWaBdvTdvM1hP62iZp0BXWDy4vTAy4fF0+Dlpg==
fflate@~0.8.2:
version "0.8.2"
resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.8.2.tgz#fc8631f5347812ad6028bbe4a2308b2792aa1dea"
integrity sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==
foreground-child@^3.1.0:
version "3.1.1"
@@ -1596,12 +1607,12 @@ gauge@^5.0.0:
strip-ansi "^6.0.1"
wide-align "^1.1.5"
generate-license-file@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/generate-license-file/-/generate-license-file-3.0.1.tgz#a30420a0c0d625da5f722fbf52f39d4313f9aeff"
integrity sha512-kQ9IoHX5bcydUugMlhOxxSKbx5zLfSJ8XuWNKZ3Jp/v30VFeAcZ8Ch4zyZcYqmm0IKy6fNzZPe2o8IhNjMQbjA==
generate-license-file@^3.4.0:
version "3.4.0"
resolved "https://registry.yarnpkg.com/generate-license-file/-/generate-license-file-3.4.0.tgz#9c0663c1a1ab3c4a86c47cc59a694f09884b0e1b"
integrity sha512-VqrocosZn9INhkA/MZk+ktc/tRrDj3rSGHdEPau2CZErLDze8BWApBT9HcnYDo4QnDNDEf7Q/ySZbymh9WfaOQ==
dependencies:
"@commander-js/extra-typings" "^11.0.0"
"@commander-js/extra-typings" "^12.0.0"
"@npmcli/arborist" "^7.0.0"
cli-spinners "^2.6.0"
cosmiconfig "^9.0.0"
@@ -1891,10 +1902,10 @@ just-diff@^6.0.0:
resolved "https://registry.yarnpkg.com/just-diff/-/just-diff-6.0.2.tgz#03b65908543ac0521caf6d8eb85035f7d27ea285"
integrity sha512-S59eriX5u3/QhMNq3v/gm8Kd0w8OS6Tz2FS1NG4blv+z0MuQcBRJyFWjdovM0Rad4/P4aUPFtnkNjMjyMlMSYA==
ktx-parse@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/ktx-parse/-/ktx-parse-0.6.0.tgz#69e12a511cf345546da27b5b046182f5f31f68f9"
integrity sha512-hYOJUI86N9+YPm0M3t8hVzW9t5FnFFibRalZCrqHs/qM2eNziqQzBtAaF0ErgkXm8F+5uE8CjPUYr32vWlXLkQ==
ktx-parse@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/ktx-parse/-/ktx-parse-0.7.0.tgz#65788a43a1a1c19c795ff26299e9318c16b436b2"
integrity sha512-naezun/2iiWrantwoRI9mw6E4iN41ggYzJSR9XAZzf6+rv+2Tb1yYN8VJhGsA0uptBexE0m4GDh+iiQhYpW+Qw==
lie@^3.0.2:
version "3.3.0"
@@ -1960,10 +1971,10 @@ lru-cache@^6.0.0:
dependencies:
yallist "^4.0.0"
magic-string@^0.30.7:
version "0.30.7"
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.7.tgz#0cecd0527d473298679da95a2d7aeb8c64048505"
integrity sha512-8vBuFF/I/+OSLRmdf2wwFCJCz+nSn0m6DPvGH1fS/KiQoSaR+sETbov0eIk9KhEKy8CYqIkIAnbohxT/4H0kuA==
magic-string@^0.30.10:
version "0.30.10"
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.10.tgz#123d9c41a0cb5640c892b041d4cfb3bd0aa4b39e"
integrity sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==
dependencies:
"@jridgewell/sourcemap-codec" "^1.4.15"
@@ -2133,10 +2144,10 @@ ndarray-ops@^1.2.2:
dependencies:
cwise-compiler "^1.0.0"
ndarray-pixels@^3.0.4:
version "3.1.0"
resolved "https://registry.yarnpkg.com/ndarray-pixels/-/ndarray-pixels-3.1.0.tgz#0e8ab0f0c04adab2f50f62f4a70442ba0c103d1b"
integrity sha512-icw7L/kbxlHVoBgFWc0fCl1sYcatYSoZrAudD6KiQ1WXy84hRXIfqel5CLkh/SeLhb02Q2NW1ud9lE5G84V0zQ==
ndarray-pixels@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/ndarray-pixels/-/ndarray-pixels-4.0.0.tgz#994cf904cfaffd5c3e90028b37ef3878c5894613"
integrity sha512-rFNR2IMEaWWI4dCVKg63LNWizE9odBdWf49ZHl/hgMa8hh/g+u/vf6vqD0KSt+0Fw83C2G+kWLpI3YuJHqRwSg==
dependencies:
"@types/ndarray" "^1.0.11"
ndarray "^1.0.19"
@@ -2410,7 +2421,7 @@ postcss-selector-parser@^6.0.10:
cssesc "^3.0.0"
util-deprecate "^1.0.2"
postcss@^8.4.35, postcss@^8.4.36:
postcss@^8.4.38:
version "8.4.38"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.38.tgz#b387d533baf2054288e337066d81c6bee9db9e0e"
integrity sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==
@@ -2473,10 +2484,10 @@ promise-worker-transferable@^1.0.4:
is-promise "^2.1.0"
lie "^3.0.2"
property-graph@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/property-graph/-/property-graph-1.3.1.tgz#25fb2c8040ba9b15f04cda90a443f3f844505293"
integrity sha512-gei3N/bHWJdCItJ4blnlGWd9iauEZI+JZYj/A0D177XSI01+QhiJGAVscYBhe3Yywow3A2QJzVtsO2P+UgrRRQ==
property-graph@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/property-graph/-/property-graph-2.0.0.tgz#aaf79cdd5fd05171c1d34c41367acdaac3cbac61"
integrity sha512-peDswWfLn7Lx+iPIxefhEUbLC7cs1KbfyKqOl5C5TF5F6urnyAORxzQ7JY21yjRzH7CpLa6+d1G+BemBr/lKyw==
pump@^3.0.0:
version "3.0.0"
@@ -2696,11 +2707,6 @@ socks@^2.7.1:
ip-address "^9.0.5"
smart-buffer "^4.2.0"
source-map-js@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
source-map-js@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af"
@@ -2767,7 +2773,16 @@ streamx@^2.13.0, streamx@^2.15.0:
optionalDependencies:
bare-events "^2.2.0"
"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.3:
"string-width-cjs@npm:string-width@^4.2.0":
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
dependencies:
emoji-regex "^8.0.0"
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"
"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@@ -2792,7 +2807,14 @@ string_decoder@^1.1.1:
dependencies:
safe-buffer "~5.2.0"
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
dependencies:
ansi-regex "^5.0.1"
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@@ -2872,9 +2894,9 @@ tar-stream@^3.1.5:
streamx "^2.15.0"
tar@^6.1.11, tar@^6.1.2:
version "6.2.0"
resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.0.tgz#b14ce49a79cb1cd23bc9b016302dea5474493f73"
integrity sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==
version "6.2.1"
resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.1.tgz#717549c541bc3c2af15751bea94b1dd068d4b03a"
integrity sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==
dependencies:
chownr "^2.0.0"
fs-minipass "^2.0.0"
@@ -2883,20 +2905,20 @@ tar@^6.1.11, tar@^6.1.2:
mkdirp "^1.0.3"
yallist "^4.0.0"
terser@^5.29.2:
version "5.29.2"
resolved "https://registry.yarnpkg.com/terser/-/terser-5.29.2.tgz#c17d573ce1da1b30f21a877bffd5655dd86fdb35"
integrity sha512-ZiGkhUBIM+7LwkNjXYJq8svgkd+QK3UUr0wJqY4MieaezBSAIPgbSPZyIx0idM6XWK5CMzSWa8MJIzmRcB8Caw==
terser@^5.31.0:
version "5.31.0"
resolved "https://registry.yarnpkg.com/terser/-/terser-5.31.0.tgz#06eef86f17007dbad4593f11a574c7f5eb02c6a1"
integrity sha512-Q1JFAoUKE5IMfI4Z/lkE/E6+SwgzO+x4tq4v1AyBLRj8VSYvRO6A/rQrPg1yud4g0En9EKI1TvFRF2tQFcoUkg==
dependencies:
"@jridgewell/source-map" "^0.3.3"
acorn "^8.8.2"
commander "^2.20.0"
source-map-support "~0.5.20"
three-mesh-bvh@^0.7.3:
version "0.7.3"
resolved "https://registry.yarnpkg.com/three-mesh-bvh/-/three-mesh-bvh-0.7.3.tgz#91f2d7e26f230288b5b0a6bdf41bdd9620348945"
integrity sha512-3W6KjzmupjfE89GuHPT31kxKWZ4YGZPEZJNysJpiOZfQRsBQQgmK7v/VJPpjG6syhAvTnY+5Fr77EvIkTLpGSw==
three-mesh-bvh@^0.7.4:
version "0.7.4"
resolved "https://registry.yarnpkg.com/three-mesh-bvh/-/three-mesh-bvh-0.7.4.tgz#a5c799856a3f26f73537a73b6ec632c30f712ba8"
integrity sha512-flxe0A4uflTPR6elgq/Y8VrLoljDNS899i422SxQcU3EtMj6o8z4kZRyqZqGWzR0qMf1InTZzY1/0xZl/rnvVw==
"three-orientation-gizmo@https://github.com/jrj2211/three-orientation-gizmo":
version "1.1.0"
@@ -2909,10 +2931,10 @@ three@^0.125.0:
resolved "https://registry.yarnpkg.com/three/-/three-0.125.2.tgz#dcba12749a2eb41522e15212b919cd3fbf729b12"
integrity sha512-7rIRO23jVKWcAPFdW/HREU2NZMGWPBZ4XwEMt0Ak0jwLUKVJhcKM55eCBWyGZq/KiQbeo1IeuAoo/9l2dzhTXA==
three@^0.160.1:
version "0.160.1"
resolved "https://registry.yarnpkg.com/three/-/three-0.160.1.tgz#61fe2907312e8604b1f64187f58e047503847413"
integrity sha512-Bgl2wPJypDOZ1stAxwfWAcJ0WQf7QzlptsxkjYiURPz+n5k4RBDLsq+6f9Y75TYxn6aHLcWz+JNmwTOXWrQTBQ==
three@^0.163.0:
version "0.163.0"
resolved "https://registry.yarnpkg.com/three/-/three-0.163.0.tgz#cbfefbfd64a1353ab7cc8bf0fc396ddca1875a49"
integrity sha512-HlMgCb2TF/dTLRtknBnjUTsR8FsDqBY43itYop2+Zg822I+Kd0Ua2vs8CvfBVefXkBdNDrLMoRTGCIIpfCuDew==
to-fast-properties@^2.0.0:
version "2.0.0"
@@ -2945,10 +2967,10 @@ tunnel-agent@^0.6.0:
dependencies:
safe-buffer "^5.0.1"
typescript@~5.4.3:
version "5.4.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.3.tgz#5c6fedd4c87bee01cd7a528a30145521f8e0feff"
integrity sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==
typescript@~5.4.5:
version "5.4.5"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.5.tgz#42ccef2c571fdbd0f6718b1d1f5e6e5ef006f611"
integrity sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==
undici-types@~5.26.4:
version "5.26.5"
@@ -3002,13 +3024,13 @@ validate-npm-package-name@^5.0.0:
dependencies:
builtins "^5.0.0"
vite@^5.2.6:
version "5.2.6"
resolved "https://registry.yarnpkg.com/vite/-/vite-5.2.6.tgz#fc2ce309e0b4871e938cb0aca3b96c422c01f222"
integrity sha512-FPtnxFlSIKYjZ2eosBQamz4CbyrTizbZ3hnGJlh/wMtCrlp1Hah6AzBLjGI5I2urTfNnpovpHdrL6YRuBOPnCA==
vite@^5.2.11:
version "5.2.11"
resolved "https://registry.yarnpkg.com/vite/-/vite-5.2.11.tgz#726ec05555431735853417c3c0bfb36003ca0cbd"
integrity sha512-HndV31LWW05i1BLPMUCE1B9E9GFbOu1MbenhS58FuK6owSO5qHm7GiCotrNY1YE5rMeQSFBGmT5ZaLEjFizgiQ==
dependencies:
esbuild "^0.20.1"
postcss "^8.4.36"
postcss "^8.4.38"
rollup "^4.13.0"
optionalDependencies:
fsevents "~2.3.3"
@@ -3021,30 +3043,30 @@ vue-template-compiler@^2.7.14:
de-indent "^1.0.2"
he "^1.2.0"
vue-tsc@^2.0.7:
version "2.0.7"
resolved "https://registry.yarnpkg.com/vue-tsc/-/vue-tsc-2.0.7.tgz#3177a2fe720bfa7355d3717929ee8c8d132bc5d0"
integrity sha512-LYa0nInkfcDBB7y8jQ9FQ4riJTRNTdh98zK/hzt4gEpBZQmf30dPhP+odzCa+cedGz6B/guvJEd0BavZaRptjg==
vue-tsc@^2.0.17:
version "2.0.17"
resolved "https://registry.yarnpkg.com/vue-tsc/-/vue-tsc-2.0.17.tgz#bd1c7704c454169b3fcb893421226be99ccae4bf"
integrity sha512-RRZsiCBD1hvATQb321xV+SkRDKsK5hgFQ4WXy5wuYsyyjz8xAK4DjxHkpH7PFoJKUbZTbeW8KzhejzXZS49Tzw==
dependencies:
"@volar/typescript" "~2.1.3"
"@vue/language-core" "2.0.7"
"@volar/typescript" "~2.2.2"
"@vue/language-core" "2.0.17"
semver "^7.5.4"
vue@^3.4.21:
version "3.4.21"
resolved "https://registry.yarnpkg.com/vue/-/vue-3.4.21.tgz#69ec30e267d358ee3a0ce16612ba89e00aaeb731"
integrity sha512-5hjyV/jLEIKD/jYl4cavMcnzKwjMKohureP8ejn3hhEjwhWIhWeuzL2kJAjzl/WyVsgPY56Sy4Z40C3lVshxXA==
vue@^3.4.27:
version "3.4.27"
resolved "https://registry.yarnpkg.com/vue/-/vue-3.4.27.tgz#40b7d929d3e53f427f7f5945386234d2854cc2a1"
integrity sha512-8s/56uK6r01r1icG/aEOHqyMVxd1bkYcSe9j8HcKtr/xTOFWvnzIVTehNW+5Yt89f+DLBe4A569pnZLS5HzAMA==
dependencies:
"@vue/compiler-dom" "3.4.21"
"@vue/compiler-sfc" "3.4.21"
"@vue/runtime-dom" "3.4.21"
"@vue/server-renderer" "3.4.21"
"@vue/shared" "3.4.21"
"@vue/compiler-dom" "3.4.27"
"@vue/compiler-sfc" "3.4.27"
"@vue/runtime-dom" "3.4.27"
"@vue/server-renderer" "3.4.27"
"@vue/shared" "3.4.27"
vuetify@^3.5.11:
version "3.5.11"
resolved "https://registry.yarnpkg.com/vuetify/-/vuetify-3.5.11.tgz#9e5b628544e736de0b7f236b704539d544588152"
integrity sha512-us5I0jyFwIQYG4v41PFmVMkoc/oJddVT4C2RFjJTI99ttigbQ92gsTeG5SB8BPfmfnUS4paR5BedZwk6W3KlJw==
vuetify@^3.6.5:
version "3.6.5"
resolved "https://registry.yarnpkg.com/vuetify/-/vuetify-3.6.5.tgz#d190d0d64592f858582f4cb6310bac69f74627b5"
integrity sha512-YrHTM1vb7UllAtfH9tWfTo1wYMjyCSybu4WtXrfMRpMwAaZWgfrMmqD/4Tc+0KqDsDsYMXaYs0nJ6HtdMJZbyA==
walk-up-path@^3.0.1:
version "3.0.1"