Compare commits

...

488 Commits

Author SHA1 Message Date
Yeicor
f1c0a21699 Automatically update version to 0.10.6 2025-08-02 11:35:48 +00:00
Yeicor
8df0401fef Fix production builds 2 2025-08-02 13:34:53 +02:00
Yeicor
2c7adf8188 Cleaner deployment 2 2025-08-02 13:18:10 +02:00
Yeicor
d2b1b3b952 Automatically update version to 0.10.5 2025-08-02 11:16:15 +00:00
Yeicor
db3bbf2d32 Cleaner deployment 2025-08-02 13:15:25 +02:00
Yeicor
1d6230ef1e Fix production builds 2025-08-02 13:12:15 +02:00
renovate[bot]
7d22ca465e fix(deps): update dependency three to ^0.179.0 2025-08-02 11:03:50 +00:00
Yeicor
7c38ccc522 Automatically update version to 0.10.4 2025-08-02 11:02:49 +00:00
Yeicor
06a95d4875 Add upload and share functionality and minor improvements 2025-08-02 12:50:20 +02:00
renovate[bot]
56fc556c0f chore(deps): update dependency @vitejs/plugin-vue to v6.0.1 2025-08-02 02:45:14 +00:00
Yeicor
fe54f48ad7 Automatically update version to 0.10.3 2025-07-31 18:25:41 +00:00
Yeicor
c47f961b0d Automatically update version to 0.10.2 2025-07-31 18:13:15 +00:00
Yeicor
f86b714c08 Automatically update version to 0.10.2-alpha.1 2025-07-31 17:56:25 +00:00
Yeicor
2ae7c86f8d Fix release CI 2025-07-31 19:54:03 +02:00
Yeicor
0908216bfc Preinstall font-fetcher package for automatically downloading any requested font. 2025-07-31 19:34:06 +02:00
renovate[bot]
7871a5070d chore(deps): lock file maintenance 2025-07-27 17:42:55 +00:00
renovate[bot]
5173f00d29 chore(deps): lock file maintenance 2025-07-27 10:42:21 +00:00
renovate[bot]
c2ef910783 chore(deps): lock file maintenance 2025-07-26 17:45:40 +00:00
Yeicor
5a5f948224 Update README.md 2025-07-26 19:30:00 +02:00
Yeicor
dbeae5632e Automatically update version to 0.10.1 2025-07-26 15:28:24 +00:00
Yeicor
59116e4a1a Merge remote-tracking branch 'origin/master' 2025-07-26 17:27:41 +02:00
Yeicor
0be0103c3c Fix loading from dev server 2025-07-26 17:27:32 +02:00
Yeicor
d6deef9e7f Automatically update version to 0.10.0 2025-07-26 15:21:57 +00:00
Yeicor
ad956762f4 Automatically update version to 0.10.0-rc.6 2025-07-26 15:05:40 +00:00
Yeicor
a4acd2f3d3 Revert "fix(deps): update python to >=3.13,<3.14 (#246)"
This reverts commit 0855a9c6c7.
2025-07-26 17:04:18 +02:00
Yeicor
c877fef490 Minor fixes and drag and drop models onto interface 2025-07-26 17:01:42 +02:00
renovate[bot]
0855a9c6c7 fix(deps): update python to >=3.13,<3.14 (#246)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-26 12:19:17 +00:00
Yeicor
657b34d098 Automatically update version to 0.10.0-rc.5 2025-07-26 12:17:21 +00:00
Yeicor
ad83f1c937 Merge remote-tracking branch 'origin/master' 2025-07-26 14:15:17 +02:00
Yeicor
38be4c638b playground: minor improvements 2025-07-26 14:15:09 +02:00
renovate[bot]
63f2b716d6 chore(deps): lock file maintenance 2025-07-26 01:37:40 +00:00
Yeicor
9e70a3998d Automatically update version to 0.10.0-rc.4 2025-07-25 23:14:16 +00:00
Yeicor
c7c4adc250 Merge remote-tracking branch 'origin/master' 2025-07-26 01:13:19 +02:00
Yeicor
393decd876 playground: fix async code usage in startup.py 2025-07-26 01:13:03 +02:00
Yeicor
111f417905 Automatically update version to 0.10.0-rc.3 2025-07-25 23:07:00 +00:00
Yeicor
7296b15a67 Merge remote-tracking branch 'origin/master' 2025-07-26 01:05:57 +02:00
Yeicor
88190b0d1e Automatically update version to 0.10.0-rc.2 2025-07-25 23:04:16 +00:00
Yeicor
f2a607bb00 playground: better readme and prerelease yacv-server 2025-07-26 01:03:14 +02:00
Yeicor
0b6ed2fc34 Automatically update version to 0.10.0-rc.1 2025-07-25 22:54:35 +00:00
Yeicor
d1e5658e07 playground: minor improvements and install default font 2025-07-26 00:51:53 +02:00
Yeicor
3545785cae Automatically update version to 0.10.0-alpha.6 2025-07-25 16:22:13 +00:00
Yeicor
1df938b067 Fix max python version 2025-07-25 18:19:07 +02:00
Yeicor
42ae6384f0 Automatically update version to 0.10.0-alpha.5 2025-07-25 16:15:39 +00:00
renovate[bot]
b10b228fcc fix(deps): update python to v3.13.5 (#240)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-25 16:14:36 +00:00
Yeicor
ffaf6f26ba Merge pull request #245 from yeicor-3d/feature/pyodide-build123d-playground
Add playground functionality: build 3d models by coding in the browser.
2025-07-25 18:11:23 +02:00
Yeicor
17357aef25 yarn upgrade and poetry update --lock 2025-07-25 18:09:08 +02:00
Yeicor
0e6118ed94 Merge branch 'master' into feature/pyodide-build123d-playground
# Conflicts:
#	poetry.lock
#	yarn.lock
2025-07-25 18:01:58 +02:00
Yeicor
8a435b5f1a playground: fully working (snapshots left as future work) and other quality of life improvements 2025-07-25 17:59:40 +02:00
Yeicor
a63d018850 playground: most of the logic for both frontend and backend is implemented, some bugs remain 2025-07-20 21:35:45 +02:00
Yeicor
0460e939e4 playground: minor build fixes 2 2025-07-19 22:10:15 +02:00
Yeicor
b54453ca06 playground: minor build fixes 2025-07-19 22:02:33 +02:00
renovate[bot]
cc4e3f427e Lock file maintenance 2025-07-19 19:50:39 +00:00
Yeicor
fc32393635 playground: basic editor functionality ready 2025-07-19 21:49:02 +02:00
renovate[bot]
ae2a5f9bb0 Update dependency vuetify to v3.9.2 2025-07-19 15:21:11 +00:00
Yeicor
46cf45e4ce Merge pull request #244 from yeicor-3d/feature/expansion-panel-buttons
Refactor Model.vue: clean up unused styles and add back expansion panel buttons
2025-07-19 17:20:10 +02:00
Yeicor
3423c99f8d Merge branch 'master' into feature/expansion-panel-buttons 2025-07-19 17:19:17 +02:00
Yeicor
667a08d2c6 Merge pull request #243 from yeicor-3d/feature/lighting-follow-camera
Main light can now be moved, intensity can be regulated
2025-07-19 17:17:09 +02:00
Yeicor
1733337331 Merge branch 'master' into feature/lighting-follow-camera 2025-07-19 17:16:06 +02:00
Yeicor
0c51b614e9 Refactor Model.vue: clean up unused styles and add back expansion panel buttons 2025-07-19 17:12:30 +02:00
Yeicor
9ef372f576 Cleaning up 2025-07-19 16:57:37 +02:00
Yeicor
a2275f2897 Main light can now be moved, intensity can be regulated and update environment image for model viewer 2025-07-19 16:52:15 +02:00
renovate[bot]
b597b1e3a5 Update dependency vue-tsc to v3.0.3 2025-07-19 10:46:01 +00:00
Yeicor
4af4315984 Merge pull request #242 from andyross/vis-defaults
Update visual defaults
2025-07-19 12:45:11 +02:00
Yeicor
83bc4c767d Merge branch 'master' into vis-defaults 2025-07-19 12:43:41 +02:00
Yeicor
10ed5e2e9e Minor backend improvements: better color and textured handling, smooth shading, better demo 2025-07-19 12:43:05 +02:00
Yeicor
41662944d6 Minor frontend improvements and license updates 2025-07-19 10:17:52 +02:00
Yeicor
7f00a3a4ee Merge branch 'master' into vis-defaults 2025-07-19 09:12:57 +02:00
renovate[bot]
7549c2543b Update dependency vite to v7.0.5 2025-07-19 06:00:16 +00:00
renovate[bot]
fb7a525a71 Update dependency @types/node to v22.16.4 2025-07-19 00:56:19 +00:00
Andy Ross
c14a823dc1 Update visual defaults
Somewhat more conventional visual presentation:

+ Use a neutral gray background a-la most other CAD/modelling software
  for better contrast with the geometry (which defaults to a bright
  yellow).  This is done with the "skybox-environment" image in
  model-viewer, so add a new setting value in settings.ts for this (it
  can be overriden in the URL just like other settings)

+ But using a skybox will cause that image to be used for lighting
  too, which is clearly not desired.  So fetch a nice professional
  HDRI image from Polyhaven for lighting.  This is much better (more
  directional, higher contrast) than the default light environment
  anyway.

+ The checkerboard texture isn't really a good default.  Use a 1x1
  white pixel instead, essentially presenting the model materials
  unchanged.

Also collect the default color in gltf.py out of the code and put it
next to the texture for clarity.  This should probably be wired
through to a setting at some point.

Signed-off-by: Andy Ross <andy@plausible.org>
2025-07-15 15:24:09 -07:00
renovate[bot]
3845720d53 Lock file maintenance 2025-07-13 10:04:14 +00:00
renovate[bot]
16c109f399 Update dependency vuetify to v3.9.0 2025-07-12 17:50:58 +00:00
Yeicor
7b58b00231 Automatically update version to 0.9.7 2025-07-12 17:50:19 +00:00
Yeicor
05a159ac6c Merge pull request #241 from andyross/pos-list-fix
Don't add location-like objects to Compound()
2025-07-12 19:46:49 +02:00
Yeicor
458f81f51d Merge branch 'master' into pos-list-fix 2025-07-12 19:45:48 +02:00
renovate[bot]
f3545bebb8 Update dependency vite to v7.0.4 2025-07-12 08:24:44 +00:00
renovate[bot]
90d05f08c4 Update dependency @types/three to v0.178.1 2025-07-12 05:37:20 +00:00
renovate[bot]
5b4865978f Update dependency @types/node to v22.16.3 2025-07-12 02:05:32 +00:00
Andy Ross
9ec2de8e4a Don't add location-like objects to Compound()
The stack scan likes to look at iterables like lists for objects, but
unlike the way it treats local variables, it tries to put them in a
Compound() object.  That doesn't work for elements like build123d
Location/Pos/Rot which aren't shapes.  Just skip them in those
contexts.
2025-07-11 09:03:35 -07:00
renovate[bot]
0c98c273b8 Lock file maintenance 2025-07-06 22:27:31 +00:00
renovate[bot]
014a68c33d Lock file maintenance 2025-07-06 02:42:33 +00:00
renovate[bot]
16bf550f75 Update dependency vue-tsc to v3 2025-07-05 22:36:10 +00:00
renovate[bot]
f4a74c2f1c Update dependency three to ^0.178.0 2025-07-05 16:32:44 +00:00
renovate[bot]
1fddd984aa Update dependency @types/node to v22.16.0 2025-07-05 14:15:01 +00:00
renovate[bot]
5809b88cee Update dependency vuetify to v3.8.12 2025-07-05 10:07:20 +00:00
renovate[bot]
5cd7fb5d9d Update dependency vue-tsc to v2.2.12 2025-07-05 07:20:08 +00:00
renovate[bot]
dbfc72c03b Update dependency vite to v7.0.2 2025-07-05 07:17:26 +00:00
Yeicor
437e8eb4ad Automatically update version to 0.9.6 2025-07-05 07:16:27 +00:00
renovate[bot]
7051a71710 Update dependency @vitejs/plugin-vue-jsx to v5.0.1 2025-07-05 00:59:09 +00:00
Yeicor
28282f4b06 Merge pull request #239 from andyross/naming
Clean up object naming
2025-07-05 00:04:06 +02:00
Andy Ross
7f43367459 Clean up object naming
Honor the upstream names for objects if they've been given them, use
the automatic variable magic as a fallback.  And in the case of truly
anonymous objects, give them a name based on their type (e.g. "Box3")
vs. "_unknown_var99".
2025-07-02 09:27:13 -07:00
renovate[bot]
ba64f70300 Update dependency pillow to v11.3.0 [SECURITY] 2025-07-01 22:06:50 +00:00
renovate[bot]
05963d58f2 Lock file maintenance 2025-06-29 21:58:54 +00:00
renovate[bot]
405c061f93 Lock file maintenance 2025-06-29 01:30:58 +00:00
renovate[bot]
e0a00b2d32 Update dependency vite to v7 2025-06-28 20:29:48 +00:00
renovate[bot]
90f4611ee8 Update dependency @vitejs/plugin-vue-jsx to v5 2025-06-28 18:37:55 +00:00
renovate[bot]
ee954622bb Update dependency @vitejs/plugin-vue to v6 2025-06-28 13:39:22 +00:00
renovate[bot]
f5be0618ad Update dependency @types/node to v22.15.34 2025-06-28 09:03:59 +00:00
renovate[bot]
f92701a969 Update dependency vuetify to v3.8.11 2025-06-28 04:42:57 +00:00
renovate[bot]
949f92a28f Update dependency @types/node to v22.15.33 2025-06-28 02:07:47 +00:00
renovate[bot]
7618581ef5 Lock file maintenance 2025-06-22 09:44:45 +00:00
renovate[bot]
5460d19fdb Lock file maintenance 2025-06-21 14:16:04 +00:00
renovate[bot]
f84292e4b7 Update dependency terser to v5.43.1 2025-06-21 10:13:19 +00:00
renovate[bot]
b597223228 Update dependency vuetify to v3.8.10 2025-06-21 04:48:58 +00:00
renovate[bot]
8ec9a3f507 Update dependency three-mesh-bvh to v0.9.1 2025-06-21 01:37:52 +00:00
renovate[bot]
0ec339283e Lock file maintenance 2025-06-16 12:02:55 +00:00
renovate[bot]
1d50dc20ba Update dependency terser to v5.42.0 2025-06-15 20:56:20 +00:00
renovate[bot]
35331746b1 Update dependency vuetify to v3.8.9 2025-06-15 17:46:57 +00:00
renovate[bot]
287f76c0ad Update dependency @types/node to v22.15.31 2025-06-15 14:48:23 +00:00
renovate[bot]
dadb2b7a39 Update dependency @tsconfig/node20 to v20.1.6 2025-06-15 11:56:58 +00:00
renovate[bot]
722432dfb0 Lock file maintenance 2025-06-08 16:34:10 +00:00
renovate[bot]
a9184b224f Lock file maintenance 2025-06-07 17:27:11 +00:00
renovate[bot]
3c732d7c85 Update dependency terser to v5.41.0 2025-06-07 13:48:03 +00:00
renovate[bot]
d8fa1f1e0b Update dependency @types/three to ^0.177.0 2025-06-07 08:40:50 +00:00
renovate[bot]
1b03699677 Update dependency vuetify to v3.8.8 2025-06-07 04:49:12 +00:00
renovate[bot]
7f6f777b47 Update dependency @types/node to v22.15.30 2025-06-07 00:40:47 +00:00
renovate[bot]
68fb3b1a67 Lock file maintenance 2025-06-01 08:53:04 +00:00
renovate[bot]
cd4a1d523b Lock file maintenance 2025-06-01 04:45:33 +00:00
renovate[bot]
84cd6ba710 Lock file maintenance 2025-06-01 01:05:35 +00:00
renovate[bot]
aa8492cd3d Lock file maintenance 2025-05-31 21:08:55 +00:00
renovate[bot]
6f8710bd7a Update dependency three to ^0.177.0 2025-05-31 17:45:00 +00:00
renovate[bot]
8b175b369a Update dependency terser to v5.40.0 2025-05-31 14:09:50 +00:00
renovate[bot]
0be05967ca Update dependency vuetify to v3.8.7 2025-05-31 09:13:12 +00:00
renovate[bot]
51f6165290 Update dependency vue to v3.5.16 2025-05-31 04:56:00 +00:00
renovate[bot]
f147c83604 Update dependency @types/node to v22.15.29 2025-05-31 00:48:49 +00:00
renovate[bot]
881de107c7 Lock file maintenance 2025-05-25 19:26:03 +00:00
renovate[bot]
6b533dfbe1 Update dependency npm-run-all2 to v8.0.4 2025-05-25 15:25:46 +00:00
renovate[bot]
2e3fb8beae Lock file maintenance 2025-05-24 19:19:40 +00:00
renovate[bot]
e8baf5cd52 Update dependency @vitejs/plugin-vue-jsx to v4.2.0 2025-05-24 13:50:12 +00:00
renovate[bot]
6c0289208f Update dependency vuetify to v3.8.6 2025-05-24 11:00:05 +00:00
renovate[bot]
496f90fb56 Update dependency npm-run-all2 to v8.0.3 2025-05-24 06:08:42 +00:00
renovate[bot]
696333e105 Update dependency @types/node to v22.15.21 2025-05-24 03:30:06 +00:00
renovate[bot]
099a7aa972 Lock file maintenance 2025-05-18 15:26:20 +00:00
renovate[bot]
b2aa568eb2 Lock file maintenance 2025-05-18 11:10:45 +00:00
renovate[bot]
e685c8adcf Update dependency commander to v14 2025-05-18 06:30:04 +00:00
renovate[bot]
19ddb670db Lock file maintenance 2025-05-17 23:07:27 +00:00
renovate[bot]
8f1cd3e203 Update dependency vuetify to v3.8.5 2025-05-17 19:18:05 +00:00
renovate[bot]
6b0fcd743f Update dependency vue to v3.5.14 2025-05-17 13:59:18 +00:00
renovate[bot]
1d275936a4 Update dependency terser to v5.39.2 2025-05-17 11:10:42 +00:00
renovate[bot]
f7c28a42c0 Update dependency npm-run-all2 to v8.0.2 2025-05-17 05:50:02 +00:00
renovate[bot]
fa54829328 Update dependency @types/node to v22.15.18 2025-05-17 02:18:37 +00:00
Yeicor
c8a7a3ac67 Update renovate.json5 2025-05-11 09:34:23 +02:00
renovate[bot]
791b2608c5 Lock file maintenance 2025-05-10 18:45:50 +00:00
renovate[bot]
ba8e40bc48 Update dependency vuetify to v3.8.4 2025-05-10 15:03:16 +00:00
renovate[bot]
712626e791 Update dependency vite to v6.3.5 2025-05-10 10:47:05 +00:00
renovate[bot]
734387a866 Update dependency @vitejs/plugin-vue to v5.2.4 2025-05-10 06:32:18 +00:00
renovate[bot]
0988db9269 Update dependency @types/node to v22.15.17 2025-05-10 01:34:50 +00:00
renovate[bot]
97d620b982 Lock file maintenance 2025-05-03 14:02:12 +00:00
renovate[bot]
857d0a602f Update dependency npm-run-all2 to v8 2025-05-03 10:09:57 +00:00
renovate[bot]
23f8aa8bdd Update dependency vuetify to v3.8.3 2025-05-03 05:39:05 +00:00
renovate[bot]
03a04bd3fd Update dependency @types/node to v22.15.3 2025-05-03 01:40:48 +00:00
renovate[bot]
57f91d046f Update dependency vite to v6.3.4 [SECURITY] 2025-04-30 20:14:19 +00:00
renovate[bot]
758bc9b874 Lock file maintenance 2025-04-28 05:52:59 +00:00
renovate[bot]
490a86796c Update dependency vite to v6.3.3 2025-04-27 05:53:47 +00:00
renovate[bot]
f44270d913 Update dependency three to ^0.176.0 2025-04-27 02:37:02 +00:00
renovate[bot]
4eed1b063e Update dependency pillow to v11.2.1 2025-04-26 22:55:41 +00:00
renovate[bot]
e3fe562d53 Update dependency @types/node to v22.15.2 2025-04-26 19:12:05 +00:00
renovate[bot]
84ba81a5e5 Update dependency @google/model-viewer to v4.1.0 2025-04-26 13:27:19 +00:00
renovate[bot]
d469f5da40 Update dependency vuetify to v3.8.2 2025-04-26 11:03:12 +00:00
renovate[bot]
98e8de75dd Update dependency vue-tsc to v2.2.10 2025-04-26 07:42:53 +00:00
renovate[bot]
e8d7985dba Update dependency pygltflib to v1.16.4 2025-04-26 01:32:54 +00:00
Yeicor
6aa680bf43 Automatically update version to 0.9.5 2025-04-20 10:53:32 +00:00
Yeicor
b629f07f5e Fix broken gltf exports and minor cleanup 2025-04-20 12:47:23 +02:00
renovate[bot]
9e4f571808 Update dependency vite to v6.2.6 [SECURITY] 2025-04-11 16:50:03 +00:00
renovate[bot]
eaad9f3774 Lock file maintenance 2025-04-05 18:12:03 +00:00
renovate[bot]
79f6359af1 Update dependency vuetify to v3.8.0 2025-04-05 10:28:54 +00:00
renovate[bot]
ca5e9e03ab Update dependency @types/node to v22.14.0 2025-04-05 06:44:09 +00:00
renovate[bot]
2ebdee2d42 Update dependency typescript to v5.8.3 2025-04-05 01:49:44 +00:00
renovate[bot]
c1773fb156 Update dependency vite to v6.2.5 [SECURITY] 2025-04-04 18:54:21 +00:00
renovate[bot]
e05cc70f3a Update dependency vite to v6.2.4 [SECURITY] 2025-03-31 19:41:40 +00:00
renovate[bot]
7d97ed5e93 Lock file maintenance 2025-03-29 18:54:49 +00:00
renovate[bot]
823ee5462f Update dependency three to ^0.175.0 2025-03-29 13:57:09 +00:00
renovate[bot]
64aebb5cf7 Update dependency vuetify to v3.7.19 2025-03-29 10:03:57 +00:00
renovate[bot]
979713bb48 Update dependency @types/node to v22.13.14 2025-03-29 06:13:03 +00:00
renovate[bot]
3b8efd628c Update dependency @tsconfig/node20 to v20.1.5 2025-03-29 02:27:01 +00:00
renovate[bot]
f91033ef3d Update dependency vite to v6.2.3 [SECURITY] 2025-03-25 18:56:53 +00:00
renovate[bot]
0f881a6de5 Lock file maintenance 2025-03-23 05:55:58 +00:00
renovate[bot]
fe919f539e Update dependency vuetify to v3.7.18 2025-03-22 13:49:32 +00:00
renovate[bot]
0b2efb006c Update dependency @vitejs/plugin-vue-jsx to v4.1.2 2025-03-22 09:28:10 +00:00
renovate[bot]
7584af683e Update dependency @vitejs/plugin-vue to v5.2.3 2025-03-22 06:17:04 +00:00
renovate[bot]
64358469ae Update dependency @types/node to v22.13.11 2025-03-22 01:25:57 +00:00
renovate[bot]
28ad995982 Lock file maintenance 2025-03-15 17:52:21 +00:00
renovate[bot]
3efb47fef1 Update dependency generate-license-file to v4 2025-03-15 13:16:46 +00:00
renovate[bot]
1ca655f2f4 Update dependency generate-license-file to v3.8.1 2025-03-15 10:08:32 +00:00
renovate[bot]
4fd6fc6e23 Update dependency vuetify to v3.7.16 2025-03-15 06:52:16 +00:00
renovate[bot]
b6d21e7ef1 Update dependency vite to v6.2.2 2025-03-15 01:50:55 +00:00
renovate[bot]
fb484b61da Lock file maintenance 2025-03-09 21:23:52 +00:00
renovate[bot]
1ebfa3dd3f Update dependency vuetify to v3.7.15 2025-03-08 14:27:32 +00:00
renovate[bot]
35bfb8679a Update dependency vue-tsc to v2.2.8 2025-03-08 10:54:52 +00:00
renovate[bot]
dce407ca2b Update dependency vite to v6.2.1 2025-03-08 06:46:23 +00:00
renovate[bot]
f9e90bee25 Update dependency @types/node to v22.13.9 2025-03-08 02:33:41 +00:00
renovate[bot]
ea44096200 Lock file maintenance (#232)
* Lock file maintenance

* Update Models.vue

* Update Models.vue

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Yeicor <4929005+Yeicor@users.noreply.github.com>
2025-03-02 09:43:49 +01:00
renovate[bot]
f3d19911c7 Update dependency vite to v6.2.0 2025-03-01 18:52:39 +00:00
renovate[bot]
2214a4812c Update dependency typescript to ~5.8.0 2025-03-01 13:41:42 +00:00
renovate[bot]
8b08afc1ea Update dependency three to ^0.174.0 2025-03-01 10:27:05 +00:00
renovate[bot]
4d77723fe6 Update dependency vuetify to v3.7.14 2025-03-01 06:29:08 +00:00
renovate[bot]
bd0364fcea Update dependency @types/node to v22.13.7 2025-03-01 02:09:53 +00:00
renovate[bot]
3b466c0291 Lock file maintenance 2025-02-23 14:27:42 +00:00
renovate[bot]
ade6faa6a3 Update dependency vuetify to v3.7.13 2025-02-22 10:36:17 +00:00
renovate[bot]
c88959cc11 Update dependency vite to v6.1.1 2025-02-22 06:43:26 +00:00
renovate[bot]
1e7fe81a60 Update dependency @types/node to v22.13.5 2025-02-22 02:04:41 +00:00
Yeicor
726e3927f4 Automatically update version to 0.9.4 2025-02-16 12:10:07 +00:00
renovate[bot]
5f6b6d7ba0 Update dependency build123d to >=0.9,<0.10 (#231)
* Update dependency build123d to >=0.9,<0.10

* Update pyproject.toml

* Small fix and updates

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Yeicor <4929005+Yeicor@users.noreply.github.com>
2025-02-16 13:06:21 +01:00
renovate[bot]
62bc825bc8 Lock file maintenance 2025-02-16 05:21:17 +00:00
renovate[bot]
de789ad8a9 Update dependency commander to v13 2025-02-16 02:40:30 +00:00
renovate[bot]
e657acaee3 Update dependency vite to v6.1.0 2025-02-15 22:46:27 +00:00
renovate[bot]
ba94f64ca0 Update dependency three-mesh-bvh to ^0.9.0 2025-02-15 18:51:07 +00:00
renovate[bot]
26722781d2 Update dependency three to ^0.173.0 2025-02-15 14:16:17 +00:00
renovate[bot]
2434df71aa Update dependency terser to v5.39.0 2025-02-15 10:58:14 +00:00
renovate[bot]
f02d561d8b Update dependency @types/node to v22.13.4 2025-02-15 05:43:15 +00:00
renovate[bot]
73c8715517 Update dependency vuetify to v3.7.12 2025-02-15 01:24:04 +00:00
renovate[bot]
1a0a8cae67 Update dependency vite to v6.0.9 [SECURITY] 2025-01-21 21:20:01 +00:00
renovate[bot]
a00665a3a1 Update dependency generate-license-file to v3.7.0 2025-01-19 08:43:48 +00:00
renovate[bot]
126d514ee3 Update dependency @types/node to v22.10.7 2025-01-18 00:13:20 +00:00
renovate[bot]
c0014f989f Update dependency typescript to v5.7.3 2025-01-11 09:56:22 +01:00
renovate[bot]
874413c3c2 Update dependency pillow to v11.1.0 2025-01-11 09:56:12 +01:00
Yeicor
bff2140b9f Update CI python versions 2025-01-11 09:18:31 +01:00
Yeicor
0aa20c7e8e Fix poetry commands after update 2025-01-11 09:17:05 +01:00
renovate[bot]
8bf29b18da Update dependency vite to v6.0.7 2025-01-04 23:29:19 +01:00
Yeicor
8330060bd9 "Proper" top-level-await workaround 2025-01-04 23:26:29 +01:00
renovate[bot]
b09d5a87fa Update dependency @types/node to v22.10.5 2025-01-04 01:59:41 +00:00
renovate[bot]
b976976cda Update dependency vite to v6 2024-12-29 07:49:49 +00:00
renovate[bot]
2a82d37da1 Update dependency typescript to ~5.7.0 2024-12-29 03:33:53 +00:00
renovate[bot]
632f09382f Update dependency three to ^0.171.0 2024-12-29 00:59:49 +00:00
renovate[bot]
558cc306e2 Update dependency @vue/tsconfig to ^0.7.0 2024-12-28 22:38:10 +00:00
renovate[bot]
f1476befe2 Lock file maintenance 2024-12-28 00:12:30 +00:00
renovate[bot]
cb386f0020 Lock file maintenance 2024-12-21 00:23:13 +00:00
Yeicor
ef37fad7fc Renovate bot changes 2024-12-14 10:38:58 +01:00
renovate[bot]
f42fa9515b Lock file maintenance (#226)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-14 04:00:27 +00:00
renovate[bot]
fca2018279 Lock file maintenance (#225)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-07 08:03:14 +00:00
renovate[bot]
1e0e755b0e Lock file maintenance (#224)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-07 04:20:12 +00:00
renovate[bot]
757007ad7b Lock file maintenance (#223)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-30 10:43:20 +00:00
renovate[bot]
bc2cc76b29 Lock file maintenance (#222)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-30 04:12:29 +00:00
Yeicor
6cc997d4ee Automatically update version to 0.9.3 2024-11-23 10:42:53 +00:00
renovate[bot]
a2f24be087 Update dependency three to ^0.170.0 2024-11-23 11:41:55 +01:00
renovate[bot]
dd38a66d2f Update dependency commander to v12.1.0 2024-11-23 11:41:45 +01:00
Yeicor
c8c6927962 Migrate dependabot to renovate 4 2024-11-23 11:38:15 +01:00
Yeicor
be7c4e3c8e Migrate dependabot to renovate 3 2024-11-23 11:37:30 +01:00
Yeicor
c20849222c Poetry lock --no-update 2 2024-11-23 11:34:11 +01:00
Yeicor
1e0cee46cd Poetry lock --no-update 2024-11-23 11:31:56 +01:00
Yeicor
77f6a0ae89 Migrate dependabot to renovate 2 2024-11-23 11:30:33 +01:00
renovate[bot]
b9bff03db1 Update dependency build123d to >=0.8,<0.9 2024-11-23 11:27:43 +01:00
Yeicor
74126b54ab Update pyproject.toml 2024-11-23 11:23:51 +01:00
Yeicor
48e81bc3bc Migrate dependabot to renovate 2024-11-23 11:15:56 +01:00
Yeicor
0f98f0d1a3 Downgrade broken typescript version 2024-11-23 11:14:57 +01:00
Yeicor
494b20ba15 Update dependabot.yml 2024-11-23 10:50:27 +01:00
dependabot[bot]
13886186c0 Bump @types/node from 22.9.0 to 22.9.3 (#216)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.9.0 to 22.9.3.
- [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-11-23 09:49:13 +00:00
dependabot[bot]
1611a8dded Bump typescript from 5.6.3 to 5.7.2 (#215)
Bumps [typescript](https://github.com/microsoft/TypeScript) from 5.6.3 to 5.7.2.
- [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.6.3...v5.7.2)

---
updated-dependencies:
- dependency-name: typescript
  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-11-23 09:49:04 +00:00
dependabot[bot]
24fb41bb77 Bump cross-spawn from 7.0.3 to 7.0.6 (#214)
Bumps [cross-spawn](https://github.com/moxystudio/node-cross-spawn) from 7.0.3 to 7.0.6.
- [Changelog](https://github.com/moxystudio/node-cross-spawn/blob/master/CHANGELOG.md)
- [Commits](https://github.com/moxystudio/node-cross-spawn/compare/v7.0.3...v7.0.6)

---
updated-dependencies:
- dependency-name: cross-spawn
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-18 18:27:15 +00:00
Yeicor
8977963b58 Update README.md with related project by @derhuerst 2024-11-18 19:18:26 +01:00
dependabot[bot]
b5f50b1a5f Bump vue from 3.5.12 to 3.5.13 (#213)
Bumps [vue](https://github.com/vuejs/core) from 3.5.12 to 3.5.13.
- [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.5.12...v3.5.13)

---
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-11-16 09:12:37 +00:00
dependabot[bot]
0f52a0b6c6 Bump @vue/tsconfig from 0.5.1 to 0.6.0 (#209)
Bumps [@vue/tsconfig](https://github.com/vuejs/tsconfig) from 0.5.1 to 0.6.0.
- [Release notes](https://github.com/vuejs/tsconfig/releases)
- [Commits](https://github.com/vuejs/tsconfig/compare/v0.5.1...v0.6.0)

---
updated-dependencies:
- dependency-name: "@vue/tsconfig"
  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-11-16 09:12:00 +00:00
dependabot[bot]
9a783750b7 Bump @vitejs/plugin-vue-jsx from 4.0.1 to 4.1.0 (#210)
Bumps [@vitejs/plugin-vue-jsx](https://github.com/vitejs/vite-plugin-vue/tree/HEAD/packages/plugin-vue-jsx) from 4.0.1 to 4.1.0.
- [Release notes](https://github.com/vitejs/vite-plugin-vue/releases)
- [Changelog](https://github.com/vitejs/vite-plugin-vue/blob/main/packages/plugin-vue-jsx/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite-plugin-vue/commits/plugin-vue@4.1.0/packages/plugin-vue-jsx)

---
updated-dependencies:
- dependency-name: "@vitejs/plugin-vue-jsx"
  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-11-16 09:10:31 +00:00
dependabot[bot]
ec083fb951 Bump vite from 5.4.10 to 5.4.11 (#212)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.4.10 to 5.4.11.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v5.4.11/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.4.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-11-16 09:09:28 +00:00
dependabot[bot]
e894dbb997 Bump three-mesh-bvh from 0.8.2 to 0.8.3 (#211)
Bumps [three-mesh-bvh](https://github.com/gkjohnson/three-mesh-bvh) from 0.8.2 to 0.8.3.
- [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.8.2...v0.8.3)

---
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-11-16 09:09:12 +00:00
dependabot[bot]
b36bc2523c Bump @vitejs/plugin-vue from 5.1.4 to 5.2.0 (#208)
Bumps [@vitejs/plugin-vue](https://github.com/vitejs/vite-plugin-vue/tree/HEAD/packages/plugin-vue) from 5.1.4 to 5.2.0.
- [Release notes](https://github.com/vitejs/vite-plugin-vue/releases)
- [Changelog](https://github.com/vitejs/vite-plugin-vue/blob/main/packages/plugin-vue/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite-plugin-vue/commits/plugin-vue@5.2.0/packages/plugin-vue)

---
updated-dependencies:
- dependency-name: "@vitejs/plugin-vue"
  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-11-16 09:08:53 +00:00
Yeicor
0c0db36718 Automatically update version to 0.9.2 2024-11-15 22:14:45 +00:00
Yeicor
4343c52466 Automatically configure default preload URL if the backend serves the frontend directly.
Fixes #207
2024-11-15 23:10:30 +01:00
Yeicor
ea181dac0b Automatically update version to 0.9.1 2024-11-09 17:26:30 +00:00
Yeicor
09525daae8 Minor improvements to custom textures feature 2024-11-09 18:25:38 +01:00
Yeicor
874f9e8d6e Minor improvements to custom textures feature 2024-11-09 18:25:38 +01:00
Chaser Huang
822672c288 Some more missing imports 2024-11-09 18:25:38 +01:00
Chaser Huang
383586c5a4 Add missing imports due to rebase 2024-11-09 18:25:38 +01:00
Chaser Huang
b4d557534d Add statement lost in rebasing 2024-11-09 18:25:38 +01:00
Chaser Huang
e6921144fb fix: type hint typo 2024-11-09 18:25:38 +01:00
Chaser Huang
f95509f4f4 Add setting base texture through environment variables 2024-11-09 18:25:38 +01:00
Chaser Huang
5a0228d4fc Support selecting base texture 2024-11-09 18:25:38 +01:00
dependabot[bot]
5c96e4e44b Bump @gltf-transform/functions from 4.0.10 to 4.1.0 (#206)
Bumps [@gltf-transform/functions](https://github.com/donmccurdy/glTF-Transform) from 4.0.10 to 4.1.0.
- [Changelog](https://github.com/donmccurdy/glTF-Transform/blob/main/CHANGELOG.md)
- [Commits](https://github.com/donmccurdy/glTF-Transform/compare/v4.0.10...v4.1.0)

---
updated-dependencies:
- dependency-name: "@gltf-transform/functions"
  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-11-09 09:34:33 +00:00
dependabot[bot]
4012bac31f Bump @gltf-transform/extensions from 4.0.10 to 4.1.0 (#203)
Bumps [@gltf-transform/extensions](https://github.com/donmccurdy/glTF-Transform) from 4.0.10 to 4.1.0.
- [Changelog](https://github.com/donmccurdy/glTF-Transform/blob/main/CHANGELOG.md)
- [Commits](https://github.com/donmccurdy/glTF-Transform/compare/v4.0.10...v4.1.0)

---
updated-dependencies:
- dependency-name: "@gltf-transform/extensions"
  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-11-09 09:32:46 +00:00
dependabot[bot]
4439c436fc Bump @types/node from 22.8.6 to 22.9.0 (#205)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.8.6 to 22.9.0.
- [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-11-09 09:31:24 +00:00
dependabot[bot]
b23119e44c Bump vuetify from 3.7.3 to 3.7.4 (#204)
Bumps [vuetify](https://github.com/vuetifyjs/vuetify/tree/HEAD/packages/vuetify) from 3.7.3 to 3.7.4.
- [Release notes](https://github.com/vuetifyjs/vuetify/releases)
- [Commits](https://github.com/vuetifyjs/vuetify/commits/v3.7.4/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-11-09 09:31:11 +00:00
dependabot[bot]
e428d9cb5a Bump @gltf-transform/core from 4.0.10 to 4.1.0 (#202)
Bumps [@gltf-transform/core](https://github.com/donmccurdy/glTF-Transform) from 4.0.10 to 4.1.0.
- [Changelog](https://github.com/donmccurdy/glTF-Transform/blob/main/CHANGELOG.md)
- [Commits](https://github.com/donmccurdy/glTF-Transform/compare/v4.0.10...v4.1.0)

---
updated-dependencies:
- dependency-name: "@gltf-transform/core"
  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-11-09 09:30:51 +00:00
dependabot[bot]
6574db6f81 Bump generate-license-file from 3.5.1 to 3.6.0 (#201)
Bumps [generate-license-file](https://github.com/TobyAndToby/generate-license-file/tree/HEAD/src/packages/generate-license-file) from 3.5.1 to 3.6.0.
- [Release notes](https://github.com/TobyAndToby/generate-license-file/releases)
- [Commits](https://github.com/TobyAndToby/generate-license-file/commits/v3.6.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-11-09 09:30:43 +00:00
dependabot[bot]
844d25483f Bump vue-tsc from 2.1.6 to 2.1.10 (#199)
Bumps [vue-tsc](https://github.com/vuejs/language-tools/tree/HEAD/packages/tsc) from 2.1.6 to 2.1.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.1.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-11-02 09:44:23 +00:00
dependabot[bot]
2f6e7def42 Bump @types/node from 22.8.1 to 22.8.6 (#198)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.8.1 to 22.8.6.
- [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-11-02 09:44:13 +00:00
Yeicor
dbf29c02a9 Add cq-studio to README.md 2024-10-26 21:08:56 +02:00
Yeicor
8303dd2d37 Fix type-check 2024-10-26 20:50:47 +02:00
dependabot[bot]
3e24a29e73 Bump three, @google/model-viewer and @types/three (#197)
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.163.0 to 0.169.0
- [Release notes](https://github.com/mrdoob/three.js/releases)
- [Commits](https://github.com/mrdoob/three.js/commits)

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

Updates `@types/three` from 0.163.0 to 0.169.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-major
- 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-10-26 12:56:10 +00:00
dependabot[bot]
e3b32a7e92 Bump vite from 5.4.9 to 5.4.10 (#196)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.4.9 to 5.4.10.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v5.4.10/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.4.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-10-26 09:28:47 +00:00
dependabot[bot]
20def41a6c Bump @types/node from 22.7.7 to 22.8.1 (#195)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.7.7 to 22.8.1.
- [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-10-26 09:28:38 +00:00
dependabot[bot]
aff3a367e6 Bump npm-run-all2 from 6.2.4 to 7.0.1 (#194)
Bumps [npm-run-all2](https://github.com/bcomnes/npm-run-all2) from 6.2.4 to 7.0.1.
- [Release notes](https://github.com/bcomnes/npm-run-all2/releases)
- [Changelog](https://github.com/bcomnes/npm-run-all2/blob/master/CHANGELOG.md)
- [Commits](https://github.com/bcomnes/npm-run-all2/compare/v6.2.4...v7.0.1)

---
updated-dependencies:
- dependency-name: npm-run-all2
  dependency-type: direct:development
  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-10-26 09:28:30 +00:00
dependabot[bot]
80c94fec80 Bump pillow from 10.4.0 to 11.0.0 (#193)
Bumps [pillow](https://github.com/python-pillow/Pillow) from 10.4.0 to 11.0.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.4.0...11.0.0)

---
updated-dependencies:
- dependency-name: pillow
  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-10-19 09:55:46 +00:00
dependabot[bot]
2d8d8178ba Bump npm-run-all2 from 6.2.3 to 6.2.4 (#190)
Bumps [npm-run-all2](https://github.com/bcomnes/npm-run-all2) from 6.2.3 to 6.2.4.
- [Release notes](https://github.com/bcomnes/npm-run-all2/releases)
- [Changelog](https://github.com/bcomnes/npm-run-all2/blob/master/CHANGELOG.md)
- [Commits](https://github.com/bcomnes/npm-run-all2/compare/v6.2.3...v6.2.4)

---
updated-dependencies:
- dependency-name: npm-run-all2
  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-10-19 09:23:43 +00:00
dependabot[bot]
6ac1365e27 Bump vite from 5.4.8 to 5.4.9 (#192)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.4.8 to 5.4.9.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v5.4.9/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.4.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-10-19 09:22:43 +00:00
dependabot[bot]
ef3938ca4a Bump vuetify from 3.7.2 to 3.7.3 (#191)
Bumps [vuetify](https://github.com/vuetifyjs/vuetify/tree/HEAD/packages/vuetify) from 3.7.2 to 3.7.3.
- [Release notes](https://github.com/vuetifyjs/vuetify/releases)
- [Commits](https://github.com/vuetifyjs/vuetify/commits/v3.7.3/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-10-19 09:22:30 +00:00
dependabot[bot]
334a23c04d Bump terser from 5.34.1 to 5.36.0 (#189)
Bumps [terser](https://github.com/terser/terser) from 5.34.1 to 5.36.0.
- [Changelog](https://github.com/terser/terser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/terser/terser/compare/v5.34.1...v5.36.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-10-19 09:22:08 +00:00
dependabot[bot]
57be98ede3 Bump @types/node from 22.7.5 to 22.7.7 (#188)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.7.5 to 22.7.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-10-19 09:22:01 +00:00
dependabot[bot]
52f97963f0 Bump vue from 3.5.11 to 3.5.12 (#187)
Bumps [vue](https://github.com/vuejs/core) from 3.5.11 to 3.5.12.
- [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.5.11...v3.5.12)

---
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-10-12 09:56:26 +00:00
dependabot[bot]
61a3f157ac Bump typescript from 5.6.2 to 5.6.3 (#186)
Bumps [typescript](https://github.com/microsoft/TypeScript) from 5.6.2 to 5.6.3.
- [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.6.2...v5.6.3)

---
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-10-12 09:56:11 +00:00
dependabot[bot]
bf4bf38dd2 Bump @types/node from 22.7.4 to 22.7.5 (#185)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.7.4 to 22.7.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-10-12 09:55:57 +00:00
Yeicor
4119656f69 Update README.md 2024-10-11 20:28:03 +02:00
Yeicor
3834e8d506 Update README.md 2024-10-11 20:25:53 +02:00
Yeicor
b4380d3a2f Update README.md 2024-10-11 20:25:24 +02:00
Yeicor
22ea0617e2 Automatically update version to 0.9.0 2024-10-11 18:20:00 +00:00
Yeicor
09c0994a34 Also color edges and vertices, add examples and minor improvements 2024-10-11 20:18:49 +02:00
Chaser Huang
0939e25da2 fix: typo 2024-10-11 20:18:49 +02:00
Chaser Huang
712e0a06e6 support bd cad objects with color tagged 2024-10-11 20:18:49 +02:00
dependabot[bot]
e73f745800 Bump @gltf-transform/functions from 4.0.8 to 4.0.10 (#183)
Bumps [@gltf-transform/functions](https://github.com/donmccurdy/glTF-Transform) from 4.0.8 to 4.0.10.
- [Changelog](https://github.com/donmccurdy/glTF-Transform/blob/main/CHANGELOG.md)
- [Commits](https://github.com/donmccurdy/glTF-Transform/compare/v4.0.8...v4.0.10)

---
updated-dependencies:
- dependency-name: "@gltf-transform/functions"
  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-10-05 09:41:37 +00:00
dependabot[bot]
773ea797a1 Bump three-mesh-bvh from 0.8.0 to 0.8.2 (#182)
Bumps [three-mesh-bvh](https://github.com/gkjohnson/three-mesh-bvh) from 0.8.0 to 0.8.2.
- [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.8.0...v0.8.2)

---
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-10-05 09:39:54 +00:00
dependabot[bot]
aae20aeedf Bump @gltf-transform/extensions from 4.0.8 to 4.0.10 (#180)
Bumps [@gltf-transform/extensions](https://github.com/donmccurdy/glTF-Transform) from 4.0.8 to 4.0.10.
- [Changelog](https://github.com/donmccurdy/glTF-Transform/blob/main/CHANGELOG.md)
- [Commits](https://github.com/donmccurdy/glTF-Transform/compare/v4.0.8...v4.0.10)

---
updated-dependencies:
- dependency-name: "@gltf-transform/extensions"
  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-10-05 09:39:43 +00:00
dependabot[bot]
a3004e59fb Bump vue from 3.5.10 to 3.5.11 (#179)
Bumps [vue](https://github.com/vuejs/core) from 3.5.10 to 3.5.11.
- [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.5.10...v3.5.11)

---
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-10-05 09:39:30 +00:00
dependabot[bot]
5e76193f43 Bump vite from 5.4.7 to 5.4.8 (#178)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.4.7 to 5.4.8.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v5.4.8/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.4.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-09-28 09:30:38 +00:00
dependabot[bot]
50a2627b55 Bump vue from 3.5.7 to 3.5.10 (#177)
Bumps [vue](https://github.com/vuejs/core) from 3.5.7 to 3.5.10.
- [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.5.7...v3.5.10)

---
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-09-28 09:30:26 +00:00
dependabot[bot]
cbddacb7b8 Bump terser from 5.33.0 to 5.34.1 (#176)
Bumps [terser](https://github.com/terser/terser) from 5.33.0 to 5.34.1.
- [Changelog](https://github.com/terser/terser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/terser/terser/compare/v5.33.0...v5.34.1)

---
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-09-28 09:30:16 +00:00
dependabot[bot]
887e71b7b2 Bump @types/node from 22.5.5 to 22.7.4 (#175)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.5.5 to 22.7.4.
- [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-09-28 09:30:03 +00:00
Yeicor
7c5bd2aea0 Automatically update version to 0.8.11 2024-09-25 09:49:17 +00:00
Charles Cazabon
b9c3b34416 Add py.typed marker so linting tools know to use the type annotations. 2024-09-25 11:48:16 +02:00
Yeicor
b2f9880fd0 Add labels to negative axes, as requested in #173 2024-09-25 11:45:48 +02:00
dependabot[bot]
4b0fdd3459 Bump rollup from 4.21.0 to 4.22.4 (#174)
Bumps [rollup](https://github.com/rollup/rollup) from 4.21.0 to 4.22.4.
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v4.21.0...v4.22.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-25 09:26:31 +00:00
Yeicor
503501df4b Merge pull request #168 from yeicor-3d/dependabot/npm_and_yarn/vitejs/plugin-vue-5.1.4
Bump @vitejs/plugin-vue from 5.1.3 to 5.1.4
2024-09-25 11:22:31 +02:00
dependabot[bot]
62fa310ec7 Bump build123d from 0.6.0 to 0.7.0 (#171)
Bumps [build123d](https://github.com/gumyr/build123d) from 0.6.0 to 0.7.0.
- [Release notes](https://github.com/gumyr/build123d/releases)
- [Commits](https://github.com/gumyr/build123d/compare/v0.6.0...v0.7.0)

---
updated-dependencies:
- dependency-name: build123d
  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-09-21 09:27:41 +00:00
dependabot[bot]
83cc12e59d Bump vue from 3.5.5 to 3.5.7 (#170)
Bumps [vue](https://github.com/vuejs/core) from 3.5.5 to 3.5.7.
- [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.5.5...v3.5.7)

---
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-09-21 09:14:48 +00:00
dependabot[bot]
016db36c50 Bump three-mesh-bvh from 0.7.8 to 0.8.0 (#169)
Bumps [three-mesh-bvh](https://github.com/gkjohnson/three-mesh-bvh) from 0.7.8 to 0.8.0.
- [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.8...v0.8.0)

---
updated-dependencies:
- dependency-name: three-mesh-bvh
  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-09-21 09:13:01 +00:00
dependabot[bot]
583c244769 Bump vite from 5.4.5 to 5.4.7 (#167)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.4.5 to 5.4.7.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v5.4.7/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.4.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-09-21 09:12:38 +00:00
dependabot[bot]
79919041f2 Bump @vitejs/plugin-vue from 5.1.3 to 5.1.4
Bumps [@vitejs/plugin-vue](https://github.com/vitejs/vite-plugin-vue/tree/HEAD/packages/plugin-vue) from 5.1.3 to 5.1.4.
- [Release notes](https://github.com/vitejs/vite-plugin-vue/releases)
- [Changelog](https://github.com/vitejs/vite-plugin-vue/blob/main/packages/plugin-vue/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite-plugin-vue/commits/plugin-vue@5.1.4/packages/plugin-vue)

---
updated-dependencies:
- dependency-name: "@vitejs/plugin-vue"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-21 09:12:27 +00:00
dependabot[bot]
263671b4a9 Bump terser from 5.32.0 to 5.33.0 (#166)
Bumps [terser](https://github.com/terser/terser) from 5.32.0 to 5.33.0.
- [Changelog](https://github.com/terser/terser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/terser/terser/compare/v5.32.0...v5.33.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-09-21 09:12:26 +00:00
dependabot[bot]
e3fc8f1e74 Bump vuetify from 3.7.1 to 3.7.2 (#165)
Bumps [vuetify](https://github.com/vuetifyjs/vuetify/tree/HEAD/packages/vuetify) from 3.7.1 to 3.7.2.
- [Release notes](https://github.com/vuetifyjs/vuetify/releases)
- [Commits](https://github.com/vuetifyjs/vuetify/commits/v3.7.2/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-09-21 09:12:14 +00:00
Yeicor
7b63f574a1 fix for typescript update to 5.6.2 2024-09-14 15:49:02 +02:00
dependabot[bot]
56929ca136 Bump typescript from 5.5.4 to 5.6.2 (#164)
Bumps [typescript](https://github.com/microsoft/TypeScript) from 5.5.4 to 5.6.2.
- [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.5.4...v5.6.2)

---
updated-dependencies:
- dependency-name: typescript
  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-09-14 09:13:40 +00:00
dependabot[bot]
dda5abfc94 Bump terser from 5.31.6 to 5.32.0 (#162)
Bumps [terser](https://github.com/terser/terser) from 5.31.6 to 5.32.0.
- [Changelog](https://github.com/terser/terser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/terser/terser/compare/v5.31.6...v5.32.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-09-14 09:12:10 +00:00
dependabot[bot]
3f9971a171 Bump vue from 3.5.3 to 3.5.5 (#163)
Bumps [vue](https://github.com/vuejs/core) from 3.5.3 to 3.5.5.
- [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.5.3...v3.5.5)

---
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-09-14 09:10:46 +00:00
dependabot[bot]
f4326c5779 Bump three-mesh-bvh from 0.7.6 to 0.7.8 (#161)
Bumps [three-mesh-bvh](https://github.com/gkjohnson/three-mesh-bvh) from 0.7.6 to 0.7.8.
- [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.6...v0.7.8)

---
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-09-14 09:10:31 +00:00
dependabot[bot]
96e73c0e7f Bump vite from 5.4.3 to 5.4.5 (#160)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.4.3 to 5.4.5.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v5.4.5/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.4.5/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-09-14 09:10:27 +00:00
dependabot[bot]
2f1d1d51b3 Bump npm-run-all2 from 6.2.2 to 6.2.3 (#159)
Bumps [npm-run-all2](https://github.com/bcomnes/npm-run-all2) from 6.2.2 to 6.2.3.
- [Release notes](https://github.com/bcomnes/npm-run-all2/releases)
- [Changelog](https://github.com/bcomnes/npm-run-all2/blob/master/CHANGELOG.md)
- [Commits](https://github.com/bcomnes/npm-run-all2/compare/v6.2.2...v6.2.3)

---
updated-dependencies:
- dependency-name: npm-run-all2
  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-09-14 09:10:20 +00:00
dependabot[bot]
fb3027fe66 Bump @types/node from 22.5.4 to 22.5.5 (#158)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.5.4 to 22.5.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-09-14 09:10:11 +00:00
Yeicor
d2b1e04e88 Fix error TS7006: Parameter 'name' implicitly has an 'any' type. 2024-09-07 13:21:06 +02:00
dependabot[bot]
8c75f02c57 Bump vue-tsc from 2.1.2 to 2.1.6 (#157)
Bumps [vue-tsc](https://github.com/vuejs/language-tools/tree/HEAD/packages/tsc) from 2.1.2 to 2.1.6.
- [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.1.6/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-09-07 09:46:54 +00:00
dependabot[bot]
68317b32e4 Bump vue from 3.4.38 to 3.5.3 (#155)
Bumps [vue](https://github.com/vuejs/core) from 3.4.38 to 3.5.3.
- [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.38...v3.5.3)

---
updated-dependencies:
- dependency-name: vue
  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-09-07 09:46:09 +00:00
dependabot[bot]
49f91383a0 Bump @types/node from 22.5.1 to 22.5.4 (#156)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.5.1 to 22.5.4.
- [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-09-07 09:45:07 +00:00
dependabot[bot]
15b0636df9 Bump vite from 5.4.2 to 5.4.3 (#154)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.4.2 to 5.4.3.
- [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.4.3/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-09-07 09:44:41 +00:00
dependabot[bot]
e880a9f53a Bump @vitejs/plugin-vue from 5.1.2 to 5.1.3 (#153)
Bumps [@vitejs/plugin-vue](https://github.com/vitejs/vite-plugin-vue/tree/HEAD/packages/plugin-vue) from 5.1.2 to 5.1.3.
- [Release notes](https://github.com/vitejs/vite-plugin-vue/releases)
- [Changelog](https://github.com/vitejs/vite-plugin-vue/blob/main/packages/plugin-vue/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite-plugin-vue/commits/plugin-vue@5.1.3/packages/plugin-vue)

---
updated-dependencies:
- dependency-name: "@vitejs/plugin-vue"
  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-08-31 09:11:31 +00:00
dependabot[bot]
0ab8126e18 Bump @types/node from 22.5.0 to 22.5.1 (#152)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.5.0 to 22.5.1.
- [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-08-31 09:11:06 +00:00
dependabot[bot]
d9da038a06 Bump vue-tsc from 2.0.29 to 2.1.2 (#151)
Bumps [vue-tsc](https://github.com/vuejs/language-tools/tree/HEAD/packages/tsc) from 2.0.29 to 2.1.2.
- [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.1.2/packages/tsc)

---
updated-dependencies:
- dependency-name: vue-tsc
  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-08-31 09:11:01 +00:00
dependabot[bot]
186ca9d5bc Bump vuetify from 3.7.0 to 3.7.1 (#150)
Bumps [vuetify](https://github.com/vuetifyjs/vuetify/tree/HEAD/packages/vuetify) from 3.7.0 to 3.7.1.
- [Release notes](https://github.com/vuetifyjs/vuetify/releases)
- [Commits](https://github.com/vuetifyjs/vuetify/commits/v3.7.1/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-08-31 09:10:50 +00:00
dependabot[bot]
739ce7f6c3 Bump @types/node from 22.4.0 to 22.5.0 (#148)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.4.0 to 22.5.0.
- [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-08-24 09:43:13 +00:00
dependabot[bot]
ba42fcfbd4 Bump vite from 5.4.1 to 5.4.2 (#147)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.4.1 to 5.4.2.
- [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.4.2/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-08-24 09:43:08 +00:00
Yeicor
a0144a5432 Merge pull request #142 from yeicor-3d/dependabot/npm_and_yarn/terser-5.31.6
Bump terser from 5.31.5 to 5.31.6
2024-08-17 14:06:06 +02:00
dependabot[bot]
66fd788398 Bump @vitejs/plugin-vue-jsx from 4.0.0 to 4.0.1 (#145)
Bumps [@vitejs/plugin-vue-jsx](https://github.com/vitejs/vite-plugin-vue/tree/HEAD/packages/plugin-vue-jsx) from 4.0.0 to 4.0.1.
- [Release notes](https://github.com/vitejs/vite-plugin-vue/releases)
- [Changelog](https://github.com/vitejs/vite-plugin-vue/blob/main/packages/plugin-vue-jsx/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite-plugin-vue/commits/plugin-vue-jsx@4.0.1/packages/plugin-vue-jsx)

---
updated-dependencies:
- dependency-name: "@vitejs/plugin-vue-jsx"
  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-08-17 09:17:45 +00:00
dependabot[bot]
9d2166dbe6 Bump terser from 5.31.5 to 5.31.6
Bumps [terser](https://github.com/terser/terser) from 5.31.5 to 5.31.6.
- [Changelog](https://github.com/terser/terser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/terser/terser/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-17 09:17:36 +00:00
dependabot[bot]
66396dfaee Bump vuetify from 3.6.14 to 3.7.0 (#143)
Bumps [vuetify](https://github.com/vuetifyjs/vuetify/tree/HEAD/packages/vuetify) from 3.6.14 to 3.7.0.
- [Release notes](https://github.com/vuetifyjs/vuetify/releases)
- [Commits](https://github.com/vuetifyjs/vuetify/commits/v3.7.0/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-08-17 09:16:36 +00:00
dependabot[bot]
c539538d74 Bump @types/node from 22.2.0 to 22.4.0 (#146)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.2.0 to 22.4.0.
- [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-08-17 09:16:00 +00:00
dependabot[bot]
7d0ea24e23 Bump vite from 5.4.0 to 5.4.1 (#144)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.4.0 to 5.4.1.
- [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.4.1/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-08-17 09:15:41 +00:00
dependabot[bot]
c7ec469796 Bump vue from 3.4.37 to 3.4.38 (#141)
Bumps [vue](https://github.com/vuejs/core) from 3.4.37 to 3.4.38.
- [Release notes](https://github.com/vuejs/core/releases)
- [Changelog](https://github.com/vuejs/core/blob/v3.4.38/CHANGELOG.md)
- [Commits](https://github.com/vuejs/core/compare/v3.4.37...v3.4.38)

---
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-08-17 09:15:09 +00:00
dependabot[bot]
0c78964316 Bump generate-license-file from 3.5.0 to 3.5.1 (#140)
Bumps [generate-license-file](https://github.com/TobyAndToby/generate-license-file/tree/HEAD/src/packages/generate-license-file) from 3.5.0 to 3.5.1.
- [Release notes](https://github.com/TobyAndToby/generate-license-file/releases)
- [Commits](https://github.com/TobyAndToby/generate-license-file/commits/v3.5.1/src/packages/generate-license-file)

---
updated-dependencies:
- dependency-name: generate-license-file
  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-08-17 09:15:01 +00:00
dependabot[bot]
04c18e5198 Bump terser from 5.31.3 to 5.31.5 (#139)
Bumps [terser](https://github.com/terser/terser) from 5.31.3 to 5.31.5.
- [Changelog](https://github.com/terser/terser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/terser/terser/compare/v5.31.3...v5.31.5)

---
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-08-10 10:00:32 +00:00
dependabot[bot]
25f0c04915 Bump @types/node from 22.1.0 to 22.2.0 (#138)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.1.0 to 22.2.0.
- [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-08-10 10:00:22 +00:00
dependabot[bot]
723efa232e Bump vite from 5.3.5 to 5.4.0 (#137)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.3.5 to 5.4.0.
- [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/create-vite@5.4.0/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  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-08-10 10:00:15 +00:00
dependabot[bot]
49d154eeb0 Bump vue from 3.4.35 to 3.4.37 (#136)
Bumps [vue](https://github.com/vuejs/core) from 3.4.35 to 3.4.37.
- [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.35...v3.4.37)

---
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-08-10 10:00:06 +00:00
dependabot[bot]
5892c454d3 Bump vue from 3.4.34 to 3.4.35 (#134)
Bumps [vue](https://github.com/vuejs/core) from 3.4.34 to 3.4.35.
- [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.34...v3.4.35)

---
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-08-03 09:28:03 +00:00
dependabot[bot]
08d89836da Bump @types/node from 20.14.12 to 22.1.0 (#135)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 20.14.12 to 22.1.0.
- [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-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-03 09:26:32 +00:00
dependabot[bot]
e5e9493b35 Bump @vitejs/plugin-vue from 5.1.1 to 5.1.2 (#133)
Bumps [@vitejs/plugin-vue](https://github.com/vitejs/vite-plugin-vue/tree/HEAD/packages/plugin-vue) from 5.1.1 to 5.1.2.
- [Release notes](https://github.com/vitejs/vite-plugin-vue/releases)
- [Changelog](https://github.com/vitejs/vite-plugin-vue/blob/main/packages/plugin-vue/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite-plugin-vue/commits/plugin-vue@5.1.2/packages/plugin-vue)

---
updated-dependencies:
- dependency-name: "@vitejs/plugin-vue"
  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-08-03 09:26:18 +00:00
dependabot[bot]
775f5d3700 Bump vuetify from 3.6.13 to 3.6.14 (#132)
Bumps [vuetify](https://github.com/vuetifyjs/vuetify/tree/HEAD/packages/vuetify) from 3.6.13 to 3.6.14.
- [Release notes](https://github.com/vuetifyjs/vuetify/releases)
- [Commits](https://github.com/vuetifyjs/vuetify/commits/v3.6.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-08-03 09:26:02 +00:00
dependabot[bot]
1ae0e508a8 Bump vite from 5.3.4 to 5.3.5 (#131)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.3.4 to 5.3.5.
- [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.3.5/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-07-27 09:32:43 +00:00
dependabot[bot]
2c5d73e957 Bump vue-tsc from 2.0.26 to 2.0.29 (#130)
Bumps [vue-tsc](https://github.com/vuejs/language-tools/tree/HEAD/packages/tsc) from 2.0.26 to 2.0.29.
- [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/HEAD/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-07-27 09:30:56 +00:00
dependabot[bot]
6e0afef6bf Bump @types/node from 20.14.11 to 20.14.12 (#129)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 20.14.11 to 20.14.12.
- [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-07-27 09:30:50 +00:00
dependabot[bot]
4884030bd6 Bump vue from 3.4.33 to 3.4.34 (#128)
Bumps [vue](https://github.com/vuejs/core) from 3.4.33 to 3.4.34.
- [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.33...v3.4.34)

---
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-07-27 09:30:40 +00:00
dependabot[bot]
64ce65a568 Bump typescript from 5.5.3 to 5.5.4 (#127)
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 5.5.3 to 5.5.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.5.3...v5.5.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-07-27 09:30:30 +00:00
dependabot[bot]
3982706365 Bump @vitejs/plugin-vue from 5.0.5 to 5.1.1 (#126)
Bumps [@vitejs/plugin-vue](https://github.com/vitejs/vite-plugin-vue/tree/HEAD/packages/plugin-vue) from 5.0.5 to 5.1.1.
- [Release notes](https://github.com/vitejs/vite-plugin-vue/releases)
- [Changelog](https://github.com/vitejs/vite-plugin-vue/blob/main/packages/plugin-vue/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite-plugin-vue/commits/plugin-vue@5.1.1/packages/plugin-vue)

---
updated-dependencies:
- dependency-name: "@vitejs/plugin-vue"
  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-07-27 09:30:22 +00:00
dependabot[bot]
e71ebd75b3 Bump vue from 3.4.31 to 3.4.33 (#123)
Bumps [vue](https://github.com/vuejs/core) from 3.4.31 to 3.4.33.
- [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.31...v3.4.33)

---
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-07-20 09:59:04 +00:00
dependabot[bot]
c013916299 Bump @gltf-transform/functions from 4.0.4 to 4.0.8 (#120)
Bumps [@gltf-transform/functions](https://github.com/donmccurdy/glTF-Transform) from 4.0.4 to 4.0.8.
- [Changelog](https://github.com/donmccurdy/glTF-Transform/blob/main/CHANGELOG.md)
- [Commits](https://github.com/donmccurdy/glTF-Transform/compare/v4.0.4...v4.0.8)

---
updated-dependencies:
- dependency-name: "@gltf-transform/functions"
  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-07-20 09:58:37 +00:00
dependabot[bot]
3787625230 Bump terser from 5.31.2 to 5.31.3 (#124)
Bumps [terser](https://github.com/terser/terser) from 5.31.2 to 5.31.3.
- [Changelog](https://github.com/terser/terser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/terser/terser/compare/v5.31.2...v5.31.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-07-20 09:57:35 +00:00
dependabot[bot]
ff712be60a Bump @types/node from 20.14.10 to 20.14.11 (#122)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 20.14.10 to 20.14.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-07-20 09:57:15 +00:00
dependabot[bot]
ab0c1b1482 Bump vuetify from 3.6.12 to 3.6.13 (#121)
Bumps [vuetify](https://github.com/vuetifyjs/vuetify/tree/HEAD/packages/vuetify) from 3.6.12 to 3.6.13.
- [Release notes](https://github.com/vuetifyjs/vuetify/releases)
- [Commits](https://github.com/vuetifyjs/vuetify/commits/v3.6.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-07-20 09:57:06 +00:00
dependabot[bot]
32246a890e Bump vite from 5.3.3 to 5.3.4 (#119)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.3.3 to 5.3.4.
- [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.3.4/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-07-20 09:56:52 +00:00
dependabot[bot]
72afb4b439 Bump @gltf-transform/extensions from 4.0.4 to 4.0.8 (#118)
Bumps [@gltf-transform/extensions](https://github.com/donmccurdy/glTF-Transform) from 4.0.4 to 4.0.8.
- [Changelog](https://github.com/donmccurdy/glTF-Transform/blob/main/CHANGELOG.md)
- [Commits](https://github.com/donmccurdy/glTF-Transform/compare/v4.0.4...v4.0.8)

---
updated-dependencies:
- dependency-name: "@gltf-transform/extensions"
  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-07-20 09:56:40 +00:00
dependabot[bot]
1b2312f0e5 Bump build123d from 0.5.0 to 0.6.0 (#117)
Bumps [build123d](https://github.com/gumyr/build123d) from 0.5.0 to 0.6.0.
- [Release notes](https://github.com/gumyr/build123d/releases)
- [Commits](https://github.com/gumyr/build123d/compare/v0.5.0...v0.6.0)

---
updated-dependencies:
- dependency-name: build123d
  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-07-20 09:43:06 +00:00
dependabot[bot]
87c6b12365 Bump vuetify from 3.6.11 to 3.6.12 (#116)
Bumps [vuetify](https://github.com/vuetifyjs/vuetify/tree/HEAD/packages/vuetify) from 3.6.11 to 3.6.12.
- [Release notes](https://github.com/vuetifyjs/vuetify/releases)
- [Commits](https://github.com/vuetifyjs/vuetify/commits/v3.6.12/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-07-13 09:49:56 +00:00
dependabot[bot]
3b4982bb24 Bump terser from 5.31.1 to 5.31.2 (#115)
Bumps [terser](https://github.com/terser/terser) from 5.31.1 to 5.31.2.
- [Changelog](https://github.com/terser/terser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/terser/terser/compare/v5.31.1...v5.31.2)

---
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-07-13 09:49:32 +00:00
dependabot[bot]
673814e1dd Bump vite from 5.3.2 to 5.3.3 (#113)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.3.2 to 5.3.3.
- [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.3.3/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-07-06 09:21:59 +00:00
dependabot[bot]
4b59ef2d1a Bump vue-tsc from 2.0.22 to 2.0.26 (#114)
Bumps [vue-tsc](https://github.com/vuejs/language-tools/tree/HEAD/packages/tsc) from 2.0.22 to 2.0.26.
- [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.26/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-07-06 09:20:44 +00:00
dependabot[bot]
cdec62f5b4 Bump @gltf-transform/functions from 4.0.2 to 4.0.4 (#112)
Bumps [@gltf-transform/functions](https://github.com/donmccurdy/glTF-Transform) from 4.0.2 to 4.0.4.
- [Changelog](https://github.com/donmccurdy/glTF-Transform/blob/main/CHANGELOG.md)
- [Commits](https://github.com/donmccurdy/glTF-Transform/compare/v4.0.2...v4.0.4)

---
updated-dependencies:
- dependency-name: "@gltf-transform/functions"
  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-07-06 09:20:25 +00:00
dependabot[bot]
48ef6d2470 Bump @types/node from 20.14.9 to 20.14.10 (#111)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 20.14.9 to 20.14.10.
- [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-07-06 09:20:19 +00:00
dependabot[bot]
74fcc1b6b6 Bump vuetify from 3.6.10 to 3.6.11 (#110)
Bumps [vuetify](https://github.com/vuetifyjs/vuetify/tree/HEAD/packages/vuetify) from 3.6.10 to 3.6.11.
- [Release notes](https://github.com/vuetifyjs/vuetify/releases)
- [Commits](https://github.com/vuetifyjs/vuetify/commits/v3.6.11/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-07-06 09:20:07 +00:00
dependabot[bot]
36da97e8c8 Bump @gltf-transform/core from 4.0.2 to 4.0.4 (#109)
Bumps [@gltf-transform/core](https://github.com/donmccurdy/glTF-Transform) from 4.0.2 to 4.0.4.
- [Changelog](https://github.com/donmccurdy/glTF-Transform/blob/main/CHANGELOG.md)
- [Commits](https://github.com/donmccurdy/glTF-Transform/compare/v4.0.2...v4.0.4)

---
updated-dependencies:
- dependency-name: "@gltf-transform/core"
  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-07-06 09:19:50 +00:00
dependabot[bot]
6a8ca13de3 Bump three-mesh-bvh from 0.7.5 to 0.7.6 (#108)
Bumps [three-mesh-bvh](https://github.com/gkjohnson/three-mesh-bvh) from 0.7.5 to 0.7.6.
- [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/commits)

---
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-07-06 09:19:34 +00:00
dependabot[bot]
60de0833b5 Bump typescript from 5.5.2 to 5.5.3 (#106)
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 5.5.2 to 5.5.3.
- [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.5.2...v5.5.3)

---
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-07-06 09:19:23 +00:00
dependabot[bot]
263a8e0c14 Bump npm-run-all2 from 6.2.0 to 6.2.2 (#105)
Bumps [npm-run-all2](https://github.com/bcomnes/npm-run-all2) from 6.2.0 to 6.2.2.
- [Release notes](https://github.com/bcomnes/npm-run-all2/releases)
- [Changelog](https://github.com/bcomnes/npm-run-all2/blob/master/CHANGELOG.md)
- [Commits](https://github.com/bcomnes/npm-run-all2/compare/v6.2.0...v6.2.2)

---
updated-dependencies:
- dependency-name: npm-run-all2
  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-07-06 09:19:14 +00:00
dependabot[bot]
4d825ed763 Bump pillow from 10.3.0 to 10.4.0 (#104)
Bumps [pillow](https://github.com/python-pillow/Pillow) from 10.3.0 to 10.4.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.3.0...10.4.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-07-06 09:09:17 +00:00
dependabot[bot]
5e3841186b Bump @gltf-transform/functions from 4.0.1 to 4.0.2 (#102)
Bumps [@gltf-transform/functions](https://github.com/donmccurdy/glTF-Transform) from 4.0.1 to 4.0.2.
- [Changelog](https://github.com/donmccurdy/glTF-Transform/blob/main/CHANGELOG.md)
- [Commits](https://github.com/donmccurdy/glTF-Transform/compare/v4.0.1...v4.0.2)

---
updated-dependencies:
- dependency-name: "@gltf-transform/functions"
  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-06-29 09:22:38 +00:00
dependabot[bot]
18f22407c9 Bump vite from 5.3.1 to 5.3.2 (#103)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.3.1 to 5.3.2.
- [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.3.2/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-06-29 09:21:49 +00:00
dependabot[bot]
14817b6505 Bump @gltf-transform/extensions from 4.0.1 to 4.0.2 (#100)
Bumps [@gltf-transform/extensions](https://github.com/donmccurdy/glTF-Transform) from 4.0.1 to 4.0.2.
- [Changelog](https://github.com/donmccurdy/glTF-Transform/blob/main/CHANGELOG.md)
- [Commits](https://github.com/donmccurdy/glTF-Transform/compare/v4.0.1...v4.0.2)

---
updated-dependencies:
- dependency-name: "@gltf-transform/extensions"
  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-06-29 09:20:36 +00:00
dependabot[bot]
82b5e305d9 Bump @types/node from 20.14.8 to 20.14.9 (#101)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 20.14.8 to 20.14.9.
- [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-06-29 09:20:00 +00:00
dependabot[bot]
da94809cd2 Bump generate-license-file from 3.4.0 to 3.5.0 (#99)
Bumps [generate-license-file](https://github.com/TobyAndToby/generate-license-file/tree/HEAD/src/packages/generate-license-file) from 3.4.0 to 3.5.0.
- [Release notes](https://github.com/TobyAndToby/generate-license-file/releases)
- [Commits](https://github.com/TobyAndToby/generate-license-file/commits/v3.5.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-06-29 09:19:35 +00:00
dependabot[bot]
933ec17293 Bump @gltf-transform/core from 4.0.1 to 4.0.2 (#98)
Bumps [@gltf-transform/core](https://github.com/donmccurdy/glTF-Transform) from 4.0.1 to 4.0.2.
- [Changelog](https://github.com/donmccurdy/glTF-Transform/blob/main/CHANGELOG.md)
- [Commits](https://github.com/donmccurdy/glTF-Transform/compare/v4.0.1...v4.0.2)

---
updated-dependencies:
- dependency-name: "@gltf-transform/core"
  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-06-29 09:19:24 +00:00
dependabot[bot]
dc91e4b497 Bump vue-tsc from 2.0.21 to 2.0.22 (#97)
Bumps [vue-tsc](https://github.com/vuejs/language-tools/tree/HEAD/packages/tsc) from 2.0.21 to 2.0.22.
- [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.22/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-06-29 09:19:16 +00:00
dependabot[bot]
9e740db791 Bump vue from 3.4.29 to 3.4.31 (#96)
Bumps [vue](https://github.com/vuejs/core) from 3.4.29 to 3.4.31.
- [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.29...v3.4.31)

---
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-06-29 09:19:09 +00:00
dependabot[bot]
c26cb78cc4 Bump vite from 5.2.13 to 5.3.1 (#90)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.2.13 to 5.3.1.
- [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.3.1/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  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-06-22 09:10:05 +00:00
dependabot[bot]
24c892c061 Bump typescript from 5.4.5 to 5.5.2 (#95)
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 5.4.5 to 5.5.2.
- [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.5...v5.5.2)

---
updated-dependencies:
- dependency-name: typescript
  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-06-22 09:08:31 +00:00
dependabot[bot]
ec63c9efdc Bump vuetify from 3.6.9 to 3.6.10 (#94)
Bumps [vuetify](https://github.com/vuetifyjs/vuetify/tree/HEAD/packages/vuetify) from 3.6.9 to 3.6.10.
- [Release notes](https://github.com/vuetifyjs/vuetify/releases)
- [Commits](https://github.com/vuetifyjs/vuetify/commits/v3.6.10/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-06-22 09:08:18 +00:00
dependabot[bot]
6f90e3c448 Bump @types/node from 20.14.2 to 20.14.8 (#93)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 20.14.2 to 20.14.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-06-22 09:07:57 +00:00
dependabot[bot]
2205901752 Bump vue from 3.4.27 to 3.4.29 (#92)
Bumps [vue](https://github.com/vuejs/core) from 3.4.27 to 3.4.29.
- [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.27...v3.4.29)

---
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-06-15 09:26:43 +00:00
dependabot[bot]
ad5bb1b8a3 Bump vuetify from 3.6.8 to 3.6.9 (#91)
Bumps [vuetify](https://github.com/vuetifyjs/vuetify/tree/HEAD/packages/vuetify) from 3.6.8 to 3.6.9.
- [Release notes](https://github.com/vuetifyjs/vuetify/releases)
- [Commits](https://github.com/vuetifyjs/vuetify/commits/v3.6.9/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-06-15 09:25:30 +00:00
dependabot[bot]
8ad0ffa147 Bump vue-tsc from 2.0.20 to 2.0.21 (#89)
Bumps [vue-tsc](https://github.com/vuejs/language-tools/tree/HEAD/packages/tsc) from 2.0.20 to 2.0.21.
- [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.21/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-06-15 09:24:58 +00:00
dependabot[bot]
96dbda0374 Bump vite from 5.2.12 to 5.2.13 (#86)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.2.12 to 5.2.13.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v5.2.13/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.2.13/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-06-08 09:31:44 +00:00
dependabot[bot]
90c03ea99a Bump terser from 5.31.0 to 5.31.1 (#88)
Bumps [terser](https://github.com/terser/terser) from 5.31.0 to 5.31.1.
- [Changelog](https://github.com/terser/terser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/terser/terser/compare/v5.31.0...v5.31.1)

---
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-06-08 09:31:06 +00:00
dependabot[bot]
50a7efa4ac Bump @types/node from 20.13.0 to 20.14.2 (#87)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 20.13.0 to 20.14.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-06-08 09:30:59 +00:00
dependabot[bot]
dd6154955c Bump three-mesh-bvh from 0.7.4 to 0.7.5 (#85)
Bumps [three-mesh-bvh](https://github.com/gkjohnson/three-mesh-bvh) from 0.7.4 to 0.7.5.
- [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.4...v0.7.5)

---
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-06-08 09:30:31 +00:00
dependabot[bot]
d3847aae12 Bump vue-tsc from 2.0.19 to 2.0.20 (#84)
Bumps [vue-tsc](https://github.com/vuejs/language-tools/tree/HEAD/packages/tsc) from 2.0.19 to 2.0.20.
- [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.20/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-06-08 09:30:25 +00:00
dependabot[bot]
c74b695907 Bump @vitejs/plugin-vue from 5.0.4 to 5.0.5 (#79)
Bumps [@vitejs/plugin-vue](https://github.com/vitejs/vite-plugin-vue/tree/HEAD/packages/plugin-vue) from 5.0.4 to 5.0.5.
- [Release notes](https://github.com/vitejs/vite-plugin-vue/releases)
- [Changelog](https://github.com/vitejs/vite-plugin-vue/blob/main/packages/plugin-vue/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite-plugin-vue/commits/plugin-vue@5.0.5/packages/plugin-vue)

---
updated-dependencies:
- dependency-name: "@vitejs/plugin-vue"
  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-06-01 09:15:25 +00:00
dependabot[bot]
c720a8c03e Bump vite from 5.2.11 to 5.2.12 (#83)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.2.11 to 5.2.12.
- [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.12/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-06-01 09:14:47 +00:00
dependabot[bot]
a05c19c25e Bump vuetify from 3.6.7 to 3.6.8 (#82)
Bumps [vuetify](https://github.com/vuetifyjs/vuetify/tree/HEAD/packages/vuetify) from 3.6.7 to 3.6.8.
- [Release notes](https://github.com/vuetifyjs/vuetify/releases)
- [Commits](https://github.com/vuetifyjs/vuetify/commits/v3.6.8/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-06-01 09:14:32 +00:00
dependabot[bot]
9437ccd987 Bump @vitejs/plugin-vue-jsx from 3.1.0 to 4.0.0 (#81)
Bumps [@vitejs/plugin-vue-jsx](https://github.com/vitejs/vite-plugin-vue/tree/HEAD/packages/plugin-vue-jsx) from 3.1.0 to 4.0.0.
- [Release notes](https://github.com/vitejs/vite-plugin-vue/releases)
- [Changelog](https://github.com/vitejs/vite-plugin-vue/blob/main/packages/plugin-vue-jsx/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite-plugin-vue/commits/plugin-vue@4.0.0/packages/plugin-vue-jsx)

---
updated-dependencies:
- dependency-name: "@vitejs/plugin-vue-jsx"
  dependency-type: direct:development
  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-06-01 09:14:11 +00:00
dependabot[bot]
20300ca2d9 Bump @types/node from 20.12.12 to 20.13.0 (#80)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 20.12.12 to 20.13.0.
- [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-06-01 09:14:03 +00:00
dependabot[bot]
42d0e0e158 Bump vuetify from 3.6.6 to 3.6.7 (#78)
Bumps [vuetify](https://github.com/vuetifyjs/vuetify/tree/HEAD/packages/vuetify) from 3.6.6 to 3.6.7.
- [Release notes](https://github.com/vuetifyjs/vuetify/releases)
- [Commits](https://github.com/vuetifyjs/vuetify/commits/v3.6.7/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-25 09:20:21 +00:00
Yeicor
4cd3e0ebfb Merge pull request #77 from yeicor-3d/dependabot/npm_and_yarn/vuetify-3.6.6
Bump vuetify from 3.6.5 to 3.6.6
2024-05-22 23:20:11 +02:00
Yeicor
83d34e5f21 Merge pull request #72 from yeicor-3d/dependabot/npm_and_yarn/gltf-transform/functions-4.0.1
Bump @gltf-transform/functions from 4.0.0 to 4.0.1
2024-05-22 23:19:48 +02:00
dependabot[bot]
94e7878c86 Bump @gltf-transform/functions from 4.0.0 to 4.0.1
Bumps [@gltf-transform/functions](https://github.com/donmccurdy/glTF-Transform) from 4.0.0 to 4.0.1.
- [Changelog](https://github.com/donmccurdy/glTF-Transform/blob/main/CHANGELOG.md)
- [Commits](https://github.com/donmccurdy/glTF-Transform/compare/v4.0.0...v4.0.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-18 09:22:22 +00:00
dependabot[bot]
56b8dbadf7 Bump vue-tsc from 2.0.17 to 2.0.19 (#76)
Bumps [vue-tsc](https://github.com/vuejs/language-tools/tree/HEAD/packages/tsc) from 2.0.17 to 2.0.19.
- [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.19/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-18 09:22:20 +00:00
dependabot[bot]
a54873314e Bump vuetify from 3.6.5 to 3.6.6
Bumps [vuetify](https://github.com/vuetifyjs/vuetify/tree/HEAD/packages/vuetify) from 3.6.5 to 3.6.6.
- [Release notes](https://github.com/vuetifyjs/vuetify/releases)
- [Commits](https://github.com/vuetifyjs/vuetify/commits/v3.6.6/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>
2024-05-18 09:22:14 +00:00
dependabot[bot]
c7d672875e Bump @types/node from 20.12.11 to 20.12.12 (#74)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 20.12.11 to 20.12.12.
- [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-18 09:21:59 +00:00
dependabot[bot]
9d261f1718 Bump npm-run-all2 from 6.1.2 to 6.2.0 (#73)
Bumps [npm-run-all2](https://github.com/bcomnes/npm-run-all2) from 6.1.2 to 6.2.0.
- [Release notes](https://github.com/bcomnes/npm-run-all2/releases)
- [Changelog](https://github.com/bcomnes/npm-run-all2/blob/master/CHANGELOG.md)
- [Commits](https://github.com/bcomnes/npm-run-all2/compare/v6.1.2...v6.2.0)

---
updated-dependencies:
- dependency-name: npm-run-all2
  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-18 09:21:50 +00:00
dependabot[bot]
db0f139cf8 Bump @gltf-transform/extensions from 4.0.0 to 4.0.1 (#71)
Bumps [@gltf-transform/extensions](https://github.com/donmccurdy/glTF-Transform) from 4.0.0 to 4.0.1.
- [Changelog](https://github.com/donmccurdy/glTF-Transform/blob/main/CHANGELOG.md)
- [Commits](https://github.com/donmccurdy/glTF-Transform/compare/v4.0.0...v4.0.1)

---
updated-dependencies:
- dependency-name: "@gltf-transform/extensions"
  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-18 09:21:22 +00:00
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
Yeicor
58440723bd Automatically update version to 0.8.4 2024-03-28 22:29:24 +00:00
Yeicor
bfdd656316 Merge remote-tracking branch 'origin/master' 2024-03-28 23:28:43 +01:00
Yeicor
7408823c02 Debug CI 2024-03-28 23:28:36 +01:00
Yeicor
856ffbc4c5 Reduce logging 2024-03-28 23:26:00 +01:00
Yeicor
d0f8463bbf Automatically update version to 0.8.3 2024-03-28 22:01:12 +00:00
Yeicor
162d3e22a2 Fix typescript 2024-03-28 22:57:26 +01:00
Yeicor
4b06559ab8 Add a progress bar to the frontend and improve slightly batched updates logic 2024-03-28 22:52:34 +01:00
Yeicor
9afa2e5786 Add support for some gltf extensions and better multi-object updates 2024-03-28 19:12:21 +01:00
Yeicor
7196fb2f32 Automatically update version to 0.8.2 2024-03-28 11:52:24 +00:00
Yeicor
8ec60faa04 Merge remote-tracking branch 'origin/master' 2024-03-28 12:51:34 +01:00
Yeicor
13bbdd5956 Fix automatic _find_var_name 2024-03-28 12:51:26 +01:00
Yeicor
3675d2f447 Automatically update version to 0.8.1 2024-03-28 11:23:32 +00:00
Yeicor
efc7a1d3b6 Merge remote-tracking branch 'origin/master' 2024-03-28 12:21:10 +01:00
Yeicor
7166f9fe3d Improved image location after build123d update 2024-03-28 12:20:56 +01:00
56 changed files with 5475 additions and 4021 deletions

View File

@@ -1,6 +1,7 @@
{
"append": [
"assets/fox.glb.license",
"assets/qwantani_afternoon_1k_hdr.jpg.license",
"LICENSE"
],
"replace": {

View File

@@ -1,26 +0,0 @@
version: 2
updates:
- package-ecosystem: "pip"
directory: "/"
schedule:
interval: "weekly"
day: "saturday"
time: "09:00"
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
day: "saturday"
time: "09:00"
- package-ecosystem: "pip"
directory: "/example"
schedule:
interval: "weekly"
day: "saturday"
time: "09:00"
- package-ecosystem: "github-actions"
directory: "/.github/workflows/"
schedule:
interval: "weekly"
day: "saturday"
time: "09:00"

14
.github/renovate.json5 vendored Normal file
View File

@@ -0,0 +1,14 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:recommended",
":disableDependencyDashboard"
],
"automerge": true,
"automergeType": "branch",
"schedule": [ "* * * * 0,6" ],
"lockFileMaintenance": {
"enabled": true,
"schedule": [ "* * * * 0,6" ]
}
}

View File

@@ -1,35 +0,0 @@
on: "pull_request_target"
permissions:
pull-requests: "write"
contents: "write"
jobs:
dependabot:
runs-on: "ubuntu-latest"
# Checking the actor will prevent your Action run failing on non-Dependabot
# PRs but also ensures that it only does work for Dependabot PRs.
if: "${{ github.actor == 'dependabot[bot]' }}"
steps:
# This first step will fail if there's no metadata and so the approval
# will not occur.
- name: "Dependabot metadata"
id: "dependabot-metadata"
uses: "dependabot/fetch-metadata@v2"
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
# Here the PR gets approved.
- uses: "actions/checkout@v4"
- name: "Approve a PR"
run: "gh pr review --approve $PR_URL"
env:
PR_URL: "${{ github.event.pull_request.html_url }}"
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
# Finally, this sets the PR to allow auto-merging for patch and minor
# updates if all checks pass
- name: "Enable auto-merge for Dependabot PRs"
#if: "${{ steps.dependabot-metadata.outputs.update-type != 'version-update:semver-major' }}"
run: "gh pr merge --auto --squash $PR_URL"
env:
PR_URL: "${{ github.event.pull_request.html_url }}"
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"

View File

@@ -1,10 +1,6 @@
on:
push:
branches:
- "master"
pull_request:
branches:
- "master"
workflow_call:
inputs:
ref:
@@ -42,10 +38,11 @@ jobs:
- run: "pipx install poetry"
- uses: "actions/setup-python@v5"
with:
python-version: "3.11"
python-version: "3.13"
cache: "poetry"
- run: "SKIP_BUILD_FRONTEND=true poetry install"
- run: "SKIP_BUILD_FRONTEND=true poetry build"
- run: "poetry lock"
- run: "poetry install"
- run: "poetry build" # Skips building frontend (not using task)
build-logo:
name: "Build logo"
@@ -57,9 +54,10 @@ jobs:
- run: "pipx install poetry"
- uses: "actions/setup-python@v5"
with:
python-version: "3.11"
python-version: "3.13"
cache: "poetry"
- run: "SKIP_BUILD_FRONTEND=true poetry install"
- run: "poetry lock"
- run: "poetry install"
- run: "poetry run python yacv_server/logo.py"
- uses: "actions/upload-artifact@v4"
with:
@@ -77,9 +75,10 @@ jobs:
- run: "pipx install poetry"
- uses: "actions/setup-python@v5"
with:
python-version: "3.11"
python-version: "3.13"
cache: "poetry"
- run: "SKIP_BUILD_FRONTEND=true poetry install"
- run: "poetry lock"
- run: "poetry install"
- run: "YACV_DISABLE_SERVER=true poetry run python example/object.py"
- uses: "actions/upload-artifact@v4"
with:

View File

@@ -12,18 +12,22 @@ jobs:
update-versions:
runs-on: "ubuntu-latest"
outputs:
skip: "${{ steps.check_recursive.outputs.skip || 'false' }}" # Default to false if not set
steps:
- uses: "actions/checkout@v4"
with: # Ensure we are not in a detached HEAD state
ref: "master"
token: "${{ secrets.GH_PAT }}"
# Check that the tag commit is the latest master commit
- run: |
- id: check_recursive
run: |
git fetch --tags
tag_commit=$(git rev-parse ${{ github.ref }})
master_commit=$(git rev-parse master)
if [ "$tag_commit" != "$master_commit" ]; then
echo "The tag commit ($tag_commit) is not the latest master commit ($master_commit)"
exit 1
echo "::warning ::The tag commit $tag_commit does not match the latest master commit $master_commit. This is probably a recursive tag push that will be ignored."
echo "skip=true" >> $GITHUB_OUTPUT
fi
- run: "echo 'CLEAN_VERSION=${{ github.ref }}' | sed 's,refs/tags/v,,g' >> $GITHUB_ENV"
# Write the new version to package.json
@@ -33,11 +37,12 @@ jobs:
- run: "pipx install poetry"
- uses: "actions/setup-python@v5"
with:
python-version: "3.11"
python-version: "3.13"
cache: "poetry"
- run: "poetry version $CLEAN_VERSION"
# Commit the changes and move the tag!
- run: |
- if: "steps.check_recursive.outputs.skip != 'true'"
run: |
git config --global user.email "yeicor@users.noreply.github.com"
git config --global user.name "Yeicor"
if git commit -am "Automatically update version to $CLEAN_VERSION"; then
@@ -53,6 +58,7 @@ jobs:
deploy: # Makes sure all artifacts are updated and use the new version for the next deployment steps
needs: "update-versions"
if: "needs.update-versions.outputs.skip != 'true'" # Only run if the update-versions job did not skip
uses: "./.github/workflows/deploy2.yml"
secrets: "inherit" # Inherit the secrets from the parent workflow
with:

View File

@@ -35,12 +35,8 @@ jobs:
- uses: "actions/download-artifact@v4"
with: # Downloads all artifacts from the build job
path: "./public"
- run: | # Merge the subdirectories of public into a single directory
for dir in public/*; do
mv "$dir/"* public/
rmdir "$dir"
done
- uses: "actions/configure-pages@v4"
merge-multiple: true
- uses: "actions/configure-pages@v5"
- uses: "actions/upload-pages-artifact@v3"
with:
path: 'public'
@@ -67,9 +63,10 @@ jobs:
- run: "pipx install poetry"
- uses: "actions/setup-python@v5"
with:
python-version: "3.11"
python-version: "3.13"
cache: "poetry"
- run: "poetry install"
- run: "poetry config pypi-token.pypi ${{ secrets.PYPI_TOKEN }}"
- run: "poetry publish --build"
- run: "poetry run task build" # This task also builds the frontend (with reduced features for less size)
- run: "poetry publish"

View File

@@ -15,14 +15,24 @@ in a web browser.
- Select any entity and measure bounding box size and distances.
- Hot reloading while editing the CAD model (using the `yacv-server` package).
- Fully-featured static deployment: just upload the viewer and models to your server.
- Build123d playground! Code and build your model fully inside the
browser: [demo](https://yeicor-3d.github.io/yet-another-cad-viewer/#pg_code_url=https://raw.githubusercontent.com/gumyr/build123d/refs/heads/dev/examples/toy_truck.py).
## Usage
The [example](example) is a fully working project that shows how to use the viewer.
You can play with the latest
demo [here](https://yeicor-3d.github.io/yet-another-cad-viewer/?preload=logo.glb&preload=fox.glb&preload=img.jpg.glb&preload=location.glb)
demo [here](https://yeicor-3d.github.io/yet-another-cad-viewer/?preload=logo.glb&preload=logo_hl.glb&preload=logo_hl_tex.glb&preload=fox.glb&preload=img.jpg.glb&preload=location.glb)
(or
[without animation](https://yeicor-3d.github.io/yet-another-cad-viewer/?autoplay=false&preload=logo.glb&preload=fox.glb&preload=img.jpg.glb&preload=location.glb)).
[without animation](https://yeicor-3d.github.io/yet-another-cad-viewer/?autoplay=false&preload=logo.glb&preload=logo_hl.glb&preload=logo_hl_tex.glb&preload=fox.glb&preload=img.jpg.glb&preload=location.glb)).
![Demo](assets/screenshot.png)
## Related projects
- [cq-studio](https://github.com/ccazabon/cq-studio) provides an alternative workflow that detects file changes instead
of relying on an interactive environment like Jupyter for hot-reloading.
Uses the same backend and frontend behind the scenes.
- [build123d-docker](https://github.com/derhuerst/build123d-docker/pkgs/container/build123d) provides docker images for
Yet Another CAD Viewer and other projects, with automatic updates.

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

View File

@@ -0,0 +1,2 @@
CC0: Qwantani Afternoon by Greg Zaal (Photography) and Jarod Guest (Processing)
https://polyhaven.com/a/qwantani_afternoon

View File

@@ -1,9 +0,0 @@
import os
import subprocess
if __name__ == "__main__":
# Building the frontend is optional
if os.getenv('SKIP_BUILD_FRONTEND') is None and os.path.exists('package.json'):
# When building the backend, make sure the frontend is built first
subprocess.run(['yarn', 'install'], check=True)
subprocess.run(['yarn', 'build', '--outDir', 'yacv_server/frontend'], check=True)

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
@@ -37,5 +36,5 @@ Once you have the `object.glb` file, you can host it on any static file server a
For the example model, the build process is set up in [build.yml](../.github/workflows/build.yml), the upload process
is set up in [deploy.yml](../.github/workflows/deploy.yml), and the final link is:
https://yeicor-3d.github.io/yet-another-cad-viewer/?preload=example.glb
https://yeicor-3d.github.io/yet-another-cad-viewer/?preload=example.glb&preload=example_hl.glb

View File

@@ -3,6 +3,7 @@ import logging
import os
from build123d import * # Also works with cadquery objects!
from build123d import Compound
logging.basicConfig(level=logging.DEBUG)
@@ -15,9 +16,17 @@ with BuildPart() as example:
Box(10, 10, 5)
Cylinder(4, 5, mode=Mode.SUBTRACT)
# Show it in the frontend with hot-reloading
show(example)
# Custom colors (optional)
example.color = (0.1, 0.3, 0.1, 1) # RGBA
to_highlight = example.edges().group_by(Axis.Z)[-1]
example_hl = Compound(to_highlight).translate((0, 0, 1e-3)) # To avoid z-fighting
example_hl.color = (1, 1, .0, 1)
# Show it in the frontend with hot-reloading (texture and other keyword arguments are optional)
texture = ( # MIT License Framework7 Line Icons: https://www.svgrepo.com/svg/437552/checkmark-seal
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASAQAAAAB+tbP6AAAAQ0lEQVQI12P4b3+A4Z/8AYYHBw8w"
"HHxwgOH8HyD+AsRPDjDMP+fAYD+fgcESiGfYOTCcqTnAcK4GogakFqQHpBdoBgAbGiPSbdzkhgAAAABJRU5ErkJggg==")
show(example, example_hl, texture=texture)
# %%

View File

@@ -1,17 +1,18 @@
<!--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";
import {mdiPlus} from '@mdi/js'
import {mdiCube, mdiPlus, mdiScriptTextPlay} from '@mdi/js'
// @ts-expect-error
import SvgIcon from '@jamescoyle/vue-icon';
// NOTE: The ModelViewer library is big (THREE.js), so we split it and import it asynchronously
@@ -21,18 +22,23 @@ const ModelViewerWrapper = defineAsyncComponent({
delay: 0,
});
let openSidebarsByDefault: Ref<boolean> = ref(window.innerWidth > 1200);
let openSidebarsByDefault: Ref<boolean> = ref(window.innerWidth > window.innerHeight);
const sceneUrl = ref("")
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});
async function onModelUpdateRequest(event: NetworkUpdateEvent) {
// Trigger progress bar as soon as possible (also triggered earlier for each raw notification)
if (viewer.value && event.models.length > 0) {
viewer.value.onProgress(0.10);
}
// Load/unload a new batch of models to optimize rendering time
console.log("Received model update request", event.models);
let shutdownRequestIndex = event.models.findIndex((model) => model.isRemove == null);
@@ -45,11 +51,13 @@ 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 {
let loadHelpers = (await settings).loadHelpers;
if (!model.isRemove) {
doc = await SceneMgr.loadModel(sceneUrl, doc, model.name, model.url, isLast && settings.loadHelpers, isLast);
doc = await SceneMgr.loadModel(sceneUrl, doc, model.name, model.url, isLast && loadHelpers, isLast);
} else {
doc = await SceneMgr.removeModel(sceneUrl, doc, model.name, isLast && settings.loadHelpers, isLast);
doc = await SceneMgr.removeModel(sceneUrl, doc, model.name, isLast && loadHelpers, isLast);
}
} catch (e) {
console.error("Error loading model", model, e);
@@ -64,22 +72,59 @@ 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
let networkMgr = new NetworkManager();
networkMgr.addEventListener('update-early',
(e) => viewer.value?.onProgress((e as CustomEvent<Array<any>>).detail.length * 0.01));
networkMgr.addEventListener('update', (e) => onModelUpdateRequest(e as NetworkUpdateEvent));
// Start loading all configured models ASAP
for (let model of settings.preload) {
networkMgr.load(model);
}
let preloadingModels = ref<Array<string>>([]);
(async () => { // Start loading all configured models ASAP
let sett = await settings;
if (sett.preload.length > 0) {
watch(viewer, (newViewer) => {
if (newViewer) {
newViewer.setPosterText('<tspan x="50%" dy="1.2em">Trying to load' +
' models from:</tspan>' + sett.preload.map((url: string) => '<tspan x="50%" dy="1.2em">- ' + url + '</tspan>').join(""));
}
});
for (let model of sett.preload) {
preloadingModels.value.push(model);
let removeFromPreloadingModels = () => {
preloadingModels.value = preloadingModels.value.filter((m) => m !== model);
};
networkMgr.load(model).then(removeFromPreloadingModels).catch((e) => {
removeFromPreloadingModels()
console.error("Error preloading model", model, e);
});
}
} // else No preloaded models (useful for playground mode)
})();
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:");
if (modelUrl) await networkMgr.load(modelUrl);
}
// Detect dropped .glb files and load them manually
document.body.addEventListener("dragover", e => {
e.preventDefault(); // Allow drop
});
document.body.addEventListener("drop", async e => {
e.preventDefault();
const file = e.dataTransfer?.files?.[0];
if (!file) return;
const ext = file.name.split('.').pop()?.toLowerCase();
if (ext === 'glb' || ext === 'gltf') {
await networkMgr.load(file);
}
});
</script>
<template>
@@ -87,28 +132,49 @@ async function loadModelManual() {
<!-- The main content of the app is the model-viewer with the SVG "2D" overlay -->
<v-main id="main">
<model-viewer-wrapper ref="viewer" :src="sceneUrl"/>
<model-viewer-wrapper v-if="sceneDocument.getRoot().listMeshes().length > 0" ref="viewer" :src="sceneUrl"/>
<!-- A nice no model loaded alternative to avoid breaking model-viewer-wrapper -->
<div v-else style="height: 100%; overflow-y: auto">
<v-toolbar-title class="text-center ma-16 text-h5">No model loaded</v-toolbar-title>
<v-btn @click="() => tools?.openPlayground()" class="mx-auto d-block my-4">
<svg-icon :path="mdiScriptTextPlay" type="mdi"/>&nbsp; Open playground...
</v-btn>
<v-btn @click="networkMgr.load('https://yeicor-3d.github.io/yet-another-cad-viewer/logo.glb')"
class="mx-auto d-block my-4">
<svg-icon :path="mdiCube" type="mdi"/>&nbsp; Load demo model...
</v-btn>
<v-btn @click="loadModelManual" class="mx-auto d-block my-4">
<svg-icon :path="mdiPlus" type="mdi"/>&nbsp; Load model manually...
</v-btn>
<span v-if="preloadingModels.length > 0" class="d-block text-center my-16">
<span class="d-block text-center text-h6">Still trying to load the following:</span>
<span class="d-block text-center" v-for="(model, index) in preloadingModels" :key="index">
{{ model }}<span v-if="index < preloadingModels.length - 1">, </span>
</span>
</span>
</div>
</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"/>
<models ref="models" :viewer="viewer" @remove-model="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" @find-model="models?.findModel" @update-model="onModelUpdateRequest"/>
</sidebar>
</v-layout>
@@ -118,6 +184,6 @@ async function loadModelManual() {
<style>
html, body {
height: 100%;
overflow: hidden;
overflow: hidden !important;
}
</style>

View File

@@ -0,0 +1,31 @@
<script setup lang="ts">
import {mdiLockQuestion} from "@mdi/js";
import {VBtn, VTooltip} from "vuetify/lib/components/index.mjs";
// @ts-expect-error
import SvgIcon from "@jamescoyle/vue-icon";
// @ts-expect-error
let isSmallBuild = typeof __YACV_SMALL_BUILD__ !== 'undefined' && __YACV_SMALL_BUILD__;
function clickedButton() { // Redirect to the main build
window.open("https://yeicor-3d.github.io/yet-another-cad-viewer/" + window.location.search + window.location.hash, '_blank');
}
</script>
<template>
<!-- @ts-ignore-->
<!-- Include the children as this is a full build -->
<slot v-if="!isSmallBuild"/>
<!-- A small info button saying that a feature is missing, and linking to the main build -->
<v-btn v-else icon @click="clickedButton" base-color="#a00" style="margin: auto; display: block;">
<v-tooltip activator="parent">
This feature is not available in the small build.<br/>
Click to go to the main build.
</v-tooltip>
<svg-icon :path="mdiLockQuestion" type="mdi"/>
</v-btn>
</template>
<style scoped>
</style>

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,7 +1,8 @@
<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'
// @ts-expect-error
import SvgIcon from '@jamescoyle/vue-icon';
const props = defineProps<{
@@ -16,22 +17,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,10 +1,14 @@
import {Buffer, Document, Scene, type Transform, WebIO} from "@gltf-transform/core";
import {unpartition} from "@gltf-transform/functions";
import {mergeDocuments, unpartition} from "@gltf-transform/functions";
import {retrieveFile} from "../tools/upload-file.ts";
let io = new WebIO();
export let extrasNameKey = "__yacv_name";
export let extrasNameValueHelpers = "__helpers";
// @ts-expect-error
let isSmallBuild = typeof __YACV_SMALL_BUILD__ !== 'undefined' && __YACV_SMALL_BUILD__;
/**
* Loads a GLB model from a URL and adds it to the document or replaces it if the names match.
*
@@ -12,16 +16,43 @@ export let extrasNameValueHelpers = "__helpers";
*
* Remember to call mergeFinalize after all models have been merged (slower required operations).
*/
export async function mergePartial(url: string, name: string, document: Document, networkFinished: () => void = () => {
export async function mergePartial(url: string | Blob, name: string, document: Document, networkFinished: () => void = () => {
}): Promise<Document> {
// Fetch the complete document from the network
// This could be done at the same time as the document is being processed, but I wanted better metrics
let response = await fetch(url);
let response = await fetchOrRead(url);
let buffer = await response.arrayBuffer();
networkFinished();
// Load the new document
let newDoc = await io.readBinary(new Uint8Array(buffer));
let newDoc = null;
let alreadyTried: { [name: string]: boolean } = {}
while (newDoc == null) { // Retry adding extensions as required until the document is loaded
try { // Try to load fast if no extensions are used
newDoc = await io.readBinary(new Uint8Array(buffer));
} catch (e) { // Fallback to wait for download and register big extensions
if (!isSmallBuild && e instanceof Error && e.message.toLowerCase().includes("khr_draco_mesh_compression")) {
if (alreadyTried["draco"]) throw e; else alreadyTried["draco"] = true;
// WARNING: Draco decompression on web is really slow for non-trivial models! (it should work?)
let {KHRDracoMeshCompression} = await import("@gltf-transform/extensions")
// @ts-expect-error
let dracoDecoderWeb = await import("three/examples/jsm/libs/draco/draco_decoder.js");
// @ts-expect-error
let dracoEncoderWeb = await import("three/examples/jsm/libs/draco/draco_encoder.js");
io.registerExtensions([KHRDracoMeshCompression])
.registerDependencies({
'draco3d.decoder': await dracoDecoderWeb.default({}),
'draco3d.encoder': await dracoEncoderWeb.default({})
});
} else if (!isSmallBuild && e instanceof Error && e.message.toLowerCase().includes("ext_texture_webp")) {
if (alreadyTried["webp"]) throw e; else alreadyTried["webp"] = true;
let {EXTTextureWebP} = await import("@gltf-transform/extensions")
io.registerExtensions([EXTTextureWebP]);
} else { // TODO: Add more extensions as required
throw e;
}
}
}
// Remove any previous model with the same name
await document.transform(dropByName(name));
@@ -31,7 +62,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> {
@@ -87,3 +119,30 @@ function mergeScenes(): Transform {
}
}
}
/** Fetches a URL or reads it if it is a Blob URL */
async function fetchOrRead(url: string | Blob) {
if (url instanceof Blob) {
// Use the FileReader API as fetch does not support Blob URLs
return new Promise<Response>((resolve, reject) => {
const reader = new FileReader();
reader.onloadend = (event: ProgressEvent<FileReader>) => {
if (event.target && event.target.result) {
resolve(new Response(event.target.result));
} else {
reject(new Error("Failed to read Blob URL: " + url));
}
};
reader.onerror = (error) => {
reject(new Error("Error reading Blob URL: " + url + " - " + error));
};
// Read the Blob URL as an ArrayBuffer
reader.readAsArrayBuffer(new Blob([url]));
});
} else {
// Fetch the URL
return retrieveFile(url);
}
}

View File

@@ -82,7 +82,7 @@ export function newAxes(doc: Document, size: Vector3, transform: Matrix4) {
* The grid is built as a box of triangles (representing lines) looking to the inside of the box.
* This ensures that only the back of the grid is always visible, regardless of the camera position.
*/
export async function newGridBox(doc: Document, size: Vector3, baseTransform: Matrix4, divisions = 10) {
export function newGridBox(doc: Document, size: Vector3, baseTransform: Matrix4, divisions = 10) {
// Create transformed positions for the inner faces of the box
let allPositions: number[] = [];
let allIndices: number[] = [];

View File

@@ -2,14 +2,14 @@ import {settings} from "./settings";
const batchTimeout = 250; // ms
class NetworkUpdateEventModel {
export class NetworkUpdateEventModel {
name: string;
url: string;
url: string | Blob;
// TODO: Detect and manage instances of the same object (same hash, different name)
hash: string | null;
isRemove: boolean | null; // This is null for a shutdown event
constructor(name: string, url: string, hash: string | null, isRemove: boolean | null) {
constructor(name: string, url: string | Blob, hash: string | null, isRemove: boolean | null) {
this.name = name;
this.url = url;
this.hash = hash;
@@ -42,18 +42,32 @@ export class NetworkManager extends EventTarget {
*
* Updates will be emitted as "update" events, including the download URL and the model name.
*/
async load(url: string) {
if (url.startsWith("dev+")) {
async load(url: string | Blob) {
if (!(url instanceof Blob) && (url.startsWith("dev+") || url.startsWith("dev "))) {
let baseUrl = new URL(url.slice(4));
baseUrl.searchParams.set("api_updates", "true");
await this.monitorDevServer(baseUrl);
} else {
// Get the last part of the URL as the "name" of the model
let name = url.split("/").pop();
name = name?.split(".")[0] || `unknown-${Math.random()}`;
// Use a head request to get the hash of the file
let response = await fetch(url, {method: "HEAD"});
let hash = response.headers.get("etag");
let name;
let hash = null;
if (url instanceof Blob) {
if (url instanceof File) name = (url as File).name
else name = `blob-${Math.random()}`;
name = name.replace('.glb', '').replace('.gltf', '');
} else {
// If there is a #name parameter in the URL, use it as the name
let urlObj = new URL(url);
let hashParams = new URLSearchParams(urlObj.hash.slice(1));
if (hashParams.has("name")) {
name = hashParams.get("name") || `unknown-${Math.random()}`;
} else { // Default to the last part of the URL as the "name" of the model
name = url.split("/").pop();
}
name = name?.split(".")[0] || `unknown-${Math.random()}`;
// Use a head request to get the hash of the file
let response = await fetch(url, {method: "HEAD"});
hash = response.headers.get("etag");
}
// Only trigger an update if the hash has changed
this.foundModel(name, hash, url, false);
}
@@ -61,6 +75,7 @@ export class NetworkManager extends EventTarget {
private async monitorDevServer(url: URL, stop: () => boolean = () => false) {
while (!stop()) {
let monitorEveryMs = (await settings).monitorEveryMs;
try {
// WARNING: This will spam the console logs with failed requests when the server is down
const controller = new AbortController();
@@ -80,38 +95,60 @@ export class NetworkManager extends EventTarget {
controller.abort(); // Notify the server that we are done
});
}
} else {
// Server is down, wait a little longer before retrying
await new Promise(resolve => setTimeout(resolve, 10 * monitorEveryMs));
}
controller.abort();
} catch (e) { // Ignore errors (retry very soon)
}
await new Promise(resolve => setTimeout(resolve, settings.monitorEveryMs));
await new Promise(resolve => setTimeout(resolve, monitorEveryMs));
}
}
private foundModel(name: string, hash: string | null, url: string, isRemove: boolean | null, disconnect: () => void = () => {
private foundModel(name: string, hash: string | null, url: string | Blob, isRemove: boolean | null, disconnect: () => void = () => {
}) {
let prevHash = this.knownObjectHashes[name];
// console.debug("Found model", name, "with hash", hash, "and previous hash", prevHash);
if (!hash || hash !== prevHash || isRemove) {
// Update known hashes
if (isRemove == false) {
this.knownObjectHashes[name] = hash;
} else if (isRemove == true) {
if (!(name in this.knownObjectHashes)) return; // Nothing to remove...
delete this.knownObjectHashes[name];
// Also update buffered updates if the model is removed
this.bufferedUpdates = this.bufferedUpdates.filter(m => m.name !== name);
}
let newModel = new NetworkUpdateEventModel(name, url, hash, isRemove);
this.bufferedUpdates.push(newModel);
// console.debug("Found model", name, "with hash", hash, "at", url, "isRemove", isRemove);
// Optimization: try to batch updates automatically for faster rendering
if (this.batchTimeout !== null) clearTimeout(this.batchTimeout);
this.batchTimeout = setTimeout(() => {
this.dispatchEvent(new NetworkUpdateEvent(this.bufferedUpdates, disconnect));
this.bufferedUpdates = [];
}, batchTimeout);
}
// We only care about the latest update per model name
this.bufferedUpdates = this.bufferedUpdates.filter(m => m.name !== name);
// Add the new model to the list of updates and dispatch the early update
let upd = new NetworkUpdateEventModel(name, url, hash, isRemove);
this.bufferedUpdates.push(upd);
this.dispatchEvent(new CustomEvent("update-early", {detail: this.bufferedUpdates}));
// Optimization: try to batch updates automatically for faster rendering
if (this.batchTimeout !== null) clearTimeout(this.batchTimeout);
this.batchTimeout = setTimeout(() => {
// Update known hashes for minimal updates
for (let model of this.bufferedUpdates) {
if (model.isRemove == false && model.hash && model.hash === this.knownObjectHashes[model.name]) {
// Delete this useless update
let foundFirst = false;
this.bufferedUpdates = this.bufferedUpdates.filter(m => {
if (m === model) {
if (!foundFirst) { // Remove only first full match
foundFirst = true;
return false;
}
}
return true;
})
} else {
// Keep this update and update the last known hash
if (model.isRemove == true) {
if (model.name in this.knownObjectHashes) delete this.knownObjectHashes[model.name];
} else if (model.isRemove == false) {
this.knownObjectHashes[model.name] = model.hash;
}
}
}
// Dispatch the event to actually update the models
this.dispatchEvent(new NetworkUpdateEvent(this.bufferedUpdates, disconnect));
this.bufferedUpdates = [];
}, batchTimeout);
}
}

View File

@@ -1,5 +1,5 @@
import {type Ref} from 'vue';
import {Document} from '@gltf-transform/core';
import {Buffer, Document, Scene} from '@gltf-transform/core';
import {extrasNameKey, extrasNameValueHelpers, mergeFinalize, mergePartial, removeModel, toBuffer} from "./gltf";
import {newAxes, newGridBox} from "./helpers";
import {Vector3} from "three/src/math/Vector3.js"
@@ -9,45 +9,34 @@ import {Matrix4} from "three/src/math/Matrix4.js"
/** This class helps manage SceneManagerData. All methods are static to support reactivity... */
export class SceneMgr {
/** Loads a GLB model from a URL and adds it to the viewer or replaces it if the names match */
static async loadModel(sceneUrl: Ref<string>, document: Document, name: string, url: string, updateHelpers: boolean = true, reloadScene: boolean = true): Promise<Document> {
static async loadModel(sceneUrl: Ref<string>, document: Document, name: string, url: string | Blob, updateHelpers: boolean = true, reloadScene: boolean = true): Promise<Document> {
let loadStart = performance.now();
let loadNetworkEnd: number;
// Start merging into the current document, replacing or adding as needed
document = await mergePartial(url, name, document, () => loadNetworkEnd = performance.now());
try {
// Start merging into the current document, replacing or adding as needed
document = await mergePartial(url, name, document, () => loadNetworkEnd = performance.now());
console.log("Model", name, "loaded in", performance.now() - loadNetworkEnd!, "ms after",
loadNetworkEnd! - loadStart, "ms of transferring data (maybe building the object on the server)");
console.log("Model", name, "loaded in", performance.now() - loadNetworkEnd!, "ms after",
loadNetworkEnd! - loadStart, "ms of transferring data (maybe building the object on the server)");
} finally {
if (updateHelpers) {
// Reload the helpers to fit the new model
await this.reloadHelpers(sceneUrl, document, reloadScene);
reloadScene = false;
}
if (updateHelpers) {
// Reload the helpers to fit the new model
await this.reloadHelpers(sceneUrl, document, reloadScene);
reloadScene = false;
}
if (reloadScene) {
// Display the final fully loaded model
let displayStart = performance.now();
document = await this.showCurrentDoc(sceneUrl, document);
console.log("Scene displayed in", performance.now() - displayStart, "ms");
if (reloadScene) {
// Display the final fully loaded model
let displayStart = performance.now();
document = await this.showCurrentDoc(sceneUrl, document);
console.log("Scene displayed in", performance.now() - displayStart, "ms");
}
}
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
@@ -89,6 +78,33 @@ 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; // Empty document, no helpers to show
// If only the helpers remain, go back to the empty scene
let noOtherModels = true;
for (let elem of document.getGraph().listEdges().map(e => e.getChild())) {
if (elem.getExtras() && !(elem instanceof Scene) && !(elem instanceof Buffer) &&
elem.getExtras()[extrasNameKey] !== extrasNameValueHelpers) {
// There are other elements in the document, so we can show the helpers
noOtherModels = false;
break;
}
}
if (noOtherModels) return await removeModel(extrasNameValueHelpers, 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)]));
let newDocument = await SceneMgr.loadModel(sceneUrl, document, extrasNameValueHelpers, helpersUrl, false, reloadScene);
URL.revokeObjectURL(helpersUrl);
return newDocument;
}
/** 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
@@ -97,7 +113,8 @@ export class SceneMgr {
// Serialize the document into a GLB and update the viewerSrc
let buffer = await toBuffer(document);
let blob = new Blob([buffer], {type: 'model/gltf-binary'});
console.debug("Showing current doc", document, "as", Array.from(buffer));
console.debug("Showing current doc", document, "with", buffer.length, "total bytes");
if (sceneUrl.value.startsWith("blob:")) URL.revokeObjectURL(sceneUrl.value);
sceneUrl.value = URL.createObjectURL(blob);
return document;

View File

@@ -1,32 +1,115 @@
// These are the default values for the settings, which are overridden below
export const settings = {
preload: [
// @ts-ignore
// new URL('../../assets/fox.glb', import.meta.url).href,
// @ts-ignore
// new URL('../../assets/logo_build/base.glb', import.meta.url).href,
// @ts-ignore
// new URL('../../assets/logo_build/location.glb', import.meta.url).href,
// @ts-ignore
// new URL('../../assets/logo_build/img.jpg.glb', import.meta.url).href,
// Websocket URLs automatically listen for new models from the python backend
"dev+http://127.0.0.1:32323/"
],
loadHelpers: true,
edgeWidth: 0, /* The default line size for edges, set to 0 to use basic gl.LINEs */
displayLoadingEveryMs: 1000, /* How often to display partially loaded models */
monitorEveryMs: 100,
monitorOpenTimeoutMs: 1000,
// ModelViewer settings
autoplay: true,
arModes: 'webxr scene-viewer quick-look',
exposure: 1,
shadowIntensity: 0,
background: '',
}
import {ungzip} from "pako";
import {b64UrlDecode} from "../tools/b64.ts";
import {retrieveFile} from "../tools/upload-file.ts";
const firstTimeNames: Array<string> = []; // Needed for array values, which clear the array when overridden
function parseSetting(name: string, value: string): any {
export const settings = (async () => {
let settings = {
preload: [
// @ts-ignore
// new URL('../../assets/fox.glb', import.meta.url).href,
// @ts-ignore
// new URL('../../assets/logo_build/base.glb', import.meta.url).href,
// @ts-ignore
// new URL('../../assets/logo_build/location.glb', import.meta.url).href,
// @ts-ignore
// new URL('../../assets/logo_build/img.jpg.glb', import.meta.url).href,
// Websocket URLs automatically listen for new models from the python backend
'<auto>', // Get the default preload URL if not overridden
],
loadHelpers: true,
edgeWidth: 0, /* The default line size for edges, set to 0 to use basic gl.LINEs */
displayLoadingEveryMs: 1000, /* How often to display partially loaded models */
monitorEveryMs: 100,
monitorOpenTimeoutMs: 1000,
// ModelViewer settings
autoplay: true, // Global animation toggle
arModes: 'webxr scene-viewer quick-look',
zoomSensitivity: 0.25,
orbitSensitivity: 1,
panSensitivity: 1,
exposure: 1,
shadowIntensity: 0,
// Nice low-res outdoor/high-contrast HDRI image (CC0 licensed) for lighting
environment: new URL('../../assets/qwantani_afternoon_1k_hdr.jpg', import.meta.url).href,
environmentIntensity: 1.0,
// Uniform (1x1 pixel) medium gray background for visibility (following dark/light mode)
skybox: (window.matchMedia("(prefers-color-scheme: dark)").matches ?
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEU4ODiyn42XAAAACklEQVQI" +
"12NgAAAAAgAB4iG8MwAAAABJRU5ErkJggg==" :
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEW6urpaLVq8AAAACklEQVQI" +
"12NgAAAAAgAB4iG8MwAAAABJRU5ErkJggg=="),
// Playground settings
pg_code: "", // Automatically loaded and executed code for the playground
pg_opacity_loading: -1, // Opacity of the code during first load and run (< 0 is 0.0 if preload and 0.9 if not)
pg_opacity_loaded: 0.9, // Opacity of the code after it has been run for the first time
};
// Auto-override any settings from the URL (either GET parameters or hash)
const url = new URL(window.location.href);
url.searchParams.forEach((value, key) => {
if (key in settings) (settings as any)[key] = parseSetting(key, value, settings);
})
if (url.hash.length > 0) { // Hash has bigger limits as it is not sent to the server
const hash = url.hash.slice(1);
const hashParams = new URLSearchParams(hash);
hashParams.forEach((value, key) => {
if (key in settings) (settings as any)[key] = parseSetting(key, value, settings);
});
}
// Get the default preload URL if not overridden (requires a fetch that is avoided if possible)
for (let i = 0; i < settings.preload.length; i++) {
let url = settings.preload[i];
// Ignore empty preload URLs to allow overriding default auto behavior
if (url === '') {
settings.preload = settings.preload.slice(0, i).concat(settings.preload.slice(i + 1));
continue; // Skip this preload URL
}
// Handle special <auto> preload URL
if (url === '<auto>') {
if (settings.pg_code != "") { // <auto> means no preload URL if code is set
settings.preload = settings.preload.slice(0, i).concat(settings.preload.slice(i + 1));
continue; // Skip this preload URL
}
const possibleBackend = new URL("./?api_updates=true", window.location.href)
await fetch(possibleBackend, {method: "HEAD"}).then((response) => {
if (response.ok && response.headers.get("Content-Type") === "text/event-stream") {
// Frontend served by the backend: default to this URL for updates
url = "dev+" + possibleBackend.href;
}
}).catch((error) => console.error("Failed to check for backend:", error));
if (url === '<auto>') { // Fallback to the default preload URL of localhost
url = "dev+http://localhost:32323";
}
}
settings.preload[i] = url;
}
// Auto-decompress the code and other playground settings
if (settings.pg_code.length > 0) {
// pg_code has a few possible formats: URL, base64url+gzipped, or raw code (try them in that order)
try {
new URL(settings.pg_code); // Check if it's a valid absolute URL
settings.pg_code = await (await retrieveFile(settings.pg_code)).text();
} catch (error1) { // Not a valid URL, try base64url+gzipped
try {
settings.pg_code = ungzip(b64UrlDecode(settings.pg_code), {to: 'string'});
} catch (error2) { // Not base64url+gzipped, assume it's raw code
console.log("pg_code is not a URL (", error1, ") or base64url+gzipped (", error2, "), using it as raw code:", settings.pg_code);
}
}
if (settings.pg_opacity_loading < 0) {
// If the opacity is not set, use 0.0 if preload is set, otherwise 0.9
settings.pg_opacity_loading = settings.preload.length > 0 ? 0.0 : 0.9;
}
}
return settings;
})()
function parseSetting(name: string, value: string, settings: any): any {
let arrayElem = name.endsWith(".0")
if (arrayElem) name = name.slice(0, -2);
let prevValue = (settings as any)[name];
@@ -39,7 +122,7 @@ function parseSetting(name: string, value: string): any {
} else {
toExtend = prevValue;
}
toExtend.push(parseSetting(name + ".0", value));
toExtend.push(parseSetting(name + ".0", value, settings));
return toExtend;
} else {
prevValue = prevValue[0];
@@ -56,9 +139,3 @@ function parseSetting(name: string, value: string): any {
throw new Error(`Unknown setting type: ${typeof prevValue} -- ${prevValue}`);
}
}
// Auto-override any settings from the URL
const url = new URL(window.location.href);
url.searchParams.forEach((value, key) => {
if (key in settings) (settings as any)[key] = parseSetting(key, value);
})

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,
@@ -25,6 +25,7 @@ import {
mdiVectorLine,
mdiVectorRectangle
} from '@mdi/js'
// @ts-expect-error
import SvgIcon from '@jamescoyle/vue-icon';
import {BackSide, FrontSide} from "three/src/constants.js";
import {Box3} from "three/src/math/Box3.js";
@@ -33,7 +34,9 @@ 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"
import {currentSceneRotation} from "../viewer/lighting.ts";
import {Matrix4} from "three/src/math/Matrix4.js";
const props = defineProps<{
meshes: Array<Mesh>,
@@ -43,10 +46,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);
@@ -54,26 +58,16 @@ const clipPlaneY = ref(1);
const clipPlaneSwappedY = ref(false);
const clipPlaneZ = ref(1);
const clipPlaneSwappedZ = ref(false);
const edgeWidth = ref(settings.edgeWidth);
const edgeWidth = ref(0);
(async () => {
let s = await settings;
edgeWidth.value = s.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 +75,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 +92,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,13 +116,10 @@ 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) {
let childIsFace = child.type == 'Mesh' || child.type == 'SkinnedMesh'
if (child.material && child.material.wireframe !== newWireframe && childIsFace) {
child.material.wireframe = newWireframe;
child.material.needsUpdate = true;
}
@@ -146,8 +130,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;
@@ -175,10 +157,11 @@ function onClipPlanesChange() {
let offsetX = bbox.min.x + clipPlaneX.value * (bbox.max.x - bbox.min.x);
let offsetY = bbox.min.y + clipPlaneY.value * (bbox.max.y - bbox.min.y);
let offsetZ = bbox.min.z + (1 - clipPlaneZ.value) * (bbox.max.z - bbox.min.z);
let rotSceneMatrix = new Matrix4().makeRotationY(currentSceneRotation);
let planes = [
new Plane(new Vector3(-1, 0, 0), offsetX),
new Plane(new Vector3(0, -1, 0), offsetY),
new Plane(new Vector3(0, 0, 1), -offsetZ),
new Plane(new Vector3(-1, 0, 0), offsetX).applyMatrix4(rotSceneMatrix),
new Plane(new Vector3(0, -1, 0), offsetY).applyMatrix4(rotSceneMatrix),
new Plane(new Vector3(0, 0, 1), -offsetZ).applyMatrix4(rotSceneMatrix),
];
if (clipPlaneSwappedX.value) planes[0].negate();
if (clipPlaneSwappedY.value) planes[1].negate();
@@ -204,8 +187,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>;
@@ -251,9 +232,10 @@ function onEdgeWidthChange(newEdgeWidth: number) {
line.userData.niceLine = line2;
// line.parent!.remove(line); // Keep it for better raycast and selection!
line2.userData.noHit = true;
line2.visible = enabledFeatures.value.includes(1);
edgeWidthChangeCleanup.push(() => {
line2.parent!.remove(line2);
line.visible = true;
line.visible = enabledFeatures.value.includes(1);
props.viewer!!.onElemReady((elem) => {
elem.removeEventListener('resize', () => resizeListener(elem));
});
@@ -268,11 +250,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 +326,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>
<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>
@@ -423,10 +436,6 @@ props.viewer!!.onElemReady((elem) => elem.addEventListener('load', onModelLoad))
}
/* More compact accordions */
.v-expansion-panel {
margin-top: 0 !important;
}
.v-expansion-panel-title {
padding: 0;
}
@@ -437,15 +446,16 @@ props.viewer!!.onElemReady((elem) => elem.addEventListener('load', onModelLoad))
}
.v-btn {
--v-btn-height: 16px;
--v-btn-height: 12px;
}
.model-name {
width: 130px;
min-height: 1.15em; /* HACK: Avoid eating the bottom of the text when using 1 line */
max-height: 2em;
width: 172px;
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;
@@ -457,10 +467,6 @@ props.viewer!!.onElemReady((elem) => elem.addEventListener('load', onModelLoad))
padding: 0 !important;
}
.hide-this-icon {
display: none !important;
}
.mdi-checkbox-blank-outline { /* HACK: mdi is not fully imported, only required icons... */
background-image: url('data:image/svg+xml;charset=UTF-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white"><path d="M19,3H5C3.89,3 3,3.89 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5C21,3.89 20.1,3 19,3M19,5V19H5V5H19Z"/></svg>');
}

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";
@@ -7,11 +7,11 @@ import Model from "./Model.vue";
import {inject, ref, type Ref} from "vue";
const props = defineProps<{ viewer: InstanceType<typeof ModelViewerWrapper> | null }>();
const emit = defineEmits<{ remove: [string] }>()
const emit = defineEmits<{ removeModel: [string] }>()
let {sceneDocument} = inject<{ sceneDocument: Ref<Document> }>('sceneDocument')!!;
let expandedNames = ref<Array<string>>([]);
const expandedNames = ref<Array<string>>([]);
function meshesList(sceneDocument: Document): Array<Array<Mesh>> {
// Grouped by shared name
@@ -32,13 +32,11 @@ function meshName(mesh: Mesh) {
}
function onRemove(mesh: Mesh) {
emit('remove', meshName(mesh))
emit('removeModel', meshName(mesh))
}
function findModel(name: string) {
console.log('Find model', name);
if (!expandedNames.value.includes(name)) expandedNames.value.push(name);
console.log('Expanded', expandedNames.value);
}
defineExpose({findModel})
@@ -46,7 +44,7 @@ defineExpose({findModel})
<template>
<v-expansion-panels v-for="meshes in meshesList(sceneDocument)" :key="meshName(meshes[0])"
v-model="expandedNames" multiple>
v-model="expandedNames as any" multiple>
<model :meshes="meshes" :viewer="props.viewer" @remove="onRemove(meshes[0])"/>
</v-expansion-panels>
</template>
@@ -63,4 +61,4 @@ defineExpose({findModel})
.v-overlay--active > .v-overlay__content {
display: block !important; /* HACK: Fix buggy tooltips not showing? */
}
</style>
</style>

3
frontend/shims.d.ts vendored
View File

@@ -1,3 +0,0 @@
// Avoids typescript error when importing some files
declare module '@jamescoyle/vue-icon'
declare module 'three-orientation-gizmo/src/OrientationGizmo'

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,27 +1,32 @@
<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";
// @ts-expect-error
import * as OrientationGizmoRaw from "three-orientation-gizmo/src/OrientationGizmo";
import type {ModelViewerElement} from '@google/model-viewer';
import type ModelViewerWrapper from "../viewer/ModelViewerWrapper.vue";
import {currentSceneRotation} from "../viewer/lighting.ts";
// Optimized minimal dependencies from three
import {Vector3} from "three/src/math/Vector3.js";
import {Matrix4} from "three/src/math/Matrix4.js";
import {Euler} from "three/src/math/Euler.js";
(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
let gizmo = new OrientationGizmoRaw.default(scene.camera, {
size: expectedParent.clientWidth,
bubbleSizePrimary: expectedParent.clientWidth / 12,
bubbleSizeSeconday: expectedParent.clientWidth / 14,
fontSize: (expectedParent.clientWidth / 10) + "px"
bubbleSizeSeconday: expectedParent.clientWidth / 12,
fontSize: (expectedParent.clientWidth / 10) + "px",
});
// Make sure all bubbles are labeled
for (let bubble of gizmo.bubbles) {
bubble.label = bubble.axis.toUpperCase();
}
// HACK: Swap axes to fake the CAD orientation
for (let swap of [["y", "-z"], ["z", "-y"], ["z", "-z"]]) {
let indexA = gizmo.bubbles.findIndex((bubble: any) => bubble.axis == swap[0])
@@ -33,21 +38,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) + currentSceneRotation;
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;
}
@@ -59,15 +69,20 @@ let gizmo: HTMLElement & { update: () => void }
function updateGizmo() {
if (gizmo.isConnected) {
// HACK: Update camera temporarily to match skybox rotation before updating the gizmo and go back
let prevRot = ((gizmo as any).camera).rotation.clone() as Euler;
let thetaMat = new Matrix4().makeRotationY(-currentSceneRotation);
((gizmo as any).camera).rotation.setFromRotationMatrix(thetaMat.multiply(new Matrix4().makeRotationFromEuler(prevRot)));
gizmo.update();
((gizmo as any).camera).rotation.set(prevRot.x, prevRot.y, prevRot.z);
requestIdleCallback(updateGizmo, {timeout: 250});
}
}
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

@@ -0,0 +1,404 @@
<script setup lang="ts">
import {setupMonaco} from "./monaco.ts";
import {VueMonacoEditor} from '@guolao/vue-monaco-editor'
import {nextTick, onMounted, ref, shallowRef} from "vue";
import Loading from "../misc/Loading.vue";
import {newPyodideWorker} from "./pyodide-worker-api.ts";
import {
mdiBroom,
mdiCircleOpacity,
mdiClose,
mdiContentSave,
mdiFolderOpen,
mdiPlay,
mdiReload,
mdiShare,
mdiUpload
} from "@mdi/js";
import {VBtn, VCard, VCardText, VSlider, VSpacer, VToolbar, VToolbarTitle, VTooltip} from "vuetify/components";
// @ts-expect-error
import SvgIcon from '@jamescoyle/vue-icon';
import {version as pyodideVersion} from "pyodide";
import {gzip} from 'pako';
import {b64UrlEncode} from "./b64.ts";
import {Base64} from 'js-base64'; // More compatible with binary data from python...
import {NetworkUpdateEvent, NetworkUpdateEventModel} from "../misc/network.ts";
import {settings} from "../misc/settings.ts";
// @ts-expect-error
import playgroundStartupCode from './PlaygroundStartup.py?raw';
import {uploadFile} from "./upload-file.ts";
const model = defineModel<{ code: string, firstTime: boolean }>({required: true}); // Initial code should only be set on first load!
const emit = defineEmits<{ close: [], updateModel: [NetworkUpdateEvent] }>()
// ============ LOAD MONACO EDITOR ============
setupMonaco() // Must be called before using the editor
const outputText = ref(``);
function output(text: string) {
outputText.value += text; // Append to output
// Avoid too much output, keep it reasonable
let max_output = 10000; // 10k characters
if (outputText.value.length > max_output) {
outputText.value = outputText.value.slice(-max_output); // Keep only the last 10k characters
}
console.log(text); // Also log to console
nextTick(() => { // Scroll to bottom
const consoleElement = document.querySelector('.playground-console');
if (consoleElement) {
consoleElement.scrollTop = consoleElement.scrollHeight;
}
})
}
const MONACO_EDITOR_OPTIONS = {
automaticLayout: true,
formatOnType: true,
formatOnPaste: true,
}
const editorTheme = window.matchMedia("(prefers-color-scheme: dark)").matches ? `vs-dark` : `vs`
const editor = shallowRef()
const handleMount = (editorInstance: typeof VueMonacoEditor) => (editor.value = editorInstance)
const opacity = ref(0.9); // Opacity for the editor (overriden when settings are loaded)
// ============ LOAD PYODIDE (ASYNC) ============
let pyodideWorker: ReturnType<typeof newPyodideWorker> | null = (import.meta as any).hot?.data?.pyodideWorker || null;
const running = ref(true);
async function setupPyodide(first: boolean, loadSnapshot: Uint8Array | undefined = undefined) {
running.value = true;
if (opacity.value == 0.0 && !first) opacity.value = 0.9; // User doesn't know how to show code again, reset after reopening
if (pyodideWorker === null) {
output("Creating new Pyodide worker...\n");
pyodideWorker = newPyodideWorker(Object.assign({
// Note: python wheels are downloaded from the CDN, as we can't know which ones are needed in advance to bundle them
// Furthermore, this lets us use the latest version of all wheels including ocp-specific ones without app updates
indexURL: `https://cdn.jsdelivr.net/pyodide/v${pyodideVersion}/full/`,
packages: ["micropip", "sqlite3"], // Faster load if done here
// _makeSnapshot: true, // Enable snapshotting for faster startup (still experimental: breaks loading any packages)
}, (loadSnapshot ? {_loadSnapshot: loadSnapshot} : {}))); // Load snapshot if provided
if ((import.meta as any).hot) (import.meta as any).hot.data.pyodideWorker = pyodideWorker
} else {
output("Reusing existing Pyodide instance...\n");
}
output("Preloading packages...\n");
await pyodideWorker.asyncRun(playgroundStartupCode, output, output); // Also import yacv_server and mock ocp_vscode here for faster custom code execution
running.value = false; // Indicate that Pyodide is ready
output("Pyodide worker ready.\n");
}
async function runCode() {
if (pyodideWorker === null) {
output("Pyodide worker is not initialized. Please wait...\n");
return;
}
if (running.value) {
output("Pyodide is already running. Please wait...\n");
return;
}
output("Running code...\n");
try {
running.value = true;
await pyodideWorker.asyncRun(model.value.code, output, (msg: string) => {
// Detect models printed to console (since http server is not available in pyodide)
if (msg.startsWith(yacvServerModelPrefix)) {
const modelData = msg.slice(yacvServerModelPrefix.length);
onModelData(modelData);
} else {
output(msg); // Print other messages directly
}
});
} catch (e) {
output(`Error running code: ${e}\n`);
} finally {
output("Code execution finished.\n");
running.value = false; // Indicate that Pyodide is ready
}
}
const yacvServerModelPrefix = "yacv_server://model/";
function onModelData(modelData: string) {
output(`Model data detected... ${modelData.length}B\n`);
// Decode the model data and emit the event for the interface to handle
// - Start by finding the end of the initial json object by looking for brackets.
let i = 0;
let openBrackets = 0;
for (; i < modelData.length; i++) {
if (modelData[i] === '{') openBrackets++;
else if (modelData[i] === '}') openBrackets--;
if (openBrackets === 0) break; // Found the end of the JSON object
}
if (openBrackets !== 0) throw `Error: Invalid model data received: ${modelData}\n`
const jsonData = modelData.slice(0, i + 1); // Extract the JSON part and parse it into the proper class
let modelMetadataRaw = JSON.parse(jsonData);
const modelMetadata: any = new NetworkUpdateEventModel(modelMetadataRaw.name, "", modelMetadataRaw.hash, modelMetadataRaw.is_remove)
// console.debug(`Model metadata:`, modelMetadata);
output(`Model metadata: ${JSON.stringify(modelMetadata)}\n`);
// - Now decode the rest of the model data which is a single base64 encoded glb file (or an empty string)
if (!modelMetadata.isRemove) {
const binaryData = Base64.toUint8Array(modelData.slice(i + 1)); // Extract the base64 part
console.assert(binaryData.slice(0, 4).toString() == "103,108,84,70", // Ugly...
"Invalid GLTF binary data received: " + binaryData.slice(0, 4).toString());
// - Save for upload and share link feature
builtModelsGlb[modelMetadata.name] = binaryData;
// - Create a Blob from the binary data to be used as a URL
const blob = new Blob([binaryData], {type: 'model/gltf-binary'});
modelMetadata.url = URL.createObjectURL(blob); // Set the hacked URL in the model metadata XXX: revoked on App.vue
} else {
delete builtModelsGlb[modelMetadata.name]; // Remove from built models if it's a remove request
}
// - Emit the event with the model metadata and URL
let networkUpdateEvent = new NetworkUpdateEvent([modelMetadata], () => {
});
emit('updateModel', networkUpdateEvent);
}
function resetWorker(loadSnapshot: Uint8Array | undefined = undefined) {
if (pyodideWorker) {
pyodideWorker.terminate(); // Terminate existing worker
pyodideWorker = null; // Reset worker reference
}
outputText.value = ``; // Clear output text
setupPyodide(false, loadSnapshot); // Reinitialize Pyodide
}
function shareLinkCommon(added: Record<string, string>, forgotten: Array<string>) {
const baseUrl = window.location
const searchParams = new URLSearchParams(baseUrl.search);
for (const k of forgotten) searchParams.delete(k);
const hashParams = new URLSearchParams(baseUrl.hash.slice(1)); // Keep all previous URL parameters
for (const k of forgotten) hashParams.delete(k);
for (const k in added) hashParams.append(k, added[k]); // Prefer hash to GET
const shareUrl = `${baseUrl.origin}${baseUrl.pathname}?${searchParams}#${hashParams}`;
output(`Share link ready: ${shareUrl}\n`)
if (navigator.clipboard?.writeText === undefined) {
output("Clipboard API not available. Please copy the link manually.\n");
return;
} else {
navigator.clipboard.writeText(shareUrl)
.then(() => output("Link copied to clipboard!\n"))
.catch(err => output(`Failed to copy link: ${err}\n`));
}
}
function shareLink() {
shareLinkCommon({'pg_code': b64UrlEncode(gzip(model.value.code, {level: 9}))}, ['pg_code']);
}
const builtModelsGlb: Record<string, Uint8Array> = {}; // Store built models to support uploading
async function uploadAndShareLink() {
try {
output("Uploading files...\n");
// Upload code.py
const codeBlob = new Blob([model.value.code], {type: 'text/x-python'});
const newParams: Record<string, string> = {
'pg_code': await uploadFile('code.py', new Uint8Array(await codeBlob.arrayBuffer()))
};
// Upload all models
for (const name in builtModelsGlb) {
const glb: any = builtModelsGlb[name];
newParams['preload'] = await uploadFile(name + '.glb', glb);
}
// Build share URL
return shareLinkCommon(newParams, ['pg_code'])
} catch (e) {
output(`Error uploading/sharing files: ${e}. Falling back to private share link.\n`);
return shareLink(); // Fallback to private share link if upload fails
}
}
function saveSnapshot() {
throw new Error("Not implemented yet!"); // TODO: Implement snapshot saving
}
function loadSnapshot() {
throw new Error("Not implemented yet!"); // TODO: Implement snapshot loading
}
(async () => {
const sett = await settings
if (model.value.firstTime) opacity.value = sett.pg_opacity_loading
await setupPyodide(true);
if (model.value.firstTime) {
await runCode();
opacity.value = sett.pg_opacity_loaded
model.value.firstTime = false
}
})()
// Add keyboard shortcuts
const editorRef = ref<HTMLElement | null>(null);
onMounted(() => {
if (editorRef.value) {
editorRef.value.addEventListener('keydown', (event: Event) => {
if (!(event instanceof KeyboardEvent)) return; // Ensure event is a KeyboardEvent
if (event.key === 'F10') { // Run code on F10
event.preventDefault(); // Prevent default behavior of the key
runCode();
} else if (event.key === 'Escape') { // Close on Escape key
emit('close');
}
});
}
});
</script>
<template>
<v-card class="popup-card"
:style="opacity == 0 ? `position: absolute; top: calc(-50vh + 24px); width: calc(100vw - 64px);` : ``">
<v-toolbar class="popup">
<v-toolbar-title style="flex: 0 1 auto">Playground</v-toolbar-title>
<v-spacer></v-spacer>
<span style="display: inline-flex; margin-right: 16px;">
<svg-icon :path="mdiCircleOpacity" type="mdi" style="height: 32px"></svg-icon>
<v-slider v-model="opacity" :max="1" :min="0" :step="0.1"
style="width: 100px; height: 32px">
</v-slider>
<v-tooltip activator="parent"
location="bottom">Opacity of the editor (0 = hidden, 1 = fully visible)</v-tooltip>
</span>
<span style="padding-left: 12px; width: 48px;"><!-- This span is only needed to force tooltip to work while button is disabled -->
<v-btn icon disabled @click="saveSnapshot()">
<svg-icon :path="mdiContentSave" type="mdi"/>
</v-btn>
<v-tooltip activator="parent"
location="bottom">Save current state to a snapshot for fast startup (WIP)</v-tooltip>
</span>
<span style="padding-right: 12px; width: 48px;"><!-- This span is only needed to force tooltip to work while button is disabled -->
<v-btn icon disabled @click="loadSnapshot()">
<svg-icon :path="mdiFolderOpen" type="mdi"/>
</v-btn>
<v-tooltip activator="parent" location="bottom">Load snapshot for fast startup (WIP)</v-tooltip>
</span>
<v-btn icon @click="shareLink()" style="padding-left: 12px;">
<svg-icon :path="mdiShare" type="mdi"/>
<v-tooltip activator="parent" location="bottom">Share link that automatically runs the code.<br/>Only people
with the link can see the code.
</v-tooltip>
</v-btn>
<v-btn icon @click="uploadAndShareLink()" style="padding-right: 12px">
<svg-icon :path="mdiShare" type="mdi" style="position: absolute; scale: 75%; top: 6px;"/>
<svg-icon :path="mdiUpload" type="mdi" style="position: absolute; scale: 75%; bottom: 6px;"/>
<v-tooltip activator="parent" location="bottom">Uploads all models and code and then shares a link to them.<br/>Useful
to view the models while the playground loads, but uses third-party storage.
</v-tooltip>
</v-btn>
<v-btn icon @click="resetWorker()" style="padding-left: 12px;">
<svg-icon :path="mdiReload" type="mdi"/>
<v-tooltip activator="parent" location="bottom">Reset Pyodide worker (this forgets all previous state and will
take a little while)
</v-tooltip>
</v-btn>
<v-btn icon @click="runCode()" :disabled="running" style="padding-right: 12px">
<svg-icon :path="mdiPlay" type="mdi"/>
<Loading v-if="running" style="position: absolute; top: -16%; left: -28%"/><!-- Ugly positioning -->
<v-tooltip activator="parent" location="bottom">Run code</v-tooltip>
</v-btn>
<v-btn icon @click="emit('close')">
<svg-icon :path="mdiClose" type="mdi"/>
<v-tooltip activator="parent" location="bottom">Close (Pyodide remains loaded)</v-tooltip>
</v-btn>
</v-toolbar>
<v-card-text class="popup-card-text" :style="opacity == 0 ? `display: none` : ``">
<!-- Only show content if opacity is greater than 0 -->
<div class="playground-container">
<div class="playground-editor" ref="editorRef">
<VueMonacoEditor v-model:value="model.code" :theme="editorTheme" :options="MONACO_EDITOR_OPTIONS"
language="python" @mount="handleMount"/>
</div>
<div class="playground-console">
<h3 style="display:flex; align-items: center; justify-content: space-between; margin: 0;">
Console Output
<v-spacer></v-spacer>
<v-btn @click="outputText = ''">
<svg-icon :path="mdiBroom" type="mdi" class="h-"/>
</v-btn>
</h3>
<pre>{{ outputText }}</pre> <!-- Placeholder for console output -->
<Loading v-if="running"/>
</div>
</div>
</v-card-text>
</v-card>
</template>
<style scoped>
.popup-card {
background-color: #00000000; /* Transparent background */
}
.v-toolbar.popup > * {
overflow-x: auto;
}
.popup-card-text {
background-color: #1e1e1e; /* Matches the Monaco editor background */
opacity: v-bind(opacity);
}
.playground-container {
display: flex;
flex-direction: row;
}
.playground-editor {
flex: 1;
height: calc(100vh - 150px);
}
.playground-console {
flex: 0.5;
padding: 10px;
overflow-y: auto;
min-width: 100px;
height: calc(100vh - 150px);
}
.playground-console pre {
margin: 0;
white-space: pre-wrap;
word-break: break-all;
}
@media (min-height: 100vw) {
/* Adjust layout for vertical space */
.playground-container {
flex-direction: column;
}
.playground-editor {
flex: 1;
min-height: 60vh;
}
.playground-editor > * {
min-height: 60vh;
}
.playground-console {
max-height: calc(40vh - 150px);
}
}
/* TODO: Adjust more colors on bright mode */
</style>
<style>
/* https://stackoverflow.com/questions/47017753/monaco-editor-dynamically-resizable/71876526#71876526 */
.monaco-editor {
position: absolute !important;
}
</style>

View File

@@ -0,0 +1,24 @@
import micropip
# Prioritize the OCP.wasm package repository for finding the ported dependencies.
micropip.set_index_urls(["https://yeicor.github.io/OCP.wasm", "https://pypi.org/simple"])
# For build123d < 0.10.0, we need to install the mock the py-lib3mf package (before the main install).
await micropip.install("lib3mf")
micropip.add_mock_package("py-lib3mf", "2.4.1", modules={"py_lib3mf": 'from lib3mf import *'})
# Install the yacv_server package, which is the main server for the OCP.wasm playground; and also preinstalls build123d.
await micropip.install("yacv_server", pre=True)
# Preimport the yacv_server package to ensure it is available in the global scope, and mock the ocp_vscode package.
from yacv_server import *
micropip.add_mock_package("ocp-vscode", "2.8.9", modules={"ocp_vscode": 'from yacv_server import *'})
show_object = show
# Preinstall the font-fetcher package and install its hook to automatically download any requested font.
await micropip.install("font-fetcher", pre=True)
from font_fetcher.ocp import install_ocp_font_hook
install_ocp_font_hook()

View File

@@ -1,6 +1,7 @@
<script setup lang="ts">
import {defineModel, inject, ref, type ShallowRef, watch} from "vue";
<script lang="ts" setup>
import {inject, ref, type ShallowRef, watch} from "vue";
import {VBtn, VSelect, VTooltip} from "vuetify/lib/components/index.mjs";
// @ts-expect-error
import SvgIcon from '@jamescoyle/vue-icon';
import type {ModelViewerElement} from '@google/model-viewer';
import type {ModelScene} from "@google/model-viewer/lib/three-components/ModelScene";
@@ -28,26 +29,28 @@ let emit = defineEmits<{ findModel: [string] }>();
let {setDisableTap} = inject<{ setDisableTap: (arg0: boolean) => void }>('disableTap')!!;
let selectionEnabled = ref(false);
let selected = defineModel<Array<SelectionInfo>>({default: []});
let highlightNextSelection = ref([false, false]); // Second is whether selection was enabled before
let openNextSelection = ref([false, false]); // Second is whether selection was enabled before
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;
}
}
@@ -147,7 +150,7 @@ let selectionListener = (event: MouseEvent) => {
// Return the best hit
[0] as Intersection<MObject3D> | undefined;
if (!highlightNextSelection.value[0]) {
if (!openNextSelection.value[0]) {
// If we are selecting, toggle the selection or deselect all if no hit
let selInfo: SelectionInfo | null = null;
if (hit) selInfo = hitToSelectionInfo(hit);
@@ -169,7 +172,7 @@ let selectionListener = (event: MouseEvent) => {
// Otherwise, highlight the model that owns the hit
emit('findModel', hit.object.userData[extrasNameKey])
// And reset the selection mode
toggleHighlightNextSelection()
toggleOpenNextSelection()
}
scene.queueRender() // Force rerender of model-viewer
}
@@ -207,17 +210,17 @@ function toggleSelection() {
setDisableTap(selectionEnabled.value);
}
function toggleHighlightNextSelection() {
highlightNextSelection.value = [
!highlightNextSelection.value[0],
highlightNextSelection.value[0] ? highlightNextSelection.value[1] : selectionEnabled.value
function toggleOpenNextSelection() {
openNextSelection.value = [
!openNextSelection.value[0],
openNextSelection.value[0] ? openNextSelection.value[1] : selectionEnabled.value
];
if (highlightNextSelection.value[0]) {
if (openNextSelection.value[0]) {
// Reuse selection code to identify the model
if (!selectionEnabled.value) toggleSelection()
} else {
if (selectionEnabled.value !== highlightNextSelection.value[1]) toggleSelection()
highlightNextSelection.value = [false, false];
if (selectionEnabled.value !== openNextSelection.value[1]) toggleSelection()
openNextSelection.value = [false, false];
}
}
@@ -254,14 +257,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);
@@ -316,7 +334,7 @@ function updateBoundingBox() {
for (let i = 0; i < 2; i++) { // Find the 2nd closest one by running twice dropping the first
edge = axisEdges[0];
let edgeDist = Infinity;
let cameraPos: Vector3 = props.viewer?.scene.camera.position;
let cameraPos: Vector3 = props.viewer?.scene?.camera?.position ?? new Vector3();
for (let testEdge of axisEdges) {
let from = new Vector3(...corners[testEdge[0]]);
let to = new Vector3(...corners[testEdge[1]]);
@@ -406,8 +424,14 @@ function updateDistances() {
return;
}
defineExpose({deselect, updateBoundingBox, updateDistances});
// Add keyboard shortcuts
window.addEventListener('keydown', (event) => {
if ((event.target as any)?.tagName && ((event.target as any).tagName === 'INPUT' || (event.target as any).tagName === 'TEXTAREA')) {
// Ignore key events when an input is focused, except for text inputs
return;
}
if (event.key === 's') {
if (selectFilter.value == 'Any (S)') toggleSelection();
else {
@@ -436,59 +460,48 @@ window.addEventListener('keydown', (event) => {
toggleShowBoundingBox();
} else if (event.key === 'd') {
toggleShowDistances();
} else if (event.key === 'h') {
toggleHighlightNextSelection();
} else if (event.key === 'o') {
toggleOpenNextSelection();
}
});
</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="openNextSelection[0] ? 'surface-light' : ''" icon @click="toggleOpenNextSelection">
<v-tooltip activator="parent">(O)pen 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,
@@ -13,14 +13,26 @@ import {
import OrientationGizmo from "./OrientationGizmo.vue";
import type {PerspectiveCamera} from "three/src/cameras/PerspectiveCamera.js";
import {OrthographicCamera} from "three/src/cameras/OrthographicCamera.js";
import {mdiClose, mdiCrosshairsGps, mdiDownload, mdiGithub, mdiLicense, mdiProjector} from '@mdi/js'
import {
mdiClose,
mdiCrosshairsGps,
mdiDownload,
mdiGithub,
mdiLicense,
mdiLightbulb,
mdiProjector,
mdiScriptTextPlay
} from '@mdi/js'
// @ts-expect-error
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} from "vue";
import type {SelectionInfo} from "./selection";
import {settings} from "../misc/settings.ts";
import type {NetworkUpdateEvent} from "../misc/network.ts";
import IfNotSmallBuild from "../misc/IfNotSmallBuild.vue";
const SelectionComponent = defineAsyncComponent({
loader: () => import("./Selection.vue"),
@@ -35,11 +47,26 @@ const LicensesDialogContent = defineAsyncComponent({
delay: 0,
});
const PlaygroundDialogContent = defineAsyncComponent({
loader: () => import("./PlaygroundDialogContent.vue"),
loadingComponent: Loading,
delay: 0,
});
let props = defineProps<{ viewer: InstanceType<typeof ModelViewerWrapper> | null }>();
const emit = defineEmits<{ findModel: [string] }>()
const emit = defineEmits<{ findModel: [string], updateModel: [NetworkUpdateEvent] }>()
let selection: Ref<Array<SelectionInfo>> = ref([]);
const sett = ref<any | null>(null);
const showPlaygroundDialog = ref(false);
const pg_model = ref({code: '# Loading...', firstTime: false});
(async () => {
sett.value = await settings;
pg_model.value = {code: sett.value.pg_code, firstTime: true};
showPlaygroundDialog.value = pg_model.value.code != "";
})();
let selection = ref<Array<SelectionInfo>>([]);
let selectionFaceCount = () => selection.value.filter((s) => s.kind == 'face').length
let selectionEdgeCount = () => selection.value.filter((s) => s.kind == 'edge').length
let selectionVertexCount = () => selection.value.filter((s) => s.kind == "vertex").length
@@ -57,14 +84,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 +106,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
}
@@ -101,15 +128,29 @@ async function downloadSceneGlb() {
link.download = file.name;
link.href = URL.createObjectURL(file);
link.click();
URL.revokeObjectURL(link.href);
}
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, openPlayground: () => showPlaygroundDialog.value = true});
// Add keyboard shortcuts
window.addEventListener('keydown', (event) => {
document.addEventListener('keydown', (event) => {
if ((event.target as any)?.tagName && ((event.target as any).tagName === 'INPUT' || (event.target as any).tagName === 'TEXTAREA')) {
// Ignore key events when an input is focused, except for text inputs
return;
}
if (event.key === 'p') toggleProjection();
else if (event.key === 'c') centerCamera();
else if (event.key === 'd') downloadSceneGlb();
@@ -118,45 +159,66 @@ 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>
<span>
<v-tooltip activator="parent">To rotate the light hold shift and drag the mouse or use two fingers<br/>
Note that this breaks slightly clipping planes for now... (restart to fix)</v-tooltip>
<v-btn icon disabled style="background: black;">
<svg-icon :path="mdiLightbulb" type="mdi"/>
</v-btn>
</span>
<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"
@findModel="(name) => emit('findModel', name)"/>
<selection-component ref="selectionComp" v-model="selection" :viewer="props.viewer as any"
@findModel="(name: string) => 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"/>
</v-btn>
<v-dialog id="licenses-dialog" fullscreen>
<v-dialog v-model="showPlaygroundDialog" persistent :scrim="false" attach="body">
<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"/>
<v-btn v-bind="props" style="width: 100%">
<v-tooltip activator="parent">Open a python editor and build models directly in the browser!</v-tooltip>
<svg-icon :path="mdiScriptTextPlay" type="mdi"/>
&nbsp;Sandbox
</v-btn>
</template>
<template v-slot:default="{ isActive }">
<v-card>
<v-toolbar>
<if-not-small-build>
<playground-dialog-content v-if="sett != null" v-model="pg_model" @close="isActive.value = false"
@update-model="(event: NetworkUpdateEvent) => emit('updateModel', event)"/>
</if-not-small-build>
</template>
</v-dialog>
<v-btn icon @click="downloadSceneGlb">
<v-tooltip activator="parent">(D)ownload Scene</v-tooltip>
<svg-icon :path="mdiDownload" type="mdi"/>
</v-btn>
<v-dialog>
<template v-slot:activator="{ props }">
<v-btn icon v-bind="props">
<v-tooltip activator="parent">Show Licenses</v-tooltip>
<svg-icon :path="mdiLicense" type="mdi"/>
</v-btn>
</template>
<template v-slot:default="{ isActive }">
<v-card style="height: 90vh">
<v-toolbar class="popup">
<v-toolbar-title>Licenses</v-toolbar-title>
<v-spacer>
</v-spacer>
<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 +229,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 +249,21 @@ window.addEventListener('keydown', (event) => {
position: relative;
top: 5px;
}
</style>
h5 {
font-size: 14px;
}
.v-toolbar {
position: sticky !important;
top: 0;
}
.v-toolbar.popup {
height: 32px;
}
.v-toolbar.popup > div {
height: 32px !important;
}
</style>

21
frontend/tools/b64.ts Normal file
View File

@@ -0,0 +1,21 @@
export function b64UrlEncode(data: Uint8Array): string {
const base64 = btoa(String.fromCharCode(...data));
return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
}
export function b64UrlDecode(encoded: string): Uint8Array {
// Replace URL-safe characters with standard base64 characters
let base64 = encoded.replace(/-/g, '+').replace(/_/g, '/');
// Add padding if necessary
const padding = base64.length % 4;
if (padding) {
base64 += '='.repeat(4 - padding);
}
// Decode the base64 string to a byte array
const binaryString = atob(base64);
const byteArray = new Uint8Array(binaryString.length);
for (let i = 0; i < binaryString.length; i++) {
byteArray[i] = binaryString.charCodeAt(i);
}
return byteArray;
}

35
frontend/tools/monaco.ts Normal file
View File

@@ -0,0 +1,35 @@
import {loader} from "@guolao/vue-monaco-editor"
import * as monaco from "monaco-editor"
//@ts-ignore
import editorWorker from "monaco-editor/esm/vs/editor/editor.worker?worker"
//@ts-ignore
import jsonWorker from "monaco-editor/esm/vs/language/json/json.worker?worker"
//@ts-ignore
import cssWorker from "monaco-editor/esm/vs/language/css/css.worker?worker"
//@ts-ignore
import htmlWorker from "monaco-editor/esm/vs/language/html/html.worker?worker"
//@ts-ignore
import tsWorker from "monaco-editor/esm/vs/language/typescript/ts.worker?worker"
self.MonacoEnvironment = {
getWorker(_, label) {
if (label === "json") {
return new jsonWorker()
}
if (label === "css" || label === "scss" || label === "less") {
return new cssWorker()
}
if (label === "html" || label === "handlebars" || label === "razor") {
return new htmlWorker()
}
if (label === "typescript" || label === "javascript") {
return new tsWorker()
}
return new editorWorker()
}
}
export function setupMonaco() {
loader.config({monaco})
}

View File

@@ -0,0 +1,45 @@
import type {loadPyodide} from "pyodide";
import type {MessageEventDataIn} from "./pyodide-worker.ts";
let requestId = 0;
/** Simple API for the Pyodide worker. */
export function newPyodideWorker(initOpts: Parameters<typeof loadPyodide>[0]) {
let worker = new Worker(new URL('./pyodide-worker.ts', import.meta.url), {type: "module"});
worker.postMessage(initOpts);
const commonRequestResponse = (event: MessageEventDataIn, stdout?: (msg: string) => void, stderr?: (msg: string) => void) => {
return new Promise((resolve, reject) => {
worker.addEventListener("message", function listener(event: MessageEvent) {
if (stdout && event.data?.stdout) {
stdout(event.data.stdout); // No clue if associated with this request, but we handle it anyway.
return;
}
if (stderr && event.data?.stderr) {
stderr(event.data.stderr); // No clue if associated with this request, but we handle it anyway.
return;
}
if (event.data?.id !== event.data.id) return; // Ignore messages that are not for this request.
if (event.data?.error) {
worker.removeEventListener("message", listener);
reject(event.data.error);
} else if (event.data?.hasOwnProperty("result")) {
worker.removeEventListener("message", listener);
resolve(event.data.result);
} else {
throw new Error("Unexpected message from worker: " + JSON.stringify(event.data));
}
})
worker.postMessage(event);
});
}
return {
asyncRun: (code: string, stdout: (msg: string) => void, stderr: (msg: string) => void) =>
commonRequestResponse({type: "asyncRun", id: requestId++, code}, stdout, stderr),
mkdirTree: (path: string) => commonRequestResponse({type: "mkdirTree", id: requestId++, path}),
writeFile: (path: string, content: string) =>
commonRequestResponse({type: "writeFile", id: requestId++, path, content}),
makeSnapshot: () => commonRequestResponse({type: "makeSnapshot", id: requestId++}),
terminate: () => worker.terminate()
}
}

View File

@@ -0,0 +1,83 @@
import {loadPyodide, type PyodideInterface} from "pyodide";
let myLoadPyodide = (initOpts: Parameters<typeof loadPyodide>[0]) => loadPyodide({
...initOpts,
stdout: (msg) => self.postMessage({stdout: msg + "\n"}), // Add newline for better readability
stderr: (msg) => self.postMessage({stderr: msg + "\n"}), // Add newline for better readability
stdin: () => {
console.warn("Input requested by Python code, but stdin is not supported in this playground.");
return "";
},
});
let pyodideReadyPromise: Promise<PyodideInterface> | null = null;
export type MessageEventDataIn = {
type: 'asyncRun';
id: number;
code: string;
} | {
type: 'mkdirTree';
id: number;
path: string;
} | {
type: 'writeFile';
id: number;
path: string;
content: string;
} | {
type: 'makeSnapshot';
id: number;
}
self.onmessage = async (event: MessageEvent<MessageEventDataIn>) => {
if (!pyodideReadyPromise) { // First message is always the init message
// If we haven't loaded Pyodide yet, do so now.
// This is a singleton, so we only load it once.
pyodideReadyPromise = myLoadPyodide(event.data as Parameters<typeof loadPyodide>[0]);
return;
}
if (event.data.type === 'mkdirTree') {
// Create a directory tree in the Pyodide filesystem.
const pyodide = await pyodideReadyPromise;
try {
pyodide.FS.mkdirTree(event.data.path);
self.postMessage({id: event.data.id, result: true});
} catch (error: any) {
self.postMessage({id: event.data.id, error: error.message});
}
return;
} else if (event.data.type === 'writeFile') {
// Write a file to the Pyodide filesystem.
const pyodide = await pyodideReadyPromise;
try {
pyodide.FS.writeFile(event.data.path, event.data.content);
self.postMessage({id: event.data.id, result: true});
} catch (error: any) {
self.postMessage({id: event.data.id, error: error.message});
}
} else if (event.data.type === 'asyncRun') {
let code = event.data.code;
// make sure loading is done
const pyodide = await pyodideReadyPromise;
// Now load any packages we need, run the code, and send the result back.
await pyodide.loadPackagesFromImports(code);
try {
self.postMessage({id: event.data.id, result: await pyodide.runPythonAsync(code)});
} catch (error: any) {
self.postMessage({id: event.data.id, error: error.message});
}
} else if (event.data.type === 'makeSnapshot') {
// Take a snapshot of the current Pyodide filesystem.
const pyodide = await pyodideReadyPromise;
try {
const snapshot = pyodide.makeMemorySnapshot();
self.postMessage({id: event.data.id, result: snapshot});
} catch (error: any) {
self.postMessage({id: event.data.id, error: error.message});
}
} else {
console.error("Unknown message type:", (event.data as any)?.type);
self.postMessage({id: (event.data as any)?.id, error: "Unknown message type: " + (event.data as any)?.type});
}
};

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();
}
@@ -66,7 +78,7 @@ export function hitToSelectionInfo(hit: Intersection<MObject3D>): SelectionInfo
function hitFaceTriangleIndices(hit: Intersection<MObject3D>): [number, number] | null {
let faceTrianglesEnd = hit?.object?.geometry?.userData?.face_triangles_end;
if (hit.faceIndex === undefined) return null;
if (!hit.faceIndex) return null;
if (!faceTrianglesEnd) { // Fallback to selecting the whole imported mesh
//console.log("No face_triangles_end found, selecting the whole mesh");
return [0, (hit.object.geometry.index ?? hit.object.geometry.attributes.position).count];

View File

@@ -0,0 +1,90 @@
import encryptCode from "tanmayo7lock/dist/index.js?raw";
function encrypt(msg: string, secret: string = "hudfhgd8fghdfgh3uhuifdgh"): string {
let exports: any = {};
eval(encryptCode.replace("exports.encrypt = encrypt;", "exports.LargeDataCrypto = LargeDataCrypto;\nexports.encrypt = encrypt;"));
return exports.LargeDataCrypto.encrypt(msg, secret);
}
async function check(lockerName: string) {
const fileUrl = `https://vouz-backend.onrender.com/api/check_key`;
const response = await fetch(fileUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify({name: encrypt(lockerName), key: encrypt(lockerName)}),
});
if (!response.ok) throw new Error(`Failed to get file URL: ${response.status} ${response.statusText} -- ${await response.text()}`);
const status = await response.json();
return {response, status};
}
export async function uploadFile(name: string, data: Uint8Array): Promise<string> {
// "Free" storage, let's see how long it lasts...
// Create a locker
const lockerUrl = `https://vouz-backend.onrender.com/api/locker`
const lockerName = `yacv-pg-${name}-${Date.now()}`; // Unique locker name
let responsePromise = fetch(lockerUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify({name: encrypt(lockerName), passkey: encrypt(lockerName)}),
});
// The previous request never answers 🤮
responsePromise.then((response) => console.warn(`Locker creation response: ${response.status} ${response.statusText} -- ${response.headers.get('Content-Type')}`));
// Instead, poll the check endpoint until the locker is created
let i: number;
for (i = 0; i < 10; i++) {
await new Promise(resolve => setTimeout(resolve, 250)); // Wait a bit before checking
try {
let {status} = await check(lockerName);
if (status && status.data && status.data.length == 0) break // Locker is created
} catch (e) { // Ignore errors, they will be thrown later
}
}
if (i >= 10) throw new Error(`Failed to create locker after 10 attempts: ${lockerName}`);
// Upload file to the locker
const uploadUrl = `https://vouz-backend.onrender.com/api/upload`;
const formData = new FormData();
formData.append('file', new Blob([data], {type: 'application/octet-stream'}), name);
formData.append("name", encrypt(lockerName));
formData.append("passkey", encrypt(lockerName));
const response = await fetch(uploadUrl, {
method: 'POST',
body: formData,
})
if (!response.ok) throw new Error(`Failed to upload file: ${response.status} ${response.statusText} -- ${await response.text()}`);
// Fake URL for retrieveFile to work
return "https://vouz.tech#name=" + encodeURIComponent(name) + "&locker=" + encodeURIComponent(lockerName);
}
/** Given any URL, it retrieves the file, with custom code for the vouz.tech locker. */
export async function retrieveFile(url: string): Promise<Response> {
let realUrl = url;// Normal fetch if the URL is not a vouz.tech locker URL
if (url.indexOf("https://vouz.tech#") !== -1) { // Check if the URL is a vouz.tech locker URL
// Parse the URL to get the locker name and file name
const urlObj = new URL(url);
const hashParams = new URLSearchParams(urlObj.hash.slice(1)); // Remove the leading '#'
const lockerName = hashParams.get('locker') || (() => {
throw new Error("Locker name not found in URL hash")
})();
const name = hashParams.get('name') || (() => {
throw new Error("File name not found in URL hash")
})();
// Get the URL of the uploaded file
let {status} = await check(lockerName);
if (!status || !status.data || status.data.length == 0 || !status.data[0].url) {
throw new Error(`No file URL found in response: ${JSON.stringify(status)}`);
}
console.debug("File access requested successfully, URL:", status.data[0].url);
realUrl = "https://corsproxy.io/?url=" + status.data[0].url + "#name=" + encodeURIComponent(name) + "&locker=" + encodeURIComponent(lockerName);
}
return await fetch(realUrl);
}

View File

@@ -1,15 +1,17 @@
<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 {inject, onUpdated, type Ref, ref, watch} from "vue";
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";
import type {Renderer} from "@google/model-viewer/lib/three-components/Renderer";
import type {Vector3} from "three";
import { computeBoundsTree, disposeBoundsTree, acceleratedRaycast } from 'three-mesh-bvh';
import {BufferGeometry, Mesh} from "three";
import {acceleratedRaycast, computeBoundsTree, disposeBoundsTree} from 'three-mesh-bvh';
import {setupLighting} from "./lighting.ts";
ModelViewerElement.modelCacheSize = 0; // Also needed to avoid tree shaking
//@ts-ignore
@@ -19,30 +21,102 @@ 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);
onMounted(() => {
if (!elem.value) return;
elem.value.addEventListener('load', async () => {
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
const sett = ref<any | null>(null);
(async () => sett.value = await settings)();
let lastCameraTargetPosition: Vector3 | undefined = undefined;
let lastCameraZoom: number | undefined = undefined;
let lastCameraUrl = props.src.toString();
let initialized = false
onUpdated(() => {
if (!elem.value) return; // Not ready yet
if (initialized) return; // Already initialized
initialized = true;
elem.value.addEventListener('before-render', () => {
if (!elem.value) return
// 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));
setupLighting(elem.value);
});
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);
let onProgressHideTimeout: number | null = null;
const onProgress = (totalProgress: number) => {
if (!progressBar.value || !updateBar.value) return;
// Update the progress bar and ensure it's visible
progressBar.value.style.display = 'block';
progressBar.value.style.opacity = '1'; // Fade in
updateBar.value.style.width = `${totalProgress * 100}%`;
// Auto-hide smoothly when no progress is made for a while
if (onProgressHideTimeout) clearTimeout(onProgressHideTimeout);
onProgressHideTimeout = setTimeout(() => {
if (!progressBar.value) return;
progressBar.value.style.opacity = '0'; // Fade out
setTimeout(() => {
if (!progressBar.value) return;
progressBar.value.style.display = 'none'; // Actually hide
}, 300); // 0.3s fade out
}, 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
@@ -95,13 +169,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) {
@@ -137,48 +204,47 @@ function entries(lines: { [id: number]: Line3DData }): [string, Line3DData][] {
return Object.entries(lines);
}
defineExpose({elem, onElemReady, scene, renderer, addLine3D, removeLine3D});
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">
<slot></slot> <!-- Controls, annotations, etc. -->
<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> -->
<model-viewer ref="elem" v-if="sett != null" :ar="sett.arModes.length > 0" :ar-modes="sett.arModes"
:environment-image="sett.environment" :exposure="sett.exposure" :autoplay="sett.autoplay"
:orbit-sensitivity="sett.orbitSensitivity" :pan-sensitivity="sett.panSensitivity"
:poster="poster" :shadow-intensity="sett.shadowIntensity" :skybox-image="sett.skybox"
:src="props.src" :zoom-sensitivity="sett.zoomSensitivity" alt="The 3D model(s)" camera-controls
camera-orbit="45deg 45deg auto" interaction-prompt="none" max-camera-orbit="Infinity 180deg auto"
min-camera-orbit="-Infinity 0deg 5%" style="width: 100%; height: 100%">
<slot></slot>
<!-- 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>
@@ -213,14 +279,29 @@ watch(disableTap, (value) => {
pointer-events: none;
}
.initial-load-banner {
width: 300px;
margin: auto;
margin-top: 3em;
overflow: hidden;
.progress-bar {
display: block;
pointer-events: none;
width: 100%;
height: 10%;
max-height: 2%;
position: absolute;
left: 50%;
top: 0;
transform: translate3d(-50%, 0%, 0);
border-radius: 25px;
box-shadow: 0 3px 10px 3px rgba(0, 0, 0, 0.5), 0 0 5px 1px rgba(0, 0, 0, 0.6);
border: 1px solid rgba(255, 255, 255, 0.9);
background-color: rgba(0, 0, 0, 0.5);
transition: opacity 0.3s;
}
.initial-load-banner .v-list-item {
overflow: hidden;
.update-bar {
background-color: rgba(255, 255, 255, 0.9);
width: 0;
height: 100%;
border-radius: 25px;
float: left;
transition: width 0.3s;
}
</style>
</style>

View File

@@ -0,0 +1,76 @@
import {ModelViewerElement} from '@google/model-viewer';
import {$scene} from "@google/model-viewer/lib/model-viewer-base";
import {settings} from "../misc/settings.ts";
export let currentSceneRotation = 0; // radians, 0 is the default rotation
export async function setupLighting(modelViewer: ModelViewerElement) {
modelViewer[$scene].environmentIntensity = (await settings).environmentIntensity;
// Code is mostly copied from the example at: https://modelviewer.dev/examples/stagingandcameras/#turnSkybox
let lastX: number;
let panning = false;
let radiansPerPixel: number;
const startPan = () => {
const orbit = modelViewer.getCameraOrbit();
const {radius} = orbit;
radiansPerPixel = -1 * radius / modelViewer.getBoundingClientRect().height;
modelViewer.interactionPrompt = 'none';
};
const updatePan = (thisX: number) => {
const delta = (thisX - lastX) * radiansPerPixel;
lastX = thisX;
currentSceneRotation += delta;
const orbit = modelViewer.getCameraOrbit();
orbit.theta += delta;
modelViewer.cameraOrbit = orbit.toString();
modelViewer.resetTurntableRotation(currentSceneRotation);
modelViewer.jumpCameraToGoal();
}
modelViewer.addEventListener('mousedown', (event) => {
panning = event.metaKey || event.shiftKey;
if (!panning)
return;
lastX = event.clientX;
startPan();
event.stopPropagation();
}, true);
modelViewer.addEventListener('touchstart', (event) => {
const {targetTouches, touches} = event;
panning = targetTouches.length === 2 && targetTouches.length === touches.length;
if (!panning)
return;
lastX = 0.5 * (targetTouches[0].clientX + targetTouches[1].clientX);
startPan();
}, true);
document.addEventListener('mousemove', (event) => {
if (!panning)
return;
updatePan(event.clientX);
event.stopPropagation();
}, true);
modelViewer.addEventListener('touchmove', (event) => {
if (!panning || event.targetTouches.length !== 2)
return;
const {targetTouches} = event;
const thisX = 0.5 * (targetTouches[0].clientX + targetTouches[1].clientX);
updatePan(thisX);
}, true);
document.addEventListener('mouseup', (event) => {
panning = false;
}, true);
modelViewer.addEventListener('touchend', (event) => {
panning = false;
}, true);
}

View File

@@ -1,6 +1,6 @@
{
"name": "yet-another-cad-viewer",
"version": "0.8.0",
"version": "0.10.6",
"description": "",
"license": "MIT",
"private": true,
@@ -15,32 +15,41 @@
"update-licenses": "generate-license-file --input package.json --output assets/licenses.txt --overwrite"
},
"dependencies": {
"@gltf-transform/core": "^3.10.0",
"@gltf-transform/functions": "^3.10.1",
"@google/model-viewer": "^3.4.0",
"@gltf-transform/core": "^4.1.0",
"@gltf-transform/extensions": "^4.1.0",
"@gltf-transform/functions": "^4.1.0",
"@google/model-viewer": "^4.0.0",
"@guolao/vue-monaco-editor": "^1.5.5",
"@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-orientation-gizmo": "https://github.com/jrj2211/three-orientation-gizmo",
"vue": "^3.4.21",
"vuetify": "^3.5.11"
"js-base64": "^3.7.7",
"monaco-editor": "^0.52.2",
"pako": "^2.1.0",
"pyodide": "^0.28.0",
"tanmayo7lock": "^1.0.18",
"three": "^0.179.0",
"three-mesh-bvh": "^0.9.0",
"three-orientation-gizmo": "git+https://github.com/jrj2211/three-orientation-gizmo.git",
"vue": "^3.5.13",
"vuetify": "^3.7.4"
},
"devDependencies": {
"@tsconfig/node20": "^20.1.3",
"@types/node": "^20.11.30",
"@types/three": "^0.160.0",
"@vitejs/plugin-vue": "^5.0.3",
"@vitejs/plugin-vue-jsx": "^3.1.0",
"@vue/tsconfig": "^0.5.1",
"@tsconfig/node20": "^20.1.4",
"@types/node": "^22.9.3",
"@types/pako": "^2.0.3",
"@types/three": "^0.178.0",
"@vitejs/plugin-vue": "^6.0.0",
"@vitejs/plugin-vue-jsx": "^5.0.0",
"@vue/tsconfig": "^0.7.0",
"buffer": "^5.5.0||^6.0.0",
"commander": "^12.0.0",
"generate-license-file": "^3.0.1",
"npm-run-all2": "^6.1.1",
"terser": "^5.29.2",
"typescript": "~5.4.3",
"vite": "^5.2.6",
"vue-tsc": "^2.0.7"
"commander": "^14.0.0",
"generate-license-file": "^4.0.0",
"npm-run-all2": "^8.0.0",
"terser": "^5.36.0",
"typescript": "~5.8.0",
"vite": "^7.0.0",
"vite-plugin-static-copy": "^3.1.1",
"vue-tsc": "^3.0.0"
}
}

1534
poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,29 +1,34 @@
[build-system]
requires = ["poetry-core==2.1.3", "taskipy==1.14.1"]
build-backend = "poetry.core.masonry.api"
[tool.poetry]
name = "yacv-server"
version = "0.8.0"
version = "0.10.6"
description = "Yet Another CAD Viewer (server)"
authors = ["Yeicor <4929005+Yeicor@users.noreply.github.com>"]
license = "MIT"
readme = "README.md"
include = [
{ path = 'yacv_server/frontend/*', format = 'wheel' },
{ path = 'yacv_server/frontend/*', format = 'sdist' },
{ path = 'yacv_server/frontend/**/*', format = 'wheel' },
{ path = 'yacv_server/frontend/**/*', format = 'sdist' },
]
[tool.taskipy.tasks]
build = "task build_frontend && task build_backend"
build_frontend = "rm -rf yacv_server/frontend || true && yarn install && YACV_SMALL_BUILD=true yarn build --outDir yacv_server/frontend"
build_backend = "poetry build --format wheel"
[tool.poetry.dependencies]
python = "^3.9"
python = ">=3.12,<3.13" # Due to vtk transitive dependency of build123d -> cadquery-ocp -> vtk
# CAD
build123d = "^0.5.0"
build123d = ">=0.9,<0.10"
# Misc
pygltflib = "^1.16.2"
pillow = "^10.2.0"
pillow = ">=10.2,<12.0"
poetry-core = "==2.1.3"
[tool.poetry.build]
generate-setup-file = false
script = "build.py"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
[tool.poetry.group.dev.dependencies]
taskipy = "^1.14.1"

View File

@@ -8,12 +8,11 @@
"frontend/**/__tests__/*"
],
"compilerOptions": {
"composite": true,
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"declaration": false,
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
}
}
}

View File

@@ -1,10 +1,17 @@
import {fileURLToPath, URL} from 'node:url'
import {defineConfig} from 'vite'
// @ts-ignore
import vue from '@vitejs/plugin-vue'
// @ts-ignore
import vueJsx from '@vitejs/plugin-vue-jsx'
import {name, version} from './package.json'
import {execSync} from 'child_process'
import {viteStaticCopy} from "vite-plugin-static-copy";
import {dirname, join} from "path";
import {version as pyodideVersion} from "pyodide";
let wantsSmallBuild = process.env.YACV_SMALL_BUILD == "true";
// https://vitejs.dev/config/
export default defineConfig({
@@ -13,12 +20,14 @@ export default defineConfig({
vue({
template: {
compilerOptions: {
isCustomElement: tag => tag == 'model-viewer'
isCustomElement: (tag: string) => tag == 'model-viewer'
}
}
}),
vueJsx(),
viteStaticCopyPyodide(),
],
optimizeDeps: {exclude: ["pyodide"]},
resolve: {
alias: {
// @ts-ignore
@@ -26,14 +35,53 @@ 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 huge
chunkSizeWarningLimit: 1024, // KB. Three.js is big. Draco is even bigger but not likely to be used.
sourcemap: true, // For debugging production
rollupOptions: {
output: {
experimentalMinChunkSize: 512000, // 512KB (avoid too many small chunks)
},
external: wantsSmallBuild ? [
// Exclude some large optional dependencies if small build is requested (for embedding in python package)
"pyodide",
/.*\/pyodide-worker.*/,
"monaco-editor",
/monaco-editor\/.*/,
"@guolao/vue-monaco-editor",
/three\/examples\/jsm\/libs\/draco\/draco_(en|de)coder\.js/,
] : [],
},
},
worker: {
format: 'es', // Use ES modules for workers (IIFE is not supported with code-splitting)
},
define: {
__APP_NAME__: JSON.stringify(name),
__APP_VERSION__: JSON.stringify(version),
__APP_GIT_SHA__: JSON.stringify(execSync('git rev-parse HEAD').toString().trim()),
__APP_GIT_DIRTY__: JSON.stringify(execSync('git diff --quiet || echo dirty').toString().trim()),
__YACV_SMALL_BUILD__: JSON.stringify(wantsSmallBuild)
}
})
function viteStaticCopyPyodide() {
const PYODIDE_EXCLUDE = [
"!**/*.{md,html}",
"!**/*.d.ts",
"!**/*.whl",
"!**/node_modules",
];
// @ts-ignore
const pyodideDir = dirname(fileURLToPath(import.meta.resolve("pyodide")));
return viteStaticCopy({
targets: wantsSmallBuild ? [] : [
{
src: [join(pyodideDir, "*")].concat(PYODIDE_EXCLUDE),
dest: "pyodide-v" + pyodideVersion, // It would be better to use hashed names instead of folder...
},
],
});
}

View File

@@ -2,15 +2,38 @@
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, Color
from yacv_server.gltf import GLTFMgr
CADCoreLike = Union[TopoDS_Shape, TopLoc_Location] # Faces, Edges, Vertices and Locations for now
CADLike = Union[CADCoreLike, any] # build123d and cadquery types
ColorTuple = Tuple[float, float, float, float]
def get_color(obj: any) -> Optional[ColorTuple]:
"""Get color from a CAD Object or any other color-like object"""
if 'color' in dir(obj):
obj = obj.color
if isinstance(obj, tuple):
c = None
if len(obj) == 3:
c = obj + (1,)
elif len(obj) == 4:
c = obj
# noinspection PyTypeChecker
return [min(max(float(x), 0), 1) for x in c]
if isinstance(obj, Color):
return obj.to_tuple()
return None
def get_shape(obj: CADLike, error: bool = True) -> Optional[CADCoreLike]:
@@ -40,22 +63,43 @@ 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 (skip locations/axes here, they can't be in a Compound)
shapes_bd = [Compound(shape) for shape in shapes_raw_filtered_sorted if
shape is not None and not isinstance(shape, TopLoc_Location)]
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:
return None
def grab_all_cad() -> List[Tuple[str, CADCoreLike]]:
def grab_all_cad() -> set[Tuple[str, CADCoreLike]]:
""" Grab all shapes by inspecting the stack """
import inspect
stack = inspect.stack()
shapes = []
shapes = set()
for frame in stack:
for key, value in frame.frame.f_locals.items():
shape = get_shape(value, error=False)
if shape:
shapes.append((key, shape))
if shape and shape not in shapes:
shapes.add((key, shape))
return shapes
@@ -78,11 +122,11 @@ def image_to_gltf(source: str | bytes, center: any, width: Optional[float] = Non
hasher = hashlib.md5()
hasher.update(source)
name = 'image_' + hasher.hexdigest()
format: str
_format: str
if save_mime == 'image/jpeg':
format = 'JPEG'
_format = 'JPEG'
elif save_mime == 'image/png':
format = 'PNG'
_format = 'PNG'
else:
raise ValueError(f'Unsupported save MIME type (for GLTF files): {save_mime}')
@@ -91,13 +135,6 @@ def image_to_gltf(source: str | bytes, center: any, width: Optional[float] = Non
if not isinstance(center_loc, TopLoc_Location):
raise ValueError('Center location not valid')
plane = Plane(Location(center_loc))
# Convert coordinates system
plane.origin = Vector(plane.origin.X, plane.origin.Z, -plane.origin.Y)
plane.z_dir = -plane.y_dir
plane.y_dir = plane.z_dir
def vert(v: Vector) -> Tuple[float, float, float]:
return v.X, v.Y, v.Z
# Load the image to a byte buffer
img = Image.open(source)
@@ -118,17 +155,21 @@ def image_to_gltf(source: str | bytes, center: any, width: Optional[float] = Non
img = img.resize((new_width, new_height))
# Save the image to a buffer
img.save(img_buf, format=format)
img.save(img_buf, format=_format)
img_buf = img_buf.getvalue()
# Convert coordinates system as a last step (gltf is Y-up instead of Z-up)
def vert(v: Vector) -> Vector:
return Vector(v.X, v.Z, -v.Y)
# Build the gltf
mgr = GLTFMgr(image=(img_buf, save_mime))
mgr.add_face([
vert(plane.origin - plane.x_dir * width / 2 - plane.y_dir * height / 2),
vert(plane.origin + plane.x_dir * width / 2 - plane.y_dir * height / 2),
vert(plane.origin + plane.x_dir * width / 2 + plane.y_dir * height / 2),
vert(plane.origin - plane.x_dir * width / 2 + plane.y_dir * height / 2),
], [
vert(plane.origin + plane.x_dir * width / 2 + plane.y_dir * height / 2),
vert(plane.origin + plane.x_dir * width / 2 - plane.y_dir * height / 2),
vert(plane.origin - plane.x_dir * width / 2 - plane.y_dir * height / 2),
], [vert(plane.z_dir)] * 4, [
(0, 2, 1),
(0, 3, 2),
], [
@@ -140,3 +181,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

@@ -4,9 +4,12 @@ import numpy as np
from build123d import Location, Plane, Vector
from pygltflib import *
_checkerboard_image_bytes = base64.decodebytes(
b'iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAAF0lEQVQI12N49OjR////Gf'
b'/////48WMATwULS8tcyj8AAAAASUVORK5CYII=')
def get_version() -> str:
try:
return importlib.metadata.version("yacv_server")
except importlib.metadata.PackageNotFoundError:
return "unknown"
class GLTFMgr:
@@ -18,6 +21,7 @@ class GLTFMgr:
# - Face data
face_indices: List[int] # 3 indices per triangle
face_positions: List[float] # x, y, z
face_normals: List[float] # x, y, z
face_tex_coords: List[float] # u, v
face_colors: List[float] # r, g, b, a
image: Optional[Tuple[bytes, str]] # image/png
@@ -30,9 +34,9 @@ class GLTFMgr:
vertex_positions: List[float] # x, y, z
vertex_colors: List[float] # r, g, b, a
def __init__(self, image: Optional[Tuple[bytes, str]] = (_checkerboard_image_bytes, 'image/png')):
def __init__(self, image: Optional[Tuple[bytes, str]] = None):
self.gltf = GLTF2(
asset=Asset(generator=f"yacv_server@{importlib.metadata.version('yacv_server')}"),
asset=Asset(generator=f"yacv_server@{get_version()}"),
scene=0,
scenes=[Scene(nodes=[0])],
nodes=[Node(mesh=0)], # TODO: Server-side detection of shallow copies --> nodes
@@ -48,6 +52,7 @@ class GLTFMgr:
)
self.face_indices = []
self.face_positions = []
self.face_normals = []
self.face_tex_coords = []
self.face_colors = []
self.image = image
@@ -70,9 +75,8 @@ class GLTFMgr:
def _vertices_primitive(self) -> Primitive:
return [p for p in self.gltf.meshes[0].primitives if p.mode == POINTS][0]
def add_face(self, vertices_raw: List[Vector], indices_raw: List[Tuple[int, int, int]],
tex_coord_raw: List[Tuple[float, float]],
color: Tuple[float, float, float, float] = (1.0, 0.75, 0.0, 1.0)):
def add_face(self, vertices_raw: List[Vector], normals: List[Vector], indices_raw: List[Tuple[int, int, int]],
tex_coord_raw: List[Tuple[float, float]], color: Tuple[float, float, float, float]):
"""Add a face to the GLTF mesh"""
# assert len(vertices_raw) == len(tex_coord_raw), f"Vertices and texture coordinates have different lengths"
# assert min([i for t in indices_raw for i in t]) == 0, f"Face indices start at {min(indices_raw)}"
@@ -80,12 +84,13 @@ class GLTFMgr:
base_index = len(self.face_positions) // 3 # All the new indices reference the new vertices
self.face_indices.extend([base_index + i for t in indices_raw for i in t])
self.face_positions.extend([v for t in vertices_raw for v in t])
self.face_normals.extend([n for t in normals for n in t])
self.face_tex_coords.extend([c for t in tex_coord_raw for c in t])
self.face_colors.extend([col for _ in range(len(vertices_raw)) for col in color])
self._faces_primitive.extras["face_triangles_end"].append(len(self.face_indices))
def add_edge(self, vertices_raw: List[Tuple[Tuple[float, float, float], Tuple[float, float, float]]],
color: Tuple[float, float, float, float] = (0.1, 0.1, 1.0, 1.0)):
color: Tuple[float, float, float, float]):
"""Add an edge to the GLTF mesh"""
vertices_flat = [v for t in vertices_raw for v in t] # Line from 0 to 1, 2 to 3, 4 to 5, etc.
base_index = len(self.edge_positions) // 3
@@ -94,8 +99,7 @@ class GLTFMgr:
self.edge_colors.extend([col for _ in range(len(vertices_flat)) for col in color])
self._edges_primitive.extras["edge_points_end"].append(len(self.edge_indices))
def add_vertex(self, vertex: Tuple[float, float, float],
color: Tuple[float, float, float, float] = (0.1, 0.1, 0.1, 1.0)):
def add_vertex(self, vertex: Tuple[float, float, float], color: Tuple[float, float, float, float]):
"""Add a vertex to the GLTF mesh"""
base_index = len(self.vertex_positions) // 3
self.vertex_indices.append(base_index)
@@ -110,10 +114,11 @@ class GLTFMgr:
return v.X, v.Y, v.Z
# Add 1 origin vertex and 3 edges with custom colors to identify the X, Y and Z axis
self.add_vertex(vert(pl.origin))
self.add_edge([(vert(pl.origin), vert(pl.origin + pl.x_dir))], color=(0.97, 0.24, 0.24, 1))
self.add_edge([(vert(pl.origin), vert(pl.origin + pl.y_dir))], color=(0.42, 0.8, 0.15, 1))
self.add_edge([(vert(pl.origin), vert(pl.origin + pl.z_dir))], color=(0.09, 0.55, 0.94, 1))
# The colors are hardcoded. You can add vertices and edges manually to change them.
self.add_vertex(vert(pl.origin), color=(0.1, 0.1, 0.1, 1.0))
self.add_edge([(vert(pl.origin), vert(pl.origin + pl.x_dir))], color=(0.97, 0.24, 0.24, 1.0))
self.add_edge([(vert(pl.origin), vert(pl.origin + pl.y_dir))], color=(0.42, 0.8, 0.15, 1.0))
self.add_edge([(vert(pl.origin), vert(pl.origin + pl.z_dir))], color=(0.09, 0.55, 0.94, 1.0))
def build(self) -> GLTF2:
"""Merge the intermediate data into the GLTF object and return it"""
@@ -124,6 +129,8 @@ class GLTFMgr:
buffers_list.append(_gen_buffer_metadata(self.face_indices, 1))
self._faces_primitive.attributes.POSITION = len(buffers_list)
buffers_list.append(_gen_buffer_metadata(self.face_positions, 3))
self._faces_primitive.attributes.NORMAL = len(buffers_list)
buffers_list.append(_gen_buffer_metadata(self.face_normals, 3))
self._faces_primitive.attributes.TEXCOORD_0 = len(buffers_list)
buffers_list.append(_gen_buffer_metadata(self.face_tex_coords, 2))
self._faces_primitive.attributes.COLOR_0 = len(buffers_list)
@@ -162,6 +169,7 @@ class GLTFMgr:
self.gltf.images = [Image(bufferView=len(buffers_list), mimeType=self.image[1])]
self.gltf.textures = [Texture(source=0, sampler=0)]
self.gltf.samplers = [Sampler(magFilter=NEAREST)]
# noinspection PyPep8Naming
self.gltf.materials[0].pbrMetallicRoughness.baseColorTexture = TextureInfo(index=0)
buffers_list.append((Accessor(), BufferView(), self.image[0]))

View File

@@ -6,29 +6,41 @@ from build123d import *
ASSETS_DIR = os.getenv('ASSETS_DIR', os.path.join(os.path.dirname(__file__), '..', 'assets'))
def build_logo(text: bool = True) -> Dict[str, Union[Part, Location, str]]:
def build_logo(text: bool = True) -> Dict[str, Union[Compound, Location, str]]:
"""Builds the CAD part of the logo"""
with BuildPart(Plane.XY.offset(50)) as logo_obj:
Box(22, 40, 30)
fillet(edges().filter_by(Axis.Y).group_by(Axis.Z)[-1], 10)
offset(solid(), 2, openings=faces().group_by(Axis.Z)[0] + faces().filter_by(Plane.XZ))
if text:
text_at_plane = Plane.YZ
text_at_plane.origin = faces().group_by(Axis.X)[-1].face().center()
with BuildSketch(text_at_plane.location):
Text('Yet Another\nCAD Viewer', 7, font_path='/usr/share/fonts/TTF/OpenSans-Regular.ttf')
with BuildSketch(Plane.YZ.move(Pos(faces().group_by(Axis.X)[-1].face().center()))):
Text('Yet Another\nCAD Viewer', 6, font_path='/usr/share/fonts/TTF/Hack-Regular.ttf')
extrude(amount=1)
logo_face_curved_front = faces().filter_by(GeomType.CYLINDER).group_by(Axis.X)[-1].face()
logo_img_location = logo_obj.faces().group_by(Axis.X)[0].face().center_location # Avoid overlapping:
logo_img_location.position = Vector(logo_img_location.position.X - 4e-2, logo_img_location.position.Y,
logo_img_location.position.Z)
# Highlight text edges with a custom color
to_highlight = logo_obj.edges().group_by(Axis.X)[-1]
logo_obj_hl = Compound(to_highlight).translate((1e-3, 0, 0)) # To avoid z-fighting
logo_obj_hl.color = (0, 0.3, 0.3, 1)
# Highlight face with custom texture
logo_face_curved_front.yacv_texture = \
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAAF0lEQVQI12N49OjR////Gf' \
'/////48WMATwULS8tcyj8AAAAASUVORK5CYII='
logo_face_curved_front.color = (0, 0.5, 0.0, 1)
logo_obj = Compound(logo_obj.faces() - ShapeList([logo_face_curved_front])) # Remove face from the main object
# Add a logo image to the CAD part
logo_img_location = logo_obj.faces().group_by(Axis.X)[0].face().center_location
logo_img_location *= Location((0, 0, 4e-2), (0, 0, 90)) # Avoid overlapping and adjust placement
logo_img_path = os.path.join(ASSETS_DIR, 'img.jpg')
img_glb_bytes, img_name = image_to_gltf(logo_img_path, logo_img_location, height=18)
# Add an animated fox to the CAD part
fox_glb_bytes = open(os.path.join(ASSETS_DIR, 'fox.glb'), 'rb').read()
return {'fox': fox_glb_bytes, 'logo': logo_obj, 'location': logo_img_location, img_name: img_glb_bytes}
return {'fox': fox_glb_bytes, 'logo': logo_obj, 'logo_hl': logo_obj_hl, 'logo_hl_tex': logo_face_curved_front,
'location': logo_img_location, img_name: img_glb_bytes}
if __name__ == "__main__":

View File

@@ -1,6 +0,0 @@
from os import system
if __name__ == '__main__':
# Just a reminder that a hot-reloading server can be started with the following command:
# Need to disable auto-start to avoid conflicts with the hot-reloading server
system('YACV_DISABLE_SERVER=true aiohttp-devtools runserver __init__.py --port 32323 --app-factory _get_app')

View File

@@ -1,7 +1,7 @@
import io
import os
import urllib.parse
from http import HTTPStatus
from http import HTTPStatus, HTTPMethod
from http.server import SimpleHTTPRequestHandler
from yacv_server.mylogger import logger
@@ -71,6 +71,19 @@ class HTTPHandler(SimpleHTTPRequestHandler):
def _api_updates(self):
"""Handles a publish-only websocket connection that send show_object events along with their hashes and URLs"""
self.send_response(HTTPStatus.OK)
self.send_header("Content-Type", "text/event-stream")
self.send_header("Cache-Control", "no-cache")
if not self.requestline.startswith(HTTPMethod.HEAD):
# Chunked transfer encoding!
self.send_header("Transfer-Encoding", "chunked")
else:
self.send_header("Content-Length", "0")
self.end_headers()
if self.requestline.startswith(HTTPMethod.HEAD):
return
# Keep a shared read lock to know if any frontend is still working before shutting down
with self.yacv.frontend_lock.r_locked():
@@ -81,13 +94,6 @@ class HTTPHandler(SimpleHTTPRequestHandler):
self.yacv.at_least_one_client.set()
logger.debug('Updates client connected')
self.send_response(HTTPStatus.OK)
self.send_header("Content-Type", "text/event-stream")
self.send_header("Cache-Control", "no-cache")
# Chunked transfer encoding!
self.send_header("Transfer-Encoding", "chunked")
self.end_headers()
def write_chunk(_chunk_data: str):
self.wfile.write(hex(len(_chunk_data))[2:].encode('utf-8'))
self.wfile.write(b'\r\n')
@@ -107,7 +113,7 @@ class HTTPHandler(SimpleHTTPRequestHandler):
# noinspection PyUnresolvedReferences
to_send = data.to_json()
write_chunk(f'data: {to_send}\n\n')
except BrokenPipeError: # Client disconnected normally
except (BrokenPipeError, ConnectionResetError): # Client disconnected normally
pass
finally:
subscription.close()
@@ -132,3 +138,4 @@ class HTTPHandler(SimpleHTTPRequestHandler):
self.send_header('E-Tag', f'"{_hash}"')
self.end_headers()
self.wfile.write(exported_glb)
return None

View File

@@ -1,8 +1,6 @@
import queue
import queue
import threading
from typing import List, TypeVar, \
Generic, Generator
from typing import List, TypeVar, Generic, Generator
from yacv_server.mylogger import logger
@@ -56,9 +54,9 @@ class BufferedPubSub(Generic[T]):
self._subscribers.remove(q)
logger.debug(f"Unsubscribed from %s (%d subscribers)", self, len(self._subscribers))
def subscribe(self, include_buffered: bool = True, include_future: bool = True, yield_timeout: float = 0.0) -> \
Generator[T, None, None]:
"""Subscribes to events as an generator that yields events and automatically unsubscribes"""
def subscribe(self, include_buffered: bool = True, include_future: bool = True,
yield_timeout: float | None = 0.0) -> Generator[T, None, None]:
"""Subscribes to events as a generator that yields events and automatically unsubscribes"""
q = self._subscribe(include_buffered, include_future)
try:
while True:

0
yacv_server/py.typed Normal file
View File

View File

@@ -1,59 +1,64 @@
import hashlib
import io
import re
from typing import List, Dict, Tuple, Union
from typing import List, Dict, Tuple, Optional
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.BRepLib import BRepLib_ToolTriangulatedShape
from OCP.TopAbs import TopAbs_Orientation
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 build123d import Vertex, Face, Location, Compound, Vector
from pygltflib import GLTF2
from yacv_server.cad import CADCoreLike
from yacv_server.cad import CADCoreLike, ColorTuple
from yacv_server.gltf import GLTFMgr
from yacv_server.mylogger import logger
def tessellate(
cad_like: CADCoreLike,
tolerance: float = 0.1,
angular_tolerance: float = 0.1,
faces: bool = True,
edges: bool = True,
vertices: bool = True,
cad_like: CADCoreLike, color_faces: ColorTuple, color_edges: ColorTuple, color_vertices: ColorTuple,
color_obj: Optional[ColorTuple] = None, tolerance: float = 0.1, angular_tolerance: float = 0.1,
faces: bool = True, edges: bool = True, vertices: bool = True, texture: Optional[Tuple[bytes, str]] = None,
) -> GLTF2:
"""Tessellate a whole shape into a list of triangle vertices and a list of triangle indices."""
mgr = GLTFMgr()
if texture is None:
mgr = GLTFMgr()
else:
mgr = GLTFMgr(texture)
if isinstance(cad_like, TopLoc_Location):
mgr.add_location(Location(cad_like))
elif isinstance(cad_like, TopoDS_Shape):
shape = Shape(cad_like)
shape = Compound(cad_like)
# Perform tessellation tasks
edge_to_faces: Dict[str, List[TopoDS_Face]] = {}
vertex_to_faces: Dict[str, List[TopoDS_Face]] = {}
if faces:
for face in shape.faces():
_tessellate_face(mgr, face.wrapped, tolerance, angular_tolerance)
if faces and hasattr(shape, 'faces'):
shape_faces = shape.faces()
for face in shape_faces:
_tessellate_face(mgr, face.wrapped, color_obj or color_faces, tolerance, angular_tolerance)
if edges:
for edge in face.edges():
edge_to_faces[edge.wrapped] = edge_to_faces.get(edge.wrapped, []) + [face.wrapped]
if vertices:
for vertex in face.vertices():
vertex_to_faces[vertex.wrapped] = vertex_to_faces.get(vertex.wrapped, []) + [face.wrapped]
if edges:
for edge in shape.edges():
_tessellate_edge(mgr, edge.wrapped, edge_to_faces.get(edge.wrapped, []), angular_tolerance,
angular_tolerance)
if vertices:
if len(shape_faces) > 0: color_obj = None # Don't color edges/vertices if faces are colored
if edges and hasattr(shape, 'edges'):
shape_edges = shape.edges()
for edge in shape_edges:
_tessellate_edge(mgr, edge.wrapped, edge_to_faces.get(edge.wrapped, []), color_obj or color_edges,
angular_tolerance, angular_tolerance)
if len(shape_edges) > 0: color_obj = None # Don't color vertices if edges are colored
if vertices and hasattr(shape, 'vertices'):
for vertex in shape.vertices():
_tessellate_vertex(mgr, vertex.wrapped, vertex_to_faces.get(vertex.wrapped, []))
_tessellate_vertex(mgr, vertex.wrapped, vertex_to_faces.get(vertex.wrapped, []),
color_obj or color_vertices)
else:
raise TypeError(f"Unsupported type: {type(cad_like)}: {cad_like}")
return mgr.build()
@@ -61,17 +66,27 @@ def tessellate(
def _tessellate_face(
mgr: GLTFMgr,
ocp_face: TopoDS_Face,
color: ColorTuple,
tolerance: float = 1e-3,
angular_tolerance: float = 0.1
angular_tolerance: float = 0.1,
):
face = Shape(ocp_face)
face = Compound(ocp_face)
# face.mesh(tolerance, angular_tolerance)
tri_mesh = face.tessellate(tolerance, angular_tolerance)
# noinspection PyArgumentList
poly = BRep_Tool.Triangulation_s(face.wrapped, TopLoc_Location())
if poly is None:
logger.warn("No triangulation found for face")
return GLTF2()
# Get the normal for each vertex (for smooth instead of flat shading!)
BRepLib_ToolTriangulatedShape.ComputeNormals_s(face.wrapped, poly)
reversed_face = face.wrapped.Orientation() == TopAbs_Orientation.TopAbs_REVERSED
normals = [
-Vector(v) if reversed_face else Vector(v)
for v in (poly.Normal(i) for i in range(1, poly.NbNodes() + 1))
]
# Get UV of each face from the parameters
uv = [
(v.X(), v.Y())
@@ -80,7 +95,8 @@ def _tessellate_face(
vertices = tri_mesh[0]
indices = tri_mesh[1]
mgr.add_face(vertices, indices, uv)
mgr.add_face(vertices, normals, indices, uv, color)
return None
def _push_point(v: Tuple[float, float, float], faces: List[TopoDS_Face]) -> Tuple[float, float, float]:
@@ -103,6 +119,7 @@ def _tessellate_edge(
mgr: GLTFMgr,
ocp_edge: TopoDS_Edge,
faces: List[TopoDS_Face],
color: ColorTuple,
angular_deflection: float = 0.1,
curvature_deflection: float = 0.1,
):
@@ -122,38 +139,9 @@ def _tessellate_edge(
# Convert strip of vertices to a list of pairs of vertices
vertices = [(vertices[i], vertices[i + 1]) for i in range(len(vertices) - 1)]
mgr.add_edge(vertices)
mgr.add_edge(vertices, color)
def _tessellate_vertex(mgr: GLTFMgr, ocp_vertex: TopoDS_Vertex, faces: List[TopoDS_Face]):
def _tessellate_vertex(mgr: GLTFMgr, ocp_vertex: TopoDS_Vertex, faces: List[TopoDS_Face], color: ColorTuple):
c = Vertex(ocp_vertex).center()
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()
mgr.add_vertex(_push_point((c.X, c.Y, c.Z), faces), color)

View File

@@ -1,4 +1,5 @@
import atexit
import base64
import copy
import inspect
import os
@@ -7,23 +8,27 @@ import sys
import threading
import time
from dataclasses import dataclass
from enum import Enum, auto
from http.server import ThreadingHTTPServer
from importlib.metadata import version
from io import BytesIO
from threading import Thread
from typing import Optional, Dict, Union, Callable, List, Tuple
from OCP.TopLoc import TopLoc_Location
from OCP.TopoDS import TopoDS_Shape
from PIL import Image
# noinspection PyProtectedMember
from build123d import Shape, Axis, Location, Vector
from dataclasses_json import dataclass_json
from yacv_server.cad import _hashcode, get_color, ColorTuple
from yacv_server.cad import get_shape, grab_all_cad, CADCoreLike, CADLike
from yacv_server.gltf import get_version
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
@dataclass_json
@@ -43,7 +48,7 @@ YACVSupported = Union[bytes, CADCoreLike]
class UpdatesApiFullData(UpdatesApiData):
obj: YACVSupported
"""The OCCT object, if any (not serialized)"""
"""The OCCT object (not serialized)"""
kwargs: Optional[Dict[str, any]]
"""The show_object options, if any (not serialized)"""
@@ -60,10 +65,20 @@ class UpdatesApiFullData(UpdatesApiData):
return super().to_json()
class YACVProtocol(Enum):
"""Enum of communication protocols supported by the server"""
HTTP = auto()
"""The recommended protocol for any platform that can run a web server."""
STDERR = auto()
"""Prints the updates one by one to stderr (first metadata, then base64 of glb file) using a special prefix. Required for Pyodide support."""
class YACV:
"""The main yacv_server class, which manages the web server and the CAD objects."""
# Startup
protocol: YACVProtocol
"""The protocol used by the server. Defaults to HTTP, but can be set to STDERR for Pyodide support."""
server_thread: Optional[Thread]
"""The main thread running the server (will spawn other threads for each request)"""
server: Optional[ThreadingHTTPServer]
@@ -87,7 +102,45 @@ class YACV:
frontend_lock: RWLock
"""Lock to ensure that the frontend has finished working before we shut down"""
texture: Optional[Tuple[bytes, str]]
"""Default texture to use for model faces, in (data, mimetype) format.
If left as None, no texture will be used.
It can be set with the YACV_TEXTURE=<uri> and overridden by the custom `yacv_texture` attribute of an object.
The <uri> can be file:<path> or data:<mime>;base64,<data> where <mime> is the mime type and
<data> is the base64 encoded image."""
color_faces: Optional[ColorTuple]
"""Overrides the default color to use for model faces. Applies even if a texture is used.
You can use `show(..., color_faces=...)` or the standard way of setting colors for build123d/cadquery objects to
override this color.
It can be set with the YACV_COLOR_FACES=<color> environment variable, where <color> is a color
in the hexadecimal format #RRGGBB or #RRGGBBAA."""
color_edges: Optional[ColorTuple]
"""Overrides the default color to use for model edges.
You can use `show(..., color_edges=...) or the standard way of setting colors for build123d/cadquery objects to
override this color.
It can be set with the YACV_COLOR_EDGES=<color> environment variable, where <color> is a color
in the hexadecimal format #RRGGBB or #RRGGBBAA."""
color_vertices: Optional[ColorTuple]
"""Overrides the default color to use for model vertices.
You can use `show(..., color_vertices=...)` or the standard way of setting colors for build123d/cadquery objects to
override this color.
It can be set with the YACV_COLOR_VERTICES=<color> environment variable, where <color> is a color
in the hexadecimal format #RRGGBB or #RRGGBBAA."""
def __init__(self):
"""Initializes the YACV server"""
raw_protocol = os.getenv('YACV_PROTOCOL', 'http' if sys.platform != 'emscripten' else 'stderr').upper()
self.protocol = YACVProtocol[raw_protocol] if raw_protocol in YACVProtocol.__members__ else YACVProtocol.HTTP
self.server_thread = None
self.server = None
self.startup_complete = threading.Event()
@@ -97,10 +150,15 @@ class YACV:
self.at_least_one_client = threading.Event()
self.shutting_down = threading.Event()
self.frontend_lock = RWLock()
logger.info('Using yacv-server v%s', version('yacv-server'))
self.texture = _read_texture_uri(os.getenv("YACV_TEXTURE"))
self.color_faces = _read_color(os.getenv("YACV_COLOR_FACES", "#ffbf00")) # Default yellow
self.color_edges = _read_color(os.getenv("YACV_COLOR_EDGES", "#1a1aff")) # Default blue
self.color_vertices = _read_color(os.getenv("YACV_COLOR_VERTICES", "#1a1a1a")) # Default dark gray
logger.info('Using yacv-server v%s', get_version())
def start(self):
"""Starts the web server in the background"""
if self.protocol == YACVProtocol.STDERR: return # No server to start, just print to stderr
assert self.server_thread is None, "Server currently running, cannot start another one"
assert self.startup_complete.is_set() is False, "Server already started"
# Start the server in a separate daemon thread
@@ -117,6 +175,8 @@ class YACV:
# noinspection PyUnusedLocal
def stop(self, *args):
"""Stops the web server"""
if self.protocol == YACVProtocol.STDERR: return # No server to stop, just print to stderr
# The remainder is for the HTTP protocol only
if self.server_thread is None:
logger.error('Cannot stop server because it is not running')
return
@@ -124,7 +184,7 @@ class YACV:
# Inform the server that we are shutting down
self.shutting_down.set()
# noinspection PyTypeChecker
self.show_events.publish(UpdatesApiFullData(name='__shutdown', _hash='', is_remove=None, obj=None))
self._show_event(UpdatesApiFullData(name='__shutdown', _hash='', is_remove=None, obj=None))
# If we were too fast, ensure that at least one client has connected
graceful_secs_connect = float(os.getenv('YACV_GRACEFUL_SECS_CONNECT', 12.0))
@@ -152,9 +212,11 @@ class YACV:
if len(args) >= 1 and args[0] in (signal.SIGINT, signal.SIGTERM):
sys.exit(0) # Exit with success
_yacvServerModelPrefix = "yacv_server://model/"
def _run_server(self):
"""Runs the web server"""
logger.info('Starting server...')
logger.info('Starting server in %s mode...', self.protocol.name)
self.server = ThreadingHTTPServer(
(os.getenv('YACV_HOST', 'localhost'), int(os.getenv('YACV_PORT', 32323))),
lambda a, b, c: HTTPHandler(a, b, c, yacv=self))
@@ -163,13 +225,50 @@ class YACV:
self.startup_complete.set()
self.server.serve_forever()
def _show_event(self, event: UpdatesApiFullData):
"""Handles a show event by publishing it to the show events buffer (and special handling for stderr protocol)."""
self.show_events.publish(event)
# If the protocol is STDERR, we need to print the event to stderr
if self.protocol == YACVProtocol.STDERR:
msg = f'{self._yacvServerModelPrefix}{event.to_json()}'
if not event.is_remove:
# Always build the object even if the interface already has it (optimization disabled for Pyodide)
glb_and_hash = self.export(event.name)
if glb_and_hash is None:
logger.warning('Object %s not found, ignoring it...', event.name)
return
glb = glb_and_hash[0]
msg += f'{base64.b64encode(glb).decode("utf-8")}'
print(msg, file=sys.stderr, flush=True)
def show(self, *objs: List[YACVSupported], names: Optional[Union[str, List[str]]] = None, **kwargs):
"""
Shows the given CAD objects in the frontend. The objects will be tessellated and converted to GLTF. Optionally,
the following keyword arguments can be used:
- auto_clear: Whether to clear the previous objects before showing the new ones (default: True)
- texture: The texture to use for the faces of the object (see `YACV.texture` for more info)
- color: The default color to use for the objects (can be overridden by the `color` attribute of each object)
- tolerance: The tolerance for tessellating the object (default: 0.1)
- angular_tolerance: The angular tolerance for tessellating the object (default: 0.1)
- faces: Whether to tessellate and show the faces of the object (default: True)
- edges: Whether to tessellate and show the edges of the object (default: True)
- vertices: Whether to tessellate and show the vertices of the object (default: True)
:param objs: The CAD objects to show. Can be CAD-like objects (solids, locations, etc.) or bytes (GLTF) objects.
:param names: The names of the objects. If None, the variable names will be used (if possible). The number of
names must match the number of objects. An object of the same name will be replaced in the frontend.
:param kwargs: Additional options for the show_object event.
"""
# Prepare the arguments
start = time.time()
names = names or [_find_var_name(obj) for obj in objs]
if isinstance(names, str):
names = [names]
assert len(names) == len(objs), 'Number of names must match the number of objects'
for color_name in ('color_faces', 'color_edges', 'color_vertices'):
if color_name in kwargs:
kwargs[color_name] = get_color(kwargs[color_name]) or _read_color(kwargs[color_name])
# Handle auto clearing of previous objects
if kwargs.get('auto_clear', True):
@@ -184,17 +283,23 @@ class YACV:
# Publish the show event
for obj, name in zip(objs, names):
obj_color = get_color(obj)
# Some properties may be lost in preprocessing, so save them in kwargs
_kwargs = kwargs.copy()
if obj_color is not None:
_kwargs['color_obj'] = obj_color # Only applies to highest-dimensional objects
_kwargs['texture'] = _read_texture_uri(getattr(obj, 'yacv_texture', None) or kwargs.get('texture', None))
if not isinstance(obj, bytes):
obj = _preprocess_cad(obj, **kwargs)
_hash = _hashcode(obj, **kwargs)
event = UpdatesApiFullData(name=name, _hash=_hash, obj=obj, kwargs=kwargs or {})
self.show_events.publish(event)
obj = _preprocess_cad(obj, **_kwargs)
_hash = _hashcode(obj, **_kwargs)
event = UpdatesApiFullData(name=name, _hash=_hash, obj=obj, kwargs=_kwargs or {})
self._show_event(event)
logger.info('show %s took %.3f seconds', names, time.time() - start)
def show_cad_all(self, **kwargs):
"""Publishes all CAD objects in the current scope to the server"""
all_cad = grab_all_cad()
"""Publishes all CAD objects in the current scope to the server. See `show` for more details."""
all_cad = list(grab_all_cad()) # List for reproducible iteration order
self.show(*[cad for _, cad in all_cad], names=[name for name, _ in all_cad], **kwargs)
def remove(self, name: str):
@@ -213,7 +318,7 @@ class YACV:
# Publish the remove event
show_event = copy.copy(show_events[-1])
show_event.is_remove = True
self.show_events.publish(show_event)
self._show_event(show_event)
def clear(self, except_names: List[str] = None):
"""Clears all previously-shown objects from the scene"""
@@ -272,11 +377,17 @@ class YACV:
if isinstance(event.obj, bytes): # Already a GLTF
publish_to.publish(event.obj)
else: # CAD object to tessellate and convert to GLTF
gltf = tessellate(event.obj, tolerance=event.kwargs.get('tolerance', 0.1),
angular_tolerance=event.kwargs.get('angular_tolerance', 0.1),
faces=event.kwargs.get('faces', True),
edges=event.kwargs.get('edges', True),
vertices=event.kwargs.get('vertices', True))
gltf = tessellate(
event.obj,
color_faces=event.kwargs.get('color_faces', self.color_faces),
color_edges=event.kwargs.get('color_edges', self.color_edges),
color_vertices=event.kwargs.get('color_vertices', self.color_vertices),
color_obj=event.kwargs.get('color_obj', None),
tolerance=event.kwargs.get('tolerance', 0.1),
angular_tolerance=event.kwargs.get('angular_tolerance', 0.1),
faces=event.kwargs.get('faces', True), edges=event.kwargs.get('edges', True),
vertices=event.kwargs.get('vertices', True),
texture=event.kwargs.get('texture', self.texture))
glb_list_of_bytes = gltf.save_to_bytes()
glb_bytes = b''.join(glb_list_of_bytes)
publish_to.publish(glb_bytes)
@@ -288,6 +399,7 @@ class YACV:
try:
return next(subscription), event.hash
finally:
# noinspection PyInconsistentReturns
subscription.close()
def export_all(self, folder: str,
@@ -300,6 +412,39 @@ class YACV:
f.write(self.export(name)[0])
def _read_texture_uri(uri: str) -> Optional[Tuple[bytes, str]]:
if uri is None:
return None
if uri.startswith("file:"):
path = uri[len("file:"):]
with open(path, 'rb') as f:
data = f.read()
buf = BytesIO(data)
img = Image.open(buf)
mtype = img.get_format_mimetype()
return data, mtype
if uri.startswith("data:"): # https://en.wikipedia.org/wiki/Data_URI_scheme#Syntax (limited)
mtype_and_data = uri[len("data:"):]
mtype = mtype_and_data.split(";", 1)[0]
data_str = mtype_and_data.split(",", 1)[1]
data = base64.b64decode(data_str)
return data, mtype
return None
def _read_color(color: str) -> Optional[ColorTuple]:
"""Reads a color from a string in the format #RRGGBB or #RRGGBBAA"""
if color is None:
return None
if not color.startswith('#') or len(color) not in (7, 9):
raise ValueError(f'Invalid color format: {color}')
r = float(int(color[1:3], 16)) / 255.0
g = float(int(color[3:5], 16)) / 255.0
b = float(int(color[5:7], 16)) / 255.0
a = float(int(color[7:9], 16)) / 255.0 if len(color) == 9 else 1.0
return r, g, b, a
# noinspection PyUnusedLocal
def _preprocess_cad(obj: CADLike, **kwargs) -> CADCoreLike:
# Get the shape of a CAD-like object
@@ -319,19 +464,31 @@ def _preprocess_cad(obj: CADLike, **kwargs) -> CADCoreLike:
return obj
_find_var_name_count = 0
_obj_name_counts = {}
def _find_var_name(obj: any, avoid_levels: int = 2) -> str:
"""A hacky way to get a stable name for an object that may change over time"""
global _find_var_name_count
obj_shape = get_shape(obj)
# Build123d objects have a "label" property, CadQuery Assembly's have "name"
for f in ('label', 'name'):
if hasattr(obj, f):
v = getattr(obj, f)
if v != '':
return v;
# Otherwise walk up our stack to see if there's a local variable that points to it
obj_shape = get_shape(obj, error=False) or obj
for frame in inspect.stack()[avoid_levels:]:
for key, value in frame.frame.f_locals.items():
if get_shape(value, error=False) is obj_shape:
return key
_find_var_name_count += 1
return 'unknown_var_' + str(_find_var_name_count)
# Last resort, name it for its type with a disambiguating number
global _obj_name_counts
t = obj.__class__.__name__
_obj_name_counts[t] = 1 if t not in _obj_name_counts else _obj_name_counts[t] + 1
return t + str(_obj_name_counts[t])
def sizeof_fmt(num, suffix="B"):

3576
yarn.lock

File diff suppressed because it is too large Load Diff