Compare commits
168 Commits
v4.12.0-be
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
b549e4c060 | ||
|
6b8c51ca6b | ||
|
91ceb36f42 | ||
|
9624352b2a | ||
|
ae5378c7d1 | ||
|
deb6927d50 | ||
|
46c20d5297 | ||
|
72c3725a10 | ||
|
bb80e4f928 | ||
|
4e5898bdd3 | ||
|
c15bbd1f77 | ||
|
34dcf0a601 | ||
|
c4fd308f73 | ||
|
acdb41af74 | ||
|
c515592598 | ||
|
7c29703b3c | ||
|
b0f9bc9dc1 | ||
|
e36c119082 | ||
|
095ed3ef76 | ||
|
834a97c47e | ||
|
1289d43eea | ||
|
a49f6494a8 | ||
|
690430ac68 | ||
|
717aed5517 | ||
|
73f4fe2cf7 | ||
|
b22df10302 | ||
|
8b81761068 | ||
|
b7d2dba3e8 | ||
|
41faa51738 | ||
|
a21c60c589 | ||
|
824000b509 | ||
|
43297d58cd | ||
|
e93ba41176 | ||
|
65862e5747 | ||
|
458a8bf7f2 | ||
|
c51a420178 | ||
|
dd4fbd9bfd | ||
|
71b0bd77ea | ||
|
2c0d8f11b3 | ||
|
e7dd11e6d9 | ||
|
03d640c569 | ||
|
7953f13112 | ||
|
d207e00cae | ||
|
b9b3a1afa3 | ||
|
65bf903fef | ||
|
a26bf1c17f | ||
|
d766cd1678 | ||
|
368efc7c82 | ||
|
774ef189e1 | ||
|
0b99ed8787 | ||
|
5e51f95352 | ||
|
75d5c59a9a | ||
|
8f0d81c5a3 | ||
|
213fd7fa40 | ||
|
4c63e657ae | ||
|
fac8535b21 | ||
|
545b052dee | ||
|
09bbf45c5f | ||
|
a11651b3ab | ||
|
f438cbb816 | ||
|
2a5bd7cf07 | ||
|
ee80888e71 | ||
|
97f6382e8a | ||
|
89bea015b1 | ||
|
f1d3243f0f | ||
|
3039c281d2 | ||
|
54838b65b1 | ||
|
8208382ccd | ||
|
fc66268c64 | ||
|
22d3497ce3 | ||
|
7488b73f9b | ||
|
3d88d91bf0 | ||
|
d9b72a218d | ||
|
d61ae83ab8 | ||
|
885991a565 | ||
|
724eea36a1 | ||
|
e620783bb0 | ||
|
4ffe74f86c | ||
|
39ff9b053a | ||
|
7b328cabbf | ||
|
8253256d09 | ||
|
5a56af019e | ||
|
86b75f066a | ||
|
777565eb6c | ||
|
c45cc65286 | ||
|
2627c9a86c | ||
|
83d173e01f | ||
|
bf148732e3 | ||
|
e4457ba114 | ||
|
47c662fb68 | ||
|
7d1600be60 | ||
|
32d7f3597c | ||
|
e049f2cf9c | ||
|
72be1f3ffb | ||
|
915c15da9d | ||
|
787cdd671e | ||
|
5cbccc98f3 | ||
|
f437b04a24 | ||
|
a74c79ac28 | ||
|
f0f06041d7 | ||
|
cd81dc8bc2 | ||
|
3c674e6cfa | ||
|
94ac808090 | ||
|
68dbf7585d | ||
|
697b2b43be | ||
|
078d4910fb | ||
|
dd9cd1798e | ||
|
afad90cf85 | ||
|
af39d3ba49 | ||
|
c1d35e4dd6 | ||
|
5ca1cd86c1 | ||
|
ee0818495d | ||
|
cd7a7e55c0 | ||
|
6896b3571d | ||
|
bbbfecb28a | ||
|
929c6df161 | ||
|
3156382ae0 | ||
|
edd3e92c74 | ||
|
85f0db0cb7 | ||
|
10ba7d995b | ||
|
c756e75c33 | ||
|
946d7f4c64 | ||
|
ce01e8bde4 | ||
|
1afe9f4130 | ||
|
1867b79aec | ||
|
bcfbee2aac | ||
|
2a3f817b88 | ||
|
a3420e9309 | ||
|
36871858da | ||
|
ead7caa716 | ||
|
4792e3725c | ||
|
b4a9be49fb | ||
|
0c94c659f8 | ||
|
ac2b38ff51 | ||
|
42d0aec873 | ||
|
f6070dd7bd | ||
|
c6f6179cef | ||
|
8c1c7b6ce9 | ||
|
85f4eab039 | ||
|
b881106fb6 | ||
|
bc2d642246 | ||
|
90f210c1c2 | ||
|
ca808cd02d | ||
|
180a691bc5 | ||
|
ba15f2e251 | ||
|
201bfd0a7d | ||
|
3e37689c16 | ||
|
e571275c68 | ||
|
f1fb415879 | ||
|
b317dca17b | ||
|
42718c184b | ||
|
0db5881da9 | ||
|
0602e600f5 | ||
|
e027c9066a | ||
|
d16319426e | ||
|
1e51e3f0c2 | ||
|
0ce96f7c5b | ||
|
6ab6bd9800 | ||
|
5e3f819a62 | ||
|
da9e7a0227 | ||
|
88a1dbafe2 | ||
|
3ed74ef095 | ||
|
aad6434fa4 | ||
|
c695e26782 | ||
|
7deb76ab43 | ||
|
9cc89be4de | ||
|
5ce93c2104 | ||
|
e108675736 |
6
.github/workflows/webapp.yml
vendored
@ -21,7 +21,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: Setup Pages
|
||||
uses: actions/configure-pages@v3
|
||||
- name: Build
|
||||
@ -29,10 +29,10 @@ jobs:
|
||||
npm install
|
||||
npm run prepublish
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-pages-artifact@v2
|
||||
uses: actions/upload-pages-artifact@v3
|
||||
with:
|
||||
# Upload entire repository
|
||||
path: '.'
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v2
|
||||
uses: actions/deploy-pages@v4
|
||||
|
@ -23,10 +23,6 @@ jobs:
|
||||
- sudo apt-get install rpm
|
||||
- electron-builder --publish=onTagOrDraft
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- node_modules
|
||||
|
||||
install:
|
||||
- npm install
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
# Blockbench
|
||||
|
||||
Blockbench is a free, modern model editor for low-poly and boxy models with pixel art textures.
|
||||
Blockbench is a free and open source model editor for low-poly models with pixel art textures.
|
||||
Models can be exported into standardized formats, to be shared, rendered, 3D-printed, or used in game engines. There are also multiple dedicated formats for Minecraft Java and Bedrock Edition with format-specific features.
|
||||
|
||||
Blockbench features a modern and intuitive UI, plugin support and innovative features. It is the industry standard for creating custom 3D models for the Minecraft Marketplace.
|
||||
Blockbench features a modern and beginner friendly interface, but also offers lots of customization and advanced features for experienced 3D artists. Plugins can extend the functionality of the program even further.
|
||||
|
||||
Website and download: [blockbench.net](https://www.blockbench.net)
|
||||
|
||||
@ -27,6 +27,8 @@ To launch Blockbench from source, you can clone the repository, navigate to the
|
||||
* Install [NodeJS](https://nodejs.org/en/).
|
||||
* Then install all dependencies via
|
||||
`npm install`
|
||||
* Bundle the code via
|
||||
`npm run bundle`
|
||||
* Finally, launch Blockbench using
|
||||
`npm run dev`
|
||||
|
||||
@ -34,7 +36,7 @@ To launch Blockbench from source, you can clone the repository, navigate to the
|
||||
|
||||
## Plugins
|
||||
|
||||
Blockbench supports Javascript-based plugins. Learn more about creating plugins on [https://www.blockbench.net/wiki/api/index](https://www.blockbench.net/wiki/api/index).
|
||||
Blockbench supports Javascript-based plugins. Learn more about creating plugins on [https://www.blockbench.net/wiki/docs/plugin](https://www.blockbench.net/wiki/docs/plugin).
|
||||
|
||||
|
||||
|
||||
|
12
assets/netlify-full-logo-dark.svg
Normal file
@ -0,0 +1,12 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="147" height="40">
|
||||
<defs>
|
||||
<radialGradient id="a" cy="0%" r="100.11%" fx="50%" fy="0%" gradientTransform="matrix(0 .9989 -1.152 0 .5 -.5)">
|
||||
<stop offset="0%" stop-color="#20C6B7"/>
|
||||
<stop offset="100%" stop-color="#4D9ABF"/>
|
||||
</radialGradient>
|
||||
</defs>
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<path fill="#FFF" d="M53.37 12.978l.123 2.198c1.403-1.7 3.245-2.55 5.525-2.55 3.951 0 5.962 2.268 6.032 6.804v12.568H60.79V19.676c0-1.207-.26-2.1-.78-2.681-.52-.58-1.371-.87-2.552-.87-1.719 0-3 .78-3.84 2.338v13.535h-4.262v-19.02h4.016zM77.748 32.35c-2.7 0-4.89-.852-6.567-2.557-1.678-1.705-2.517-3.976-2.517-6.812v-.527c0-1.898.365-3.595 1.096-5.089.73-1.494 1.757-2.657 3.078-3.49 1.321-.831 2.794-1.247 4.42-1.247 2.583 0 4.58.826 5.988 2.478 1.41 1.653 2.114 3.99 2.114 7.014v1.723h-12.4c.13 1.57.652 2.812 1.57 3.726.918.914 2.073 1.371 3.464 1.371 1.952 0 3.542-.79 4.77-2.373l2.297 2.198c-.76 1.136-1.774 2.018-3.042 2.645-1.269.627-2.692.94-4.27.94zm-.508-16.294c-1.17 0-2.113.41-2.832 1.23-.72.82-1.178 1.963-1.377 3.428h8.12v-.317c-.094-1.43-.474-2.51-1.14-3.243-.667-.732-1.59-1.098-2.771-1.098zm16.765-7.7v4.623h3.35v3.164h-3.35V26.76c0 .726.144 1.25.43 1.573.286.322.798.483 1.535.483a6.55 6.55 0 0 0 1.49-.176v3.305c-.97.27-1.905.404-2.806.404-3.273 0-4.91-1.81-4.91-5.431V16.142H86.62v-3.164h3.122V8.355h4.261zm11.137 23.643h-4.262v-27h4.262v27zm9.172 0h-4.262v-19.02h4.262v19.02zm-4.525-23.96c0-.655.207-1.2.622-1.634.416-.433 1.009-.65 1.78-.65.772 0 1.368.217 1.79.65.42.434.63.979.63 1.635 0 .644-.21 1.18-.63 1.608-.422.428-1.018.642-1.79.642-.771 0-1.364-.214-1.78-.642-.415-.427-.622-.964-.622-1.608zm10.663 23.96V16.142h-2.894v-3.164h2.894v-1.74c0-2.11.584-3.738 1.753-4.887 1.17-1.148 2.806-1.722 4.91-1.722.749 0 1.544.105 2.386.316l-.105 3.34a8.375 8.375 0 0 0-1.631-.14c-2.035 0-3.052 1.048-3.052 3.146v1.687h3.858v3.164h-3.858v15.856h-4.261zm17.87-6.117l3.858-12.903h4.542l-7.54 21.903c-1.158 3.199-3.122 4.799-5.893 4.799-.62 0-1.304-.106-2.052-.317v-3.305l.807.053c1.075 0 1.885-.196 2.429-.589.543-.392.973-1.051 1.289-1.977l.613-1.635-6.664-18.932h4.595l4.016 12.903z"/>
|
||||
<path fill="url(#a)" fill-rule="nonzero" d="M28.589 14.135l-.014-.006c-.008-.003-.016-.006-.023-.013a.11.11 0 0 1-.028-.093l.773-4.726 3.625 3.626-3.77 1.604a.083.083 0 0 1-.033.006h-.015c-.005-.003-.01-.007-.02-.017a1.716 1.716 0 0 0-.495-.381zm5.258-.288l3.876 3.876c.805.806 1.208 1.208 1.355 1.674.022.069.04.138.054.209l-9.263-3.923a.728.728 0 0 0-.015-.006c-.037-.015-.08-.032-.08-.07 0-.038.044-.056.081-.071l.012-.005 3.98-1.684zm5.127 7.003c-.2.376-.59.766-1.25 1.427l-4.37 4.369-5.652-1.177-.03-.006c-.05-.008-.103-.017-.103-.062a1.706 1.706 0 0 0-.655-1.193c-.023-.023-.017-.059-.01-.092 0-.005 0-.01.002-.014l1.063-6.526.004-.022c.006-.05.015-.108.06-.108a1.73 1.73 0 0 0 1.16-.665c.009-.01.015-.021.027-.027.032-.015.07 0 .103.014l9.65 4.082zm-6.625 6.801l-7.186 7.186 1.23-7.56.002-.01c.001-.01.003-.02.006-.029.01-.024.036-.034.061-.044l.012-.005a1.85 1.85 0 0 0 .695-.517c.024-.028.053-.055.09-.06a.09.09 0 0 1 .029 0l5.06 1.04zm-8.707 8.707l-.81.81-8.955-12.942a.424.424 0 0 0-.01-.014c-.014-.019-.029-.038-.026-.06 0-.016.011-.03.022-.042l.01-.013c.027-.04.05-.08.075-.123l.02-.035.003-.003c.014-.024.027-.047.051-.06.021-.01.05-.006.073-.001l9.921 2.046a.164.164 0 0 1 .076.033c.013.013.016.027.019.043a1.757 1.757 0 0 0 1.028 1.175c.028.014.016.045.003.078a.238.238 0 0 0-.015.045c-.125.76-1.197 7.298-1.485 9.063zm-1.692 1.691c-.597.591-.949.904-1.347 1.03a2 2 0 0 1-1.206 0c-.466-.148-.869-.55-1.674-1.356L8.73 28.73l2.349-3.643c.011-.018.022-.034.04-.047.025-.018.061-.01.091 0a2.434 2.434 0 0 0 1.638-.083c.027-.01.054-.017.075.002a.19.19 0 0 1 .028.032L21.95 38.05zM7.863 27.863L5.8 25.8l4.074-1.738a.084.084 0 0 1 .033-.007c.034 0 .054.034.072.065a2.91 2.91 0 0 0 .13.184l.013.016c.012.017.004.034-.008.05l-2.25 3.493zm-2.976-2.976l-2.61-2.61c-.444-.444-.766-.766-.99-1.043l7.936 1.646a.84.84 0 0 0 .03.005c.049.008.103.017.103.063 0 .05-.059.073-.109.092l-.023.01-4.337 1.837zM.831 19.892a2 2 0 0 1 .09-.495c.148-.466.55-.868 1.356-1.674l3.34-3.34a2175.525 2175.525 0 0 0 4.626 6.687c.027.036.057.076.026.106-.146.161-.292.337-.395.528a.16.16 0 0 1-.05.062c-.013.008-.027.005-.042.002H9.78L.831 19.891zm5.68-6.403L11 8.998c.423.185 1.96.834 3.333 1.414 1.04.44 1.988.84 2.286.97.03.012.057.024.07.054.008.018.004.041 0 .06a2.003 2.003 0 0 0 .523 1.828c.03.03 0 .073-.026.11l-.014.021-4.56 7.063c-.012.02-.023.037-.043.05-.024.015-.058.008-.086.001a2.274 2.274 0 0 0-.543-.074c-.164 0-.342.03-.522.063h-.001c-.02.003-.038.007-.054-.005a.21.21 0 0 1-.045-.051l-4.808-7.013zm5.398-5.398l5.814-5.814c.805-.805 1.208-1.208 1.674-1.355a2 2 0 0 1 1.206 0c.466.147.869.55 1.674 1.355l1.26 1.26-4.135 6.404a.155.155 0 0 1-.041.048c-.025.017-.06.01-.09 0a2.097 2.097 0 0 0-1.92.37c-.027.028-.067.012-.101-.003-.54-.235-4.74-2.01-5.341-2.265zm12.506-3.676l3.818 3.818-.92 5.698v.015a.135.135 0 0 1-.008.038c-.01.02-.03.024-.05.03a1.83 1.83 0 0 0-.548.273.154.154 0 0 0-.02.017c-.011.012-.022.023-.04.025a.114.114 0 0 1-.043-.007l-5.818-2.472-.011-.005c-.037-.015-.081-.033-.081-.071a2.198 2.198 0 0 0-.31-.915c-.028-.046-.059-.094-.035-.141l4.066-6.303zm-3.932 8.606l5.454 2.31c.03.014.063.027.076.058a.106.106 0 0 1 0 .057c-.016.08-.03.171-.03.263v.153c0 .038-.039.054-.075.069l-.011.004c-.864.369-12.13 5.173-12.147 5.173-.017 0-.035 0-.052-.017-.03-.03 0-.072.027-.11a.76.76 0 0 0 .014-.02l4.482-6.94.008-.012c.026-.042.056-.089.104-.089l.045.007c.102.014.192.027.283.027.68 0 1.31-.331 1.69-.897a.16.16 0 0 1 .034-.04c.027-.02.067-.01.098.004zm-6.246 9.185l12.28-5.237s.018 0 .035.017c.067.067.124.112.179.154l.027.017c.025.014.05.03.052.056 0 .01 0 .016-.002.025L25.756 23.7l-.004.026c-.007.05-.014.107-.061.107a1.729 1.729 0 0 0-1.373.847l-.005.008c-.014.023-.027.045-.05.057-.021.01-.048.006-.07.001l-9.793-2.02c-.01-.002-.152-.519-.163-.52z" transform="translate(-.702)"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 200 KiB After Width: | Height: | Size: 197 KiB |
Before Width: | Height: | Size: 131 KiB After Width: | Height: | Size: 159 KiB |
Before Width: | Height: | Size: 201 KiB After Width: | Height: | Size: 226 KiB |
BIN
assets/splash_art/4.webp
Normal file
After Width: | Height: | Size: 180 KiB |
BIN
content/collections.png
Normal file
After Width: | Height: | Size: 115 KiB |
Before Width: | Height: | Size: 60 KiB |
BIN
content/group_multi_select.png
Normal file
After Width: | Height: | Size: 99 KiB |
BIN
content/lasso.png
Normal file
After Width: | Height: | Size: 106 KiB |
@ -1,29 +1,38 @@
|
||||
{
|
||||
"new_version": {
|
||||
"color": "var(--color-bright_ui)",
|
||||
"text_color": "var(--color-bright_ui_text)",
|
||||
"color": "var(--color-dark)",
|
||||
"layout": "vertical",
|
||||
"insert_after": "splash_screen",
|
||||
"text": [
|
||||
{"text": "Welcome to Blockbench 4.11", "type": "h3"},
|
||||
{"text": "The Texture Group Update!", "type": "h1"},
|
||||
{"text": "Check out the [full changelog](https://github.com/JannisX11/blockbench/releases/tag/v4.11.0)!"}
|
||||
{"text": "Welcome to Blockbench 4.12", "type": "h3"},
|
||||
{"text": "The Collection & Selection Update!", "type": "h1"},
|
||||
{"text": "Check out the [full changelog](https://github.com/JannisX11/blockbench/releases/tag/v4.12.0)!"}
|
||||
],
|
||||
"features": [
|
||||
{
|
||||
"image": "https://web.blockbench.net/content/texture_groups.png",
|
||||
"title": "Texture Groups",
|
||||
"text": "Organize your textures with groups!"
|
||||
"image": "https://web.blockbench.net/content/pbr.png",
|
||||
"title": "PBR Editing + Preview",
|
||||
"text": "Create, edit, and view physically based materials"
|
||||
},
|
||||
{
|
||||
"image": "https://web.blockbench.net/content/tiled_view.png",
|
||||
"title": "Onion Skin and Tiled View",
|
||||
"text": "Use onion skinning on animated textures or create tiled textures."
|
||||
"image": "https://web.blockbench.net/content/collections.png",
|
||||
"title": "Collections",
|
||||
"text": "A new way to organize your model!"
|
||||
},
|
||||
{
|
||||
"image": "https://web.blockbench.net/content/cube_knife.png",
|
||||
"title": "Knife Tool for Cubes",
|
||||
"text": "Use the knife tool to cut cubes and speed up your workflow!"
|
||||
"image": "https://web.blockbench.net/content/lasso.png",
|
||||
"title": "Lasso Selection Tool",
|
||||
"text": "Select free-form shapes in the 2D Editor"
|
||||
},
|
||||
{
|
||||
"image": "https://web.blockbench.net/content/group_multi_select.png",
|
||||
"title": "Group Multi Selection",
|
||||
"text": "You can finally select multiple groups at once!"
|
||||
},
|
||||
{
|
||||
"image": "https://web.blockbench.net/content/rotation_snap.png",
|
||||
"title": "Rotation Snap",
|
||||
"text": "It's vertex snap, but for rotations!"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
BIN
content/pbr.png
Normal file
After Width: | Height: | Size: 342 KiB |
BIN
content/rotation_snap.png
Normal file
After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 24 KiB |
@ -387,6 +387,9 @@
|
||||
flex-grow: 1;
|
||||
padding: 3px 5px;
|
||||
}
|
||||
.form_bar > .nslide_tool {
|
||||
flex-grow: 1;
|
||||
}
|
||||
.dialog_form_description {
|
||||
margin-left: auto;
|
||||
padding-top: 8px;
|
||||
@ -1982,7 +1985,7 @@
|
||||
cursor: pointer;
|
||||
border: 2px solid transparent;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 5px;
|
||||
}
|
||||
#edit_history_list ul li.current {
|
||||
border-color: var(--color-accent);
|
||||
@ -2009,6 +2012,9 @@
|
||||
#edit_history_list .edit_history_time {
|
||||
color: var(--color-subtle_text);
|
||||
}
|
||||
#edit_history_list > ul > li label {
|
||||
margin-right: auto;
|
||||
}
|
||||
#edit_history_list ul li.selected .edit_history_time {
|
||||
color: inherit;
|
||||
}
|
||||
|
@ -1218,6 +1218,10 @@
|
||||
}
|
||||
|
||||
/* Placeholders */
|
||||
ul#placeholder_buttons {
|
||||
max-height: 32%;
|
||||
overflow: auto;
|
||||
}
|
||||
#placeholder_buttons li {
|
||||
padding: 0px 8px;
|
||||
height: 30px;
|
||||
@ -2031,6 +2035,7 @@ span.controller_state_section_info {
|
||||
.controller_state_connection_wrapper_top,
|
||||
.controller_state_connection_wrapper_bottom {
|
||||
height: calc(20px + var(--max-layer) * 10px);
|
||||
min-height: calc(20px + var(--max-layer) * 10px);
|
||||
position: relative;
|
||||
}
|
||||
.controller_state_connection {
|
||||
@ -2376,6 +2381,33 @@ span.controller_state_section_info {
|
||||
stroke-dashoffset: -10px;
|
||||
}
|
||||
}
|
||||
#texture_selection_polygon {
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
width: calc(100% + 2px);
|
||||
height: calc(100% + 2px);
|
||||
top: -1px;
|
||||
left: -1px;
|
||||
object-fit: cover;
|
||||
object-position: 0 0;
|
||||
}
|
||||
#texture_selection_polygon path {
|
||||
fill: none;
|
||||
stroke-width: 2px;
|
||||
stroke: var(--color-light);
|
||||
stroke-dasharray: 5px 3px;
|
||||
stroke-dashoffset: 0;
|
||||
animation: selection-outline-shift 700ms linear infinite;
|
||||
animation-timing-function: steps(3, end);
|
||||
}
|
||||
#texture_selection_polygon circle {
|
||||
fill: var(--color-ui);
|
||||
stroke-width: 1;
|
||||
stroke: var(--color-border);
|
||||
}
|
||||
#texture_selection_polygon circle.closed {
|
||||
fill: var(--color-accent);
|
||||
}
|
||||
|
||||
.face_properties_toggle {
|
||||
width: 32px;
|
||||
|
@ -221,6 +221,7 @@
|
||||
padding-right: 15px;
|
||||
padding-left: 100px;
|
||||
background: linear-gradient(90deg, rgba(3,86,112,0) 0%, rgba(0,10,22,0.63) 34%, rgba(0,9,20,0.72) 45%);
|
||||
color: #d5d5d5;
|
||||
position: absolute;
|
||||
}
|
||||
#start_screen div.start_screen_right {
|
||||
@ -240,15 +241,17 @@
|
||||
#start_screen i.start_screen_close_button:not(:hover) {
|
||||
opacity: 0.8;
|
||||
}
|
||||
#start_screen section.vertical .start_screen_right {
|
||||
box-shadow: 0 0 40px rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
#start_screen section.vertical.bright_ui .start_screen_right {
|
||||
box-shadow: 0 0 14px #00103030;
|
||||
}
|
||||
#start_screen .start_screen_features {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex-wrap: wrap-reverse;
|
||||
box-sizing: border-box;
|
||||
padding: 12px;
|
||||
background: #00004006;
|
||||
}
|
||||
#start_screen .start_screen_features > li {
|
||||
width: 30%;
|
||||
@ -260,6 +263,10 @@
|
||||
margin: 7px;
|
||||
padding: 7px;
|
||||
}
|
||||
#start_screen .start_screen_features > li:nth-child(1),
|
||||
#start_screen .start_screen_features > li:nth-child(2) {
|
||||
order: 1;
|
||||
}
|
||||
#start_screen .start_screen_features > li > * {
|
||||
max-width: 100%;
|
||||
font-weight: 300;
|
||||
@ -268,6 +275,7 @@
|
||||
}
|
||||
#start_screen .start_screen_features > li > img {
|
||||
border-radius: 5px;
|
||||
-webkit-user-drag: none;
|
||||
}
|
||||
#start_screen .start_screen_features > li > h3 {
|
||||
font-size: 1.4em;
|
||||
|
@ -1228,7 +1228,7 @@
|
||||
width: fit-content;
|
||||
z-index: 3;
|
||||
}
|
||||
#amend_edit_menu > form {
|
||||
#amend_edit_menu > div.form {
|
||||
background-color: var(--color-ui);
|
||||
padding: 2px 10px;
|
||||
}
|
||||
|
@ -98,6 +98,7 @@
|
||||
<script src="js/util/array_util.js"></script>
|
||||
<script src="js/util/event_system.js"></script>
|
||||
<script src="js/util/property.js"></script>
|
||||
<script src="js/util/json.js"></script>
|
||||
<script src="js/interface/menu.js"></script>
|
||||
<script src="js/interface/actions.js"></script>
|
||||
<script src="js/interface/themes.js"></script>
|
||||
|
@ -133,8 +133,8 @@ class Animation extends AnimationItem {
|
||||
copy.animators = {}
|
||||
for (var uuid in this.animators) {
|
||||
let ba = this.animators[uuid]
|
||||
var kfs = ba.keyframes
|
||||
if ((kfs && kfs.length) || ba.rotation_global) {
|
||||
let kfs = ba.keyframes
|
||||
if ((kfs && kfs.length) || ba.rotation_global || !save) {
|
||||
let ba_copy = copy.animators[uuid] = {
|
||||
name: ba.name,
|
||||
type: ba.type,
|
||||
@ -160,10 +160,10 @@ class Animation extends AnimationItem {
|
||||
|
||||
if (this.length) ani_tag.animation_length = Math.roundTo(this.length, 4);
|
||||
if (this.override) ani_tag.override_previous_animation = true;
|
||||
if (this.anim_time_update) ani_tag.anim_time_update = this.anim_time_update.replace(/\n/g, '');
|
||||
if (this.blend_weight) ani_tag.blend_weight = this.blend_weight.replace(/\n/g, '');
|
||||
if (this.start_delay) ani_tag.start_delay = this.start_delay.replace(/\n/g, '');
|
||||
if (this.loop_delay && ani_tag.loop) ani_tag.loop_delay = this.loop_delay.replace(/\n/g, '');
|
||||
if (this.anim_time_update) ani_tag.anim_time_update = exportMolang(this.anim_time_update);
|
||||
if (this.blend_weight) ani_tag.blend_weight = exportMolang(this.blend_weight);
|
||||
if (this.start_delay) ani_tag.start_delay = exportMolang(this.start_delay);
|
||||
if (this.loop_delay && ani_tag.loop) ani_tag.loop_delay = exportMolang(this.loop_delay);
|
||||
ani_tag.bones = {};
|
||||
|
||||
for (var uuid in this.animators) {
|
||||
@ -433,14 +433,19 @@ class Animation extends AnimationItem {
|
||||
return this;
|
||||
}
|
||||
select() {
|
||||
var scope = this;
|
||||
Prop.active_panel = 'animations';
|
||||
let previous_animation = Animation.selected;
|
||||
if (this == Animation.selected) return;
|
||||
var selected_bone = Group.first_selected;
|
||||
AnimationItem.all.forEach((a) => {
|
||||
a.selected = false;
|
||||
if (a.playing == true) a.playing = false;
|
||||
})
|
||||
let animator_keys = previous_animation && Object.keys(previous_animation.animators);
|
||||
let selected_animator_key;
|
||||
let timeline_animator_keys = previous_animation && Timeline.animators.map(a => {
|
||||
let key = animator_keys.find(key => previous_animation.animators[key] == a);
|
||||
if (a.selected) selected_animator_key = key;
|
||||
return key;
|
||||
});
|
||||
Timeline.clear();
|
||||
Timeline.vue._data.markers = this.markers;
|
||||
Timeline.vue._data.animation_length = this.length;
|
||||
@ -453,15 +458,21 @@ class Animation extends AnimationItem {
|
||||
BarItems.slider_animation_length.update();
|
||||
|
||||
Group.all.forEach(group => {
|
||||
scope.getBoneAnimator(group);
|
||||
this.getBoneAnimator(group);
|
||||
})
|
||||
Outliner.elements.forEach(element => {
|
||||
if (!element.constructor.animator) return;
|
||||
scope.getBoneAnimator(element);
|
||||
this.getBoneAnimator(element);
|
||||
})
|
||||
|
||||
if (selected_bone) {
|
||||
selected_bone.select();
|
||||
if (timeline_animator_keys) {
|
||||
timeline_animator_keys.forEachReverse(key => {
|
||||
let animator = this.animators[key];
|
||||
if (animator) {
|
||||
animator.addToTimeline();
|
||||
if (selected_animator_key == key) animator.select(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (Modes.animate) {
|
||||
Animator.preview();
|
||||
@ -470,6 +481,12 @@ class Animation extends AnimationItem {
|
||||
Blockbench.dispatchEvent('select_animation', {animation: this})
|
||||
return this;
|
||||
}
|
||||
clickSelect() {
|
||||
Undo.initSelection();
|
||||
Prop.active_panel = 'animations';
|
||||
this.select();
|
||||
Undo.finishSelection('Select animation')
|
||||
}
|
||||
setLength(len = this.length) {
|
||||
this.length = 0;
|
||||
this.length = limitNumber(len, this.getMaxLength(), 1e4);
|
||||
@ -1752,12 +1769,17 @@ BARS.defineActions(function() {
|
||||
temp_animators[target_uuid] = new animator.constructor(target_uuid, animation);
|
||||
copyAnimator(temp_animators[target_uuid], target_animator);
|
||||
}
|
||||
|
||||
let tempsave_current_animator = !temp_animators[animator.uuid];
|
||||
if (tempsave_current_animator) {
|
||||
temp_animators[animator.uuid] = new animator.constructor(animator.uuid, animation);
|
||||
copyAnimator(temp_animators[animator.uuid], animator);
|
||||
}
|
||||
|
||||
copyAnimator(target_animator, temp_animators[animator.uuid] ?? animator);
|
||||
|
||||
// Reset animator
|
||||
if (!temp_animators[animator.uuid]) {
|
||||
temp_animators[animator.uuid] = new animator.constructor(animator.uuid, animation);
|
||||
copyAnimator(temp_animators[animator.uuid], animator);
|
||||
if (tempsave_current_animator) {
|
||||
resetAnimator(animator)
|
||||
}
|
||||
}
|
||||
@ -2110,8 +2132,8 @@ Interface.definePanels(function() {
|
||||
v-bind:class="{ selected: animation.selected }"
|
||||
v-bind:anim_id="animation.uuid"
|
||||
class="animation"
|
||||
v-on:click.stop="animation.select()"
|
||||
v-on:dblclick.stop="animation.propertiesDialog()"
|
||||
@click.stop="animation.clickSelect()"
|
||||
@dblclick.stop="animation.propertiesDialog()"
|
||||
:key="animation.uuid"
|
||||
@contextmenu.prevent.stop="animation.showContextMenu($event)"
|
||||
>
|
||||
|
@ -2,6 +2,8 @@ class AnimationControllerState {
|
||||
constructor(controller, data = 0) {
|
||||
this.controller = controller;
|
||||
this.uuid = guid();
|
||||
this.transitions = [];
|
||||
this.animations = [];
|
||||
|
||||
for (let key in AnimationControllerState.properties) {
|
||||
AnimationControllerState.properties[key].reset(this);
|
||||
@ -39,60 +41,63 @@ class AnimationControllerState {
|
||||
}
|
||||
}
|
||||
if (data.animations instanceof Array) {
|
||||
let previous_animations = this.animations.slice();
|
||||
this.animations.empty();
|
||||
data.animations.forEach(a => {
|
||||
let animation;
|
||||
let animation = previous_animations.find(a1 => a1.uuid == a.uuid) ?? {
|
||||
uuid: guid(),
|
||||
key: '',
|
||||
animation: '',
|
||||
blend_value: ''
|
||||
};
|
||||
if (typeof a == 'object' && typeof a.uuid == 'string' && a.uuid.length == 36) {
|
||||
// Internal
|
||||
animation = {
|
||||
uuid: a.uuid || guid(),
|
||||
key: a.key || '',
|
||||
animation: a.animation || '',// UUID
|
||||
blend_value: a.blend_value || ''
|
||||
};
|
||||
Object.assign(animation, a);
|
||||
} else if (typeof a == 'object' || typeof a == 'string') {
|
||||
// Bedrock
|
||||
let key = typeof a == 'object' ? Object.keys(a)[0] : a;
|
||||
let anim_match = Animation.all.find(anim => anim.getShortName() == key);
|
||||
animation = {
|
||||
uuid: guid(),
|
||||
Object.assign(animation, {
|
||||
key: key || '',
|
||||
animation: anim_match ? anim_match.uuid : '',// UUID
|
||||
blend_value: (typeof a == 'object' && a[key]) || ''
|
||||
};
|
||||
});
|
||||
}
|
||||
this.animations.push(animation);
|
||||
})
|
||||
}
|
||||
if (data.transitions instanceof Array) {
|
||||
let previous_transitions = this.transitions.slice();
|
||||
this.transitions.empty();
|
||||
data.transitions.forEach(a => {
|
||||
let transition;
|
||||
let transition = previous_transitions.find(t1 => t1.uuid == a.uuid) ?? {
|
||||
uuid: guid(),
|
||||
target: '',
|
||||
condition: ''
|
||||
};
|
||||
this.transitions.push(transition);
|
||||
if (typeof a == 'object' && typeof a.uuid == 'string' && a.uuid.length == 36) {
|
||||
// Internal
|
||||
transition = {
|
||||
uuid: a.uuid || guid(),
|
||||
target: a.target || '',
|
||||
condition: a.condition || ''
|
||||
};
|
||||
Object.assign(transition, a);
|
||||
} else if (typeof a == 'object') {
|
||||
// Bedrock
|
||||
let key = Object.keys(a)[0];
|
||||
let state_match = this.controller.states.find(state => state !== this && state.name == key);
|
||||
transition = {
|
||||
uuid: guid(),
|
||||
Object.assign(transition, {
|
||||
target: state_match ? state_match.uuid : '',
|
||||
condition: a[key] || ''
|
||||
};
|
||||
});
|
||||
if (!state_match) {
|
||||
setTimeout(() => {
|
||||
// Delay to after loading controller so that all states can be found
|
||||
let state_match = this.controller.states.find(state => state !== this && state.name == key);
|
||||
if (state_match) transition.target = state_match.uuid;
|
||||
if (state_match) {
|
||||
let updated_transition = this.transitions.find(t => t.uuid == transition.uuid) ?? transitions;
|
||||
updated_transition.target = state_match.uuid;
|
||||
}
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
this.transitions.push(transition);
|
||||
})
|
||||
}
|
||||
if (data.particles instanceof Array) {
|
||||
@ -1040,7 +1045,6 @@ class AnimationController extends AnimationItem {
|
||||
return this;
|
||||
}
|
||||
select() {
|
||||
Prop.active_panel = 'animations';
|
||||
if (this == AnimationController.selected) return;
|
||||
if (Timeline.playing) Timeline.pause()
|
||||
AnimationItem.all.forEach((a) => {
|
||||
@ -1061,6 +1065,11 @@ class AnimationController extends AnimationItem {
|
||||
}
|
||||
return this;
|
||||
}
|
||||
clickSelect() {
|
||||
Undo.initSelection();
|
||||
this.select();
|
||||
Undo.finishSelection('Select animation')
|
||||
}
|
||||
createUniqueName(arr) {
|
||||
var scope = this;
|
||||
var others = AnimationController.all.slice();
|
||||
@ -1499,6 +1508,7 @@ Interface.definePanels(() => {
|
||||
'_',
|
||||
{id: 'remove', name: 'generic.remove', icon: 'clear', click() {
|
||||
Undo.initEdit({animation_controller_state: state});
|
||||
animation = state.animations.find(t => t.uuid == animation.uuid);
|
||||
state.animations.remove(animation);
|
||||
Undo.finishEdit('Remove animation from controller state');
|
||||
}}
|
||||
@ -1522,6 +1532,7 @@ Interface.definePanels(() => {
|
||||
'_',
|
||||
{id: 'remove', name: 'generic.remove', icon: 'clear', click() {
|
||||
Undo.initEdit({animation_controller_state: state});
|
||||
transition = state.transitions.find(t => t.uuid == transition.uuid);
|
||||
state.transitions.remove(transition);
|
||||
Undo.finishEdit('Remove transition from controller state');
|
||||
}}
|
||||
@ -2007,13 +2018,13 @@ Interface.definePanels(() => {
|
||||
<div class="text_button" @click.stop="addAnimationButton(state, $event)"><i class="icon fa fa-plus"></i></div>
|
||||
</div>
|
||||
<ul v-if="!state.fold.animations" v-sortable="{onUpdate(event) {sortAnimation(state, event)}, animation: 160, handle: '.controller_item_drag_handle'}">
|
||||
<li v-for="animation in state.animations" :key="animation.uuid" class="controller_animation">
|
||||
<li v-for="(animation, i) in state.animations" :key="animation.uuid" class="controller_animation">
|
||||
<div class="controller_item_drag_handle"></div>
|
||||
<div class="tool" title="" @click="openAnimationMenu(state, animation, $event.target)"><i class="material-icons">movie</i></div>
|
||||
<input type="text" class="dark_bordered tab_target animation_controller_text_input" v-model="animation.key">
|
||||
<div class="tool" title="" @click="openAnimationMenu(state, state.animations[i], $event.target)"><i class="material-icons">movie</i></div>
|
||||
<input type="text" class="dark_bordered tab_target animation_controller_text_input" v-model="state.animations[i].key">
|
||||
<vue-prism-editor
|
||||
class="molang_input animation_controller_text_input tab_target"
|
||||
v-model="animation.blend_value"
|
||||
v-model="state.animations[i].blend_value"
|
||||
language="molang"
|
||||
:autocomplete="autocomplete"
|
||||
:placeholder="'${tl('animation_controllers.state.condition')}'"
|
||||
@ -2040,24 +2051,24 @@ Interface.definePanels(() => {
|
||||
</div>
|
||||
</div>
|
||||
<ul v-if="!state.fold.particles">
|
||||
<li v-for="particle in state.particles" :key="particle.uuid" class="controller_particle" @contextmenu="openParticleMenu(state, particle, $event)">
|
||||
<li v-for="(particle, i) in state.particles" :key="particle.uuid" class="controller_particle" @contextmenu="openParticleMenu(state, state.particles[i], $event)">
|
||||
<div class="bar flex">
|
||||
<label>${tl('data.effect')}</label>
|
||||
<input type="text" class="dark_bordered tab_target animation_controller_text_input" v-model="particle.effect">
|
||||
<div class="tool" title="${tl('timeline.select_particle_file')}" @click="changeParticleFile(state, particle)">
|
||||
<input type="text" class="dark_bordered tab_target animation_controller_text_input" v-model="state.particles[i].effect">
|
||||
<div class="tool" title="${tl('timeline.select_particle_file')}" @click="changeParticleFile(state, state.particles[i])">
|
||||
<i class="material-icons">upload_file</i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bar flex">
|
||||
<label>${tl('data.locator')}</label>
|
||||
<input type="text" class="dark_bordered tab_target animation_controller_text_input" v-model="particle.locator" list="locator_suggestion_list" @focus="updateLocatorSuggestionList()">
|
||||
<input type="checkbox" v-model="particle.bind_to_actor" title="${tl('timeline.bind_to_actor')}">
|
||||
<input type="text" class="dark_bordered tab_target animation_controller_text_input" v-model="state.particles[i].locator" list="locator_suggestion_list" @focus="updateLocatorSuggestionList()">
|
||||
<input type="checkbox" v-model="state.particles[i].bind_to_actor" title="${tl('timeline.bind_to_actor')}">
|
||||
</div>
|
||||
<div class="bar flex">
|
||||
<label>${tl('timeline.pre_effect_script')}</label>
|
||||
<vue-prism-editor
|
||||
class="molang_input animation_controller_text_input tab_target"
|
||||
v-model="particle.script"
|
||||
v-model="state.particles[i].script"
|
||||
language="molang"
|
||||
:autocomplete="autocomplete"
|
||||
:ignoreTabKey="true"
|
||||
@ -2084,11 +2095,11 @@ Interface.definePanels(() => {
|
||||
</div>
|
||||
</div>
|
||||
<ul v-if="!state.fold.sounds">
|
||||
<li v-for="sound in state.sounds" :key="sound.uuid" class="controller_sound" @contextmenu="openSoundMenu(state, sound, $event)">
|
||||
<li v-for="(sound, i) in state.sounds" :key="sound.uuid" class="controller_sound" @contextmenu="openSoundMenu(state, state.sounds[i], $event)">
|
||||
<div class="bar flex">
|
||||
<label>${tl('data.effect')}</label>
|
||||
<input type="text" class="dark_bordered tab_target animation_controller_text_input" v-model="sound.effect">
|
||||
<div class="tool" title="${tl('timeline.select_sound_file')}" @click="changeSoundFile(state, sound)">
|
||||
<input type="text" class="dark_bordered tab_target animation_controller_text_input" v-model="state.sounds[i].effect">
|
||||
<div class="tool" title="${tl('timeline.select_sound_file')}" @click="changeSoundFile(state, state.sounds[i])">
|
||||
<i class="material-icons">upload_file</i>
|
||||
</div>
|
||||
</div>
|
||||
@ -2138,12 +2149,12 @@ Interface.definePanels(() => {
|
||||
</div>
|
||||
<template v-if="!state.fold.transitions">
|
||||
<ul v-sortable="{onUpdate(event) {sortTransition(state, event)}, animation: 160, handle: '.controller_item_drag_handle'}">
|
||||
<li v-for="transition in state.transitions" :key="transition.uuid" :uuid="transition.uuid" class="controller_transition">
|
||||
<li v-for="(transition, i) in state.transitions" :key="transition.uuid" :uuid="transition.uuid" class="controller_transition"">
|
||||
<div class="controller_item_drag_handle" :style="{'--color-marker': connections.colors[transition.uuid]}"></div>
|
||||
<bb-select @click="openTransitionMenu(state, transition, $event)">{{ getStateName(transition.target) }}</bb-select>
|
||||
<bb-select @click="openTransitionMenu(state, state.transitions[i], $event)">{{ getStateName(state.transitions[i].target) }}</bb-select>
|
||||
<vue-prism-editor
|
||||
class="molang_input animation_controller_text_input tab_target"
|
||||
v-model="transition.condition"
|
||||
v-model="state.transitions[i].condition"
|
||||
language="molang"
|
||||
:autocomplete="autocomplete"
|
||||
:ignoreTabKey="true"
|
||||
@ -2224,7 +2235,7 @@ Interface.definePanels(() => {
|
||||
if (val != molang_edit_value) {
|
||||
Undo.finishEdit('Edit animation controller molang');
|
||||
} else {
|
||||
Undo.cancelEdit();
|
||||
Undo.cancelEdit(false);
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -1470,8 +1470,8 @@ Interface.definePanels(function() {
|
||||
<ul id="placeholder_buttons">
|
||||
<li v-for="button in buttons" :key="button.id" :class="{placeholder_slider: button.type == 'slider'}" @click="button.type == 'impulse' && changeButtonValue(button, $event)" :buttontype="button.type">
|
||||
<i v-if="button.type == 'impulse'" class="material-icons">play_arrow</i>
|
||||
<input v-if="button.type == 'toggle'" type="checkbox" class="tab_target" :value="button.value == 1" @change="changeButtonValue(button, $event)" :id="'placeholder_button_'+button.id">
|
||||
<numeric-input v-if="button.type == 'slider'" class="dark_bordered tab_target" :step="button.step" :min="button.min" :max="button.max" v-model="button.value" @input="changeButtonValue(button, $event)" />
|
||||
<input v-if="button.type == 'toggle'" type="checkbox" :value="button.value == 1" @change="changeButtonValue(button, $event)" :id="'placeholder_button_'+button.id">
|
||||
<numeric-input v-if="button.type == 'slider'" :step="button.step" :min="button.min" :max="button.max" v-model="button.value" @input="changeButtonValue(button, $event)" />
|
||||
<label :for="'placeholder_button_'+button.id" @mousedown="slideButton(button, $event)" @touchstart="slideButton(button, $event)">{{ button.id }}</label>
|
||||
</li>
|
||||
</ul>
|
||||
|
@ -94,11 +94,8 @@ class Keyframe {
|
||||
data_point = this.data_points[data_point];
|
||||
if (!data_point || !data_point[axis]) {
|
||||
return this.transform ? 0 : '';
|
||||
} else if (!isNaN(data_point[axis])) {
|
||||
let num = parseFloat(data_point[axis]);
|
||||
return isNaN(num) ? 0 : num;
|
||||
} else {
|
||||
return data_point[axis]
|
||||
return exportMolang(data_point[axis])
|
||||
}
|
||||
}
|
||||
calc(axis, data_point = 0) {
|
||||
@ -113,6 +110,7 @@ class Keyframe {
|
||||
}
|
||||
set(axis, value, data_point = 0) {
|
||||
if (data_point) data_point = Math.clamp(data_point, 0, this.data_points.length-1);
|
||||
if (typeof value == 'number') value = Math.roundTo(value, 10).toString();
|
||||
if (this.data_points[data_point]) {
|
||||
if (this.uniform) {
|
||||
this.data_points[data_point].x = value;
|
||||
@ -435,13 +433,20 @@ class Keyframe {
|
||||
}
|
||||
Timeline.selected.safePush(this);
|
||||
if (Timeline.selected.length == 1 && Timeline.selected[0].animator.selected == false) {
|
||||
Timeline.selected[0].animator.select()
|
||||
Timeline.selected[0].animator.select();
|
||||
}
|
||||
this.selected = true
|
||||
this.selected = true;
|
||||
TickUpdates.keyframe_selection = true;
|
||||
|
||||
if (this.transform) Timeline.vue.graph_editor_channel = this.channel;
|
||||
|
||||
return this;
|
||||
}
|
||||
clickSelect(event) {
|
||||
Undo.initSelection({timeline: true});
|
||||
|
||||
this.select(event);
|
||||
|
||||
var select_tool = true;
|
||||
Timeline.selected.forEach(kf => {
|
||||
if (kf.channel != this.channel) select_tool = false;
|
||||
@ -453,7 +458,7 @@ class Keyframe {
|
||||
case 'scale': BarItems.resize_tool.select(); break;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
Undo.finishSelection('Select keyframe')
|
||||
}
|
||||
callPlayhead() {
|
||||
Timeline.setTime(this.time)
|
||||
|
@ -104,6 +104,7 @@ const Timeline = {
|
||||
if (e.shiftKey || Pressing.overrides.shift) {
|
||||
Timeline.selector.selected_before = Timeline.selected.slice();
|
||||
}
|
||||
Undo.initSelection({timeline: true});
|
||||
},
|
||||
move(e) {
|
||||
var R = Timeline.selector;
|
||||
@ -204,6 +205,7 @@ const Timeline = {
|
||||
if (settings.canvas_unselect.value) {
|
||||
Timeline.selected.empty();
|
||||
updateKeyframeSelection();
|
||||
Undo.finishSelection('Unselect keyframes');
|
||||
}
|
||||
Timeline.vue.clickGraphEditor(e);
|
||||
return false;
|
||||
@ -215,6 +217,7 @@ const Timeline = {
|
||||
.css('width', 0)
|
||||
.css('height', 0)
|
||||
.hide();
|
||||
Undo.finishSelection('Select keyframes');
|
||||
}
|
||||
},
|
||||
},
|
||||
@ -928,7 +931,7 @@ Interface.definePanels(() => {
|
||||
|
||||
let padding = 16;
|
||||
let min_size = 2.4;
|
||||
let unit_size = Math.clamp(max-min, min_size, 1e4);
|
||||
let unit_size = Math.clamp(max-min, min_size, Timeline.graph_editor_limit);
|
||||
this.graph_size = (clientHeight - 2*padding) / unit_size;
|
||||
let blend = Math.clamp(1 - (max-min) / min_size, 0, 1)
|
||||
this.graph_offset = clientHeight - padding + (this.graph_size * (min - unit_size/2 * blend ) );
|
||||
@ -1039,6 +1042,7 @@ Interface.definePanels(() => {
|
||||
selectChannel(animator, channel) {
|
||||
if (this.graph_editor_channel == channel && animator.selected) return;
|
||||
if (!animator.channels[channel].transform) return;
|
||||
Undo.initSelection();
|
||||
if (!animator.selected) animator.select();
|
||||
// Select keyframe in new channel
|
||||
if (animator[channel].length && Keyframe.selected.length > 0) {
|
||||
@ -1053,6 +1057,7 @@ Interface.definePanels(() => {
|
||||
}
|
||||
}
|
||||
this.graph_editor_channel = channel;
|
||||
Undo.finishSelection('Select animation channel');
|
||||
},
|
||||
getColor(index) {
|
||||
if (index == -1 || index == undefined) return;
|
||||
@ -1099,6 +1104,7 @@ Interface.definePanels(() => {
|
||||
}
|
||||
} else if (distance > 6) {
|
||||
active = true;
|
||||
Undo.initSelection();
|
||||
}
|
||||
} else {
|
||||
if (e2) e2.preventDefault();
|
||||
@ -1151,6 +1157,7 @@ Interface.definePanels(() => {
|
||||
if (Timeline.animators[index] == animator) return;
|
||||
Timeline.animators.remove(animator);
|
||||
Timeline.animators.splice(index, 0, animator);
|
||||
Undo.finishSelection('Rearrange animators in timeline');
|
||||
}
|
||||
}
|
||||
|
||||
@ -1672,13 +1679,13 @@ Interface.definePanels(() => {
|
||||
</div>
|
||||
<div id="timeline_body" ref="timeline_body" @scroll="updateScroll($event)">
|
||||
<div id="timeline_body_inner" v-bind:style="{width: (size*length + head_width)+'px'}" @contextmenu.stop="Timeline.showMenu($event)">
|
||||
<li v-for="animator in animators" class="animator" :class="{selected: animator.selected, boneless: animator.constructor.name == 'BoneAnimator' && !animator.group}" :uuid="animator.uuid" v-on:click="animator.select();">
|
||||
<li v-for="animator in animators" class="animator" :class="{selected: animator.selected, boneless: animator.constructor.name == 'BoneAnimator' && !animator.group}" :uuid="animator.uuid" v-on:click="animator.clickSelect();">
|
||||
<div class="animator_head_bar">
|
||||
<div class="channel_head" v-bind:style="{left: '0px', width: head_width+'px'}" v-on:dblclick.stop="toggleAnimator(animator)" @contextmenu.stop="animator.showContextMenu($event)">
|
||||
<div class="text_button" v-on:click.stop="toggleAnimator(animator)">
|
||||
<i class="icon-open-state fa" v-bind:class="{'fa-angle-right': !animator.expanded, 'fa-angle-down': animator.expanded}"></i>
|
||||
</div>
|
||||
<span v-on:click.stop="animator.select();" @mousedown="dragAnimator(animator, $event)" @touchstart="dragAnimator(animator, $event)">{{animator.name}}</span>
|
||||
<span v-on:click.stop="animator.clickSelect();" @mousedown="dragAnimator(animator, $event)" @touchstart="dragAnimator(animator, $event)">{{animator.name}}</span>
|
||||
<div class="text_button" v-on:click.stop="removeAnimator(animator)">
|
||||
<i class="material-icons">remove</i>
|
||||
</div>
|
||||
@ -1738,7 +1745,7 @@ Interface.definePanels(() => {
|
||||
class="keyframe"
|
||||
v-bind:class="{[keyframe.channel]: true, selected: keyframe.selected, has_expressions: keyframe.has_expressions}"
|
||||
v-bind:id="keyframe.uuid"
|
||||
v-on:click.stop="keyframe.select($event)"
|
||||
v-on:click.stop="keyframe.clickSelect($event)"
|
||||
v-on:dblclick="keyframe.callPlayhead()"
|
||||
:title="tl('timeline.'+keyframe.channel)"
|
||||
@mousedown="dragKeyframes(keyframe, $event)" @touchstart="dragKeyframes(keyframe, $event)"
|
||||
@ -1796,7 +1803,7 @@ Interface.definePanels(() => {
|
||||
class="keyframe graph_keyframe"
|
||||
v-bind:class="[keyframe.channel, keyframe.selected?'selected':'']"
|
||||
v-bind:id="keyframe.uuid"
|
||||
v-on:click.stop="keyframe.select($event)"
|
||||
v-on:click.stop="keyframe.clickSelect($event)"
|
||||
v-on:dblclick="keyframe.callPlayhead()"
|
||||
:title="trimFloatNumber(keyframe.time, 2) + ' ⨉ ' + trimFloatNumber(keyframe.display_value || 0)"
|
||||
@mousedown="dragKeyframes(keyframe, $event)" @touchstart="dragKeyframes(keyframe, $event)"
|
||||
|
@ -29,9 +29,18 @@ class GeneralAnimator {
|
||||
})
|
||||
return this;
|
||||
}
|
||||
addToTimeline() {
|
||||
clickSelect() {
|
||||
Undo.initSelection();
|
||||
this.select();
|
||||
Undo.finishSelection('Select animator');
|
||||
}
|
||||
addToTimeline(end_of_list = false) {
|
||||
if (!Timeline.animators.includes(this)) {
|
||||
Timeline.animators.splice(0, 0, this);
|
||||
if (end_of_list == true) {
|
||||
Timeline.animators.push(this);
|
||||
} else {
|
||||
Timeline.animators.splice(0, 0, this);
|
||||
}
|
||||
}
|
||||
for (let channel in this.channels) {
|
||||
if (!this[channel]) this[channel] = [];
|
||||
@ -230,7 +239,7 @@ class BoneAnimator extends GeneralAnimator {
|
||||
}
|
||||
super.select();
|
||||
|
||||
if (this[Toolbox.selected.animation_channel] && (Timeline.selected.length == 0 || Timeline.selected[0].animator != this)) {
|
||||
if (this[Toolbox.selected.animation_channel] && (Timeline.selected.length == 0 || Timeline.selected[0].animator != this) && !Blockbench.hasFlag('loading_selection_save')) {
|
||||
var nearest;
|
||||
this[Toolbox.selected.animation_channel].forEach(kf => {
|
||||
if (Math.abs(kf.time - Timeline.time) < 0.002) {
|
||||
|
@ -85,7 +85,7 @@ const Clipbench = {
|
||||
}
|
||||
if (Modes.edit && p == 'preview') {
|
||||
let options = [];
|
||||
if (Clipbench.elements.length || Clipbench.group) {
|
||||
if (Clipbench.elements.length || Clipbench.groups) {
|
||||
options.push(Clipbench.types.outliner);
|
||||
}
|
||||
if (Mesh.selected[0] && Mesh.selected[0].getSelectedVertices().length && Clipbench.vertices) {
|
||||
@ -153,7 +153,7 @@ const Clipbench = {
|
||||
case 'face':
|
||||
UVEditor.copy(event);
|
||||
if (Prop.active_panel == 'uv') {
|
||||
Clipbench.group = undefined;
|
||||
Clipbench.groups = undefined;
|
||||
Clipbench.elements = [];
|
||||
}
|
||||
break;
|
||||
@ -223,12 +223,12 @@ const Clipbench = {
|
||||
},
|
||||
setGroups(groups) {
|
||||
if (!groups || !groups.length) {
|
||||
Clipbench.group = undefined
|
||||
Clipbench.groups = undefined
|
||||
return;
|
||||
}
|
||||
Clipbench.groups = groups.map(g => group.getSaveCopy())
|
||||
Clipbench.groups = groups.map(group => group.getSaveCopy())
|
||||
if (isApp) {
|
||||
clipboard.writeHTML(JSON.stringify({type: 'groups', content: Clipbench.group}))
|
||||
clipboard.writeHTML(JSON.stringify({type: 'groups', content: Clipbench.groups}))
|
||||
}
|
||||
},
|
||||
setElements(arr) {
|
||||
@ -320,15 +320,15 @@ const Clipbench = {
|
||||
try {
|
||||
var data = JSON.parse(raw)
|
||||
if (data.type === 'elements' && data.content) {
|
||||
Clipbench.group = undefined;
|
||||
Clipbench.groups = undefined;
|
||||
Clipbench.elements = data.content;
|
||||
} else if (data.type === 'group' && data.content) {
|
||||
Clipbench.group = data.content;
|
||||
Clipbench.groups = data.content;
|
||||
Clipbench.elements = [];
|
||||
}
|
||||
} catch (err) {}
|
||||
}
|
||||
if (Clipbench.group) {
|
||||
if (Clipbench.groups) {
|
||||
function iterate(obj, parent) {
|
||||
if (obj.children) {
|
||||
let copy = new Group(obj).addTo(parent).init();
|
||||
@ -350,8 +350,10 @@ const Clipbench = {
|
||||
return copy;
|
||||
}
|
||||
}
|
||||
let copy = iterate(Clipbench.group, target);
|
||||
copy.select();
|
||||
for (let group_template of Clipbench.groups) {
|
||||
let copy = iterate(group_template, target);
|
||||
copy.multiSelect();
|
||||
}
|
||||
|
||||
} else if (Clipbench.elements && Clipbench.elements.length) {
|
||||
let elements = [];
|
||||
|
@ -288,7 +288,7 @@ async function updateRecentProjectThumbnail() {
|
||||
}
|
||||
}
|
||||
function loadDataFromModelMemory() {
|
||||
let project = Project.getProjectMemory();
|
||||
let project = Project && Project.getProjectMemory();
|
||||
if (!project) return;
|
||||
|
||||
if (project.textures) {
|
||||
@ -346,6 +346,7 @@ function changeImageEditor(texture, not_found) {
|
||||
type: 'file',
|
||||
file_type: 'Program',
|
||||
extensions: app_file_extension[Blockbench.platform],
|
||||
readtype: 'none',
|
||||
description: 'message.image_editor.exe',
|
||||
condition: result => result.editor == 'other'
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ const DisplayMode = {};
|
||||
|
||||
class DisplaySlot {
|
||||
constructor(id, data) {
|
||||
this.slot_id = id;
|
||||
this.default()
|
||||
if (data) this.extend(data)
|
||||
}
|
||||
@ -19,6 +20,7 @@ class DisplaySlot {
|
||||
this.rotation_pivot = [0, 0, 0];
|
||||
this.scale_pivot = [0, 0, 0];
|
||||
this.mirror = [false, false, false]
|
||||
this.fit_to_frame = false;
|
||||
return this;
|
||||
}
|
||||
copy() {
|
||||
@ -51,6 +53,32 @@ class DisplaySlot {
|
||||
return build;
|
||||
}
|
||||
}
|
||||
exportBedrock() {
|
||||
let has_data = !this.rotation.allEqual(0)
|
||||
|| !this.translation.allEqual(0)
|
||||
|| !this.scale.allEqual(1)
|
||||
|| !this.mirror.allEqual(false)
|
||||
|| !this.rotation_pivot.allEqual(0)
|
||||
|| !this.scale_pivot.allEqual(0);
|
||||
if (!has_data) return;
|
||||
|
||||
let build = {
|
||||
rotation: this.rotation.slice(),
|
||||
translation: this.translation.slice(),
|
||||
scale: this.scale.slice(),
|
||||
rotation_pivot: this.rotation_pivot,
|
||||
scale_pivot: this.scale_pivot,
|
||||
}
|
||||
if (this.slot_id == 'gui') {
|
||||
build.fit_to_frame = this.fit_to_frame;
|
||||
}
|
||||
if (!this.mirror.allEqual(false)) {
|
||||
for (let i = 0; i < 3; i++) {
|
||||
build.scale[i] *= this.mirror[i] ? -1 : 1;
|
||||
}
|
||||
}
|
||||
return build;
|
||||
}
|
||||
extend(data) {
|
||||
if (!data) return this;
|
||||
for (var i = 0; i < 3; i++) {
|
||||
@ -63,6 +91,7 @@ class DisplaySlot {
|
||||
this.scale[i] = Math.abs(this.scale[i])
|
||||
if (data.scale && data.scale[i] < 0) this.mirror[i] = true;
|
||||
}
|
||||
if (typeof data.fit_to_frame == 'boolean') this.fit_to_frame = data.fit_to_frame;
|
||||
this.update()
|
||||
return this;
|
||||
}
|
||||
@ -373,6 +402,13 @@ class refModel {
|
||||
0.8, 0.8, 0.8)
|
||||
}
|
||||
break;
|
||||
case 'tooting':
|
||||
this.updateBasePosition = function() {
|
||||
var side = display_slot.includes('left') ? -1 : 1;
|
||||
//setDisplayArea(side*-0.6, 19.8, 23.8, 31.5, side*22, -11, 1, 1, 1)
|
||||
setDisplayArea(side == 1 ? -2.7 : 2.1, 20.1, Format.id.includes('bedrock') ? 24.5 : 25.6, 36, side*21.5, side*-12, 1, 1, 1)
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
buildModel(things, texture, texture_res = [16, 16]) {
|
||||
@ -488,6 +524,7 @@ class refModel {
|
||||
case 'crossbow':
|
||||
case 'bow':
|
||||
case 'eating':
|
||||
case 'tooting':
|
||||
case 'monitor': this.buildMonitor(); break;
|
||||
case 'block': this.buildBlock(); break;
|
||||
case 'frame': this.buildFrame(); break;
|
||||
@ -1222,6 +1259,7 @@ window.displayReferenceObjects = {
|
||||
bow: new refModel('bow', {icon: 'icon-bow'}),
|
||||
crossbow: new refModel('crossbow', {icon: 'icon-crossbow'}),
|
||||
eating: new refModel('eating', {icon: 'fa-apple-whole'}),
|
||||
tooting: new refModel('tooting', {icon: 'fa-bullhorn'}),
|
||||
block: new refModel('block', {icon: 'fa-cube'}),
|
||||
frame: new refModel('frame', {icon: 'filter_frames'}),
|
||||
frame_invisible: new refModel('frame_invisible', {icon: 'visibility_off'}),
|
||||
@ -1419,13 +1457,16 @@ DisplayMode.applyPreset = function(preset, all) {
|
||||
Undo.initEdit({display_slots: slots})
|
||||
slots.forEach(function(sl) {
|
||||
if (!Project.display_settings[sl]) {
|
||||
Project.display_settings[sl] = new DisplaySlot()
|
||||
Project.display_settings[sl] = new DisplaySlot(sl)
|
||||
}
|
||||
let preset_values = preset.areas[sl];
|
||||
if (preset_values) {
|
||||
if (!preset_values.rotation_pivot) Project.display_settings[sl].rotation_pivot.replace([0, 0, 0]);
|
||||
if (!preset_values.scale_pivot) Project.display_settings[sl].scale_pivot.replace([0, 0, 0]);
|
||||
Project.display_settings[sl].extend(preset.areas[sl]);
|
||||
if (preset.id == 'block' && Format.id == 'bedrock_block' && sl == 'gui') {
|
||||
Project.display_settings[sl].rotation[1] = 45;
|
||||
}
|
||||
}
|
||||
})
|
||||
DisplayMode.updateDisplayBase()
|
||||
@ -1434,7 +1475,7 @@ DisplayMode.applyPreset = function(preset, all) {
|
||||
DisplayMode.loadJSON = function(data) {
|
||||
for (var slot in data) {
|
||||
if (displayReferenceObjects.slots.includes(slot)) {
|
||||
Project.display_settings[slot] = new DisplaySlot().extend(data[slot])
|
||||
Project.display_settings[slot] = new DisplaySlot(slot).extend(data[slot])
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1495,7 +1536,7 @@ function loadDisp(key) { //Loads The Menu and slider values, common for all Radi
|
||||
display_preview.camPers.setFocalLength(45)
|
||||
|
||||
if (Project.display_settings[key] == undefined) {
|
||||
Project.display_settings[key] = new DisplaySlot()
|
||||
Project.display_settings[key] = new DisplaySlot(key)
|
||||
}
|
||||
display_preview.force_locked_angle = false;
|
||||
DisplayMode.vue._data.slot = Project.display_settings[key]
|
||||
@ -1541,7 +1582,7 @@ DisplayMode.loadFirstRight = function() { //Loader
|
||||
})
|
||||
display_preview.controls.enabled = false
|
||||
if (display_preview.orbit_gizmo) display_preview.orbit_gizmo.hide();
|
||||
displayReferenceObjects.bar(['monitor', 'bow', 'crossbow', 'eating']);
|
||||
displayReferenceObjects.bar(['monitor', 'bow', 'crossbow', 'tooting', 'eating']);
|
||||
$('.single_canvas_wrapper').append('<div id="display_crosshair"></div>')
|
||||
}
|
||||
DisplayMode.loadFirstLeft = function() { //Loader
|
||||
@ -1553,7 +1594,7 @@ DisplayMode.loadFirstLeft = function() { //Loader
|
||||
})
|
||||
display_preview.controls.enabled = false
|
||||
if (display_preview.orbit_gizmo) display_preview.orbit_gizmo.hide();
|
||||
displayReferenceObjects.bar(['monitor', 'bow', 'crossbow', 'eating']);
|
||||
displayReferenceObjects.bar(['monitor', 'bow', 'crossbow', 'tooting', 'eating']);
|
||||
$('.single_canvas_wrapper').append('<div id="display_crosshair"></div>')
|
||||
}
|
||||
DisplayMode.loadHead = function() { //Loader
|
||||
@ -1916,7 +1957,7 @@ Interface.definePanels(function() {
|
||||
axes: [0, 1, 2],
|
||||
reference_model: 'player',
|
||||
pose_angle: 0,
|
||||
slot: new DisplaySlot(),
|
||||
slot: new DisplaySlot(''),
|
||||
allow_mirroring: Settings.get('allow_display_slot_mirror')
|
||||
}},
|
||||
watch: {
|
||||
@ -1984,14 +2025,20 @@ Interface.definePanels(function() {
|
||||
DisplayMode.slot.update()
|
||||
Undo.finishEdit('Mirror display setting')
|
||||
},
|
||||
start: (axis, channel) => {
|
||||
start: () => {
|
||||
Undo.initEdit({display_slots: [display_slot]});
|
||||
Interface.addSuggestedModifierKey('shift', 'modifier_actions.uniform_scaling');
|
||||
},
|
||||
save: (axis, channel) => {
|
||||
save: () => {
|
||||
Undo.finishEdit('Change display setting');
|
||||
Interface.removeSuggestedModifierKey('shift', 'modifier_actions.uniform_scaling');
|
||||
},
|
||||
toggleFitToFrame() {
|
||||
Undo.initEdit({display_slots: [display_slot]});
|
||||
this.slot.fit_to_frame = !this.slot.fit_to_frame;
|
||||
Undo.finishEdit('Change display setting fit-to-frame property');
|
||||
Interface.removeSuggestedModifierKey('shift', 'modifier_actions.uniform_scaling');
|
||||
},
|
||||
showMirroringSetting() {
|
||||
Settings.openDialog({search_term: tl('settings.allow_display_slot_mirror')});
|
||||
},
|
||||
@ -2071,6 +2118,10 @@ Interface.definePanels(function() {
|
||||
value="0" @input="change(axis, 'scale')" @mousedown="start(axis, 'scale')" @change="save(axis, 'scale')">
|
||||
<numeric-input class="tool disp_text" v-model.number="slot.scale[axis]" :min="0" :max="4" :step="0.01" @input="change(axis, 'scale')" @focusout="focusout(axis, 'scale');save()" @mousedown="start()" />
|
||||
</div>
|
||||
<div class="bar" v-if="isBedrockStyle() && slot.slot_id == 'gui'" @click="toggleFitToFrame()">
|
||||
<input type="checkbox" :checked="slot.fit_to_frame == true">
|
||||
<label style="padding-top: 3px;">Fit to Frame</label>
|
||||
</div>
|
||||
|
||||
<template v-if="reference_model == 'player'">
|
||||
<div class="bar display_slot_section_bar">
|
||||
|
@ -128,6 +128,16 @@ Object.assign(Blockbench, {
|
||||
var errant;
|
||||
var i = 0;
|
||||
if (isApp) {
|
||||
if (options.readtype == 'none') {
|
||||
let results = files.map(file => {
|
||||
return {
|
||||
name: pathToName(file, true),
|
||||
path: file
|
||||
}
|
||||
})
|
||||
cb(results);
|
||||
return results;
|
||||
}
|
||||
while (index < files.length) {
|
||||
(function() {
|
||||
var this_i = index;
|
||||
@ -176,7 +186,7 @@ Object.assign(Blockbench, {
|
||||
try {
|
||||
data = fs.readFileSync(file, readtype == 'text' ? 'utf8' : undefined);
|
||||
} catch(err) {
|
||||
console.log(err)
|
||||
console.error(err)
|
||||
if (!errant && options.errorbox !== false) {
|
||||
Blockbench.showMessageBox({
|
||||
translateKey: 'file_not_found',
|
||||
@ -300,7 +310,13 @@ Object.assign(Blockbench, {
|
||||
saveAs(blob, file_name)
|
||||
|
||||
} else {
|
||||
var blob = new Blob([options.content], {type: "text/plain;charset=utf-8"});
|
||||
let type = 'text/plain;charset=utf-8';
|
||||
if (file_name.endsWith('json')) {
|
||||
type = 'application/json;charset=utf-8';
|
||||
} else if (file_name.endsWith('bbmodel')) {
|
||||
type = 'model/vnd.blockbench.bbmodel';
|
||||
}
|
||||
var blob = new Blob([options.content], {type});
|
||||
saveAs(blob, file_name, {autoBOM: true})
|
||||
}
|
||||
|
||||
|
@ -1534,17 +1534,21 @@ class Toolbar {
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Builds the toolbar from data
|
||||
* @param {object} data Data used to build the toolbar
|
||||
* @param {boolean} force If true, customization data will be ignored. Used when resetting toolbar
|
||||
*/
|
||||
build(data, force) {
|
||||
var scope = this;
|
||||
//Items
|
||||
this.children.length = 0;
|
||||
var items = data.children
|
||||
if (!force && BARS.stored[scope.id] && typeof BARS.stored[scope.id] === 'object') {
|
||||
items = BARS.stored[scope.id]
|
||||
if (!force && BARS.stored[this.id] && typeof BARS.stored[this.id] === 'object') {
|
||||
items = BARS.stored[this.id];
|
||||
if (data.children) {
|
||||
// Add new actions to existing toolbars
|
||||
// Add new actions (newly added via bb update) to existing toolbars
|
||||
data.children.forEach((key, index) => {
|
||||
if (typeof key == 'string' && key.length > 1 && !items.includes(key) && !Keybinds.stored[key] && BarItems[key]) {
|
||||
if (typeof key == 'string' && key.length > 1 && !items.includes(key) && !Keybinds.stored[key] && BARS.stored._known?.includes(key) == false && BarItems[key]) {
|
||||
// Figure out best index based on item before. Otherwise use index from original array
|
||||
let prev_index = items.indexOf(data.children[index-1]);
|
||||
if (prev_index != -1) index = prev_index+1;
|
||||
@ -1554,7 +1558,7 @@ class Toolbar {
|
||||
}
|
||||
}
|
||||
if (items && items instanceof Array) {
|
||||
var content = $(scope.node).find('div.content')
|
||||
var content = $(this.node).find('div.content')
|
||||
content.children().detach()
|
||||
for (var itemPosition = 0; itemPosition < items.length; itemPosition++) {
|
||||
let item = items[itemPosition];
|
||||
@ -1566,7 +1570,10 @@ class Toolbar {
|
||||
|
||||
continue;
|
||||
}
|
||||
if (typeof item == 'string') item = BarItems[item]
|
||||
if (typeof item == 'string') {
|
||||
BARS.stored._known?.safePush(item);
|
||||
item = BarItems[item];
|
||||
}
|
||||
|
||||
if (item) {
|
||||
item.pushToolbar(this);
|
||||
@ -1581,8 +1588,8 @@ class Toolbar {
|
||||
}
|
||||
}
|
||||
}
|
||||
$(scope.node).toggleClass('no_wrap', this.no_wrap)
|
||||
$(scope.node).toggleClass('vertical', this.vertical)
|
||||
$(this.node).toggleClass('no_wrap', this.no_wrap)
|
||||
$(this.node).toggleClass('vertical', this.vertical)
|
||||
if (data.default_place) {
|
||||
this.toPlace(this.id)
|
||||
}
|
||||
@ -1748,7 +1755,10 @@ class Toolbar {
|
||||
}
|
||||
})
|
||||
BARS.stored[this.id] = arr;
|
||||
if (arr.equals(this.default_children)) {
|
||||
let identical_to_default = this.default_children.length == arr.length && this.default_children.allAre((item, i) => {
|
||||
return arr[i] == item || (typeof arr[i] == 'string' && arr[i].startsWith(item));
|
||||
})
|
||||
if (identical_to_default) {
|
||||
delete BARS.stored[this.id];
|
||||
}
|
||||
// Temporary fix
|
||||
@ -1779,7 +1789,9 @@ Toolbar.prototype.menu = new Menu([
|
||||
])
|
||||
|
||||
const BARS = {
|
||||
stored: {},
|
||||
stored: {
|
||||
_known: []
|
||||
},
|
||||
editing_bar: undefined,
|
||||
action_definers: [],
|
||||
condition: Condition,
|
||||
@ -2145,6 +2157,9 @@ const BARS = {
|
||||
stored = JSON.parse(stored)
|
||||
if (typeof stored === 'object') {
|
||||
BARS.stored = stored;
|
||||
if (!BARS.stored._known) {
|
||||
BARS.stored._known = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2266,9 +2281,6 @@ const BARS = {
|
||||
}
|
||||
})
|
||||
}
|
||||
Blockbench.onUpdateTo('4.4.0-beta.0', () => {
|
||||
delete BARS.stored.brush;
|
||||
})
|
||||
Toolbars.brush = new Toolbar({
|
||||
id: 'brush',
|
||||
no_wrap: true,
|
||||
|
@ -535,6 +535,8 @@ window.MessageBox = class MessageBox extends Dialog {
|
||||
super(options.id, options);
|
||||
this.options = options;
|
||||
if (!options.buttons) this.buttons = ['dialog.ok'];
|
||||
this.cancelIndex = Math.min(this.buttons.length-1, this.cancelIndex);
|
||||
this.confirmIndex = Math.min(this.buttons.length-1, this.confirmIndex);
|
||||
this.callback = callback;
|
||||
}
|
||||
close(button, result, event) {
|
||||
@ -687,6 +689,17 @@ window.ToolConfig = class ToolConfig extends Dialog {
|
||||
}
|
||||
save() {
|
||||
localStorage.setItem(`tool_config.${this.id}`, JSON.stringify(this.options));
|
||||
return this;
|
||||
}
|
||||
changeOptions(options) {
|
||||
for (let key in options) {
|
||||
this.options[key] = options[key];
|
||||
}
|
||||
if (this.form) {
|
||||
this.form.setValues(options);
|
||||
}
|
||||
this.save();
|
||||
return this;
|
||||
}
|
||||
close(button, event) {
|
||||
this.save();
|
||||
@ -703,6 +716,7 @@ window.ToolConfig = class ToolConfig extends Dialog {
|
||||
this.object.style.top = (anchor_position.top+anchor.offsetHeight) + 'px';
|
||||
this.object.style.left = Math.clamp(anchor_position.left - 30, 0, window.innerWidth-this.object.clientWidth - (this.title ? 0 : 30)) + 'px';
|
||||
}
|
||||
return this;
|
||||
}
|
||||
build() {
|
||||
if (this.object) this.object.remove();
|
||||
|
@ -4,7 +4,7 @@ class InputForm extends EventSystem {
|
||||
this.uuid = guid();
|
||||
this.form_config = form_config;
|
||||
this.form_data = {};
|
||||
this.node = Interface.createElement('form', {class: 'form'});
|
||||
this.node = Interface.createElement('div', {class: 'form'});
|
||||
this.max_label_width = 0;
|
||||
this.uses_wide_inputs = false;
|
||||
|
||||
@ -284,6 +284,29 @@ class InputForm extends EventSystem {
|
||||
scope.updateValues();
|
||||
})
|
||||
break;
|
||||
|
||||
case 'num_slider':
|
||||
let getInterval = input_config.getInterval;
|
||||
if (input_config.interval_type == 'position') getInterval = getSpatialInterval;
|
||||
if (input_config.interval_type == 'rotation') getInterval = getRotationInterval;
|
||||
let slider = new NumSlider({
|
||||
id: 'form_slider_'+form_id,
|
||||
private: true,
|
||||
onChange: () => {
|
||||
scope.updateValues();
|
||||
},
|
||||
getInterval,
|
||||
settings: {
|
||||
default: input_config.value || 0,
|
||||
min: input_config.min,
|
||||
max: input_config.max,
|
||||
step: input_config.step||1,
|
||||
},
|
||||
});
|
||||
bar.append(slider.node);
|
||||
slider.update();
|
||||
data.slider = slider;
|
||||
break;
|
||||
|
||||
|
||||
case 'vector':
|
||||
@ -325,8 +348,9 @@ class InputForm extends EventSystem {
|
||||
linked_ratio_toggle.addEventListener('click', event => {
|
||||
data.linked_ratio = !data.linked_ratio;
|
||||
if (data.linked_ratio) {
|
||||
updateInputs(vector_inputs[0]);
|
||||
scope.updateValues();
|
||||
initial_value = vector_inputs.map(v => v.value);
|
||||
// updateInputs(vector_inputs[0]);
|
||||
// scope.updateValues();
|
||||
}
|
||||
updateState();
|
||||
})
|
||||
@ -487,7 +511,6 @@ class InputForm extends EventSystem {
|
||||
for (let form_id in this.form_config) {
|
||||
let data = this.form_data[form_id];
|
||||
let input_config = this.form_config[form_id];
|
||||
console.log(form_id, values[form_id])
|
||||
if (values[form_id] != undefined && typeof input_config == 'object' && data.bar) {
|
||||
let value = values[form_id];
|
||||
switch (input_config.type) {
|
||||
@ -523,6 +546,9 @@ class InputForm extends EventSystem {
|
||||
case 'number': case 'range':
|
||||
data.bar.find('input').val(value);
|
||||
break;
|
||||
case 'num_slider':
|
||||
data.slider.setValue(value);
|
||||
break;
|
||||
case 'vector':
|
||||
for (let i = 0; i < (input_config.dimensions || 3); i++) {
|
||||
data.bar.find(`input#${form_id}_${i}`).val(value[i])
|
||||
@ -532,7 +558,6 @@ class InputForm extends EventSystem {
|
||||
data.colorpicker.set(value);
|
||||
break;
|
||||
case 'checkbox':
|
||||
console.log(data.bar.find('input'), value)
|
||||
data.bar.find('input').prop('checked', value);
|
||||
break;
|
||||
case 'file':
|
||||
@ -611,6 +636,9 @@ class InputForm extends EventSystem {
|
||||
result[form_id] = Math.round(result[form_id] / input_config.step) * input_config.step;
|
||||
}
|
||||
break;
|
||||
case 'num_slider':
|
||||
result[form_id] = data.slider.get();
|
||||
break;
|
||||
case 'vector':
|
||||
result[form_id] = [];
|
||||
for (let i = 0; i < (input_config.dimensions || 3); i++) {
|
||||
@ -645,7 +673,7 @@ class InputForm extends EventSystem {
|
||||
switch (input_config.type) {
|
||||
case 'checkbox': return false;
|
||||
case 'text': case 'textarea': return '';
|
||||
case 'number': case 'range': return Math.clamp(0, input_config.min, input_config.max);
|
||||
case 'number': case 'range': case 'num_slider': return Math.clamp(0, input_config.min, input_config.max);
|
||||
case 'select': case 'inline_select': case 'radio': return Object.keys(input_config.options)[0] ?? '';
|
||||
case 'inline_multi_select': return {};
|
||||
case 'file': case 'folder': return '';
|
||||
|
@ -233,7 +233,7 @@ class Keybind {
|
||||
let modifiers_used = new Set();
|
||||
if (this.variations) {
|
||||
for (let option in this.variations) {
|
||||
modifiers_used.add(this.variations[option]);
|
||||
modifiers_used.add(this.variations[option].replace('unless_', ''));
|
||||
}
|
||||
}
|
||||
return (
|
||||
@ -250,10 +250,14 @@ class Keybind {
|
||||
if (variation && option != variation) continue;
|
||||
let key = this.variations[option];
|
||||
if (
|
||||
(key == 'always') ||
|
||||
(key == 'ctrl' && (event.ctrlOrCmd || Pressing.overrides.ctrl)) ||
|
||||
(key == 'shift' && (event.shiftKey || Pressing.overrides.shift)) ||
|
||||
(key == 'alt' && (event.altKey || Pressing.overrides.alt)) ||
|
||||
(key == 'meta' && (event.metaKey || Pressing.overrides.meta))
|
||||
(key == 'meta' && (event.metaKey || Pressing.overrides.meta)) ||
|
||||
(key == 'unless_ctrl' && !(event.ctrlOrCmd || Pressing.overrides.ctrl)) ||
|
||||
(key == 'unless_shift' && !(event.shiftKey || Pressing.overrides.shift)) ||
|
||||
(key == 'unless_alt' && !(event.altKey || Pressing.overrides.alt))
|
||||
) {
|
||||
return variation ? true : option;
|
||||
}
|
||||
@ -531,15 +535,20 @@ onVueSetup(function() {
|
||||
}
|
||||
},
|
||||
component: {
|
||||
data() {return {
|
||||
data() {
|
||||
return {
|
||||
structure: Keybinds.structure,
|
||||
open_category: 'navigate',
|
||||
search_term: '',
|
||||
modifier_options: {
|
||||
'': '-',
|
||||
always: tl('modifier_actions.always'),
|
||||
ctrl: tl(Blockbench.platform == 'darwin' ? 'keys.meta' : 'keys.ctrl'),
|
||||
shift: tl('keys.shift'),
|
||||
alt: tl('keys.alt'),
|
||||
'': '-',
|
||||
unless_ctrl: tl('modifier_actions.unless', tl(Blockbench.platform == 'darwin' ? 'keys.meta' : 'keys.ctrl')),
|
||||
unless_shift: tl('modifier_actions.unless', tl('keys.shift')),
|
||||
unless_alt: tl('modifier_actions.unless', tl('keys.alt')),
|
||||
}
|
||||
}},
|
||||
methods: {
|
||||
@ -935,6 +944,12 @@ addEventListeners(document, 'keydown mousedown', function(e) {
|
||||
ReferenceImageMode.deactivate();
|
||||
used = true;
|
||||
}
|
||||
} else if (Project && Undo.amend_edit_menu && (Keybinds.extra.confirm.keybind.isTriggered(e) || Keybinds.extra.cancel.keybind.isTriggered(e))) {
|
||||
Undo.closeAmendEditMenu();
|
||||
|
||||
} else if (UVEditor.vue.texture_selection_polygon.length && Keybinds.extra.cancel.keybind.isTriggered(e)) {
|
||||
UVEditor.vue.texture_selection_polygon.empty();
|
||||
|
||||
} else if (Prop.active_panel == 'uv' && Modes.paint && Texture.selected && Texture.selected.selection.is_custom) {
|
||||
if (Keybinds.extra.cancel.keybind.isTriggered(e)) {
|
||||
SharedActions.run('unselect_all', e);
|
||||
|
@ -254,20 +254,6 @@ const MenuBar = {
|
||||
'delete',
|
||||
'apply_mirror_modeling',
|
||||
new MenuSeparator('mesh_specific'),
|
||||
{name: 'data.mesh', id: 'mesh', icon: 'fa-gem', children: [
|
||||
'extrude_mesh_selection',
|
||||
'inset_mesh_selection',
|
||||
'loop_cut',
|
||||
'create_face',
|
||||
'invert_face',
|
||||
'switch_face_crease',
|
||||
'merge_vertices',
|
||||
'dissolve_edges',
|
||||
'solidify_mesh_selection',
|
||||
'apply_mesh_rotation',
|
||||
'split_mesh',
|
||||
'merge_meshes',
|
||||
]},
|
||||
new MenuSeparator('editing_mode'),
|
||||
'proportional_editing',
|
||||
'mirror_modeling',
|
||||
@ -311,6 +297,22 @@ const MenuBar = {
|
||||
icon: 'open_with',
|
||||
condition: {modes: ['edit']},
|
||||
})
|
||||
new BarMenu('mesh', [
|
||||
new MenuSeparator('geometry'),
|
||||
'extrude_mesh_selection',
|
||||
'inset_mesh_selection',
|
||||
'loop_cut',
|
||||
'create_face',
|
||||
'invert_face',
|
||||
'switch_face_crease',
|
||||
'merge_vertices',
|
||||
'dissolve_edges',
|
||||
'solidify_mesh_selection',
|
||||
new MenuSeparator('element'),
|
||||
'apply_mesh_rotation',
|
||||
'split_mesh',
|
||||
'merge_meshes',
|
||||
], {icon: 'fa-gem', condition: {selected: {mesh: true}, modes: ['edit']}})
|
||||
|
||||
new BarMenu('uv', UVEditor.menu.structure, {
|
||||
condition: {modes: ['edit']},
|
||||
@ -329,6 +331,7 @@ const MenuBar = {
|
||||
'adjust_curves',
|
||||
new MenuSeparator('filters'),
|
||||
'limit_to_palette',
|
||||
'split_rgb_into_layers',
|
||||
'clear_unused_texture_space',
|
||||
new MenuSeparator('transform'),
|
||||
'flip_texture_x',
|
||||
@ -447,20 +450,8 @@ const MenuBar = {
|
||||
MenuBar.menus.filter = MenuBar.menus.tools;
|
||||
|
||||
new BarMenu('view', [
|
||||
new MenuSeparator('viewport'),
|
||||
new MenuSeparator('window'),
|
||||
'fullscreen',
|
||||
new MenuSeparator('viewport'),
|
||||
'view_mode',
|
||||
'toggle_shading',
|
||||
'toggle_all_grids',
|
||||
'toggle_ground_plane',
|
||||
'preview_checkerboard',
|
||||
'pixel_grid',
|
||||
'painting_grid',
|
||||
new MenuSeparator('references'),
|
||||
'bedrock_animation_mode',
|
||||
'preview_scene',
|
||||
'edit_reference_images',
|
||||
new MenuSeparator('interface'),
|
||||
{
|
||||
id: 'panels',
|
||||
@ -501,6 +492,18 @@ const MenuBar = {
|
||||
},
|
||||
'toggle_sidebars',
|
||||
'split_screen',
|
||||
new MenuSeparator('viewport'),
|
||||
'view_mode',
|
||||
'toggle_shading',
|
||||
'toggle_all_grids',
|
||||
'toggle_ground_plane',
|
||||
'preview_checkerboard',
|
||||
'pixel_grid',
|
||||
'painting_grid',
|
||||
new MenuSeparator('references'),
|
||||
'bedrock_animation_mode',
|
||||
'preview_scene',
|
||||
'edit_reference_images',
|
||||
new MenuSeparator('model'),
|
||||
'hide_everything_except_selection',
|
||||
'focus_on_selection',
|
||||
|
@ -11,7 +11,7 @@ class Panel extends EventSystem {
|
||||
this.condition = data.condition;
|
||||
this.display_condition = data.display_condition;
|
||||
this.previous_slot = 'left_bar';
|
||||
this.optional = data.optional ?? false;
|
||||
this.optional = data.optional ?? true;
|
||||
this.plugin = data.plugin || (typeof Plugins != 'undefined' ? Plugins.currently_loading : '');
|
||||
|
||||
this.growable = data.growable;
|
||||
|
@ -412,6 +412,7 @@ const Settings = {
|
||||
}});
|
||||
new Setting('seethrough_outline', {category: 'interface', value: false, onChange(value) {
|
||||
Canvas.outlineMaterial.depthTest = !value;
|
||||
Canvas.meshOutlineMaterial.depthTest = !value;
|
||||
}});
|
||||
new Setting('outliner_colors', {category: 'interface', value: true});
|
||||
new Setting('preview_checkerboard', {category: 'interface', value: true, onChange() {
|
||||
@ -435,7 +436,7 @@ const Settings = {
|
||||
Canvas.updateShading()
|
||||
}});
|
||||
new Setting('antialiasing', {category: 'preview', value: true, requires_restart: true});
|
||||
new Setting('antialiasing_bleed_fix', {category: 'preview', value: true, requires_restart: true});
|
||||
new Setting('antialiasing_bleed_fix', {category: 'preview', value: false, requires_restart: true});
|
||||
new Setting('fov', {category: 'preview', value: 45, type: 'number', min: 1, max: 120, onChange(val) {
|
||||
Preview.all.forEach(preview => preview.setFOV(val));
|
||||
}});
|
||||
@ -489,10 +490,13 @@ const Settings = {
|
||||
Preview.all.forEach(viewport => viewport.controls.zoomSpeed = value / 100 * 1.5)
|
||||
}});
|
||||
new Setting('editor_2d_zoom_speed', {category: 'controls', value: 100, min: 10, max: 1000, type: 'number'});
|
||||
new Setting('gamepad_controls', {category: 'controls', value: false, name: 'Gamepad Controls', description: 'Use a gamepad or 3D mouse to navigate the viewport'});
|
||||
new Setting('double_click_switch_tools',{category: 'controls', value: true});
|
||||
new Setting('canvas_unselect', {category: 'controls', value: false});
|
||||
new Setting('selection_tolerance', {category: 'controls', value: 10, type: 'number', min: 1, max: 50});
|
||||
|
||||
//Edit
|
||||
new Setting('undo_selections', {category: 'edit', value: false});
|
||||
new Setting('undo_limit', {category: 'edit', value: 256, type: 'number', min: 1});
|
||||
new Setting('highlight_cubes', {category: 'edit', value: true, onChange() {
|
||||
updateCubeHighlights();
|
||||
@ -524,6 +528,7 @@ const Settings = {
|
||||
new Setting('outlines_in_paint_mode', {category: 'paint', value: true});
|
||||
new Setting('move_with_selection_tool', {category: 'paint', value: true});
|
||||
new Setting('pick_color_opacity', {category: 'paint', value: false});
|
||||
new Setting('pick_combined_color', {category: 'paint', value: false});
|
||||
new Setting('paint_through_transparency', {category: 'paint', value: true});
|
||||
new Setting('paint_side_restrict', {category: 'paint', value: true});
|
||||
new Setting('paint_with_stylus_only', {category: 'paint', value: false});
|
||||
@ -623,9 +628,8 @@ const Settings = {
|
||||
new Setting('sketchfab_token', {category: 'export', value: '', type: 'password'});
|
||||
new Setting('credit', {category: 'export', value: 'Made with Blockbench', type: 'text'});
|
||||
|
||||
Blockbench.onUpdateTo('4.7.1', () => {
|
||||
settings.brush_opacity_modifier.set('none');
|
||||
settings.brush_size_modifier.set('none');
|
||||
Blockbench.onUpdateTo('4.12.1', () => {
|
||||
settings.antialiasing_bleed_fix.set(false);
|
||||
})
|
||||
},
|
||||
setupProfiles() {
|
||||
|
@ -83,10 +83,15 @@ BARS.defineActions(() => {
|
||||
new Action('delete', {
|
||||
icon: 'delete',
|
||||
category: 'edit',
|
||||
keybind: new Keybind({key: 46}),
|
||||
keybind: new Keybind({key: 46}, {
|
||||
keep_vertices: 'alt'
|
||||
}),
|
||||
variations: {
|
||||
keep_vertices: {name: 'action.delete.keep_vertices'}
|
||||
},
|
||||
condition: () => !Dialog.open,
|
||||
click() {
|
||||
SharedActions.run('delete');
|
||||
click(event) {
|
||||
SharedActions.run('delete', event);
|
||||
}
|
||||
})
|
||||
new Action('duplicate', {
|
||||
@ -94,8 +99,8 @@ BARS.defineActions(() => {
|
||||
category: 'edit',
|
||||
condition: () => SharedActions.condition('duplicate'),
|
||||
keybind: new Keybind({key: 'd', ctrl: true}),
|
||||
click() {
|
||||
SharedActions.run('duplicate');
|
||||
click(event) {
|
||||
SharedActions.run('duplicate', event);
|
||||
}
|
||||
})
|
||||
new Action('select_all', {
|
||||
@ -103,8 +108,8 @@ BARS.defineActions(() => {
|
||||
category: 'select',
|
||||
condition: () => !Modes.display,
|
||||
keybind: new Keybind({key: 'a', ctrl: true}),
|
||||
click() {
|
||||
SharedActions.run('select_all');
|
||||
click(event) {
|
||||
SharedActions.run('select_all', event);
|
||||
Blockbench.dispatchEvent('select_all');
|
||||
}
|
||||
})
|
||||
@ -112,8 +117,8 @@ BARS.defineActions(() => {
|
||||
icon: 'border_clear',
|
||||
category: 'select',
|
||||
condition: () => !Modes.display,
|
||||
click() {
|
||||
SharedActions.run('unselect_all');
|
||||
click(event) {
|
||||
SharedActions.run('unselect_all', event);
|
||||
Blockbench.dispatchEvent('unselect_all');
|
||||
}
|
||||
})
|
||||
@ -121,8 +126,8 @@ BARS.defineActions(() => {
|
||||
icon: 'swap_vert',
|
||||
category: 'select',
|
||||
keybind: new Keybind({key: 'i', ctrl: true}),
|
||||
click() {
|
||||
SharedActions.run('invert_selection');
|
||||
click(event) {
|
||||
SharedActions.run('invert_selection', event);
|
||||
Blockbench.dispatchEvent('invert_selection');
|
||||
}
|
||||
})
|
||||
|
@ -182,15 +182,19 @@ onVueSetup(async function() {
|
||||
slideshow: [
|
||||
{
|
||||
source: "./assets/splash_art/1.webp",
|
||||
description: "Splash Art 1st Place by [BonoGakure](https://twitter.com/bonogakure) & [GlenFebrian](https://twitter.com/glenn_turu)",
|
||||
description: "Splash Art 1st Place by [Handon_撼动](https://x.com/_2Lein) & [PICASSO](https://twitter.com/Picasso114514)",
|
||||
},
|
||||
{
|
||||
source: "./assets/splash_art/2.webp",
|
||||
description: "Splash Art 2nd Place by [Wanwin](https://wan-win.com/#3darts) & Artem x",
|
||||
description: "Splash Art 2nd Place by [guzuper](https://x.com/guzuper200?s=21) & [rainyday](https://x.com/YuTian131)",
|
||||
},
|
||||
{
|
||||
source: "./assets/splash_art/3.webp",
|
||||
description: "Splash Art 3rd Place by [FairyZelz](https://x.com/FairyZelz) & [AnolXD](https://x.com/_AnolXD_)",
|
||||
description: "Splash Art 3rd Place by [PeacedoveWum丨無名.](https://twitter.com/PeacedoveWum) & mccaca",
|
||||
},
|
||||
{
|
||||
source: "./assets/splash_art/4.webp",
|
||||
description: "Splash Art 3rd Place by [Orange](https://twitter.com/OrangewithMC)",
|
||||
}
|
||||
],
|
||||
show_splash_screen: (Blockbench.hasFlag('after_update') || settings.always_show_splash_art.value),
|
||||
@ -569,23 +573,39 @@ ModelLoader.loaders = {};
|
||||
});
|
||||
documentReady.then(() => {
|
||||
|
||||
//Twitter
|
||||
let twitter_ad;
|
||||
if (!settings.classroom_mode.value && Blockbench.startup_count < 20 && Blockbench.startup_count % 5 === 4) {
|
||||
twitter_ad = true;
|
||||
addStartScreenSection('twitter_link', {
|
||||
color: '#1da1f2',
|
||||
//Bluesky
|
||||
let bsky_ad;
|
||||
Blockbench.onUpdateTo('4.12.2', () => {
|
||||
//Bluesky
|
||||
if (!settings.classroom_mode.value) {
|
||||
bsky_ad = true;
|
||||
addStartScreenSection('bluesky_link', {
|
||||
color: 'rgb(32, 139, 254);',
|
||||
text_color: '#ffffff',
|
||||
graphic: {type: 'icon', icon: 'fab.fa-bluesky'},
|
||||
text: [
|
||||
{type: 'h3', text: 'Blockbench on Bluesky'},
|
||||
{text: 'Follow Blockbench on Bluesky for the latest news & cool models from the community! [@blockbench.net](https://bsky.app/profile/blockbench.net)'}
|
||||
],
|
||||
last: true
|
||||
})
|
||||
}
|
||||
})
|
||||
if (!settings.classroom_mode.value && !bsky_ad && Blockbench.startup_count < 20 && Blockbench.startup_count % 5 === 4) {
|
||||
bsky_ad = true;
|
||||
addStartScreenSection('bluesky_link', {
|
||||
color: 'rgb(32, 139, 254);',
|
||||
text_color: '#ffffff',
|
||||
graphic: {type: 'icon', icon: 'fab.fa-twitter'},
|
||||
graphic: {type: 'icon', icon: 'fab.fa-bluesky'},
|
||||
text: [
|
||||
{type: 'h2', text: 'Blockbench on Twitter'},
|
||||
{text: 'Follow Blockbench on Twitter for the latest news as well as cool models from the community! [twitter.com/blockbench](https://twitter.com/blockbench/)'}
|
||||
{type: 'h3', text: 'Blockbench on Bluesky'},
|
||||
{text: 'Follow Blockbench on Bluesky for the latest news & cool models from the community! [@blockbench.net](https://bsky.app/profile/blockbench.net)'}
|
||||
],
|
||||
last: true
|
||||
})
|
||||
}
|
||||
//Discord
|
||||
if (!settings.classroom_mode.value && Blockbench.startup_count < 6 && !twitter_ad) {
|
||||
if (!settings.classroom_mode.value && Blockbench.startup_count < 6 && !bsky_ad) {
|
||||
addStartScreenSection('discord_link', {
|
||||
color: '#5865F2',
|
||||
text_color: '#ffffff',
|
||||
|
@ -256,6 +256,7 @@ class ModelFormat {
|
||||
}
|
||||
}
|
||||
|
||||
new Property(ModelFormat, 'string', 'node_name_regex');
|
||||
new Property(ModelFormat, 'boolean', 'box_uv');
|
||||
new Property(ModelFormat, 'boolean', 'optional_box_uv');
|
||||
new Property(ModelFormat, 'boolean', 'box_uv_float_size');
|
||||
|
@ -253,10 +253,17 @@ var codec = new Codec('project', {
|
||||
model.texture_groups.push(copy);
|
||||
}
|
||||
|
||||
let collections = [];
|
||||
for (let collection of Collection.all) {
|
||||
let copy = collection.getSaveCopy();
|
||||
collections.push(copy);
|
||||
}
|
||||
if (collections.length) model.collections = collections;
|
||||
|
||||
if (Animation.all.length) {
|
||||
model.animations = [];
|
||||
Animation.all.forEach(a => {
|
||||
model.animations.push(a.getUndoCopy({bone_names: true, absolute_paths: options.absolute_paths}, true))
|
||||
model.animations.push(a.getUndoCopy({absolute_paths: options.absolute_paths}, true))
|
||||
})
|
||||
}
|
||||
if (AnimationController.all.length) {
|
||||
@ -325,15 +332,11 @@ var codec = new Codec('project', {
|
||||
if (options.raw) {
|
||||
return model;
|
||||
} else if (options.compressed) {
|
||||
var json_string = JSON.stringify(model);
|
||||
var json_string = compileJSON(model, {small: true});
|
||||
var compressed = '<lz>'+LZUTF8.compress(json_string, {outputEncoding: 'StorageBinaryString'});
|
||||
return compressed;
|
||||
} else {
|
||||
if (Settings.get('minify_bbmodel') || options.minify) {
|
||||
return JSON.stringify(model);
|
||||
} else {
|
||||
return compileJSON(model);
|
||||
}
|
||||
return compileJSON(model, {small: Settings.get('minify_bbmodel') || options.minify});
|
||||
}
|
||||
},
|
||||
parse(model, path) {
|
||||
@ -440,6 +443,12 @@ var codec = new Codec('project', {
|
||||
if (model.outliner) {
|
||||
parseGroups(model.outliner)
|
||||
}
|
||||
if (model.collections instanceof Array) {
|
||||
for (let collection_data of model.collections) {
|
||||
let collection = new Collection(collection_data, collection_data.uuid);
|
||||
collection.add();
|
||||
}
|
||||
}
|
||||
if (model.animations) {
|
||||
model.animations.forEach(ani => {
|
||||
var base_ani = new Animation()
|
||||
@ -703,6 +712,12 @@ var codec = new Codec('project', {
|
||||
|
||||
parseGroups(model.outliner, true);
|
||||
}
|
||||
if (model.collections instanceof Array) {
|
||||
for (let collection_data of model.collections) {
|
||||
let collection = new Collection(collection_data, collection_data.uuid);
|
||||
collection.add();
|
||||
}
|
||||
}
|
||||
if (model.animations && Format.animation_mode) {
|
||||
model.animations.forEach(ani => {
|
||||
var base_ani = new Animation();
|
||||
|
@ -96,7 +96,8 @@ window.BedrockEntityManager = class BedrockEntityManager {
|
||||
}
|
||||
}
|
||||
if (valid_textures_list.length == 1) {
|
||||
new Texture({keep_size: true, render_mode}).fromPath(valid_textures_list[0]).add()
|
||||
let texture = new Texture({keep_size: true, render_mode}).fromPath(valid_textures_list[0]).add()
|
||||
if (isApp) loadAdjacentTextureSet(texture);
|
||||
if (render_mode == 'layered') {
|
||||
updateLayeredTextures();
|
||||
}
|
||||
@ -169,14 +170,15 @@ window.BedrockEntityManager = class BedrockEntityManager {
|
||||
cancelIndex: 2,
|
||||
onButton(index) {
|
||||
dialog.hide();
|
||||
let textures_to_import = [];
|
||||
if (index == 1) {
|
||||
valid_textures_list.forEach(path => {
|
||||
new Texture({keep_size: true, render_mode}).fromPath(path).add()
|
||||
})
|
||||
textures_to_import = valid_textures_list;
|
||||
} else if (index == 0) {
|
||||
selected_textures.forEach(path => {
|
||||
new Texture({keep_size: true, render_mode}).fromPath(path).add()
|
||||
})
|
||||
textures_to_import = selected_textures;
|
||||
}
|
||||
for (let path of textures_to_import) {
|
||||
let texture = new Texture({keep_size: true, render_mode}).fromPath(path).add();
|
||||
if (isApp) loadAdjacentTextureSet(texture);
|
||||
}
|
||||
if (render_mode == 'layered') {
|
||||
updateLayeredTextures();
|
||||
@ -234,7 +236,9 @@ window.BedrockEntityManager = class BedrockEntityManager {
|
||||
try {
|
||||
let content = fs.readFileSync(path, 'utf8');
|
||||
Animator.loadFile({path, content}, animation_names);
|
||||
} catch (err) {}
|
||||
} catch (err) {
|
||||
console.err(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -320,7 +324,8 @@ window.BedrockEntityManager = class BedrockEntityManager {
|
||||
} else {
|
||||
function tryItWith(extension) {
|
||||
if (fs.existsSync(texture_path+'.'+extension)) {
|
||||
var texture = new Texture({keep_size: true}).fromPath(texture_path+'.'+extension).add()
|
||||
var texture = new Texture({keep_size: true}).fromPath(texture_path+'.'+extension).add();
|
||||
loadAdjacentTextureSet(texture);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -452,6 +457,7 @@ window.BedrockBlockManager = class BedrockBlockManager {
|
||||
])
|
||||
if (full_texture_path) {
|
||||
let texture = new Texture({keep_size: true}).fromPath(full_texture_path).add();
|
||||
if (isApp) loadAdjacentTextureSet(texture);
|
||||
if (target == '*') {
|
||||
texture.use_as_default = true;
|
||||
|
||||
@ -718,6 +724,11 @@ function calculateVisibleBox() {
|
||||
|
||||
if (data.object.item_display_transforms !== undefined) {
|
||||
DisplayMode.loadJSON(data.object.item_display_transforms)
|
||||
if (data.object.item_display_transforms.gui) {
|
||||
if (data.object.item_display_transforms.gui.fit_to_frame == undefined) {
|
||||
Project.display_settings.gui.fit_to_frame = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var bones = {}
|
||||
@ -1033,7 +1044,6 @@ let entity_file_codec = new Codec('bedrock_entity_file', {
|
||||
|
||||
function getFormatVersion() {
|
||||
if (Format.display_mode) {
|
||||
let has_new_displays = false;
|
||||
for (let i in DisplayMode.slots) {
|
||||
let key = DisplayMode.slots[i]
|
||||
if (Project.display_settings[key] && Project.display_settings[key].export) {
|
||||
@ -1045,6 +1055,7 @@ function getFormatVersion() {
|
||||
}
|
||||
}
|
||||
for (let cube of Cube.all) {
|
||||
if (cube.box_uv) continue;
|
||||
for (let fkey in cube.faces) {
|
||||
if (cube.faces[fkey].rotation) return '1.21.0';
|
||||
}
|
||||
@ -1150,15 +1161,14 @@ var codec = new Codec('bedrock', {
|
||||
}
|
||||
|
||||
let new_display = {};
|
||||
let has_new_displays = false;
|
||||
for (let i in DisplayMode.slots) {
|
||||
let key = DisplayMode.slots[i]
|
||||
if (Project.display_settings[key] && Project.display_settings[key].export) {
|
||||
new_display[key] = Project.display_settings[key].export();
|
||||
if (new_display[key]) has_new_displays = true;
|
||||
if (Project.display_settings[key] && Project.display_settings[key].exportBedrock) {
|
||||
let data = Project.display_settings[key].exportBedrock();
|
||||
if (data) new_display[key] = data;
|
||||
}
|
||||
}
|
||||
if (has_new_displays) {
|
||||
if (Object.keys(new_display).length) {
|
||||
entitymodel.item_display_transforms = new_display
|
||||
}
|
||||
|
||||
@ -1342,6 +1352,7 @@ var entity_format = new ModelFormat({
|
||||
}
|
||||
]
|
||||
},
|
||||
node_name_regex: '\\w.-',
|
||||
rotate_cubes: true,
|
||||
box_uv: true,
|
||||
optional_box_uv: true,
|
||||
@ -1381,6 +1392,7 @@ var block_format = new ModelFormat({
|
||||
}
|
||||
]
|
||||
},
|
||||
node_name_regex: '\\w.-',
|
||||
show_on_start_screen: new Date().dayOfYear() >= 298 || new Date().getYear() > 122,
|
||||
rotate_cubes: true,
|
||||
box_uv: false,
|
||||
|
@ -24,4 +24,5 @@ new ModelFormat({
|
||||
animation_mode: true,
|
||||
animated_textures: true,
|
||||
locators: true,
|
||||
pbr: true,
|
||||
})
|
||||
|
@ -1,6 +1,7 @@
|
||||
(function() {
|
||||
|
||||
let codec = new Codec('image', {
|
||||
name: tl('format.image'),
|
||||
extension: 'png',
|
||||
remember: true,
|
||||
load_filter: {
|
||||
@ -117,6 +118,9 @@ let codec = new Codec('image', {
|
||||
savetype: 'image',
|
||||
content,
|
||||
}, path => this.afterDownload(path));
|
||||
},
|
||||
write(content, path) {
|
||||
Blockbench.writeFile(path, {content, savetype: 'image'}, path => this.afterSave(path));
|
||||
}
|
||||
})
|
||||
codec.parse = null;
|
||||
|
@ -453,7 +453,7 @@ var codec = new Codec('java_block', {
|
||||
open_with_textures: {text: 'message.child_model_only.open_with_textures', condition: Texture.all.length > 0}
|
||||
}
|
||||
}, (result) => {
|
||||
if (result) {
|
||||
if (typeof result == 'string') {
|
||||
let parent = model.parent.replace(/\w+:/, '');
|
||||
let path_arr = path.split(osfs);
|
||||
let index = path_arr.length - path_arr.indexOf('models');
|
||||
|
@ -1071,6 +1071,7 @@ var format = new ModelFormat({
|
||||
]
|
||||
},
|
||||
codec,
|
||||
node_name_regex: '\\w',
|
||||
box_uv: true,
|
||||
box_uv_float_size: true,
|
||||
single_texture: true,
|
||||
|
@ -29,7 +29,7 @@ var codec = new Codec('optifine_entity', {
|
||||
}
|
||||
entitymodel.textureSize = [Project.texture_width, Project.texture_height];
|
||||
let default_texture = Texture.getDefault();
|
||||
if (default_texture?.use_as_default || (settings.optifine_save_default_texture.value && !isAppliedInModel(default_texture))) {
|
||||
if (default_texture && (default_texture.use_as_default || (settings.optifine_save_default_texture.value && !isAppliedInModel(default_texture)))) {
|
||||
let texture = Texture.getDefault();
|
||||
entitymodel.texture = getTexturePath(Texture.getDefault());
|
||||
entitymodel.textureSize = [texture.uv_width, texture.uv_height];
|
||||
@ -39,8 +39,7 @@ var codec = new Codec('optifine_entity', {
|
||||
if (Project.shadow_size != 1) entitymodel.shadowSize = Project.shadow_size;
|
||||
entitymodel.models = []
|
||||
|
||||
Outliner.root.forEach(function(g) {
|
||||
if (g instanceof Group == false) return;
|
||||
function compilePart(g) {
|
||||
if (!settings.export_empty_groups.value && !g.children.find(child => child.export)) return;
|
||||
//Bone
|
||||
var bone = {
|
||||
@ -184,7 +183,22 @@ var codec = new Codec('optifine_entity', {
|
||||
}
|
||||
|
||||
entitymodel.models.push(bone)
|
||||
})
|
||||
}
|
||||
|
||||
if (options.build_part) {
|
||||
compilePart({
|
||||
name: Project.name,
|
||||
origin: [0, 0, 0],
|
||||
rotation: [0, 0, 0],
|
||||
children: Outliner.root.filter(g => g.export)
|
||||
});
|
||||
} else {
|
||||
for (let group of Outliner.root) {
|
||||
if (group instanceof Group && group.export) {
|
||||
compilePart(group);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.dispatchEvent('compile', {entitymodel, options});
|
||||
|
||||
@ -238,17 +252,21 @@ var codec = new Codec('optifine_entity', {
|
||||
|
||||
//Bone
|
||||
let texture = importTexture(b.texture, b.textureSize);
|
||||
let group = new Group({
|
||||
name: b.part,
|
||||
origin: b.translate,
|
||||
rotation: b.rotate,
|
||||
mirror_uv: (b.mirrorTexture && b.mirrorTexture.includes('u')),
|
||||
cem_animations: b.animations,
|
||||
cem_attach: b.attach,
|
||||
cem_scale: b.scale,
|
||||
texture: texture ? texture.uuid : undefined,
|
||||
})
|
||||
group.origin.V3_multiply(-1);
|
||||
let group = 0;
|
||||
if (!model._is_jpm) {
|
||||
group = new Group({
|
||||
name: b.part,
|
||||
origin: b.translate,
|
||||
rotation: b.rotate,
|
||||
mirror_uv: (b.mirrorTexture && b.mirrorTexture.includes('u')),
|
||||
cem_animations: b.animations,
|
||||
cem_attach: b.attach,
|
||||
cem_scale: b.scale,
|
||||
texture: texture ? texture.uuid : undefined,
|
||||
})
|
||||
group.origin.V3_multiply(-1);
|
||||
group.init().addTo();
|
||||
}
|
||||
|
||||
function readContent(submodel, p_group, depth, texture) {
|
||||
|
||||
@ -302,7 +320,7 @@ var codec = new Codec('optifine_entity', {
|
||||
}
|
||||
})
|
||||
}
|
||||
if (p_group.parent !== 'root') {
|
||||
if (p_group && (p_group.parent !== 'root' || model._is_jpm)) {
|
||||
for (var i = 0; i < 3; i++) {
|
||||
base_cube.from[i] += p_group.origin[i];
|
||||
base_cube.to[i] += p_group.origin[i];
|
||||
@ -320,7 +338,7 @@ var codec = new Codec('optifine_entity', {
|
||||
}
|
||||
let sub_texture = importTexture(subsub.texture, subsub.textureSize);
|
||||
let group = new Group({
|
||||
name: subsub.id || `${b.part}_sub_${subcount}`,
|
||||
name: subsub.id || subsub.comment || `${b.part??'part'}_sub_${subcount}`,
|
||||
origin: subsub.translate || (depth >= 1 ? submodel.translate : undefined),
|
||||
rotation: subsub.rotate,
|
||||
mirror_uv: (subsub.mirrorTexture && subsub.mirrorTexture.includes('u')),
|
||||
@ -333,7 +351,6 @@ var codec = new Codec('optifine_entity', {
|
||||
}
|
||||
|
||||
}
|
||||
group.init().addTo()
|
||||
readContent(b, group, 0, texture || main_texture)
|
||||
})
|
||||
}
|
||||
|
@ -10,330 +10,41 @@ var part_codec = new Codec('optifine_part', {
|
||||
extensions: ['jpm']
|
||||
},
|
||||
compile(options) {
|
||||
if (options === undefined) options = {}
|
||||
var entitymodel = {}
|
||||
if (Project.credit || settings.credit.value) {
|
||||
entitymodel.credit = Project.credit || settings.credit.value
|
||||
let original_options = options??0;
|
||||
options = options ? Object.assign({}, options) : {};
|
||||
options.raw = true;
|
||||
options.build_part = true;
|
||||
let entitymodel = Codecs.optifine_entity.compile(options);
|
||||
let part_model = entitymodel.models[0];
|
||||
part_model.credit = entitymodel.credit;
|
||||
if (!part_model.textureSize) {
|
||||
part_model.textureSize = entitymodel.textureSize;
|
||||
}
|
||||
var geo_code = 'geometry.'+Project.geometry_name
|
||||
function getTexturePath(tex) {
|
||||
return tex.folder ? (tex.folder + '/' + tex.name) : tex.name;
|
||||
}
|
||||
entitymodel.textureSize = [Project.texture_width, Project.texture_height];
|
||||
let default_texture = Texture.getDefault();
|
||||
if (!settings.optifine_save_default_texture.value && !default_texture?.use_as_default) {
|
||||
default_texture = null;
|
||||
}
|
||||
if (default_texture) {
|
||||
let texture = Texture.getDefault();
|
||||
entitymodel.texture = getTexturePath(Texture.getDefault());
|
||||
entitymodel.textureSize = [texture.uv_width, texture.uv_height];
|
||||
}
|
||||
if (Project.shadow_size != 1) entitymodel.shadowSize = Project.shadow_size;
|
||||
entitymodel.submodels = []
|
||||
if (part_model.id == '') delete part_model.id;
|
||||
delete part_model.part;
|
||||
|
||||
Outliner.root.forEach(function(g) {
|
||||
if (g instanceof Group == false) return;
|
||||
if (!settings.export_empty_groups.value && !g.children.find(child => child.export)) return;
|
||||
//Bone
|
||||
var bone = {
|
||||
part: g.name,
|
||||
id: g.name,
|
||||
invertAxis: 'xy',
|
||||
mirrorTexture: undefined,
|
||||
translate: g.origin.slice()
|
||||
}
|
||||
bone.translate.V3_multiply(-1);
|
||||
this.dispatchEvent('compile', {model: part_model, original_options});
|
||||
|
||||
if (!g.rotation.allEqual(0)) {
|
||||
bone.rotate = g.rotation.slice()
|
||||
}
|
||||
if (entityMode.hardcodes[geo_code]) {
|
||||
var codes = entityMode.hardcodes[geo_code]
|
||||
var bone_codes = codes[bone.part] || codes[bone.part+'1']
|
||||
if (bone_codes) {
|
||||
if (!bone.rotate) bone.rotate = [0, 0, 0];
|
||||
bone_codes.rotation.forEach((dft, i) => {
|
||||
bone.rotate[i] += dft;
|
||||
})
|
||||
}
|
||||
}
|
||||
if (g.mirror_uv) {
|
||||
bone.mirrorTexture = 'u'
|
||||
}
|
||||
if (g.cem_attach) {
|
||||
bone.attach = true;
|
||||
}
|
||||
if (g.cem_scale) {
|
||||
bone.scale = g.cem_scale;
|
||||
}
|
||||
|
||||
function populate(p_model, group, depth, parent_texture) {
|
||||
|
||||
if (group.children.length === 0) return;
|
||||
let mirror_sub;
|
||||
|
||||
let child_cubes = group.children.filter(obj => obj.export && obj.type === 'cube')
|
||||
let has_different_mirrored_children = !!child_cubes.find(obj => obj.mirror_uv !== child_cubes[0].mirror_uv);
|
||||
let texture = parent_texture;
|
||||
if (group.texture) {
|
||||
let match = Texture.all.find(t => t.uuid == group.texture);
|
||||
if (match) texture = match;
|
||||
}
|
||||
|
||||
if (texture && texture != parent_texture) {
|
||||
p_model.texture = getTexturePath(texture);
|
||||
if (!parent_texture || texture.uv_width != parent_texture.uv_width || texture.uv_height != parent_texture.uv_height) {
|
||||
p_model.textureSize = [texture.uv_width, texture.uv_height];
|
||||
}
|
||||
}
|
||||
|
||||
group.children.forEach(obj => {
|
||||
if (!obj.export) return;
|
||||
if (obj.type === 'cube') {
|
||||
|
||||
if (obj.box_uv) {
|
||||
var box = new oneLiner()
|
||||
} else {
|
||||
var box = {};
|
||||
}
|
||||
var c_size = obj.size()
|
||||
box.coordinates = [
|
||||
obj.from[0],
|
||||
obj.from[1],
|
||||
obj.from[2],
|
||||
c_size[0],
|
||||
c_size[1],
|
||||
c_size[2]
|
||||
]
|
||||
if (p_model && p_model.part === undefined) {
|
||||
box.coordinates[0] -= p_model.translate[0];
|
||||
box.coordinates[1] -= p_model.translate[1];
|
||||
box.coordinates[2] -= p_model.translate[2];
|
||||
}
|
||||
if (obj.box_uv) {
|
||||
box.textureOffset = obj.uv_offset
|
||||
} else {
|
||||
for (let face in obj.faces) {
|
||||
if (obj.faces[face].texture !== null) {
|
||||
let uv = obj.faces[face].uv;
|
||||
box[`uv${capitalizeFirstLetter(face)}`] = uv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (obj.inflate && typeof obj.inflate === 'number') {
|
||||
box.sizeAdd = obj.inflate
|
||||
}
|
||||
|
||||
if (obj.mirror_uv !== group.mirror_uv && has_different_mirrored_children) {
|
||||
if (!mirror_sub) {
|
||||
mirror_sub = {
|
||||
invertAxis: 'xy',
|
||||
mirrorTexture: 'u',
|
||||
boxes: []
|
||||
}
|
||||
if (!p_model.submodels) p_model.submodels = [];
|
||||
p_model.submodels.splice(0, 0, mirror_sub)
|
||||
}
|
||||
mirror_sub.boxes.push(box);
|
||||
} else {
|
||||
if (!p_model.boxes) p_model.boxes = [];
|
||||
if (obj.mirror_uv !== group.mirror_uv) {
|
||||
p_model.mirrorTexture = obj.mirror_uv ? 'u' : undefined;
|
||||
}
|
||||
p_model.boxes.push(box)
|
||||
}
|
||||
} else if (obj.type === 'group') {
|
||||
|
||||
var bone = {
|
||||
id: obj.name,
|
||||
invertAxis: 'xy',
|
||||
mirrorTexture: undefined,
|
||||
translate: obj.origin.slice()
|
||||
}
|
||||
if (obj.mirror_uv) {
|
||||
bone.mirrorTexture = 'u';
|
||||
}
|
||||
if (!obj.rotation.allEqual(0)) {
|
||||
bone.rotate = obj.rotation.slice()
|
||||
}
|
||||
populate(bone, obj, depth+1, texture)
|
||||
if (depth >= 1) {
|
||||
bone.translate[0] -= group.origin[0];
|
||||
bone.translate[1] -= group.origin[1];
|
||||
bone.translate[2] -= group.origin[2];
|
||||
}
|
||||
|
||||
if (!p_model.submodels) p_model.submodels = [];
|
||||
p_model.submodels.push(bone)
|
||||
}
|
||||
})
|
||||
}
|
||||
populate(bone, g, 0, default_texture)
|
||||
|
||||
if (g.cem_animations && g.cem_animations.length) {
|
||||
bone.animations = g.cem_animations;
|
||||
}
|
||||
|
||||
entitymodel.submodels.push(bone)
|
||||
})
|
||||
|
||||
this.dispatchEvent('compile', {entitymodel, options});
|
||||
|
||||
if (options.raw) {
|
||||
return entitymodel
|
||||
if (original_options.raw) {
|
||||
return part_model
|
||||
} else {
|
||||
return autoStringify(entitymodel)
|
||||
return autoStringify(part_model)
|
||||
}
|
||||
},
|
||||
parse(model, path, add) {
|
||||
parse(model, path) {
|
||||
this.dispatchEvent('parse', {model});
|
||||
|
||||
const imported_textures = {};
|
||||
function importTexture(string, uv) {
|
||||
if (typeof string !== 'string') return;
|
||||
if (imported_textures[string]) return imported_textures[string];
|
||||
|
||||
let texture_path = string.replace(/[\\/]/g, osfs);
|
||||
if (texture_path.match(/^textures/) && path.includes('optifine')) {
|
||||
texture_path = path.replace(/[\\/]optifine[\\/].+$/i, osfs+texture_path);
|
||||
} else {
|
||||
texture_path = path.replace(/[\\/][^\\/]+$/, osfs+texture_path);
|
||||
}
|
||||
if (!texture_path.match(/\.\w{3,4}$/)) texture_path = texture_path + '.png';
|
||||
let texture = new Texture().fromPath(texture_path).add(false);
|
||||
imported_textures[string] = texture;
|
||||
if (uv instanceof Array) {
|
||||
texture.extend({
|
||||
uv_width: uv[0],
|
||||
uv_height: uv[1]
|
||||
})
|
||||
}
|
||||
return texture;
|
||||
}
|
||||
|
||||
if (typeof model.credit == 'string') Project.credit = model.credit;
|
||||
if (model.textureSize) {
|
||||
Project.texture_width = parseInt(model.textureSize[0])||16;
|
||||
Project.texture_height = parseInt(model.textureSize[1])||16;
|
||||
}
|
||||
let main_texture = importTexture(model.texture, model.textureSize);
|
||||
if (main_texture) {
|
||||
main_texture.use_as_default = true;
|
||||
let jem_model = {
|
||||
_is_jpm: true,
|
||||
invertAxis: 'xy',
|
||||
models: [model]
|
||||
}
|
||||
if (typeof model.shadowSize == 'number') Project.shadow_size = model.shadowSize;
|
||||
let empty_face = {uv: [0, 0, 0, 0], texture: null}
|
||||
if (model.submodels) {
|
||||
model.submodels.forEach(function(b) {
|
||||
if (typeof b !== 'object') return;
|
||||
let subcount = 0;
|
||||
|
||||
//Bone
|
||||
let texture = importTexture(b.texture, b.textureSize);
|
||||
let group = new Group({
|
||||
name: b.part,
|
||||
origin: b.translate,
|
||||
rotation: b.rotate,
|
||||
mirror_uv: (b.mirrorTexture && b.mirrorTexture.includes('u')),
|
||||
cem_animations: b.animations,
|
||||
cem_attach: b.attach,
|
||||
cem_scale: b.scale,
|
||||
texture: texture ? texture.uuid : undefined,
|
||||
})
|
||||
group.origin.V3_multiply(-1);
|
||||
|
||||
function readContent(submodel, p_group, depth, texture) {
|
||||
|
||||
if (submodel.boxes && submodel.boxes.length) {
|
||||
submodel.boxes.forEach(box => {
|
||||
|
||||
var base_cube = new Cube({
|
||||
name: box.name || p_group.name,
|
||||
autouv: 0,
|
||||
uv_offset: box.textureOffset,
|
||||
box_uv: !!box.textureOffset,
|
||||
inflate: box.sizeAdd,
|
||||
mirror_uv: p_group.mirror_uv
|
||||
})
|
||||
/*if (texture) {
|
||||
for (let fkey in base_cube.faces) {
|
||||
base_cube.faces[fkey].texture = texture.uuid;
|
||||
}
|
||||
}*/
|
||||
if (box.coordinates) {
|
||||
base_cube.extend({
|
||||
from: [
|
||||
box.coordinates[0],
|
||||
box.coordinates[1],
|
||||
box.coordinates[2]
|
||||
],
|
||||
to: [
|
||||
box.coordinates[0]+box.coordinates[3],
|
||||
box.coordinates[1]+box.coordinates[4],
|
||||
box.coordinates[2]+box.coordinates[5]
|
||||
]
|
||||
})
|
||||
}
|
||||
if (!box.textureOffset && (
|
||||
box.uvNorth
|
||||
|| box.uvEast
|
||||
|| box.uvSouth
|
||||
|| box.uvWest
|
||||
|| box.uvUp
|
||||
|| box.uvDown
|
||||
)) {
|
||||
base_cube.extend({
|
||||
box_uv: false,
|
||||
faces: {
|
||||
north: box.uvNorth ? {uv: box.uvNorth} : empty_face,
|
||||
east: box.uvEast ? {uv: box.uvEast} : empty_face,
|
||||
south: box.uvSouth ? {uv: box.uvSouth} : empty_face,
|
||||
west: box.uvWest ? {uv: box.uvWest} : empty_face,
|
||||
up: box.uvUp ? {uv: box.uvUp} : empty_face,
|
||||
down: box.uvDown ? {uv: box.uvDown} : empty_face,
|
||||
}
|
||||
})
|
||||
}
|
||||
if (p_group.parent !== 'root') {
|
||||
for (var i = 0; i < 3; i++) {
|
||||
base_cube.from[i] += p_group.origin[i];
|
||||
base_cube.to[i] += p_group.origin[i];
|
||||
}
|
||||
}
|
||||
base_cube.addTo(p_group).init()
|
||||
})
|
||||
}
|
||||
if (submodel.submodels && submodel.submodels.length) {
|
||||
submodel.submodels.forEach(subsub => {
|
||||
if (depth >= 1 && subsub.translate) {
|
||||
subsub.translate[0] += p_group.origin[0];
|
||||
subsub.translate[1] += p_group.origin[1];
|
||||
subsub.translate[2] += p_group.origin[2];
|
||||
}
|
||||
let sub_texture = importTexture(subsub.texture, subsub.textureSize);
|
||||
let group = new Group({
|
||||
name: subsub.id || `${b.part}_sub_${subcount}`,
|
||||
origin: subsub.translate || (depth >= 1 ? submodel.translate : undefined),
|
||||
rotation: subsub.rotate,
|
||||
mirror_uv: (subsub.mirrorTexture && subsub.mirrorTexture.includes('u')),
|
||||
texture: (sub_texture || texture)?.uuid,
|
||||
})
|
||||
subcount++;
|
||||
group.addTo(p_group).init()
|
||||
readContent(subsub, group, depth+1, sub_texture || texture)
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
group.init().addTo()
|
||||
readContent(b, group, 0, texture || main_texture)
|
||||
})
|
||||
}
|
||||
Project.box_uv = Cube.all.filter(cube => cube.box_uv).length > Cube.all.length/2;
|
||||
Codecs.optifine_entity.parse(jem_model, path);
|
||||
this.dispatchEvent('parsed', {model});
|
||||
Canvas.updateAllBones();
|
||||
Validator.validate()
|
||||
}
|
||||
})
|
||||
|
||||
|
147
js/io/io.js
@ -487,149 +487,6 @@ const Extruder = {
|
||||
Undo.finishEdit('Add extruded texture', {elements: selected, outliner: true, textures: [Texture.all[Texture.all.length-1]]})
|
||||
}
|
||||
}
|
||||
//Json
|
||||
function compileJSON(object, options = {}) {
|
||||
let indentation = options.indentation;
|
||||
if (typeof indentation !== 'string') {
|
||||
switch (settings.json_indentation.value) {
|
||||
case 'spaces_4': indentation = ' '; break;
|
||||
case 'spaces_2': indentation = ' '; break;
|
||||
case 'tabs': default: indentation = '\t'; break;
|
||||
}
|
||||
}
|
||||
function newLine(tabs) {
|
||||
if (options.small === true) {return '';}
|
||||
let s = '\n';
|
||||
for (let i = 0; i < tabs; i++) {
|
||||
s += indentation;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
function escape(string) {
|
||||
return string.replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n|\r\n/g, '\\n').replace(/\t/g, '\\t')
|
||||
}
|
||||
function handleVar(o, tabs, breaks = true) {
|
||||
var out = ''
|
||||
if (typeof o === 'string') {
|
||||
//String
|
||||
out += '"' + escape(o) + '"'
|
||||
} else if (typeof o === 'boolean') {
|
||||
//Boolean
|
||||
out += (o ? 'true' : 'false')
|
||||
} else if (o === null || o === Infinity || o === -Infinity) {
|
||||
//Null
|
||||
out += 'null'
|
||||
} else if (typeof o === 'number') {
|
||||
//Number
|
||||
o = (Math.round(o*100000)/100000).toString()
|
||||
out += o
|
||||
} else if (o instanceof Array) {
|
||||
//Array
|
||||
let has_content = false
|
||||
let multiline = !!o.find(item => typeof item === 'object');
|
||||
if (!multiline) {
|
||||
let length = 0;
|
||||
o.forEach(item => {
|
||||
length += typeof item === 'string' ? (item.length+4) : 3;
|
||||
});
|
||||
if (length > 140) multiline = true;
|
||||
}
|
||||
out += '['
|
||||
for (var i = 0; i < o.length; i++) {
|
||||
var compiled = handleVar(o[i], tabs+1)
|
||||
if (compiled) {
|
||||
if (has_content) {out += ',' + ((options.small || multiline) ? '' : ' ')}
|
||||
if (multiline) {out += newLine(tabs)}
|
||||
out += compiled
|
||||
has_content = true
|
||||
}
|
||||
}
|
||||
if (multiline) {out += newLine(tabs-1)}
|
||||
out += ']'
|
||||
} else if (typeof o === 'object') {
|
||||
//Object
|
||||
breaks = breaks && o.constructor.name !== 'oneLiner';
|
||||
var has_content = false
|
||||
out += '{'
|
||||
for (var key in o) {
|
||||
if (o.hasOwnProperty(key)) {
|
||||
var compiled = handleVar(o[key], tabs+1, breaks)
|
||||
if (compiled) {
|
||||
if (has_content) {out += ',' + (breaks || options.small?'':' ')}
|
||||
if (breaks) {out += newLine(tabs)}
|
||||
out += '"' + escape(key) + '":' + (options.small === true ? '' : ' ')
|
||||
out += compiled
|
||||
has_content = true
|
||||
}
|
||||
}
|
||||
}
|
||||
if (breaks && has_content) {out += newLine(tabs-1)}
|
||||
out += '}'
|
||||
}
|
||||
return out;
|
||||
}
|
||||
let file = handleVar(object, 1);
|
||||
if ((settings.final_newline.value && options.final_newline != false) || options.final_newline == true) {
|
||||
file += '\n';
|
||||
}
|
||||
return file;
|
||||
}
|
||||
function autoParseJSON(data, feedback) {
|
||||
if (data.substr(0, 4) === '<lz>') {
|
||||
data = LZUTF8.decompress(data.substr(4), {inputEncoding: 'StorageBinaryString'})
|
||||
}
|
||||
if (data.charCodeAt(0) === 0xFEFF) {
|
||||
data = data.substr(1)
|
||||
}
|
||||
try {
|
||||
data = JSON.parse(data)
|
||||
} catch (err1) {
|
||||
data = data.replace(/\/\*[^(\*\/)]*\*\/|\/\/.*/g, '')
|
||||
try {
|
||||
data = JSON.parse(data)
|
||||
} catch (err) {
|
||||
if (feedback === false) return;
|
||||
if (data.match(/\n\r?[><]{7}/)) {
|
||||
Blockbench.showMessageBox({
|
||||
title: 'message.invalid_file.title',
|
||||
icon: 'fab.fa-git-alt',
|
||||
message: 'message.invalid_file.merge_conflict'
|
||||
})
|
||||
return;
|
||||
}
|
||||
let error_part = '';
|
||||
function logErrantPart(whole, start, length) {
|
||||
var line = whole.substr(0, start).match(/\n/gm)
|
||||
line = line ? line.length+1 : 1
|
||||
var result = '';
|
||||
var lines = whole.substr(start, length).split(/\n/gm)
|
||||
lines.forEach((s, i) => {
|
||||
result += `#${line+i} ${s}\n`
|
||||
})
|
||||
error_part = result.substr(0, result.length-1) + ' <-- HERE';
|
||||
console.log(error_part);
|
||||
}
|
||||
console.error(err)
|
||||
var length = err.toString().split('at position ')[1]
|
||||
if (length) {
|
||||
length = parseInt(length)
|
||||
var start = limitNumber(length-32, 0, Infinity)
|
||||
|
||||
logErrantPart(data, start, 1+length-start)
|
||||
} else if (err.toString().includes('Unexpected end of JSON input')) {
|
||||
|
||||
logErrantPart(data, data.length-16, 10)
|
||||
}
|
||||
Blockbench.showMessageBox({
|
||||
translateKey: 'invalid_file',
|
||||
icon: 'error',
|
||||
message: tl('message.invalid_file.message', [err]) + (error_part ? `\n\n\`\`\`\n${error_part}\n\`\`\`` : '')
|
||||
})
|
||||
return;
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
BARS.defineActions(function() {
|
||||
@ -719,7 +576,9 @@ BARS.defineActions(function() {
|
||||
Codecs.project.write(Codecs.project.compile(), Project.save_path);
|
||||
}
|
||||
if (Project.export_path && export_codec?.compile) {
|
||||
export_codec.write(export_codec.compile(), Project.export_path)
|
||||
if (export_codec.id != 'image') {
|
||||
export_codec.write(export_codec.compile(), Project.export_path)
|
||||
}
|
||||
|
||||
} else if (export_codec?.export && !Project.save_path) {
|
||||
if (export_codec.id === 'project' || settings.dialog_save_codec.value == false) {
|
||||
|
@ -71,7 +71,6 @@ class ModelProject {
|
||||
|
||||
ProjectData[this.uuid] = {
|
||||
model_3d: new THREE.Object3D(),
|
||||
materials: {},
|
||||
nodes_3d: {}
|
||||
}
|
||||
}
|
||||
@ -135,9 +134,6 @@ class ModelProject {
|
||||
get model_3d() {
|
||||
return ProjectData[this.uuid].model_3d;
|
||||
}
|
||||
get materials() {
|
||||
return ProjectData[this.uuid].materials;
|
||||
}
|
||||
get nodes_3d() {
|
||||
return ProjectData[this.uuid].nodes_3d;
|
||||
}
|
||||
|
@ -209,11 +209,15 @@ function updateSelection(options = {}) {
|
||||
if (Condition(BarItems.layer_blend_mode.condition)) BarItems.layer_blend_mode.set(TextureLayer.selected?.blend_mode);
|
||||
|
||||
BARS.updateConditions();
|
||||
MenuBar.update()
|
||||
delete TickUpdates.selection;
|
||||
Blockbench.dispatchEvent('update_selection');
|
||||
}
|
||||
function unselectAllElements() {
|
||||
Project.selected_elements.forEachReverse(obj => obj.unselect())
|
||||
function unselectAllElements(exceptions) {
|
||||
Project.selected_elements.forEachReverse(obj => {
|
||||
if (exceptions instanceof Array && exceptions.includes(obj)) return;
|
||||
obj.unselect()
|
||||
})
|
||||
for (let group of Group.multi_selected) {
|
||||
group.unselect();
|
||||
}
|
||||
|
@ -677,7 +677,7 @@ class KnifeToolCubeContext {
|
||||
return getAxisLetter(this.axis);
|
||||
}
|
||||
hover(data) {
|
||||
if (!data) {
|
||||
if (!data || data.element instanceof Cube == false) {
|
||||
if (this.cross_mesh.parent) {
|
||||
this.cross_mesh.parent.remove(this.cross_mesh);
|
||||
}
|
||||
@ -1067,7 +1067,8 @@ SharedActions.add('delete', {
|
||||
condition: () => Modes.edit && Prop.active_panel == 'preview' && Mesh.selected[0] && Project.mesh_selection[Mesh.selected[0].uuid],
|
||||
run() {
|
||||
let meshes = Mesh.selected.slice();
|
||||
Undo.initEdit({elements: meshes, outliner: true})
|
||||
let keep_vertices = BarItems.delete.keybind.additionalModifierTriggered(event, 'keep_vertices');
|
||||
Undo.initEdit({elements: meshes, outliner: true, selection: true})
|
||||
|
||||
Mesh.selected.forEach(mesh => {
|
||||
let selected_vertices = mesh.getSelectedVertices();
|
||||
@ -1076,20 +1077,37 @@ SharedActions.add('delete', {
|
||||
|
||||
if ((BarItems.selection_mode.value == 'face' || BarItems.selection_mode.value == 'cluster') && selected_faces.length < Object.keys(mesh.faces).length) {
|
||||
let affected_vertices = [];
|
||||
let affected_edges = [];
|
||||
selected_faces.forEach(fkey => {
|
||||
affected_vertices.safePush(...mesh.faces[fkey].vertices);
|
||||
let face = mesh.faces[fkey];
|
||||
affected_vertices.safePush(...face.vertices);
|
||||
if (keep_vertices) {
|
||||
affected_edges.push(...face.getEdges());
|
||||
}
|
||||
delete mesh.faces[fkey];
|
||||
})
|
||||
affected_vertices.forEach(vertex_key => {
|
||||
let used = false;
|
||||
for (let key in mesh.faces) {
|
||||
let face = mesh.faces[key];
|
||||
if (face.vertices.includes(vertex_key)) used = true;
|
||||
if (keep_vertices) {
|
||||
edges: for (let edge of affected_edges) {
|
||||
for (let fkey in mesh.faces) {
|
||||
let vertices = mesh.faces[fkey].vertices;
|
||||
if (vertices.includes(edge[0]) && vertices.includes(edge[1])) {
|
||||
continue edges;
|
||||
}
|
||||
}
|
||||
mesh.addFaces(new MeshFace(mesh, {vertices: edge}));
|
||||
}
|
||||
if (!used) {
|
||||
delete mesh.vertices[vertex_key];
|
||||
}
|
||||
})
|
||||
} else {
|
||||
affected_vertices.forEach(vertex_key => {
|
||||
let used = false;
|
||||
for (let key in mesh.faces) {
|
||||
let face = mesh.faces[key];
|
||||
if (face.vertices.includes(vertex_key)) used = true;
|
||||
}
|
||||
if (!used) {
|
||||
delete mesh.vertices[vertex_key];
|
||||
}
|
||||
})
|
||||
}
|
||||
} else if (BarItems.selection_mode.value == 'edge') {
|
||||
for (let key in mesh.faces) {
|
||||
let face = mesh.faces[key];
|
||||
@ -1110,7 +1128,7 @@ SharedActions.add('delete', {
|
||||
let face = mesh.faces[key];
|
||||
if (face.vertices.includes(vkey)) used = true;
|
||||
}
|
||||
if (!used) {
|
||||
if (!used && !keep_vertices) {
|
||||
delete mesh.vertices[vkey];
|
||||
selected_vertices.remove(vkey);
|
||||
selected_edges.remove(edge);
|
||||
@ -1620,7 +1638,7 @@ BARS.defineActions(function() {
|
||||
|
||||
elements.push(mesh);
|
||||
mesh.init()
|
||||
unselectAll()
|
||||
unselectAllElements()
|
||||
mesh.select()
|
||||
UVEditor.setAutoSize(null, true, Object.keys(mesh.faces));
|
||||
Undo.finishEdit('Add primitive');
|
||||
@ -1636,12 +1654,12 @@ BARS.defineActions(function() {
|
||||
runEdit(false, result);
|
||||
|
||||
Undo.amendEdit({
|
||||
diameter: {label: 'dialog.add_primitive.diameter', type: 'number', value: result.diameter, interval_type: 'position'},
|
||||
height: {label: 'dialog.add_primitive.height', type: 'number', value: result.height, condition: ['cylinder', 'cone', 'cuboid', 'beveled_cuboid', 'pyramid', 'tube'].includes(result.shape), interval_type: 'position'},
|
||||
sides: {label: 'dialog.add_primitive.sides', type: 'number', value: result.sides, min: 3, max: 48, condition: ['cylinder', 'cone', 'circle', 'torus', 'sphere', 'tube'].includes(result.shape)},
|
||||
minor_diameter: {label: 'dialog.add_primitive.minor_diameter', type: 'number', value: result.minor_diameter, condition: ['torus', 'tube'].includes(result.shape), interval_type: 'position'},
|
||||
minor_sides: {label: 'dialog.add_primitive.minor_sides', type: 'number', value: result.minor_sides, min: 2, max: 32, condition: ['torus'].includes(result.shape)},
|
||||
edge_size: {label: 'dialog.add_primitive.edge_size', type: 'number', value: result.edge_size, condition: ['beveled_cuboid'].includes(result.shape)},
|
||||
diameter: {label: 'dialog.add_primitive.diameter', type: 'num_slider', value: result.diameter, interval_type: 'position'},
|
||||
height: {label: 'dialog.add_primitive.height', type: 'num_slider', value: result.height, condition: ['cylinder', 'cone', 'cuboid', 'beveled_cuboid', 'pyramid', 'tube'].includes(result.shape), interval_type: 'position'},
|
||||
sides: {label: 'dialog.add_primitive.sides', type: 'num_slider', value: result.sides, min: 3, max: 48, condition: ['cylinder', 'cone', 'circle', 'torus', 'sphere', 'tube'].includes(result.shape)},
|
||||
minor_diameter: {label: 'dialog.add_primitive.minor_diameter', type: 'num_slider', value: result.minor_diameter, condition: ['torus', 'tube'].includes(result.shape), interval_type: 'position'},
|
||||
minor_sides: {label: 'dialog.add_primitive.minor_sides', type: 'num_slider', value: result.minor_sides, min: 2, max: 32, condition: ['torus'].includes(result.shape)},
|
||||
edge_size: {label: 'dialog.add_primitive.edge_size', type: 'num_slider', value: result.edge_size, condition: ['beveled_cuboid'].includes(result.shape)},
|
||||
}, form => {
|
||||
Object.assign(result, form);
|
||||
runEdit(true, result);
|
||||
@ -2190,9 +2208,9 @@ BARS.defineActions(function() {
|
||||
Mesh.selected.forEach(mesh => {
|
||||
let original_vertices = mesh.getSelectedVertices().slice();
|
||||
let selected_edges = mesh.getSelectedEdges(true);
|
||||
let selected_face_keys = mesh.getSelectedFaces();
|
||||
let new_vertices;
|
||||
let new_face_keys = [];
|
||||
let selected_face_keys = mesh.getSelectedFaces();
|
||||
if (original_vertices.length && (BarItems.selection_mode.value == 'vertex' || BarItems.selection_mode.value == 'edge')) {
|
||||
selected_face_keys.empty();
|
||||
}
|
||||
@ -2267,7 +2285,6 @@ BARS.defineActions(function() {
|
||||
}
|
||||
}
|
||||
})
|
||||
console.log(count, direction.slice());
|
||||
if (count > 1) {
|
||||
let magnitude = Math.sqrt(direction[0]**2 + direction[1]**2 + direction[2]**2);
|
||||
direction.V3_divide(magnitude);
|
||||
@ -2362,13 +2379,13 @@ BARS.defineActions(function() {
|
||||
if (vertices.length == 2) delete mesh.faces[selected_face_keys[face_index]];
|
||||
})
|
||||
|
||||
// Create Face between extruded edges
|
||||
// Create Faces for extruded edges
|
||||
let new_faces = [];
|
||||
selected_edges.forEach(edge => {
|
||||
let face, sorted_vertices;
|
||||
for (let fkey in mesh.faces) {
|
||||
let face2 = mesh.faces[fkey];
|
||||
let vertices = face2.getSortedVertices();
|
||||
let vertices = face2.vertices;
|
||||
if (vertices.includes(edge[0]) && vertices.includes(edge[1])) {
|
||||
face = face2;
|
||||
sorted_vertices = vertices;
|
||||
@ -2383,6 +2400,9 @@ BARS.defineActions(function() {
|
||||
let new_face = new MeshFace(mesh, face).extend({
|
||||
vertices: [a, b, c, d]
|
||||
});
|
||||
if (new_face.getAngleTo(face) > 90) {
|
||||
new_face.invert();
|
||||
}
|
||||
let [face_key] = mesh.addFaces(new_face);
|
||||
new_face_keys.push(face_key);
|
||||
new_faces.push(new_face);
|
||||
@ -2423,7 +2443,7 @@ BARS.defineActions(function() {
|
||||
runEdit();
|
||||
|
||||
Undo.amendEdit({
|
||||
extend: {type: 'number', value: 1, label: 'edit.extrude_mesh_selection.extend', interval_type: 'position'},
|
||||
extend: {type: 'num_slider', value: 1, label: 'edit.extrude_mesh_selection.extend', interval_type: 'position'},
|
||||
direction_mode: {type: 'select', label: 'edit.extrude_mesh_selection.direction', options: {
|
||||
outwards: 'edit.extrude_mesh_selection.direction.outwards',
|
||||
average: 'edit.extrude_mesh_selection.direction.average',
|
||||
@ -2603,7 +2623,7 @@ BARS.defineActions(function() {
|
||||
runEdit();
|
||||
|
||||
Undo.amendEdit({
|
||||
thickness: {type: 'number', value: 1, label: 'edit.solidify_mesh_selection.thickness', interval_type: 'position'},
|
||||
thickness: {type: 'num_slider', value: 1, label: 'edit.solidify_mesh_selection.thickness', interval_type: 'position'},
|
||||
}, form => {
|
||||
runEdit(true, form.thickness);
|
||||
})
|
||||
@ -2727,7 +2747,7 @@ BARS.defineActions(function() {
|
||||
runEdit();
|
||||
|
||||
Undo.amendEdit({
|
||||
offset: {type: 'number', value: 50, label: 'edit.loop_cut.offset', min: 0, max: 100, interval_type: 'position'},
|
||||
offset: {type: 'num_slider', value: 50, label: 'edit.loop_cut.offset', min: 0, max: 100, interval_type: 'position'},
|
||||
}, form => {
|
||||
runEdit(true, form.offset);
|
||||
})
|
||||
@ -3060,9 +3080,9 @@ BARS.defineActions(function() {
|
||||
runEdit();
|
||||
|
||||
Undo.amendEdit({
|
||||
direction: {type: 'number', value: 0, label: 'edit.loop_cut.direction', condition: !!selected_face, min: 0},
|
||||
cuts: {type: 'number', value: 1, label: 'edit.loop_cut.cuts', min: 0, max: 16},
|
||||
offset: {type: 'number', value: length/2, label: 'edit.loop_cut.offset', min: 0, /*max: length,*/ interval_type: 'position'},
|
||||
direction: {type: 'num_slider', value: 0, label: 'edit.loop_cut.direction', condition: !!selected_face, min: 0},
|
||||
cuts: {type: 'num_slider', value: 1, label: 'edit.loop_cut.cuts', min: 0, max: 16},
|
||||
offset: {type: 'num_slider', value: length/2, label: 'edit.loop_cut.offset', min: 0, /*max: length,*/ interval_type: 'position'},
|
||||
unit: {type: 'inline_select', label: 'edit.loop_cut.unit', options: {size: 'edit.loop_cut.unit.size_units', percent: 'edit.loop_cut.unit.percent'}},
|
||||
}, (form, form_options) => {
|
||||
let direction = form.direction || 0;
|
||||
@ -3612,7 +3632,7 @@ BARS.defineActions(function() {
|
||||
new Toggle('proportional_editing', {
|
||||
icon: 'wifi_tethering',
|
||||
category: 'edit',
|
||||
condition: {modes: ['edit'], features: ['meshes'], method: () => (Mesh.selected[0] && Mesh.selected[0].getSelectedVertices().length > 0)},
|
||||
condition: {modes: ['edit'], features: ['meshes']},
|
||||
tool_config: new ToolConfig('proportional_editing_options', {
|
||||
title: 'action.proportional_editing',
|
||||
width: 400,
|
||||
|
@ -18,6 +18,8 @@ const MirrorModeling = {
|
||||
},
|
||||
createClone(original, undo_aspects) {
|
||||
// Create or update clone
|
||||
let options = BarItems.mirror_modeling.tool_config.options;
|
||||
let mirror_uv = options.mirror_uv;
|
||||
let center = Format.centered_grid ? 0 : 8;
|
||||
let mirror_element = MirrorModeling.cached_elements[original.uuid]?.counterpart;
|
||||
let element_before_snapshot;
|
||||
@ -33,6 +35,30 @@ const MirrorModeling = {
|
||||
mirror_element.extend({
|
||||
name: element_before_snapshot.name
|
||||
});
|
||||
if (!mirror_uv) {
|
||||
if (original instanceof Mesh) {
|
||||
for (let fkey in mirror_element.faces) {
|
||||
let face = mirror_element.faces[fkey];
|
||||
let face_before = element_before_snapshot.faces[fkey];
|
||||
if (face_before) {
|
||||
face.texture = face_before.texture;
|
||||
for (let vkey of face_before.vertices) {
|
||||
if (face.vertices.includes(vkey) && face_before.uv[vkey]) {
|
||||
face.uv[vkey] = face_before.uv[vkey].slice();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mirror_element.extend({
|
||||
faces: element_before_snapshot.faces,
|
||||
uv_offset: element_before_snapshot.uv_offset,
|
||||
mirror_uv: element_before_snapshot.mirror_uv,
|
||||
box_uv: element_before_snapshot.box_uv,
|
||||
autouv: element_before_snapshot.autouv
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Update hierarchy up
|
||||
function updateParent(child, child_b) {
|
||||
@ -116,9 +142,51 @@ const MirrorModeling = {
|
||||
return 16 - input;
|
||||
}
|
||||
},
|
||||
createLocalSymmetry(mesh) {
|
||||
discoverMeshPartConnections(mesh) {
|
||||
let data = {
|
||||
faces: {},
|
||||
vertices: {},
|
||||
}
|
||||
// Detect vertex counterparts
|
||||
for (let vkey in mesh.vertices) {
|
||||
if (data.vertices[vkey]) continue;
|
||||
let vector = Reusable.vec1.fromArray(mesh.vertices[vkey]);
|
||||
vector.x *= -1;
|
||||
for (let vkey2 in mesh.vertices) {
|
||||
//if (vkey == vkey2) continue;
|
||||
let distance = vector.distanceTo(Reusable.vec2.fromArray(mesh.vertices[vkey2]));
|
||||
if (distance < 0.001) {
|
||||
data.vertices[vkey] = vkey2;
|
||||
data.vertices[vkey2] = vkey;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Detect face counterparts
|
||||
for (let fkey in mesh.faces) {
|
||||
if (data.faces[fkey]) continue;
|
||||
for (let fkey2 in mesh.faces) {
|
||||
if (fkey == fkey2) continue;
|
||||
let match = mesh.faces[fkey].vertices.allAre(vkey => {
|
||||
let other_vkey = data.vertices[vkey];
|
||||
if (!other_vkey) return false;
|
||||
return mesh.faces[fkey2].vertices.includes(other_vkey);
|
||||
})
|
||||
if (match) {
|
||||
data.faces[fkey] = fkey2;
|
||||
data.faces[fkey2] = fkey;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return data;
|
||||
},
|
||||
createLocalSymmetry(mesh, cached_data) {
|
||||
// Create or update clone
|
||||
let edit_side = MirrorModeling.getEditSide();
|
||||
let options = BarItems.mirror_modeling.tool_config.options;
|
||||
let mirror_uv = options.mirror_uv;
|
||||
let pre_part_connections = cached_data?.pre_part_connections;
|
||||
// Delete all vertices on the non-edit side
|
||||
let deleted_vertices = {};
|
||||
let deleted_vertices_by_position = {};
|
||||
@ -155,6 +223,7 @@ const MirrorModeling = {
|
||||
}
|
||||
}
|
||||
|
||||
// Delete faces temporarily if all their vertices have been removed
|
||||
let deleted_faces = {};
|
||||
for (let fkey in mesh.faces) {
|
||||
let face = mesh.faces[fkey];
|
||||
@ -165,6 +234,7 @@ const MirrorModeling = {
|
||||
}
|
||||
}
|
||||
|
||||
// Create mirrored faces
|
||||
let original_fkeys = Object.keys(mesh.faces);
|
||||
for (let fkey of original_fkeys) {
|
||||
let face = mesh.faces[fkey];
|
||||
@ -201,21 +271,23 @@ const MirrorModeling = {
|
||||
|
||||
} else if (deleted_face_vertices.length == 0 && face.vertices.find((vkey) => vkey != vertex_counterpart[vkey])) {
|
||||
// Recreate face as mirrored
|
||||
let new_face_key;
|
||||
for (let key in deleted_faces) {
|
||||
let deleted_face = deleted_faces[key];
|
||||
if (face.vertices.allAre(vkey => deleted_face.vertices.includes(vertex_counterpart[vkey]))) {
|
||||
new_face_key = key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
let new_face_key = pre_part_connections && pre_part_connections.faces[fkey];
|
||||
let original_face = deleted_faces[new_face_key];
|
||||
|
||||
let new_face = new MeshFace(mesh, face);
|
||||
face.vertices.forEach((vkey, i) => {
|
||||
let new_vkey = vertex_counterpart[vkey];
|
||||
new_face.vertices.splice(i, 1, new_vkey);
|
||||
delete new_face.uv[vkey];
|
||||
new_face.uv[new_vkey] = face.uv[vkey].slice();
|
||||
if (mirror_uv || !original_face) {
|
||||
new_face.uv[new_vkey] = face.uv[vkey].slice();
|
||||
} else {
|
||||
// change
|
||||
let original_vkey = pre_part_connections.vertices[vkey];
|
||||
if (original_face.uv[original_vkey]) {
|
||||
new_face.uv[new_vkey] = original_face.uv[original_vkey].slice();
|
||||
}
|
||||
}
|
||||
})
|
||||
new_face.invert();
|
||||
if (new_face_key) {
|
||||
@ -224,8 +296,14 @@ const MirrorModeling = {
|
||||
[new_face_key] = mesh.addFaces(new_face);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
let selected_vertices = mesh.getSelectedVertices(true);
|
||||
selected_vertices.replace(selected_vertices.filter(vkey => mesh.vertices[vkey]));
|
||||
let selected_edges = mesh.getSelectedEdges(true);
|
||||
selected_edges.replace(selected_edges.filter(edge => edge.allAre(vkey => mesh.vertices[vkey])));
|
||||
let selected_faces = mesh.getSelectedFaces(true);
|
||||
selected_faces.replace(selected_faces.filter(fkey => mesh.faces[fkey]));
|
||||
|
||||
let {preview_controller} = mesh;
|
||||
preview_controller.updateGeometry(mesh);
|
||||
preview_controller.updateFaces(mesh);
|
||||
@ -331,6 +409,9 @@ Blockbench.on('init_edit', ({aspects}) => {
|
||||
if (!data.counterpart) data.is_copy = false;
|
||||
} else {
|
||||
data.is_copy = false;
|
||||
if (element instanceof Mesh) {
|
||||
data.pre_part_connections = MirrorModeling.discoverMeshPartConnections(element)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -372,15 +453,16 @@ Blockbench.on('finish_edit', ({aspects}) => {
|
||||
aspects.elements = aspects.elements.slice();
|
||||
let static_elements_copy = aspects.elements.slice();
|
||||
static_elements_copy.forEach((element) => {
|
||||
let cached_data = MirrorModeling.cached_elements[element.uuid]
|
||||
if (element.allow_mirror_modeling && !element.locked) {
|
||||
let is_centered = MirrorModeling.isCentered(element);
|
||||
|
||||
if (is_centered && element instanceof Mesh) {
|
||||
// Complete other side of mesh
|
||||
MirrorModeling.createLocalSymmetry(element);
|
||||
MirrorModeling.createLocalSymmetry(element, cached_data);
|
||||
}
|
||||
if (is_centered) {
|
||||
let mirror_element = MirrorModeling.cached_elements[element.uuid]?.counterpart;
|
||||
let mirror_element = cached_data?.counterpart;
|
||||
if (mirror_element && mirror_element.uuid != element.uuid) {
|
||||
MirrorModeling.insertElementIntoUndo(mirror_element, Undo.current_save.aspects, mirror_element.getUndoCopy());
|
||||
mirror_element.remove();
|
||||
@ -424,7 +506,22 @@ BARS.defineActions(() => {
|
||||
Project.mirror_modeling_enabled = this.value;
|
||||
MirrorModeling.cached_elements = {};
|
||||
updateSelection();
|
||||
}
|
||||
},
|
||||
tool_config: new ToolConfig('mirror_modeling_options', {
|
||||
title: 'action.mirror_modeling',
|
||||
form: {
|
||||
enabled: {type: 'checkbox', label: 'menu.mirror_painting.enabled', value: false},
|
||||
mirror_uv: {type: 'checkbox', label: 'menu.mirror_modeling.mirror_uv', value: true}
|
||||
},
|
||||
onOpen() {
|
||||
this.setFormValues({enabled: BarItems.mirror_modeling.value}, false);
|
||||
},
|
||||
onFormChange(formResult) {
|
||||
if (BarItems.mirror_modeling.value != formResult.enabled) {
|
||||
BarItems.mirror_modeling.trigger();
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
let allow_toggle = new Toggle('allow_element_mirror_modeling', {
|
||||
icon: 'align_horizontal_center',
|
||||
|
@ -335,9 +335,9 @@ const Vertexsnap = {
|
||||
let mode = BarItems.vertex_snap_mode.get();
|
||||
|
||||
function ignoreVectorAxes(vector) {
|
||||
if (options.ignore_x) vector.x = 0;
|
||||
if (options.ignore_y) vector.y = 0;
|
||||
if (options.ignore_z) vector.z = 0;
|
||||
if (options.ignore_axis?.x) vector.x = 0;
|
||||
if (options.ignore_axis?.y) vector.y = 0;
|
||||
if (options.ignore_axis?.z) vector.z = 0;
|
||||
}
|
||||
|
||||
if (Vertexsnap.move_origin) {
|
||||
@ -497,9 +497,7 @@ const Vertexsnap = {
|
||||
y: tl('edit.vertex_snap.align.align_axis', 'Y'),
|
||||
z: tl('edit.vertex_snap.align.align_axis', 'Z'),
|
||||
}},
|
||||
ignore_x: {type: 'checkbox', label: tl('edit.vertex_snap.ignore_axis', 'X'), value: false},
|
||||
ignore_y: {type: 'checkbox', label: tl('edit.vertex_snap.ignore_axis', 'Y'), value: false},
|
||||
ignore_z: {type: 'checkbox', label: tl('edit.vertex_snap.ignore_axis', 'Z'), value: false},
|
||||
ignore_axis: {type: 'inline_multi_select', label: tl('edit.vertex_snap.ignore_axis', ''), options: {x: 'X', y: 'Y', z: 'Z'}, value: {x: false, y: false, z: false}},
|
||||
}, form => {
|
||||
Vertexsnap.snap(data, form, true);
|
||||
})
|
||||
@ -508,10 +506,6 @@ const Vertexsnap = {
|
||||
}
|
||||
|
||||
//Center
|
||||
function centerElementsAll(axis) {
|
||||
centerElements(0, false);
|
||||
centerElements(2, false);
|
||||
}
|
||||
function centerElements(axis, update) {
|
||||
if (!Outliner.selected.length) return;
|
||||
let center = getSelectionCenter()[axis];
|
||||
@ -526,7 +520,7 @@ function centerElements(axis, update) {
|
||||
}
|
||||
})
|
||||
Group.all.forEach(group => {
|
||||
if (!Group.multi_selected) return;
|
||||
if (!group.selected) return;
|
||||
group.origin[axis] += difference;
|
||||
})
|
||||
Canvas.updateView({
|
||||
@ -540,9 +534,9 @@ function centerElements(axis, update) {
|
||||
|
||||
//Move
|
||||
function moveElementsInSpace(difference, axis) {
|
||||
let space = Transformer.getTransformSpace()
|
||||
let space = Transformer.getTransformSpace();
|
||||
let groups;
|
||||
if (Format.bone_rig && (Group.multi_selected.length > 1 || Group.first_selected.matchesSelection())) {
|
||||
if (Format.bone_rig && Group.first_selected && (Group.multi_selected.length > 1 || Group.first_selected.matchesSelection())) {
|
||||
groups = Group.multi_selected;
|
||||
}
|
||||
var group_m;
|
||||
@ -733,7 +727,7 @@ function getRotationInterval(event) {
|
||||
return 2.5;
|
||||
}
|
||||
}
|
||||
function getRotationObject() {
|
||||
function getRotationObjects() {
|
||||
if (Format.bone_rig && Group.first_selected) return Group.multi_selected;
|
||||
let elements = Outliner.selected.filter(element => {
|
||||
return element.rotatable && (element instanceof Cube == false || Format.rotate_cubes);
|
||||
@ -741,7 +735,7 @@ function getRotationObject() {
|
||||
if (elements.length) return elements;
|
||||
}
|
||||
function rotateOnAxis(modify, axis, slider) {
|
||||
var things = getRotationObject();
|
||||
var things = getRotationObjects();
|
||||
if (!things) return;
|
||||
if (things instanceof Array == false) things = [things];
|
||||
//Warning
|
||||
@ -1329,7 +1323,7 @@ BARS.defineActions(function() {
|
||||
description: tl('action.slider_rotation.desc', ['X']),
|
||||
color: 'x',
|
||||
category: 'transform',
|
||||
condition: () => ((Modes.edit || Modes.pose) && getRotationObject()),
|
||||
condition: () => ((Modes.edit || Modes.pose) && getRotationObjects()),
|
||||
get: function() {
|
||||
if (Format.bone_rig && Group.first_selected) {
|
||||
return Group.first_selected.rotation[0];
|
||||
@ -1348,7 +1342,7 @@ BARS.defineActions(function() {
|
||||
},
|
||||
onAfter: function() {
|
||||
afterRotateOnAxis();
|
||||
Undo.finishEdit(getRotationObject() instanceof Group ? 'Rotate group' : 'Rotate elements');
|
||||
Undo.finishEdit(getRotationObjects()?.find(el => el instanceof Group) ? 'Rotate group' : 'Rotate elements');
|
||||
},
|
||||
getInterval: getRotationInterval
|
||||
})
|
||||
@ -1357,7 +1351,7 @@ BARS.defineActions(function() {
|
||||
description: tl('action.slider_rotation.desc', ['Y']),
|
||||
color: 'y',
|
||||
category: 'transform',
|
||||
condition: () => ((Modes.edit || Modes.pose) && getRotationObject()),
|
||||
condition: () => ((Modes.edit || Modes.pose) && getRotationObjects()),
|
||||
get: function() {
|
||||
if (Format.bone_rig && Group.first_selected) {
|
||||
return Group.first_selected.rotation[1];
|
||||
@ -1376,7 +1370,7 @@ BARS.defineActions(function() {
|
||||
},
|
||||
onAfter: function() {
|
||||
afterRotateOnAxis();
|
||||
Undo.finishEdit(getRotationObject() instanceof Group ? 'Rotate group' : 'Rotate elements');
|
||||
Undo.finishEdit(getRotationObjects()?.find(el => el instanceof Group) ? 'Rotate group' : 'Rotate elements');
|
||||
},
|
||||
getInterval: getRotationInterval
|
||||
})
|
||||
@ -1385,7 +1379,7 @@ BARS.defineActions(function() {
|
||||
description: tl('action.slider_rotation.desc', ['Z']),
|
||||
color: 'z',
|
||||
category: 'transform',
|
||||
condition: () => ((Modes.edit || Modes.pose) && getRotationObject()),
|
||||
condition: () => ((Modes.edit || Modes.pose) && getRotationObjects()),
|
||||
get: function() {
|
||||
if (Format.bone_rig && Group.first_selected) {
|
||||
return Group.first_selected.rotation[2];
|
||||
@ -1404,7 +1398,7 @@ BARS.defineActions(function() {
|
||||
},
|
||||
onAfter: function() {
|
||||
afterRotateOnAxis();
|
||||
Undo.finishEdit(getRotationObject() instanceof Group ? 'Rotate group' : 'Rotate elements');
|
||||
Undo.finishEdit(getRotationObjects()?.find(el => el instanceof Group) ? 'Rotate group' : 'Rotate elements');
|
||||
},
|
||||
getInterval: getRotationInterval
|
||||
})
|
||||
@ -1413,15 +1407,17 @@ BARS.defineActions(function() {
|
||||
|
||||
//Origin
|
||||
function moveOriginOnAxis(modify, axis) {
|
||||
var rotation_object = getRotationObject()
|
||||
var rotation_objects = getRotationObjects()
|
||||
|
||||
if (rotation_object instanceof Group) {
|
||||
var val = modify(rotation_object.origin[axis]);
|
||||
rotation_object.origin[axis] = val;
|
||||
if (rotation_objects && rotation_objects[0] instanceof Group) {
|
||||
let elements_to_update = [];
|
||||
rotation_object.forEachChild(element => elements_to_update.push(element), OutlinerElement);
|
||||
for (let group of rotation_objects) {
|
||||
let val = modify(group.origin[axis]);
|
||||
group.origin[axis] = val;
|
||||
group.forEachChild(element => elements_to_update.safePush(element), OutlinerElement);
|
||||
}
|
||||
Canvas.updateView({
|
||||
groups: [rotation_object],
|
||||
groups: rotation_objects,
|
||||
group_aspects: {transform: true},
|
||||
elements: elements_to_update,
|
||||
element_aspects: {transform: true},
|
||||
@ -1431,11 +1427,11 @@ BARS.defineActions(function() {
|
||||
Canvas.updateAllBones();
|
||||
}
|
||||
} else {
|
||||
rotation_object.forEach(function(obj, i) {
|
||||
var val = modify(obj.origin[axis]);
|
||||
rotation_objects.forEach(function(obj, i) {
|
||||
let val = modify(obj.origin[axis]);
|
||||
obj.origin[axis] = val;
|
||||
})
|
||||
Canvas.updateView({elements: rotation_object, element_aspects: {transform: true, geometry: true}, selection: true})
|
||||
Canvas.updateView({elements: rotation_objects, element_aspects: {transform: true, geometry: true}, selection: true})
|
||||
}
|
||||
if (Modes.animate) {
|
||||
Animator.preview();
|
||||
@ -1446,7 +1442,7 @@ BARS.defineActions(function() {
|
||||
description: tl('action.slider_origin.desc', ['X']),
|
||||
color: 'x',
|
||||
category: 'transform',
|
||||
condition: () => (Modes.edit || Modes.animate || Modes.pose) && getRotationObject() && (Group.first_selected || Outliner.selected.length > Locator.selected.length),
|
||||
condition: () => (Modes.edit || Modes.animate || Modes.pose) && getRotationObjects() && (Group.first_selected || Outliner.selected.length > Locator.selected.length),
|
||||
getInterval: getSpatialInterval,
|
||||
get: function() {
|
||||
if (Format.bone_rig && Group.first_selected) {
|
||||
@ -1473,7 +1469,7 @@ BARS.defineActions(function() {
|
||||
description: tl('action.slider_origin.desc', ['Y']),
|
||||
color: 'y',
|
||||
category: 'transform',
|
||||
condition: () => (Modes.edit || Modes.animate || Modes.pose) && getRotationObject() && (Group.first_selected || Outliner.selected.length > Locator.selected.length),
|
||||
condition: () => (Modes.edit || Modes.animate || Modes.pose) && getRotationObjects() && (Group.first_selected || Outliner.selected.length > Locator.selected.length),
|
||||
getInterval: getSpatialInterval,
|
||||
get: function() {
|
||||
if (Format.bone_rig && Group.first_selected) {
|
||||
@ -1500,7 +1496,7 @@ BARS.defineActions(function() {
|
||||
description: tl('action.slider_origin.desc', ['Z']),
|
||||
color: 'z',
|
||||
category: 'transform',
|
||||
condition: () => (Modes.edit || Modes.animate || Modes.pose) && getRotationObject() && (Group.first_selected || Outliner.selected.length > Locator.selected.length),
|
||||
condition: () => (Modes.edit || Modes.animate || Modes.pose) && getRotationObjects() && (Group.first_selected || Outliner.selected.length > Locator.selected.length),
|
||||
getInterval: getSpatialInterval,
|
||||
get: function() {
|
||||
if (Format.bone_rig && Group.first_selected) {
|
||||
@ -1615,7 +1611,7 @@ BARS.defineActions(function() {
|
||||
category: 'transform',
|
||||
click() {
|
||||
Undo.initEdit({elements: Outliner.selected, outliner: true});
|
||||
centerElements(0);
|
||||
centerElements(0, true);
|
||||
Undo.finishEdit('Center selection on X axis')
|
||||
}
|
||||
})
|
||||
@ -1626,7 +1622,7 @@ BARS.defineActions(function() {
|
||||
category: 'transform',
|
||||
click() {
|
||||
Undo.initEdit({elements: Outliner.selected, outliner: true});
|
||||
centerElements(1);
|
||||
centerElements(1, true);
|
||||
Undo.finishEdit('Center selection on Y axis')
|
||||
}
|
||||
})
|
||||
@ -1637,7 +1633,7 @@ BARS.defineActions(function() {
|
||||
category: 'transform',
|
||||
click() {
|
||||
Undo.initEdit({elements: Outliner.selected, outliner: true});
|
||||
centerElements(2);
|
||||
centerElements(2, true);
|
||||
Undo.finishEdit('Center selection on Z axis')
|
||||
}
|
||||
})
|
||||
@ -1646,7 +1642,8 @@ BARS.defineActions(function() {
|
||||
category: 'transform',
|
||||
click() {
|
||||
Undo.initEdit({elements: Outliner.selected, outliner: true});
|
||||
centerElementsAll();
|
||||
centerElements(0, false);
|
||||
centerElements(2, true);
|
||||
Undo.finishEdit('Center selection')
|
||||
}
|
||||
})
|
||||
@ -1852,7 +1849,7 @@ BARS.defineActions(function() {
|
||||
click() {
|
||||
Undo.initEdit({outliner: true, elements: Outliner.selected})
|
||||
for (let group of Group.all) {
|
||||
if (!Group.multi_selected) continue;
|
||||
if (!group.selected) continue;
|
||||
let position = new THREE.Vector3();
|
||||
let amount = 0;
|
||||
group.children.forEach((obj) => {
|
||||
|
@ -805,7 +805,7 @@
|
||||
scope.attach(element);
|
||||
}
|
||||
})
|
||||
} else if (Group.first_selected && getRotationObject() == Group.first_selected) {
|
||||
} else if (Group.first_selected && getRotationObjects()?.equals(Group.multi_selected)) {
|
||||
scope.attach(Group.first_selected)
|
||||
} else {
|
||||
this.update()
|
||||
@ -896,12 +896,12 @@
|
||||
if (!scope.dragging) Transformer.rotation_selection.set(0, 0, 0);
|
||||
if (Modes.edit || Modes.pose || Toolbox.selected.id == 'pivot_tool') {
|
||||
if (Transformer.visible) {
|
||||
var rotation_tool = Toolbox.selected.id === 'rotate_tool' || Toolbox.selected.id === 'pivot_tool'
|
||||
var rotation_object = getRotationObject()
|
||||
let rotation_tool = Toolbox.selected.id === 'rotate_tool' || Toolbox.selected.id === 'pivot_tool'
|
||||
let rotation_object = getRotationObjects()
|
||||
if (rotation_object instanceof Array || (!rotation_object && !rotation_tool)) {
|
||||
var arr = rotation_object instanceof Array ? rotation_object : selected;
|
||||
let arr = rotation_object instanceof Array ? rotation_object : Outliner.selected;
|
||||
rotation_object = undefined;
|
||||
for (var obj of arr) {
|
||||
for (let obj of arr) {
|
||||
if (obj.visibility !== false) {
|
||||
rotation_object = obj;
|
||||
break;
|
||||
@ -1023,7 +1023,7 @@
|
||||
}
|
||||
this.cancelMovement = function(event, keep_changes = false) {
|
||||
onPointerUp(event, keep_changes);
|
||||
Undo.cancelEdit();
|
||||
Undo.cancelEdit(true);
|
||||
}
|
||||
function displayDistance(number) {
|
||||
Blockbench.setCursorTooltip(trimFloatNumber(number));
|
||||
@ -1152,7 +1152,7 @@
|
||||
}
|
||||
})
|
||||
}
|
||||
_has_groups = Format.bone_rig && Group.first_selected && Group.first_selected.matchesSelection() && Toolbox.selected.transformerMode == 'translate';
|
||||
_has_groups = Format.bone_rig && Group.first_selected && Toolbox.selected.transformerMode == 'translate';
|
||||
var rotate_group = Format.bone_rig && Group.first_selected && (Toolbox.selected.transformerMode == 'rotate');
|
||||
|
||||
if (Toolbox.selected.id == 'move_tool') {
|
||||
|
@ -16,23 +16,43 @@ class Collection {
|
||||
}
|
||||
select(event) {
|
||||
this.selected = true;
|
||||
Outliner.selected.empty();
|
||||
if (!(event?.shiftKey || Pressing.overrides.shift) && !(event?.ctrlOrCmd || Pressing.overrides.ctrl)) {
|
||||
unselectAll();
|
||||
if ((!(event?.shiftKey || Pressing.overrides.shift) && !(event?.ctrlOrCmd || Pressing.overrides.ctrl)) || Modes.animate) {
|
||||
unselectAllElements();
|
||||
Collection.all.forEach(c => c.selected = false);
|
||||
}
|
||||
this.selected = true;
|
||||
for (let uuid of this.children) {
|
||||
let node = OutlinerNode.uuids[uuid];
|
||||
if (node instanceof Group) {
|
||||
node.multiSelect();
|
||||
let i = 0;
|
||||
if (Modes.animate && Animation.selected && !(event?.ctrlOrCmd || Pressing.overrides.ctrl)) {
|
||||
Timeline.animators.empty();
|
||||
}
|
||||
for (let node of this.getChildren()) {
|
||||
if (Modes.animate && Animation.selected) {
|
||||
if (node.constructor.animator) {
|
||||
let animator = Animation.selected.getBoneAnimator(node);
|
||||
if (animator) {
|
||||
animator.addToTimeline(true);
|
||||
}
|
||||
if (i == 0) {
|
||||
node.select();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Outliner.selected.push(node);
|
||||
if (node instanceof Group) {
|
||||
node.multiSelect();
|
||||
} else {
|
||||
Outliner.selected.safePush(node);
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
updateSelection();
|
||||
return this;
|
||||
}
|
||||
clickSelect(event) {
|
||||
Undo.initSelection({collections: true, timeline: Modes.animate});
|
||||
this.select(event);
|
||||
Undo.finishSelection('Select collection');
|
||||
}
|
||||
getChildren() {
|
||||
return this.children.map(uuid => OutlinerNode.uuids[uuid]).filter(node => node != undefined);
|
||||
}
|
||||
@ -104,7 +124,7 @@ class Collection {
|
||||
Undo.finishEdit('Toggle collection visibility');
|
||||
}
|
||||
showContextMenu(event) {
|
||||
if (!this.selected) this.select();
|
||||
if (!this.selected) this.clickSelect(event);
|
||||
this.menu.open(event, this);
|
||||
return this;
|
||||
}
|
||||
@ -119,7 +139,9 @@ class Collection {
|
||||
return copy;
|
||||
}
|
||||
getSaveCopy() {
|
||||
let copy = {};
|
||||
let copy = {
|
||||
uuid: this.uuid
|
||||
};
|
||||
for (var key in Collection.properties) {
|
||||
Collection.properties[key].copy(this, copy);
|
||||
}
|
||||
@ -340,7 +362,7 @@ Object.defineProperty(Collection, 'all', {
|
||||
})
|
||||
Object.defineProperty(Collection, 'selected', {
|
||||
get() {
|
||||
return Project.collections.filter(c => c.selected);
|
||||
return Project ? Project.collections.filter(c => c.selected) : [];
|
||||
}
|
||||
})
|
||||
|
||||
@ -400,7 +422,7 @@ BARS.defineActions(() => {
|
||||
icon: 'inventory_2',
|
||||
category: 'select',
|
||||
keybind: new Keybind({key: 'l', ctrl: true}),
|
||||
condition: {modes: ['edit', 'paint']},
|
||||
condition: {modes: ['edit', 'paint', 'animate']},
|
||||
click() {
|
||||
Undo.initEdit({collections: []});
|
||||
let collection = new Collection({});
|
||||
@ -473,7 +495,7 @@ Interface.definePanels(function() {
|
||||
float_size: [300, 300],
|
||||
height: 300
|
||||
},
|
||||
condition: {modes: ['edit', 'paint']},
|
||||
condition: {modes: ['edit', 'paint', 'animate'], method: () => (!Format.image_editor)},
|
||||
toolbars: [
|
||||
new Toolbar('collections', {
|
||||
children: [
|
||||
@ -637,7 +659,7 @@ Interface.definePanels(function() {
|
||||
:key="collection.uuid"
|
||||
:uuid="collection.uuid"
|
||||
class="collection"
|
||||
@click.stop="collection.select()"
|
||||
@click.stop="collection.clickSelect($event)"
|
||||
@dblclick.stop="collection.propertiesDialog()"
|
||||
@contextmenu.prevent.stop="collection.showContextMenu($event)"
|
||||
>
|
||||
|
@ -69,12 +69,12 @@ class Group extends OutlinerNode {
|
||||
if (!event) event = true
|
||||
var allSelected = Group.multi_selected.length == 1 && Group.first_selected === this && selected.length && this.matchesSelection();
|
||||
let previous_first_selected = Project.selected_elements[0];
|
||||
let multi_select = event.ctrlOrCmd || Pressing.overrides.ctrl;
|
||||
let shift_select = event.shiftKey || Pressing.overrides.shift;
|
||||
let multi_select = (event.ctrlOrCmd || Pressing.overrides.ctrl) && !Modes.animate;
|
||||
let shift_select = (event.shiftKey || Pressing.overrides.shift) && !Modes.animate;
|
||||
|
||||
//Unselect others
|
||||
if (!multi_select && !shift_select) {
|
||||
unselectAll();
|
||||
unselectAllElements();
|
||||
Project.groups.forEach(function(s) {
|
||||
s.selected = false;
|
||||
})
|
||||
@ -114,7 +114,7 @@ class Group extends OutlinerNode {
|
||||
} else {
|
||||
// Fix for #2401
|
||||
if (previous_first_selected && previous_first_selected.isChildOf(this)) {
|
||||
selected.push(previous_first_selected);
|
||||
selected.safePush(previous_first_selected);
|
||||
}
|
||||
this.children.forEach(function(s) {
|
||||
s.selectLow()
|
||||
@ -126,6 +126,12 @@ class Group extends OutlinerNode {
|
||||
updateSelection()
|
||||
return this;
|
||||
}
|
||||
clickSelect(event, is_outliner_click) {
|
||||
if (Blockbench.hasFlag('renaming') || this.locked) return this;
|
||||
Undo.initSelection();
|
||||
this.select(event, is_outliner_click);
|
||||
Undo.finishSelection('Select group');
|
||||
}
|
||||
multiSelect() {
|
||||
if (this.locked) return this;
|
||||
this.selected = true;
|
||||
@ -393,6 +399,7 @@ class Group extends OutlinerNode {
|
||||
obj.locked = this.locked;
|
||||
obj.visibility = this.visibility;
|
||||
obj.autouv = this.autouv;
|
||||
obj.selected = Group.multi_selected.includes(this);
|
||||
}
|
||||
|
||||
if (this.rotation.allEqual(0)) {
|
||||
@ -433,7 +440,7 @@ class Group extends OutlinerNode {
|
||||
Group.prototype.icon = 'folder';
|
||||
Group.prototype.isParent = true;
|
||||
Group.prototype.rotatable = true;
|
||||
Group.prototype.name_regex = () => Format.bone_rig ? 'a-zA-Z0-9_' : false;
|
||||
Group.prototype.name_regex = () => Format.bone_rig ? (Format.node_name_regex ?? 'a-zA-Z0-9_') : false;
|
||||
Group.prototype.buttons = [
|
||||
Outliner.buttons.autouv,
|
||||
Outliner.buttons.mirror_uv,
|
||||
@ -447,7 +454,7 @@ class Group extends OutlinerNode {
|
||||
let elements = Outliner.selected.filter(el => el.setColor)
|
||||
Undo.initEdit({outliner: true, elements: elements, selection: true})
|
||||
Group.all.forEach(group => {
|
||||
if (Group.multi_selected) {
|
||||
if (group.selected) {
|
||||
group.color = color;
|
||||
}
|
||||
})
|
||||
@ -471,7 +478,7 @@ class Group extends OutlinerNode {
|
||||
}})
|
||||
}},
|
||||
"randomize_marker_colors",
|
||||
{name: 'menu.cube.texture', icon: 'collections', condition: () => Format.per_group_texture, children(a, b, c) {
|
||||
{name: 'menu.cube.texture', icon: 'collections', condition: () => Format.per_group_texture, children(context) {
|
||||
function applyTexture(texture_value, undo_message) {
|
||||
let affected_groups = Group.all.filter(g => g.selected);
|
||||
Undo.initEdit({outliner: true});
|
||||
@ -490,7 +497,7 @@ class Group extends OutlinerNode {
|
||||
arr.push({
|
||||
name: t.name,
|
||||
icon: (t.mode === 'link' ? t.img : t.source),
|
||||
marked: t.uuid == /*Group.multi_selected*/context.texture,
|
||||
marked: t.uuid == context.texture,
|
||||
click(group) {
|
||||
applyTexture(t.uuid, 'Apply texture to group');
|
||||
}
|
||||
@ -516,7 +523,7 @@ class Group extends OutlinerNode {
|
||||
})
|
||||
Object.defineProperty(Group, 'multi_selected', {
|
||||
get() {
|
||||
return Project.selected_groups
|
||||
return Project.selected_groups || []
|
||||
},
|
||||
set(arr) {
|
||||
if (arr instanceof Array == false) {
|
||||
@ -528,16 +535,20 @@ class Group extends OutlinerNode {
|
||||
Object.defineProperty(Group, 'selected', {
|
||||
get() {
|
||||
console.warn('"Group.selected" will be an array in the future!');
|
||||
return Project.selected_groups[0]
|
||||
return Project.selected_groups?.[0]
|
||||
},
|
||||
set(group) {
|
||||
console.warn('"Group.selected" will be an array in the future!');
|
||||
Project.selected_groups.replace([groups]);
|
||||
if (group instanceof Group) {
|
||||
Project.selected_groups.replace([group]);
|
||||
} else {
|
||||
Project.selected_groups.empty();
|
||||
}
|
||||
}
|
||||
})
|
||||
Object.defineProperty(Group, 'first_selected', {
|
||||
get() {
|
||||
return Project.selected_groups[0]
|
||||
return Project.selected_groups?.[0]
|
||||
},
|
||||
set(group) {
|
||||
Project.selected_groups.replace([groups]);
|
||||
@ -552,7 +563,7 @@ new Property(Group, 'string', 'bedrock_binding', {condition: {formats: ['bedrock
|
||||
new Property(Group, 'array', 'cem_animations', {condition: {formats: ['optifine_entity']}});
|
||||
new Property(Group, 'boolean', 'cem_attach', {condition: {formats: ['optifine_entity']}});
|
||||
new Property(Group, 'number', 'cem_scale', {condition: {formats: ['optifine_entity']}});
|
||||
new Property(Group, 'string', 'texture', {condition: {formats: ['optifine_entity']}});
|
||||
new Property(Group, 'string', 'texture', {condition: {features: ['per_group_texture']}});
|
||||
//new Property(Group, 'vector2', 'texture_size', {condition: {formats: ['optifine_entity']}});
|
||||
new Property(Group, 'vector', 'skin_original_origin', {condition: {formats: ['skin']}});
|
||||
new Property(Group, 'number', 'color');
|
||||
@ -669,7 +680,9 @@ BARS.defineActions(function() {
|
||||
base_group.createUniqueName()
|
||||
}
|
||||
if (add_group instanceof Group) {
|
||||
add_group.addTo(base_group);
|
||||
for (let group of Group.multi_selected) {
|
||||
group.addTo(base_group);
|
||||
}
|
||||
} else if (add_group instanceof OutlinerElement) {
|
||||
Outliner.selected.forEach(function(s, i) {
|
||||
s.addTo(base_group);
|
||||
@ -726,7 +739,7 @@ BARS.defineActions(function() {
|
||||
showPresetMenu(event) {
|
||||
new Menu([
|
||||
{
|
||||
name: 'Main Hand',
|
||||
name: 'Item Slot',
|
||||
icon: 'build',
|
||||
click: () => {
|
||||
this.binding = 'q.item_slot_to_bone_name(c.item_slot)';
|
||||
@ -796,11 +809,19 @@ BARS.defineActions(function() {
|
||||
icon: 'fa-leaf',
|
||||
condition: {modes: ['edit'], method: () => Group.first_selected},
|
||||
click() {
|
||||
let all_elements = [];
|
||||
for (let group of Group.multi_selected) {
|
||||
group.forEachChild(obj => {
|
||||
if (obj instanceof Group == false) {
|
||||
all_elements.safePush(obj);
|
||||
}
|
||||
})
|
||||
}
|
||||
Undo.initEdit({outliner: true, elements: all_elements})
|
||||
for (let group of Group.multi_selected) {
|
||||
group.resolve(false);
|
||||
}
|
||||
Undo.finishEdit('Resolve group')
|
||||
Undo.finishEdit('Resolve group');
|
||||
}
|
||||
})
|
||||
})
|
||||
|
@ -78,7 +78,7 @@ class Locator extends OutlinerElement {
|
||||
Locator.prototype.title = tl('data.locator');
|
||||
Locator.prototype.type = 'locator';
|
||||
Locator.prototype.icon = 'fa-anchor';
|
||||
Locator.prototype.name_regex = 'a-z0-9_'
|
||||
Locator.prototype.name_regex = () => Format.node_name_regex ?? 'a-zA-Z0-9_',
|
||||
Locator.prototype.movable = true;
|
||||
Locator.prototype.rotatable = true;
|
||||
Locator.prototype.visibility = true;
|
||||
|
@ -31,19 +31,16 @@ class MeshFace extends Face {
|
||||
}
|
||||
return this;
|
||||
}
|
||||
getNormal(normalize) {
|
||||
getNormal(normalize, alt_tri) {
|
||||
let vertices = this.getSortedVertices();
|
||||
if (vertices.length < 3) return [0, 0, 0];
|
||||
let a = [
|
||||
this.mesh.vertices[vertices[1]][0] - this.mesh.vertices[vertices[0]][0],
|
||||
this.mesh.vertices[vertices[1]][1] - this.mesh.vertices[vertices[0]][1],
|
||||
this.mesh.vertices[vertices[1]][2] - this.mesh.vertices[vertices[0]][2],
|
||||
]
|
||||
let b = [
|
||||
this.mesh.vertices[vertices[2]][0] - this.mesh.vertices[vertices[0]][0],
|
||||
this.mesh.vertices[vertices[2]][1] - this.mesh.vertices[vertices[0]][1],
|
||||
this.mesh.vertices[vertices[2]][2] - this.mesh.vertices[vertices[0]][2],
|
||||
]
|
||||
let indices = [0, 1, 2];
|
||||
if (vertices.length == 4 && alt_tri) {
|
||||
indices = [0, 2, 3];
|
||||
}
|
||||
let base = this.mesh.vertices[vertices[indices[0]]];
|
||||
let a = this.mesh.vertices[vertices[indices[1]]].slice().V3_subtract(base);
|
||||
let b = this.mesh.vertices[vertices[indices[2]]].slice().V3_subtract(base);
|
||||
let direction = [
|
||||
a[1] * b[2] - a[2] * b[1],
|
||||
a[2] * b[0] - a[0] * b[2],
|
||||
@ -1139,6 +1136,10 @@ new NodePreviewController(Mesh, {
|
||||
|
||||
Mesh.preview_controller.updatePixelGrid(element);
|
||||
|
||||
if (Project.view_mode == 'wireframe' && this.fixWireframe) {
|
||||
this.fixWireframe(element);
|
||||
}
|
||||
|
||||
this.dispatchEvent('update_geometry', {element});
|
||||
},
|
||||
updateFaces(element) {
|
||||
@ -1450,5 +1451,20 @@ new NodePreviewController(Mesh, {
|
||||
mesh.add(box);
|
||||
|
||||
this.dispatchEvent('update_painting_grid', {element});
|
||||
},
|
||||
fixWireframe(element) {
|
||||
let geometry_orig = element.mesh.geometry;
|
||||
if (!geometry_orig) return;
|
||||
let geometry_clone = element.mesh.geometry.clone();
|
||||
element.mesh.geometry = geometry_clone;
|
||||
geometry_orig.dispose();
|
||||
}
|
||||
})
|
||||
|
||||
Blockbench.dispatchEvent('change_view_mode', ({view_mode}) => {
|
||||
if (view_mode == 'wireframe') {
|
||||
for (let mesh of Mesh.selected) {
|
||||
Mesh.preview_controller.fixWireframe(mesh);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -16,15 +16,15 @@ const Outliner = {
|
||||
visibility: {
|
||||
id: 'visibility',
|
||||
title: tl('switches.visibility'),
|
||||
icon: ' fa fa-eye',
|
||||
icon_off: ' fa fa-eye-slash',
|
||||
icon: 'visibility',
|
||||
icon_off: 'visibility_off',
|
||||
advanced_option: false
|
||||
},
|
||||
locked: {
|
||||
id: 'locked',
|
||||
title: tl('switches.lock'),
|
||||
icon: ' fas fa-lock',
|
||||
icon_off: ' fas fa-lock-open',
|
||||
icon: 'fa-lock',
|
||||
icon_off: 'fa-lock-open',
|
||||
advanced_option: true,
|
||||
visibilityException(node) {
|
||||
return node.locked
|
||||
@ -33,8 +33,8 @@ const Outliner = {
|
||||
export: {
|
||||
id: 'export',
|
||||
title: tl('switches.export'),
|
||||
icon: ' far fa-square-check',
|
||||
icon_off: ' far fa-window-close',
|
||||
icon: 'far.fa-square-check',
|
||||
icon_off: 'far.fa-window-close',
|
||||
advanced_option: true,
|
||||
condition: {modes: ['edit']},
|
||||
visibilityException(node) {
|
||||
@ -45,24 +45,24 @@ const Outliner = {
|
||||
id: 'shade',
|
||||
condition: {modes: ['edit'], features: ['java_cube_shading_properties']},
|
||||
title: tl('switches.shade'),
|
||||
icon: 'fa fa-star',
|
||||
icon_off: 'far fa-star',
|
||||
icon: 'fa-star',
|
||||
icon_off: 'far.fa-star',
|
||||
advanced_option: true,
|
||||
},
|
||||
mirror_uv: {
|
||||
id: 'mirror_uv',
|
||||
condition: {modes: ['edit'], method: (element) => (element instanceof Group) ? element.children.find(c => c.box_uv) : element.box_uv},
|
||||
title: tl('switches.mirror'),
|
||||
icon: 'icon-mirror_x icon',
|
||||
icon_off: 'icon-mirror_x icon',
|
||||
icon: 'icon-mirror_x',
|
||||
icon_off: 'icon-mirror_x',
|
||||
advanced_option: true,
|
||||
},
|
||||
autouv: {
|
||||
id: 'autouv',
|
||||
title: tl('switches.autouv'),
|
||||
icon: ' fa fa-thumbtack',
|
||||
icon_off: ' far fa-times-circle',
|
||||
icon_alt: ' fa fa-magic',
|
||||
icon: 'fa-thumbtack',
|
||||
icon_off: 'far.fa-times-circle',
|
||||
icon_alt: 'fa-magic',
|
||||
advanced_option: true,
|
||||
condition: {modes: ['edit']},
|
||||
getState(element) {
|
||||
@ -379,7 +379,7 @@ class OutlinerElement extends OutlinerNode {
|
||||
showContextMenu(event) {
|
||||
if (this.locked) return this;
|
||||
if (!this.selected) {
|
||||
this.select()
|
||||
this.clickSelect(event)
|
||||
}
|
||||
this.menu.open(event, this)
|
||||
return this;
|
||||
@ -441,6 +441,7 @@ class OutlinerElement extends OutlinerNode {
|
||||
Blockbench.showQuickMessage('message.group_required_to_animate');
|
||||
return false;
|
||||
}
|
||||
Undo.initSelection();
|
||||
//Shift
|
||||
var just_selected = [];
|
||||
let allow_multi_select = (!Modes.paint || (Toolbox.selected.id == 'fill_tool' && BarItems.fill_mode.value == 'selected_elements'));
|
||||
@ -487,23 +488,26 @@ class OutlinerElement extends OutlinerNode {
|
||||
|
||||
//Normal
|
||||
} else {
|
||||
unselectAll()
|
||||
unselectAllElements([this]);
|
||||
this.selectLow()
|
||||
just_selected.push(this)
|
||||
if (settings.outliner_reveal_on_select.value) {
|
||||
this.showInOutliner()
|
||||
}
|
||||
}
|
||||
for (let group of Group.multi_selected) {
|
||||
group.unselect();
|
||||
}
|
||||
Group.all.forEach(function(s) {
|
||||
s.selected = false;
|
||||
})
|
||||
Blockbench.dispatchEvent('added_to_selection', {added: just_selected})
|
||||
TickUpdates.selection = true;
|
||||
return this;
|
||||
}
|
||||
clickSelect(event, outliner_click) {
|
||||
Undo.initSelection();
|
||||
let result = this.select(event, outliner_click);
|
||||
if (result === false) {
|
||||
Undo.cancelSelection();
|
||||
return;
|
||||
}
|
||||
Undo.finishSelection('Select element');
|
||||
}
|
||||
selectLow() {
|
||||
Project.selected_elements.safePush(this);
|
||||
this.selected = true;
|
||||
@ -796,7 +800,8 @@ function parseGroups(array, import_reference, startIndex) {
|
||||
OutlinerNode.uuids[array[i].uuid].removeFromParent();
|
||||
delete OutlinerNode.uuids[array[i].uuid];
|
||||
}
|
||||
var obj = new Group(array[i], array[i].uuid)
|
||||
// todo: Update old groups instead of rebuilding all
|
||||
let obj = new Group(array[i], array[i].uuid)
|
||||
obj.parent = addGroup
|
||||
obj.isOpen = !!array[i].isOpen
|
||||
if (array[i].uuid) {
|
||||
@ -810,6 +815,9 @@ function parseGroups(array, import_reference, startIndex) {
|
||||
if (array[i].content && array[i].content.length > 0) {
|
||||
iterate(array[i].content, obj.children, obj)
|
||||
}
|
||||
if (array[i].selected) {
|
||||
obj.multiSelect();
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
@ -840,20 +848,20 @@ function moveOutlinerSelectionTo(item, target, event, order) {
|
||||
iterate(target)
|
||||
if (is_parent) return;
|
||||
}
|
||||
if (item instanceof OutlinerElement && Outliner.selected.includes( item )) {
|
||||
if (item instanceof OutlinerNode && item.selected) {
|
||||
var items = [];
|
||||
// ensure elements are in displayed order
|
||||
Outliner.root.forEach(node => {
|
||||
if (node instanceof Group) {
|
||||
node.forEachChild(child => {
|
||||
if (child.selected && child instanceof Group == false) items.push(child);
|
||||
})
|
||||
if (child.selected && !child.parent.selected && (target instanceof OutlinerNode == false || !target.isChildOf?.(child))) {
|
||||
items.push(child);
|
||||
}
|
||||
}, null, true);
|
||||
} else if (node.selected) {
|
||||
items.push(node);
|
||||
}
|
||||
})
|
||||
} else if (item instanceof Group) {
|
||||
var items = Group.multi_selected.filter(g => !g.parent.selected);
|
||||
} else {
|
||||
var items = [item];
|
||||
}
|
||||
@ -878,6 +886,9 @@ function moveOutlinerSelectionTo(item, target, event, order) {
|
||||
}
|
||||
} else {
|
||||
item.preview_controller.updateTransform(item);
|
||||
if (Format.per_group_texture && item.preview_controller.updateFaces) {
|
||||
item.preview_controller.updateFaces(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1031,7 +1042,7 @@ SharedActions.add('delete', {
|
||||
priority: -1,
|
||||
run() {
|
||||
let array;
|
||||
Undo.initEdit({elements: selected, outliner: true, selection: true})
|
||||
Undo.initEdit({elements: Outliner.selected, outliner: true, selection: true})
|
||||
if (array == undefined) {
|
||||
array = selected.slice(0);
|
||||
} else if (array.constructor !== Array) {
|
||||
@ -1063,12 +1074,16 @@ SharedActions.add('duplicate', {
|
||||
}
|
||||
|
||||
let all_new = [];
|
||||
for (let group of Group.multi_selected) {
|
||||
let old_selected_groups = Group.multi_selected.slice();
|
||||
Group.multi_selected.empty();
|
||||
for (let group of old_selected_groups) {
|
||||
group.selected = false;
|
||||
let new_group = group.duplicate();
|
||||
new_group.forEachChild(g => all_new.push(g), Group, true);
|
||||
new_group.multiSelect();
|
||||
}
|
||||
new_group.multiSelect();
|
||||
|
||||
updateSelection();
|
||||
Undo.finishEdit('Duplicate group', {outliner: true, elements: elements.slice().slice(cubes_before), selection: true});
|
||||
|
||||
if (Animation.all.length) {
|
||||
@ -1120,18 +1135,22 @@ SharedActions.add('select_all', {
|
||||
condition: () => Modes.edit || Modes.paint,
|
||||
priority: -2,
|
||||
run() {
|
||||
Undo.initSelection();
|
||||
let selectable_elements = Outliner.elements.filter(element => !element.locked);
|
||||
if (Outliner.selected.length < selectable_elements.length) {
|
||||
if (Outliner.root.length == 1 && !Outliner.root[0].locked) {
|
||||
Outliner.root[0].select();
|
||||
} else {
|
||||
selectable_elements.forEach(obj => {
|
||||
obj.selectLow()
|
||||
})
|
||||
TickUpdates.selection = true;
|
||||
for (let node of Outliner.root) {
|
||||
if (node instanceof Group) {
|
||||
node.multiSelect();
|
||||
}
|
||||
}
|
||||
selectable_elements.forEach(obj => {
|
||||
obj.selectLow()
|
||||
})
|
||||
TickUpdates.selection = true;
|
||||
Undo.finishSelection('Select all elements');
|
||||
} else {
|
||||
unselectAllElements()
|
||||
Undo.finishSelection('Unselect all elements');
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -1140,7 +1159,9 @@ SharedActions.add('unselect_all', {
|
||||
condition: () => Modes.edit || Modes.paint,
|
||||
priority: -2,
|
||||
run() {
|
||||
unselectAllElements()
|
||||
Undo.initSelection();
|
||||
unselectAllElements();
|
||||
Undo.finishSelection('Unselect all elements');
|
||||
}
|
||||
})
|
||||
SharedActions.add('invert_selection', {
|
||||
@ -1227,7 +1248,7 @@ BARS.defineActions(function() {
|
||||
if (Animator.open) {
|
||||
var sel = 0;
|
||||
for (let group of Group.all) {
|
||||
if (Group.multi_selected) sel++;
|
||||
if (group.selected) sel++;
|
||||
}
|
||||
this.set(stringifyLargeInt(sel)+' / '+stringifyLargeInt(Group.all.length));
|
||||
} else {
|
||||
@ -1436,7 +1457,7 @@ Interface.definePanels(function() {
|
||||
class="outliner_object"
|
||||
v-bind:class="{ cube: node.type === 'cube', group: node.type === 'group', selected: node.selected }"
|
||||
@contextmenu.prevent.stop="node.showContextMenu($event)"
|
||||
@click="node.select($event, true)"
|
||||
@click="node.clickSelect($event, true)"
|
||||
:title="node.title"
|
||||
@dblclick.stop.self="!node.locked && renameOutliner()"
|
||||
>` +
|
||||
@ -1453,14 +1474,15 @@ Interface.definePanels(function() {
|
||||
<input type="text" class="cube_name tab_target" :class="{locked: node.locked}" v-model="node.name" disabled>` +
|
||||
|
||||
|
||||
`<i v-for="btn in node.buttons"
|
||||
`<dynamic-icon v-for="btn in node.buttons"
|
||||
v-if="Condition(btn, node) && (!btn.advanced_option || options.show_advanced_toggles || (btn.visibilityException && btn.visibilityException(node)) )"
|
||||
class="outliner_toggle"
|
||||
:class="getBtnClasses(btn, node)"
|
||||
:icon="getButtonIcon(btn, node)"
|
||||
:class="getButtonClasses(btn, node)"
|
||||
:title="getBtnTooltip(btn, node)"
|
||||
:toggle="btn.id"
|
||||
@click.stop
|
||||
></i>` +
|
||||
/>` +
|
||||
'</div>' +
|
||||
//Other Entries
|
||||
'<ul v-if="node.isOpen">' +
|
||||
@ -1504,14 +1526,26 @@ Interface.definePanels(function() {
|
||||
return node.closedIcon || node.icon;
|
||||
}
|
||||
},
|
||||
getBtnClasses: function (btn, node) {
|
||||
getButtonIcon: function (btn, node) {
|
||||
let value = node.isIconEnabled(btn);
|
||||
let icon_string = '';
|
||||
if (value === true) {
|
||||
icon_string = typeof btn.icon == 'function' ? btn.icon(node) : btn.icon;
|
||||
} else if (value === false) {
|
||||
icon_string = typeof btn.icon_off == 'function' ? btn.icon_off(node) : btn.icon_off
|
||||
} else {
|
||||
icon_string = typeof btn.icon_alt == 'function' ? btn.icon_alt(node) : btn.icon_alt
|
||||
}
|
||||
return icon_string.trim().replace(/fa[rs]* /, '');
|
||||
},
|
||||
getButtonClasses: function (btn, node) {
|
||||
let value = node.isIconEnabled(btn);
|
||||
if (value === true) {
|
||||
return [(typeof btn.icon == 'function' ? btn.icon(node) : btn.icon)];
|
||||
return ''
|
||||
} else if (value === false) {
|
||||
return [(typeof btn.icon_off == 'function' ? btn.icon_off(node) : btn.icon_off), 'icon_off'];
|
||||
return 'icon_off';
|
||||
} else {
|
||||
return [(typeof btn.icon_alt == 'function' ? btn.icon_alt(node) : btn.icon_alt), 'icon_alt'];
|
||||
return 'icon_alt';
|
||||
}
|
||||
},
|
||||
getBtnTooltip: function (btn, node) {
|
||||
@ -1709,7 +1743,11 @@ Interface.definePanels(function() {
|
||||
function off(e2) {
|
||||
removeEventListeners(document, 'mouseup touchend', off);
|
||||
if (e1.target && e1.offsetX > e1.target.clientWidth) return;
|
||||
if (e2.target && e2.target.id == 'cubes_list') unselectAllElements();
|
||||
if (e2.target && e2.target.id == 'cubes_list') {
|
||||
Undo.initSelection({});
|
||||
unselectAllElements();
|
||||
Undo.finishSelection('Unselect outliner');
|
||||
}
|
||||
}
|
||||
addEventListeners(document, 'mouseup touchend', off);
|
||||
return;
|
||||
|
@ -405,7 +405,7 @@ class Plugin {
|
||||
Plugins.sort()
|
||||
// Save
|
||||
if (isApp) {
|
||||
await new Promise((resolve) => {
|
||||
await new Promise((resolve, reject) => {
|
||||
let file = originalFs.createWriteStream(Plugins.path+this.id+'.js')
|
||||
https.get(url, (response) => {
|
||||
response.pipe(file);
|
||||
|
@ -1,4 +1,6 @@
|
||||
/**
|
||||
* Original source: https://github.com/mrdoob/three.js, MIT
|
||||
* Modified for Blockbench
|
||||
* @author qiao / https://github.com/qiao
|
||||
* @author mrdoob / http://mrdoob.com
|
||||
* @author alteredq / http://alteredqualia.com/
|
||||
@ -298,6 +300,10 @@ THREE.OrbitControls = function ( object, preview ) {
|
||||
|
||||
}();
|
||||
|
||||
this.panLeft = panLeft;
|
||||
this.panUp = panUp;
|
||||
|
||||
|
||||
// deltaX and deltaY are in pixels; right and down are positive
|
||||
var pan = function () {
|
||||
|
||||
|
@ -118,11 +118,14 @@ const Canvas = {
|
||||
gizmos: [rot_origin],
|
||||
outlineMaterial: new THREE.LineBasicMaterial({
|
||||
linewidth: 2,
|
||||
depthTest: settings.seethrough_outline.value == false,
|
||||
transparent: true,
|
||||
color: gizmo_colors.outline
|
||||
}),
|
||||
meshOutlineMaterial: new THREE.LineBasicMaterial({
|
||||
linewidth: 2,
|
||||
depthTest: settings.seethrough_outline.value == false,
|
||||
transparent: true,
|
||||
//color: gizmo_colors.outline,
|
||||
vertexColors: true
|
||||
}),
|
||||
@ -1391,6 +1394,20 @@ const Canvas = {
|
||||
if (height === Infinity) height = 0;
|
||||
|
||||
return [width, height]
|
||||
},
|
||||
getSelectionBounds() {
|
||||
let pivot_marker_parent = Canvas.pivot_marker.parent;
|
||||
let visible_box = new THREE.Box3();
|
||||
if (pivot_marker_parent) pivot_marker_parent.remove(Canvas.pivot_marker);
|
||||
Canvas.withoutGizmos(() => {
|
||||
Outliner.selected.forEach(element => {
|
||||
if (element.visibility && element.mesh && element.mesh.geometry) {
|
||||
visible_box.expandByObject(element.mesh);
|
||||
}
|
||||
})
|
||||
})
|
||||
if (pivot_marker_parent) pivot_marker_parent.add(Canvas.pivot_marker);
|
||||
return visible_box;
|
||||
}
|
||||
}
|
||||
var buildGrid = Canvas.buildGrid;
|
||||
|
@ -412,6 +412,11 @@ class Preview {
|
||||
} else {
|
||||
intersects.sort((a, b) => a.distance - b.distance);
|
||||
}
|
||||
if (settings.seethrough_outline.value && BarItems.selection_mode.value == 'edge') {
|
||||
let all_intersects = intersects;
|
||||
intersects = intersects.filter(a => a.object.isLine);
|
||||
if (intersects.length == 0) intersects = all_intersects;
|
||||
}
|
||||
|
||||
let intersect = intersects[0];
|
||||
let intersect_object = intersect.object;
|
||||
@ -800,6 +805,7 @@ class Preview {
|
||||
}
|
||||
|
||||
if (Toolbox.selected.selectElements && Modes.selected.selectElements && (data.type === 'element' || Toolbox.selected.id == 'knife_tool')) {
|
||||
Undo.initSelection();
|
||||
if (Toolbox.selected.selectFace && data.face && data.element.type != 'mesh') {
|
||||
let face_selection = UVEditor.getSelectedFaces(data.element, true);
|
||||
if (data.element.selected && (multi_select || group_select)) {
|
||||
@ -952,14 +958,19 @@ class Preview {
|
||||
} else {
|
||||
data.element.select(event);
|
||||
}
|
||||
Undo.finishSelection('Select from viewport');
|
||||
|
||||
} else if (Animator.open && data.type == 'keyframe') {
|
||||
if (data.keyframe instanceof Keyframe) {
|
||||
Undo.initSelection({timeline: true});
|
||||
data.keyframe.select(event).callPlayhead();
|
||||
updateSelection();
|
||||
Undo.finishSelection('Select keyframe');
|
||||
}
|
||||
|
||||
} else if (data.type == 'vertex' && Toolbox.selected.id !== 'vertex_snap_tool') {
|
||||
|
||||
Undo.initSelection();
|
||||
let list = data.element.getSelectedVertices(true);
|
||||
let edges = data.element.getSelectedEdges(true);
|
||||
let faces = data.element.getSelectedEdges(true);
|
||||
@ -973,8 +984,11 @@ class Preview {
|
||||
faces.empty();
|
||||
}
|
||||
updateSelection();
|
||||
Undo.finishSelection('Select vertex');
|
||||
|
||||
} else if (data.type == 'line') {
|
||||
|
||||
Undo.initSelection();
|
||||
let vertices = data.element.getSelectedVertices(true);
|
||||
let edges = data.element.getSelectedEdges(true);
|
||||
let faces = data.element.getSelectedFaces(true);
|
||||
@ -1050,6 +1064,7 @@ class Preview {
|
||||
splitFace(start_face, data.vertices);
|
||||
}
|
||||
updateSelection();
|
||||
Undo.finishSelection('Select edge');
|
||||
}
|
||||
if (typeof Toolbox.selected.onCanvasClick === 'function') {
|
||||
Toolbox.selected.onCanvasClick(data)
|
||||
@ -1122,7 +1137,12 @@ class Preview {
|
||||
brush_coord.x += 8;
|
||||
brush_coord.z += 8;
|
||||
}
|
||||
brush_matrix.multiplyMatrices(intersect.object.parent.matrixWorld, brush_matrix);
|
||||
|
||||
// Size
|
||||
let scale = new THREE.Vector3(BarItems.slider_brush_size.get(), BarItems.slider_brush_size.get(), 1);
|
||||
brush_matrix.scale(scale);
|
||||
|
||||
brush_matrix.multiplyMatrices(intersect.object.matrixWorld, brush_matrix);
|
||||
|
||||
// Z-fighting
|
||||
let z_fight_offset = Preview.selected.calculateControlScale(brush_coord) / 8;
|
||||
@ -1135,11 +1155,9 @@ class Preview {
|
||||
let matrix_offset = new THREE.Matrix4().makeTranslation(z_offset.x, z_offset.y, z_offset.z);
|
||||
brush_matrix.multiplyMatrices(matrix_offset, brush_matrix);
|
||||
|
||||
// Size
|
||||
let scale = new THREE.Vector3(BarItems.slider_brush_size.get(), BarItems.slider_brush_size.get(), 1);
|
||||
brush_matrix.scale(scale);
|
||||
|
||||
brush_matrix.multiplyMatrices(intersect.object.matrix, brush_matrix);
|
||||
// Since we're setting the brush matrix, we need to multiply in its parents matrix as well in case there are any.
|
||||
if (Canvas.brush_outline.parent)
|
||||
brush_matrix.multiplyMatrices(Canvas.brush_outline.parent.matrixWorld.clone().invert(), brush_matrix);
|
||||
Canvas.brush_outline.matrix = brush_matrix;
|
||||
}
|
||||
|
||||
@ -1276,7 +1294,8 @@ class Preview {
|
||||
this.selection.old_selected = Outliner.selected.slice();
|
||||
this.selection.old_mesh_selection = JSON.parse(JSON.stringify(Project.mesh_selection));
|
||||
|
||||
this.moveSelRect(event)
|
||||
Undo.initSelection();
|
||||
this.moveSelRect(event);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1480,6 +1499,7 @@ class Preview {
|
||||
delete this.sr_stop_f;
|
||||
this.selection.box.detach()
|
||||
this.selection.activated = false;
|
||||
Undo.finishSelection('Area select');
|
||||
}
|
||||
// Background
|
||||
loadBackground() {
|
||||
@ -1728,6 +1748,7 @@ Preview.split_screen = {
|
||||
Blockbench.on('update_camera_position', e => {
|
||||
let scale = Preview.selected.calculateControlScale(Transformer.position) || 0.8;
|
||||
if (Blockbench.isTouch) scale *= 1.5;
|
||||
scale *= (settings.selection_tolerance.value / 10);
|
||||
Preview.all.forEach(preview => {
|
||||
if (preview.canvas.isConnected) {
|
||||
preview.raycaster.params.Points.threshold = scale * 0.8;
|
||||
@ -1919,13 +1940,19 @@ class OrbitGizmo {
|
||||
|
||||
|
||||
window.addEventListener("gamepadconnected", function(event) {
|
||||
if (event.gamepad.id.includes('SpaceMouse') || event.gamepad.id.includes('SpaceNavigator') || event.gamepad.id.includes('3Dconnexion')) {
|
||||
let is_space_mouse = event.gamepad.id.includes('SpaceMouse') || event.gamepad.id.includes('SpaceNavigator') || event.gamepad.id.includes('3Dconnexion');
|
||||
|
||||
let interval = setInterval(() => {
|
||||
let gamepad = navigator.getGamepads()[event.gamepad.index];
|
||||
let preview = Preview.selected;
|
||||
if (!document.hasFocus() || !preview || !gamepad || !gamepad.axes || gamepad.axes.allEqual(0) || gamepad.axes.find(v => isNaN(v)) != undefined) return;
|
||||
console.log('Gamepad Connected', event);
|
||||
|
||||
let zoom_timer = 0;
|
||||
|
||||
let interval = setInterval(() => {
|
||||
let gamepad = navigator.getGamepads()[event.gamepad.index];
|
||||
let preview = Preview.selected;
|
||||
if (settings.gamepad_controls.value == false) return;
|
||||
if (!document.hasFocus() || !preview || !gamepad || !gamepad.axes || !gamepad.connected || gamepad.axes.allEqual(0) || gamepad.axes.find(v => isNaN(v)) != undefined) return;
|
||||
|
||||
if (is_space_mouse) {
|
||||
let offset = new THREE.Vector3(
|
||||
gamepad.axes[0],
|
||||
-gamepad.axes[2],
|
||||
@ -1951,15 +1978,37 @@ window.addEventListener("gamepadconnected", function(event) {
|
||||
preview.controls.target.copy(camera_diff).add(preview.camera.position);
|
||||
|
||||
main_preview.controls.updateSceneScale();
|
||||
} else {
|
||||
let drift_threshold = 0.2;
|
||||
let axes = gamepad.axes.map(v => Math.abs(v) > drift_threshold ? v - drift_threshold * Math.sign(v) : 0);
|
||||
let camera_matrix = preview.camera.matrixWorld;
|
||||
let rotate_speed = settings.viewport_rotate_speed.value / 100;
|
||||
let zoom_speed = settings.viewport_zoom_speed.value / 100;
|
||||
|
||||
}, 16)
|
||||
if (axes[0]) preview.controls.rotateLeft(Math.signedPow(axes[0]) / 8 * rotate_speed);
|
||||
if (axes[1]) preview.controls.rotateUp(Math.signedPow(axes[1]) / 8 * rotate_speed);
|
||||
if (axes[2]) preview.controls.panLeft(Math.signedPow(axes[2]) * 1.5, camera_matrix);
|
||||
if (axes[3]) preview.controls.panUp(Math.signedPow(axes[3]) * 1.5, camera_matrix);
|
||||
|
||||
window.addEventListener("gamepadconnected", function(event2) {
|
||||
if (event2.gamepad.id == event.gamepad.id && event2.gamepad.index == event.gamepad.index) {
|
||||
clearInterval(interval);
|
||||
let smooth_zoom = 1-Math.exp(-zoom_timer/10)
|
||||
if (gamepad.buttons[6]?.pressed) {
|
||||
preview.controls.dollyOut(1 + 0.03 * zoom_speed * smooth_zoom);
|
||||
zoom_timer++;
|
||||
} else if (gamepad.buttons[7]?.pressed) {
|
||||
preview.controls.dollyIn(1 + 0.03 * zoom_speed * smooth_zoom);
|
||||
zoom_timer++;
|
||||
} else {
|
||||
zoom_timer = 0;
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
}, 16)
|
||||
|
||||
window.addEventListener("gamepadconnected", function(event2) {
|
||||
if (event2.gamepad.id == event.gamepad.id && event2.gamepad.index == event.gamepad.index) {
|
||||
clearInterval(interval);
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
//Init/Update
|
||||
@ -2074,6 +2123,7 @@ function updateShading() {
|
||||
Sun.intensity = settings_brightness;
|
||||
let view_mode = window.BarItems ? BarItems.view_mode.value : 'textured';
|
||||
|
||||
lights.add(Sun);
|
||||
if (view_mode == 'material') {
|
||||
|
||||
let light = Canvas.material_light;
|
||||
@ -2106,11 +2156,12 @@ function updateShading() {
|
||||
let parent = scene;
|
||||
parent.add(lights);
|
||||
lights.position.copy(parent.position).multiplyScalar(-1);
|
||||
} else {
|
||||
Canvas.scene.add(Sun);
|
||||
}
|
||||
if (Canvas.material_light) {
|
||||
Canvas.scene.remove(Canvas.material_light);
|
||||
}
|
||||
lights.add(Sun);
|
||||
Texture.all.forEach(tex => {
|
||||
let material = tex.getMaterial();
|
||||
if (!material.uniforms) return;
|
||||
@ -2158,6 +2209,7 @@ BARS.defineActions(function() {
|
||||
material: {name: true, icon: 'pages', condition: () => ((!Toolbox.selected.allowed_view_modes || Toolbox.selected.allowed_view_modes.includes('material')) && TextureGroup.all.find(tg => tg.is_material))},
|
||||
},
|
||||
onChange() {
|
||||
let previous_view_mode = Project.view_mode;
|
||||
Project.view_mode = this.value;
|
||||
Canvas.updateViewMode();
|
||||
if (Modes.id === 'animate') {
|
||||
@ -2170,6 +2222,9 @@ BARS.defineActions(function() {
|
||||
if (icon_node) icon_node.replaceWith(icon);
|
||||
}
|
||||
})
|
||||
if (Project.view_mode != previous_view_mode) {
|
||||
Blockbench.dispatchEvent('change_view_mode', {view_mode: Project.view_mode, previous_view_mode});
|
||||
}
|
||||
//Blockbench.showQuickMessage(tl('action.view_mode') + ': ' + tl('action.view_mode.' + this.value));
|
||||
}
|
||||
})
|
||||
@ -2257,14 +2312,19 @@ BARS.defineActions(function() {
|
||||
icon: 'center_focus_weak',
|
||||
category: 'view',
|
||||
condition: () => !Format.image_editor,
|
||||
keybind: new Keybind({}, {rotate_only: 'shift'}),
|
||||
keybind: new Keybind({}, {
|
||||
rotate_only: 'shift',
|
||||
zoom: 'ctrl'
|
||||
}),
|
||||
variations: {
|
||||
rotate_only: {name: 'action.focus_on_selection.rotate_only'}
|
||||
rotate_only: {name: 'action.focus_on_selection.rotate_only'},
|
||||
zoom: {name: 'action.focus_on_selection.zoom'}
|
||||
},
|
||||
click(event = 0) {
|
||||
if (!Project) return;
|
||||
let zoom = this.keybind.additionalModifierTriggered(event, 'zoom');
|
||||
if (Prop.active_panel == 'uv') {
|
||||
UVEditor.focusOnSelection()
|
||||
UVEditor.focusOnSelection(zoom)
|
||||
|
||||
} else {
|
||||
let preview = Preview.selected;
|
||||
@ -2277,8 +2337,26 @@ BARS.defineActions(function() {
|
||||
Transformer.getWorldPosition(center)
|
||||
}
|
||||
|
||||
let zoom_offset;
|
||||
let difference = new THREE.Vector3().copy(preview.controls.target).sub(center);
|
||||
difference.divideScalar(6)
|
||||
let cam_boom = center.clone().sub(preview.camera.position).add(difference);
|
||||
difference.divideScalar(6);
|
||||
|
||||
if (zoom) {
|
||||
let bounds = Canvas.getSelectionBounds();
|
||||
let radius = Math.max(
|
||||
Math.abs(bounds.min.x-center.x), Math.abs(bounds.max.x-center.x),
|
||||
Math.abs(bounds.min.z-center.z), Math.abs(bounds.max.z-center.z),
|
||||
);
|
||||
let height = Math.max(Math.abs(bounds.min.y-center.y), Math.abs(bounds.max.y-center.y));
|
||||
if (Math.abs(height) != Infinity) {
|
||||
let focal_length = preview.camera.getFocalLength();
|
||||
let cam_distance = cam_boom.length();
|
||||
let target_distance = Math.max(radius, height) * (focal_length / 10);
|
||||
zoom_factor = target_distance / cam_distance;
|
||||
zoom_offset = cam_boom.multiplyScalar((zoom_factor-1) / 6);
|
||||
}
|
||||
}
|
||||
|
||||
let i = 0;
|
||||
let interval = setInterval(() => {
|
||||
@ -2287,6 +2365,10 @@ BARS.defineActions(function() {
|
||||
if (this.keybind.additionalModifierTriggered(event) != 'rotate_only' || preview.angle != null) {
|
||||
preview.camera.position.sub(difference);
|
||||
}
|
||||
if (zoom_offset) {
|
||||
preview.camera.position.sub(zoom_offset);
|
||||
}
|
||||
Transformer.update();
|
||||
i++;
|
||||
if (i == 6) clearInterval(interval);
|
||||
|
||||
|
@ -39,7 +39,11 @@ class PreviewScene {
|
||||
this.cubemap = null;
|
||||
if (data.cubemap) {
|
||||
let urls = data.cubemap;
|
||||
let texture_cube = new THREE.CubeTextureLoader().load( urls );
|
||||
let texture_cube = new THREE.CubeTextureLoader().load(urls, () => {
|
||||
if (PreviewScene.active == this && Project.view_mode == 'material') {
|
||||
Canvas.updateShading();
|
||||
}
|
||||
});
|
||||
texture_cube.colorSpace = THREE.SRGBColorSpace;
|
||||
texture_cube.mapping = THREE.CubeRefractionMapping;
|
||||
this.cubemap = texture_cube;
|
||||
@ -106,9 +110,6 @@ class PreviewScene {
|
||||
Canvas.global_light_side = this.light_side;
|
||||
Canvas.scene.background = this.cubemap;
|
||||
Canvas.scene.fog = this.fog;
|
||||
|
||||
let pmremGenerator = new THREE.PMREMGenerator( Preview.selected.renderer );
|
||||
Canvas.scene.environment = pmremGenerator.fromCubemap(this.cubemap).texture;
|
||||
|
||||
if (this.fov && !(Modes.display && display_slot.startsWith('firstperson'))) {
|
||||
Preview.selected.setFOV(this.fov);
|
||||
|
@ -349,14 +349,19 @@ class ReferenceImage {
|
||||
(e2.clientX - e1.clientX) * multiplier,
|
||||
(e2.clientY - e1.clientY) * multiplier,
|
||||
];
|
||||
this.size[0] = Math.max(original_size[0] + offset[0] * sign_x, 48);
|
||||
let zoom_level = this.getZoomLevel();
|
||||
let max_size = [
|
||||
32 / zoom_level,
|
||||
24 / zoom_level
|
||||
];
|
||||
this.size[0] = Math.max(original_size[0] + offset[0] * sign_x, max_size[0]);
|
||||
this.position[0] = original_position[0] + offset[0] / 2, 0;
|
||||
|
||||
if (!e2.ctrlOrCmd && !Pressing.overrides.ctrl) {
|
||||
offset[1] = sign_y * (this.size[0] / this.aspect_ratio - original_size[1]);
|
||||
}
|
||||
|
||||
this.size[1] = Math.max(original_size[1] + offset[1] * sign_y, 32);
|
||||
this.size[1] = Math.max(original_size[1] + offset[1] * sign_y, max_size[1]);
|
||||
this.position[1] = original_position[1] + offset[1] / 2, 0;
|
||||
|
||||
if (this.layer !== 'blueprint') {
|
||||
|
@ -123,7 +123,7 @@ BARS.defineActions(function() {
|
||||
Undo.finishEdit('Adjust brightness and contrast');
|
||||
},
|
||||
onCancel() {
|
||||
Undo.cancelEdit();
|
||||
Undo.cancelEdit(true);
|
||||
}
|
||||
}).show();
|
||||
}
|
||||
@ -218,7 +218,7 @@ BARS.defineActions(function() {
|
||||
Undo.finishEdit('Adjust saturation and hue');
|
||||
},
|
||||
onCancel() {
|
||||
Undo.cancelEdit();
|
||||
Undo.cancelEdit(true);
|
||||
}
|
||||
}).show();
|
||||
}
|
||||
@ -500,7 +500,7 @@ BARS.defineActions(function() {
|
||||
Undo.finishEdit('Adjust curves');
|
||||
},
|
||||
onCancel() {
|
||||
Undo.cancelEdit();
|
||||
Undo.cancelEdit(true);
|
||||
}
|
||||
}).show();
|
||||
}
|
||||
@ -596,7 +596,7 @@ BARS.defineActions(function() {
|
||||
Undo.finishEdit('Adjust opacity');
|
||||
},
|
||||
onCancel() {
|
||||
Undo.cancelEdit();
|
||||
Undo.cancelEdit(true);
|
||||
}
|
||||
}).show();
|
||||
}
|
||||
@ -643,6 +643,43 @@ BARS.defineActions(function() {
|
||||
Undo.finishEdit('Limit texture to palette')
|
||||
}
|
||||
})
|
||||
new Action('split_rgb_into_layers', {
|
||||
icon: 'stacked_bar_chart',
|
||||
category: 'textures',
|
||||
condition: {modes: ['paint'], selected: {texture: true}},
|
||||
click() {
|
||||
let texture = Texture.getDefault();
|
||||
let original_data = texture.ctx.getImageData(0, 0, texture.canvas.width, texture.canvas.height);
|
||||
|
||||
Undo.initEdit({textures: [texture], bitmap: true});
|
||||
|
||||
texture.layers_enabled = true;
|
||||
let i = 0;
|
||||
for (let color of ['red', 'green', 'blue']) {
|
||||
data_copy = new ImageData(original_data.data.slice(), original_data.width, original_data.height);
|
||||
for (let j = 0; j < data_copy.data.length; j += 4) {
|
||||
if (i != 0) data_copy.data[j+0] = 0;
|
||||
if (i != 1) data_copy.data[j+1] = 0;
|
||||
if (i != 2) data_copy.data[j+2] = 0;
|
||||
}
|
||||
let layer = new TextureLayer({
|
||||
name: color,
|
||||
blend_mode: 'add'
|
||||
}, texture);
|
||||
layer.setSize(original_data.width, original_data.height);
|
||||
layer.ctx.putImageData(data_copy, 0, 0);
|
||||
texture.layers.unshift(layer);
|
||||
if (color == 'red') {
|
||||
layer.select();
|
||||
}
|
||||
i++;
|
||||
}
|
||||
texture.updateLayerChanges(true);
|
||||
Undo.finishEdit('Split texture into RGB layers');
|
||||
updateInterfacePanels();
|
||||
BARS.updateConditions();
|
||||
}
|
||||
})
|
||||
new Action('clear_unused_texture_space', {
|
||||
icon: 'cleaning_services',
|
||||
category: 'textures',
|
||||
|
@ -58,8 +58,13 @@ class TextureLayer {
|
||||
BarItems.layer_opacity.update();
|
||||
BarItems.layer_blend_mode.set(this.blend_mode);
|
||||
}
|
||||
clickSelect(event) {
|
||||
Undo.initSelection();
|
||||
this.select(event);
|
||||
Undo.finishSelection();
|
||||
}
|
||||
showContextMenu(event) {
|
||||
if (!this.selected) this.select();
|
||||
if (!this.selected) this.clickSelect(event);
|
||||
this.menu.open(event, this);
|
||||
}
|
||||
remove(undo) {
|
||||
@ -359,7 +364,7 @@ new Property(TextureLayer, 'vector2', 'offset');
|
||||
new Property(TextureLayer, 'vector2', 'scale', {default: [1, 1]});
|
||||
new Property(TextureLayer, 'number', 'opacity', {default: 100});
|
||||
new Property(TextureLayer, 'boolean', 'visible', {default: true});
|
||||
new Property(TextureLayer, 'enum', 'blend_mode', {default: 'default', values: ['default', 'set_opacity', 'color', 'multiply', 'add', 'screen', 'difference']});
|
||||
new Property(TextureLayer, 'enum', 'blend_mode', {default: 'default', values: ['default', 'set_opacity', 'color', 'multiply', 'add', 'screen', 'overlay', 'difference']});
|
||||
new Property(TextureLayer, 'boolean', 'in_limbo', {default: false});
|
||||
|
||||
Object.defineProperty(TextureLayer, 'all', {
|
||||
@ -750,7 +755,7 @@ Interface.definePanels(function() {
|
||||
:key="layer.uuid"
|
||||
:layer_id="layer.uuid"
|
||||
class="texture_layer"
|
||||
@click.stop="layer.select()"
|
||||
@click.stop="layer.clickSelect()"
|
||||
@dblclick.stop="layer.propertiesDialog()"
|
||||
@contextmenu.prevent.stop="layer.showContextMenu($event)"
|
||||
>
|
||||
|
@ -509,15 +509,17 @@ const Painter = {
|
||||
|
||||
function paintElement(element) {
|
||||
if (element instanceof Cube) {
|
||||
texture.selection.maskCanvas(ctx, offset);
|
||||
ctx.beginPath();
|
||||
for (var face in element.faces) {
|
||||
var tag = element.faces[face]
|
||||
if (Painter.getTextureToEdit(tag.getTexture()) === texture) {
|
||||
for (var fkey in element.faces) {
|
||||
var face = element.faces[fkey]
|
||||
if (fill_mode === 'face' && fkey !== Painter.current.face) continue;
|
||||
if (Painter.getTextureToEdit(face.getTexture()) === texture) {
|
||||
var face_rect = getRectangle(
|
||||
tag.uv[0] * uvFactorX,
|
||||
tag.uv[1] * uvFactorY,
|
||||
tag.uv[2] * uvFactorX,
|
||||
tag.uv[3] * uvFactorY
|
||||
face.uv[0] * uvFactorX,
|
||||
face.uv[1] * uvFactorY,
|
||||
face.uv[2] * uvFactorX,
|
||||
face.uv[3] * uvFactorY
|
||||
)
|
||||
let animation_offset = texture.currentFrame * texture.display_height;
|
||||
ctx.rect(
|
||||
@ -529,6 +531,7 @@ const Painter = {
|
||||
}
|
||||
}
|
||||
ctx.fill()
|
||||
ctx.restore();
|
||||
|
||||
} else if (element instanceof Mesh) {
|
||||
ctx.beginPath();
|
||||
@ -542,8 +545,8 @@ const Painter = {
|
||||
for (let x in matrix) {
|
||||
for (let y in matrix[x]) {
|
||||
if (!matrix[x][y]) continue;
|
||||
if (!texture.selection.allow(x, y)) continue;
|
||||
x = parseInt(x); y = parseInt(y);
|
||||
if (!texture.selection.allow(x, y)) continue;
|
||||
ctx.rect(x, y, 1, 1);
|
||||
}
|
||||
}
|
||||
@ -552,15 +555,13 @@ const Painter = {
|
||||
}
|
||||
}
|
||||
|
||||
if (element instanceof Cube && fill_mode === 'element') {
|
||||
paintElement(element);
|
||||
|
||||
} else if (element instanceof Mesh && (fill_mode === 'element' || fill_mode === 'face')) {
|
||||
if ((element instanceof Cube || element instanceof Mesh) && (fill_mode === 'element' || fill_mode === 'face')) {
|
||||
paintElement(element);
|
||||
|
||||
} else if (fill_mode === 'face' || fill_mode === 'element' || fill_mode === 'selection') {
|
||||
texture.selection.maskCanvas(ctx, offset);
|
||||
ctx.fill();
|
||||
ctx.restore();
|
||||
|
||||
} else if (fill_mode === 'selected_elements') {
|
||||
for (let element of Outliner.selected) {
|
||||
@ -1180,7 +1181,7 @@ const Painter = {
|
||||
}, {no_undo: true, use_cache: true});
|
||||
},
|
||||
colorPicker(texture, x, y, event) {
|
||||
var ctx = Painter.getCanvas(texture).getContext('2d')
|
||||
let {ctx} = settings.pick_combined_color.value ? texture : texture.getActiveCanvas();
|
||||
let color = Painter.getPixelColor(ctx, x, y);
|
||||
if (settings.pick_color_opacity.value) {
|
||||
let opacity = Math.floor(color.getAlpha()*256);
|
||||
@ -1262,6 +1263,15 @@ const Painter = {
|
||||
mix[ch] = ((1 - ((1-normal_base) * (1-normal_added))) * added.a) + (normal_base * (1-added.a));
|
||||
break;
|
||||
|
||||
case 'overlay':
|
||||
if (base[ch] < 128) {
|
||||
mix[ch] = (((2*normal_base*normal_added)) * added.a) + (normal_base * (1-added.a));
|
||||
}
|
||||
else{
|
||||
mix[ch] = ((1 - 2*((1-normal_base) * (1-normal_added))) * added.a) + (normal_base * (1-added.a));
|
||||
}
|
||||
break;
|
||||
|
||||
//case 'hard_light':
|
||||
//mix[ch] = ((normal_base / normal_added) * added.a) + (normal_base * (1-added.a));
|
||||
//break;
|
||||
@ -1345,6 +1355,7 @@ const Painter = {
|
||||
case 'add': return 'lighter';
|
||||
//case 'subtract': return 'darken';
|
||||
case 'screen': return 'screen';
|
||||
case 'overlay': return 'overlay';
|
||||
case 'difference': return 'difference';
|
||||
default: return 'source-over';
|
||||
}
|
||||
@ -1683,6 +1694,7 @@ const Painter = {
|
||||
add: 'action.blend_mode.add',
|
||||
//subtract: 'action.blend_mode.subtract',
|
||||
screen: 'action.blend_mode.screen',
|
||||
overlay: 'action.blend_mode.overlay',
|
||||
difference: 'action.blend_mode.difference',
|
||||
}},
|
||||
size: {
|
||||
@ -2036,9 +2048,8 @@ class IntMatrix {
|
||||
return boxes;
|
||||
}
|
||||
maskCanvas(ctx, offset = [0, 0]) {
|
||||
if (!this.is_custom) return;
|
||||
|
||||
ctx.save();
|
||||
if (!this.is_custom) return;
|
||||
ctx.beginPath();
|
||||
let boxes = this.toBoxes();
|
||||
boxes.forEach(box => {
|
||||
@ -2658,7 +2669,7 @@ BARS.defineActions(function() {
|
||||
let selection_tools = {
|
||||
rectangle: {name: 'action.selection_tool.rectangle', icon: 'select'},
|
||||
ellipse: {name: 'action.selection_tool.ellipse', icon: 'lasso_select'},
|
||||
//lasso: {name: 'action.selection_tool.lasso', icon: 'fa-draw-polygon'},
|
||||
lasso: {name: 'action.selection_tool.lasso', icon: 'fa-draw-polygon'},
|
||||
wand: {name: 'action.selection_tool.wand', icon: 'fa-magic'},
|
||||
color: {name: 'action.selection_tool.color', icon: 'fa-eye-dropper'},
|
||||
};
|
||||
@ -2723,6 +2734,7 @@ BARS.defineActions(function() {
|
||||
if (TextureLayer.selected?.in_limbo) {
|
||||
TextureLayer.selected.resolveLimbo();
|
||||
}
|
||||
UVEditor.vue.texture_selection_polygon.empty();
|
||||
Interface.removeSuggestedModifierKey('alt', 'modifier_actions.drag_to_duplicate');
|
||||
}
|
||||
})
|
||||
@ -2812,6 +2824,7 @@ BARS.defineActions(function() {
|
||||
add: true,
|
||||
//subtract: true,
|
||||
screen: true,
|
||||
overlay: true,
|
||||
difference: true,
|
||||
}
|
||||
})
|
||||
@ -3055,7 +3068,6 @@ BARS.defineActions(function() {
|
||||
}
|
||||
},
|
||||
onFormChange(result) {
|
||||
console.log('abaw')
|
||||
UVEditor.updateOverlayCanvas();
|
||||
}
|
||||
})
|
||||
|
@ -36,23 +36,24 @@ const TextureGenerator = {
|
||||
title: tl('action.create_texture'),
|
||||
width: 610,
|
||||
form: {
|
||||
name: {label: 'generic.name', value: 'texture'},
|
||||
folder: {label: 'dialog.create_texture.folder', condition: {features: ['texture_folder']}},
|
||||
type: {label: 'dialog.create_texture.type', type: 'inline_select', options: type_options, condition: Object.keys(type_options).length > 1},
|
||||
section2: "_",
|
||||
name: {label: 'generic.name', value: 'texture'},
|
||||
folder: {label: 'dialog.create_texture.folder', condition: {features: ['texture_folder']}},
|
||||
type: {label: 'dialog.create_texture.type', type: 'inline_select', options: type_options, condition: Object.keys(type_options).length > 1},
|
||||
section2: "_",
|
||||
|
||||
resolution: {label: 'dialog.create_texture.pixel_density', description: 'dialog.create_texture.pixel_density.desc', type: 'select', value: resolution_presets[resolution] ? resolution : undefined, condition: (form) => (form.type == 'template'), options: resolution_presets},
|
||||
resolution: {label: 'dialog.create_texture.pixel_density', description: 'dialog.create_texture.pixel_density.desc', type: 'select', value: resolution_presets[resolution] ? resolution : undefined, condition: (form) => (form.type == 'template'), options: resolution_presets},
|
||||
resolution_vec: {label: 'dialog.create_texture.resolution', type: 'vector', condition: (form) => (form.type == 'blank'), dimensions: 2, value: [Project.texture_width, Project.texture_height], min: 16, max: 2048},
|
||||
color: {label: 'data.color', type: 'color', colorpicker: TextureGenerator.background_color, toggle_enabled: true, toggle_default: false},
|
||||
color: {label: 'data.color', type: 'color', colorpicker: TextureGenerator.background_color, toggle_enabled: true, toggle_default: false},
|
||||
|
||||
rearrange_uv:{label: 'dialog.create_texture.rearrange_uv', description: 'dialog.create_texture.rearrange_uv.desc', type: 'checkbox', value: true, condition: (form) => (form.type == 'template')},
|
||||
box_uv: {label: 'dialog.project.uv_mode.box_uv', type: 'checkbox', value: false, condition: (form) => (form.type == 'template' && !Project.box_uv && Cube.all.length)},
|
||||
power: {label: 'dialog.create_texture.power', description: 'dialog.create_texture.power.desc', type: 'checkbox', value: true, condition: (form) => (form.type !== 'blank' && (form.rearrange_uv || form.type == 'color_map'))},
|
||||
double_use: {label: 'dialog.create_texture.double_use', description: 'dialog.create_texture.double_use.desc', type: 'checkbox', value: true, condition: ((form) => (form.type == 'template' && form.rearrange_uv))},
|
||||
combine_polys: {label: 'dialog.create_texture.combine_polys', description: 'dialog.create_texture.combine_polys.desc', type: 'checkbox', value: true, condition: (form) => (form.type == 'template' && form.rearrange_uv && Mesh.selected.length)},
|
||||
max_edge_angle: {label: 'dialog.create_texture.max_edge_angle', description: 'dialog.create_texture.max_edge_angle.desc', type: 'number', value: 36, condition: (form) => (form.type == 'template' && form.rearrange_uv && Mesh.selected.length)},
|
||||
rearrange_uv: {label: 'dialog.create_texture.rearrange_uv', description: 'dialog.create_texture.rearrange_uv.desc', type: 'checkbox', value: true, condition: (form) => (form.type == 'template')},
|
||||
box_uv: {label: 'dialog.project.uv_mode.box_uv', type: 'checkbox', value: false, condition: (form) => (form.type == 'template' && !Project.box_uv && Cube.all.length)},
|
||||
power: {label: 'dialog.create_texture.power', description: 'dialog.create_texture.power.desc', type: 'checkbox', value: true, condition: (form) => (form.type !== 'blank' && (form.rearrange_uv || form.type == 'color_map'))},
|
||||
double_use: {label: 'dialog.create_texture.double_use', description: 'dialog.create_texture.double_use.desc', type: 'checkbox', value: true, condition: ((form) => (form.type == 'template' && form.rearrange_uv))},
|
||||
combine_polys: {label: 'dialog.create_texture.combine_polys', description: 'dialog.create_texture.combine_polys.desc', type: 'checkbox', value: true, condition: (form) => (form.type == 'template' && form.rearrange_uv && Mesh.selected.length)},
|
||||
max_edge_angle: {label: 'dialog.create_texture.max_edge_angle', description: 'dialog.create_texture.max_edge_angle.desc', type: 'number', value: 36, condition: (form) => (form.type == 'template' && form.rearrange_uv && Mesh.selected.length)},
|
||||
max_island_angle: {label: 'dialog.create_texture.max_island_angle', description: 'dialog.create_texture.max_island_angle.desc', type: 'number', value: 45, condition: (form) => (form.type == 'template' && form.rearrange_uv && Mesh.selected.length)},
|
||||
padding: {label: 'dialog.create_texture.padding', description: 'dialog.create_texture.padding.desc', type: 'checkbox', value: Mesh.selected.length > 0, condition: (form) => (form.type == 'template' && form.rearrange_uv)},
|
||||
padding: {label: 'dialog.create_texture.padding', description: 'dialog.create_texture.padding.desc', type: 'checkbox', value: Mesh.selected.length > 0, condition: (form) => (form.type == 'template' && form.rearrange_uv)},
|
||||
disable_mirror_uv:{label: 'dialog.create_texture.disable_mirror_uv', description: 'dialog.create_texture.disable_mirror_uv.desc', type: 'checkbox', value: true, condition: (form) => BarItems.mirror_modeling.value && BarItems.mirror_modeling.tool_config.options.mirror_uv},
|
||||
|
||||
},
|
||||
onConfirm: function(results) {
|
||||
@ -60,6 +61,9 @@ const TextureGenerator = {
|
||||
if (results.type == 'blank') {
|
||||
results.resolution = results.resolution_vec;
|
||||
}
|
||||
if (results.disable_mirror_uv) {
|
||||
BarItems.mirror_modeling.tool_config.changeOptions({mirror_uv: false});
|
||||
}
|
||||
dialog.hide()
|
||||
if (Format.edit_mode && Outliner.selected.length == 0) {
|
||||
SharedActions.runSpecific('select_all', 'outliner');
|
||||
@ -344,21 +348,23 @@ const TextureGenerator = {
|
||||
});
|
||||
function faceRect(cube, face_key, tex, x, y, face_old_pos_id) {
|
||||
this.cube = cube;
|
||||
this.face = cube.faces[face_key];
|
||||
if (options.rearrange_uv) {
|
||||
this.width = Math.abs(x) * res_multiple;
|
||||
this.height = Math.abs(y) * res_multiple;
|
||||
this.mirror_x = Math.sign(this.face.uv_size[0]);
|
||||
this.mirror_y = Math.sign(this.face.uv_size[1]);
|
||||
this.width = ((this.width >= 0.01 && this.width < 1) ? 1 : Math.round(this.width)) / res_multiple;
|
||||
this.height = ((this.height >= 0.01 && this.height < 1) ? 1 : Math.round(this.height)) / res_multiple;
|
||||
} else {
|
||||
this.posx = cube.faces[face_key].uv[0], cube.faces[face_key].uv[0+2];
|
||||
this.posy = cube.faces[face_key].uv[1], cube.faces[face_key].uv[1+2];
|
||||
this.width = cube.faces[face_key].uv[0+2] - cube.faces[face_key].uv[0];
|
||||
this.height = cube.faces[face_key].uv[1+2] - cube.faces[face_key].uv[1];
|
||||
this.posx = this.face.uv[0], this.face.uv[0+2];
|
||||
this.posy = this.face.uv[1], this.face.uv[1+2];
|
||||
this.width = this.face.uv[0+2] - this.face.uv[0];
|
||||
this.height = this.face.uv[1+2] - this.face.uv[1];
|
||||
}
|
||||
this.size = this.width * this.height;
|
||||
this.face_key = face_key;
|
||||
this.texture = tex
|
||||
this.face = cube.faces[face_key];
|
||||
this.face_old_pos_id = face_old_pos_id;
|
||||
}
|
||||
function faceOldPositionIdentifier(face) {
|
||||
@ -370,7 +376,14 @@ const TextureGenerator = {
|
||||
vertex_identifiers.sort(sort_collator.compare);
|
||||
uv_id = vertex_identifiers.join(',');
|
||||
} else if (face.uv instanceof Array) {
|
||||
uv_id = face.uv.map(v => Math.roundTo(v, 4)).join(',');
|
||||
let absolute_uv = face.uv.slice();
|
||||
for (let i = 0; i < 2; i++) {
|
||||
if (absolute_uv[i] > absolute_uv[i+2]) {
|
||||
absolute_uv[i] = absolute_uv[i+2];
|
||||
absolute_uv[i+2] = face.uv[i];
|
||||
}
|
||||
}
|
||||
uv_id = absolute_uv.map(v => Math.roundTo(v, 4)).join(',');
|
||||
}
|
||||
let texture = face.getTexture();
|
||||
return uv_id + ':' + (texture ? texture.uuid : 'blank');
|
||||
@ -412,6 +425,7 @@ const TextureGenerator = {
|
||||
if (mirror_modeling_duplicate) return;
|
||||
if (element instanceof Cube) {
|
||||
if (element.box_uv || options.box_uv) {
|
||||
element.box_uv = true;
|
||||
|
||||
let template = new TextureGenerator.boxUVCubeTemplate(element, element.box_uv ? 0 : 1);
|
||||
let mirror_modeling_duplicate = BarItems.mirror_modeling.value && MirrorModeling.cached_elements[element.uuid] && MirrorModeling.cached_elements[element.uuid].is_copy;
|
||||
@ -433,7 +447,6 @@ const TextureGenerator = {
|
||||
doubles[double_key] = [template]
|
||||
}
|
||||
}
|
||||
element.box_uv = true;
|
||||
box_uv_templates.push(template)
|
||||
avg_size += box_uv_templates[box_uv_templates.length-1].template_size
|
||||
|
||||
@ -1404,6 +1417,15 @@ const TextureGenerator = {
|
||||
uv: flip_rotation ? [pos.y, pos.x] : [pos.x, pos.y]
|
||||
})
|
||||
target.face.uv_size = flip_rotation ? [pos.h, pos.w] : [pos.w, pos.h];
|
||||
if (source != target) {
|
||||
// Double occupancy mirroring
|
||||
if (target.mirror_x == -1) {
|
||||
[target.face.uv[2], target.face.uv[0]] = [target.face.uv[0], target.face.uv[2]];
|
||||
}
|
||||
if (target.mirror_y == -1) {
|
||||
[target.face.uv[3], target.face.uv[1]] = [target.face.uv[1], target.face.uv[3]];
|
||||
}
|
||||
}
|
||||
if (target.face_key == 'up') {
|
||||
[target.face.uv[2], target.face.uv[0]] = [target.face.uv[0], target.face.uv[2]];
|
||||
[target.face.uv[3], target.face.uv[1]] = [target.face.uv[1], target.face.uv[3]];
|
||||
|
@ -87,22 +87,31 @@ class TextureGroup {
|
||||
}
|
||||
|
||||
updateMaterial() {
|
||||
/**
|
||||
* @link https://threejs.org/docs/index.html#api/en/materials/MeshStandardMaterial
|
||||
* @type {THREE.MeshStandardMaterial}
|
||||
*/
|
||||
let material = this._static.properties.material;
|
||||
|
||||
if (!material) {
|
||||
//let g = new THREE.PMREMGenerator(Preview.selected.renderer);
|
||||
//let pmrem_render_target = g.fromScene(Canvas.scene);
|
||||
// https://threejs.org/docs/index.html#api/en/materials/MeshStandardMaterial
|
||||
material = this._static.properties.material = new THREE.MeshStandardMaterial({
|
||||
envMap: PreviewScene.active?.cubemap ?? null,
|
||||
envMapIntensity: 0.8,
|
||||
alphaTest: 0.05,
|
||||
});
|
||||
}
|
||||
|
||||
if (PreviewScene.active) {
|
||||
const g = new THREE.PMREMGenerator(Preview.selected.renderer);
|
||||
material.envMap = g.fromScene(Canvas.scene, 0.0, 100, 1024).texture;
|
||||
}
|
||||
|
||||
let textures = this.getTextures();
|
||||
let color_tex = textures.find(t => t.pbr_channel == 'color');
|
||||
let normal_tex = textures.find(t => t.pbr_channel == 'normal');
|
||||
let height_tex = textures.find(t => t.pbr_channel == 'height');
|
||||
let mer_tex = textures.find(t => t.pbr_channel == 'mer');
|
||||
|
||||
// Albedo
|
||||
if (color_tex) {
|
||||
material.map = color_tex.getOwnMaterial().map;
|
||||
material.color.set('#ffffff');
|
||||
@ -113,12 +122,15 @@ class TextureGroup {
|
||||
material.color.set({r: c[0] / 255, g: c[1] / 255, b: c[2] / 255});
|
||||
material.opacity = c[4] / 255;
|
||||
}
|
||||
|
||||
// Height
|
||||
if (normal_tex) {
|
||||
material.normalMap = normal_tex.getOwnMaterial().map;
|
||||
material.bumpMap = null;
|
||||
|
||||
// Use DirectX normal maps for RenderDragon. Flips the "handedness" of the normal map.
|
||||
material.normalScale = Project.format.id.includes('bedrock') ? new THREE.Vector2(1, -1) : new THREE.Vector2(1, 1);
|
||||
} else if (height_tex) {
|
||||
material.bumpMap = height_tex.getOwnMaterial().map;
|
||||
material.bumpMap = height_tex.getOwnMaterial().map.clone();
|
||||
material.bumpScale = 0.4;
|
||||
material.normalMap = null;
|
||||
// Bump map scale
|
||||
@ -131,47 +143,74 @@ class TextureGroup {
|
||||
material.bumpMap.image = canvas;
|
||||
material.bumpMap.magFilter = THREE.LinearFilter;
|
||||
material.bumpMap.needsUpdate = true;
|
||||
} else {
|
||||
material.normalMap = null;
|
||||
material.bumpMap = null;
|
||||
}
|
||||
if (mer_tex && mer_tex.img?.naturalWidth) {
|
||||
|
||||
// MER
|
||||
if (mer_tex && mer_tex.img?.naturalWidth && mer_tex.width) {
|
||||
let image_data = mer_tex.canvas.getContext('2d').getImageData(0, 0, mer_tex.width, mer_tex.height);
|
||||
let image_data_albedo = color_tex.canvas.getContext('2d').getImageData(0, 0, color_tex.width, color_tex.height);
|
||||
function generateMap(source_channel, target_channel, key) {
|
||||
let canvas = material[key]?.image ?? document.createElement('canvas');
|
||||
|
||||
const extractEmissiveChannel = () => {
|
||||
// The green channel is the emissive level.
|
||||
// Use it as an mask on the color texture to create the emissive map.
|
||||
const color_data = color_tex.canvas.getContext('2d').getImageData(0, 0, color_tex.width, color_tex.height);
|
||||
let emissive_data = new Uint8ClampedArray(color_data.data.length);
|
||||
for (let i = 0; i < image_data.data.length; i += 4) {
|
||||
if (image_data.data[i + 1] > 0) {
|
||||
emissive_data[i] = color_data.data[i];
|
||||
emissive_data[i + 1] = color_data.data[i + 1];
|
||||
emissive_data[i + 2] = color_data.data[i + 2];
|
||||
emissive_data[i + 3] = 255;
|
||||
continue;
|
||||
}
|
||||
|
||||
emissive_data[i] = 0;
|
||||
emissive_data[i + 1] = 0;
|
||||
emissive_data[i + 2] = 0;
|
||||
emissive_data[i + 3] = 255;
|
||||
}
|
||||
|
||||
return new ImageData(emissive_data, mer_tex.width, mer_tex.height);
|
||||
}
|
||||
|
||||
const extractGrayscaleValue = (channel) => {
|
||||
let grayscale_data = new Uint8ClampedArray(image_data.data.length);
|
||||
for (let i = 0; i < image_data.data.length; i += 4) {
|
||||
grayscale_data[i + 0] = image_data.data[i + channel];
|
||||
grayscale_data[i + 1] = image_data.data[i + channel];
|
||||
grayscale_data[i + 2] = image_data.data[i + channel];
|
||||
grayscale_data[i + 3] = 255;
|
||||
}
|
||||
|
||||
return new ImageData(grayscale_data, mer_tex.width, mer_tex.height);
|
||||
}
|
||||
|
||||
function generateMap(source_channel, key) {
|
||||
let canvas = material[key]?.image;
|
||||
if (!canvas || key == 'emissiveMap') {
|
||||
canvas = document.createElement('canvas');
|
||||
}
|
||||
let ctx = canvas.getContext('2d');
|
||||
canvas.width = mer_tex.width;
|
||||
canvas.height = mer_tex.height;
|
||||
ctx.fillStyle = 'black';
|
||||
ctx.fillRect(0, 0, mer_tex.width, mer_tex.height);
|
||||
document.body.append(canvas)
|
||||
// document.body.append(canvas);
|
||||
|
||||
let image_data_new = ctx.getImageData(0, 0, mer_tex.width, mer_tex.height);
|
||||
for (let i = 0; i < image_data.data.length; i += 4) {
|
||||
if (target_channel == 0) {
|
||||
let value = image_data.data[i + source_channel] / 255;
|
||||
image_data_new.data[i + 0] = image_data_albedo.data[i + 0] * value;
|
||||
image_data_new.data[i + 1] = image_data_albedo.data[i + 1] * value;
|
||||
image_data_new.data[i + 2] = image_data_albedo.data[i + 2] * value;
|
||||
} else {
|
||||
image_data_new.data[i + target_channel] = image_data.data[i + source_channel];
|
||||
if (source_channel == 2 && image_data_new.data[i + target_channel] == 0) {
|
||||
//image_data_new.data[i + target_channel] = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
ctx.putImageData(image_data_new, 0, 0);
|
||||
ctx.putImageData(source_channel === 1 ? extractEmissiveChannel() : extractGrayscaleValue(source_channel), 0, 0);
|
||||
|
||||
if (!material[key] || true) {
|
||||
material[key] = new THREE.Texture(canvas, THREE.UVMapping, THREE.RepeatWrapping, THREE.RepeatWrapping, THREE.NearestFilter, THREE.NearestFilter);
|
||||
material[key].needsUpdate = true;
|
||||
}
|
||||
//material.map = material[key];
|
||||
material[key] = new THREE.Texture(canvas, THREE.UVMapping, THREE.RepeatWrapping, THREE.RepeatWrapping, THREE.NearestFilter, THREE.NearestFilter);
|
||||
material[key].needsUpdate = true;
|
||||
}
|
||||
generateMap(0, 2, 'metalnessMap');
|
||||
generateMap(1, 0, 'emissiveMap');
|
||||
generateMap(2, 1, 'roughnessMap');
|
||||
generateMap(0, 'metalnessMap');
|
||||
generateMap(1, 'emissiveMap');
|
||||
generateMap(2, 'roughnessMap');
|
||||
material.emissive.set(0xffffff);
|
||||
material.emissiveIntensity = 5;
|
||||
material.emissiveIntensity = 1;
|
||||
material.metalness = 1;
|
||||
material.roughness = 1;
|
||||
} else {
|
||||
material.metalnessMap = null;
|
||||
material.emissiveMap = material.map;
|
||||
@ -288,7 +327,14 @@ class TextureGroupMaterialConfig {
|
||||
texture_set.color = this.color_value.slice();
|
||||
}
|
||||
if (mer_tex) {
|
||||
texture_set.metalness_emissive_roughness = getTextureName(mer_tex);
|
||||
let texture_name = getTextureName(mer_tex);
|
||||
if (this.subsurface_value) {
|
||||
texture_set.metalness_emissive_roughness_subsurface = texture_name;
|
||||
} else {
|
||||
texture_set.metalness_emissive_roughness = texture_name;
|
||||
}
|
||||
} else if (this.subsurface_value) {
|
||||
texture_set.metalness_emissive_roughness_subsurface = [...this.mer_value, this.subsurface_value];
|
||||
} else if (!this.mer_value.allEqual(0)) {
|
||||
texture_set.metalness_emissive_roughness = this.mer_value.slice();
|
||||
}
|
||||
@ -298,8 +344,12 @@ class TextureGroupMaterialConfig {
|
||||
texture_set.heightmap = getTextureName(height_tex);
|
||||
}
|
||||
|
||||
let format_version = "1.16.100";
|
||||
if (texture_set.metalness_emissive_roughness_subsurface) {
|
||||
format_version = "1.21.30";
|
||||
}
|
||||
let file = {
|
||||
format_version: "1.16.100",
|
||||
format_version,
|
||||
"minecraft:texture_set": texture_set
|
||||
}
|
||||
return file;
|
||||
@ -368,7 +418,7 @@ class TextureGroupMaterialConfig {
|
||||
a: this.color_value[3] / 255
|
||||
}
|
||||
},
|
||||
'mer': '_',
|
||||
'_mers': '_',
|
||||
mer: {
|
||||
type: 'select',
|
||||
label: 'dialog.material_config.mer',
|
||||
@ -382,7 +432,21 @@ class TextureGroupMaterialConfig {
|
||||
min: 0, max: 255, step: 1, force_step: true,
|
||||
value: this.mer_value.map(v => Math.clamp(v, 0, 255)),
|
||||
},
|
||||
'depth': '_',
|
||||
subsurface: {
|
||||
type: 'checkbox',
|
||||
label: 'dialog.material_config.subsurface',
|
||||
description: 'dialog.material_config.subsurface_enabled.desc',
|
||||
condition: form => isUUID(form.mer),
|
||||
value: this.subsurface_value > 0,
|
||||
},
|
||||
subsurface_value: {
|
||||
label: 'dialog.material_config.subsurface',
|
||||
condition: form => form.mer == 'uniform',
|
||||
type: 'number',
|
||||
min: 0, max: 255, step: 1, force_step: true,
|
||||
value: Math.clamp(this.subsurface_value, 0, 255),
|
||||
},
|
||||
'_depth': '_',
|
||||
depth_type: {
|
||||
type: 'inline_select',
|
||||
label: 'dialog.material_config.depth_type',
|
||||
@ -414,6 +478,9 @@ class TextureGroupMaterialConfig {
|
||||
let color = result.color_value.toRgb();
|
||||
let color_array = [color.r, color.g, color.b, Math.round(color.a * 255)];
|
||||
this.color_value.replace(color_array);
|
||||
for (let texture of textures) {
|
||||
if (texture.pbr_channel == 'color') texture.group = '';
|
||||
}
|
||||
} else {
|
||||
let target = textures.find(t => t.uuid == result.color);
|
||||
if (target) target.pbr_channel = 'color';
|
||||
@ -421,10 +488,15 @@ class TextureGroupMaterialConfig {
|
||||
|
||||
if (result.mer == 'uniform') {
|
||||
this.mer_value.replace(result.mer_value);
|
||||
for (let texture of textures) {
|
||||
if (texture.pbr_channel == 'mer') texture.group = '';
|
||||
}
|
||||
this.subsurface_value = result.subsurface_value;
|
||||
} else {
|
||||
this.mer_value.replace([0, 0, 0]);
|
||||
let target = textures.find(t => t.uuid == result.mer);
|
||||
if (target) target.pbr_channel = 'mer';
|
||||
this.subsurface_value = result.subsurface ? 1 : 0;
|
||||
}
|
||||
|
||||
if (result.depth_type == 'normal') {
|
||||
@ -449,6 +521,7 @@ class TextureGroupMaterialConfig {
|
||||
}
|
||||
new Property(TextureGroupMaterialConfig, 'vector4', 'color_value', {default: [255, 255, 255, 255]});
|
||||
new Property(TextureGroupMaterialConfig, 'vector', 'mer_value');
|
||||
new Property(TextureGroupMaterialConfig, 'number', 'subsurface_value');
|
||||
new Property(TextureGroupMaterialConfig, 'boolean', 'saved', {default: true});
|
||||
TextureGroupMaterialConfig.prototype.menu = new Menu('texture_group_material_config', [
|
||||
'generate_pbr_map',
|
||||
@ -496,7 +569,7 @@ function importTextureSet(file) {
|
||||
Undo.initEdit({textures: new_textures, texture_groups: new_texture_groups});
|
||||
if (file.name.endsWith('texture_set.json')) {
|
||||
let texture_group = new TextureGroup({is_material: true});
|
||||
texture_group.name = file.name.replace('.texture_set.json', '');
|
||||
texture_group.name = file.name.replace('.texture_set.json', '.png material');
|
||||
|
||||
let content = fs.readFileSync(file.path, {encoding: 'utf-8'});
|
||||
let content_json = autoParseJSON(content);
|
||||
@ -507,6 +580,7 @@ function importTextureSet(file) {
|
||||
normal: 'normal',
|
||||
heightmap: 'height',
|
||||
metalness_emissive_roughness: 'mer',
|
||||
metalness_emissive_roughness_subsurface: 'mer',
|
||||
};
|
||||
for (let key in channels) {
|
||||
let source = content_json['minecraft:texture_set'][key];
|
||||
@ -522,6 +596,9 @@ function importTextureSet(file) {
|
||||
new_textures.push(t);
|
||||
t.group = texture_group.uuid;
|
||||
})
|
||||
if (key == 'metalness_emissive_roughness_subsurface') {
|
||||
texture_group.material_config.subsurface_value = 1;
|
||||
}
|
||||
} else {
|
||||
let color_array = source;
|
||||
if (typeof source == 'string') {
|
||||
@ -536,6 +613,9 @@ function importTextureSet(file) {
|
||||
}
|
||||
} else if (key == 'metalness_emissive_roughness') {
|
||||
texture_group.material_config.mer_value.V3_set(color_array);
|
||||
} else if (key == 'metalness_emissive_roughness_subsurface') {
|
||||
texture_group.material_config.mer_value.V3_set(color_array);
|
||||
texture_group.material_config.subsurface_value = Math.clamp(color_array[3] ?? 0, 0, 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -547,6 +627,14 @@ function importTextureSet(file) {
|
||||
}
|
||||
Undo.finishEdit('Import texture set');
|
||||
}
|
||||
function loadAdjacentTextureSet(texture) {
|
||||
let path = texture.path.replace(/\.png$/i, '.texture_set.json');
|
||||
if (fs.existsSync(path)) {
|
||||
Blockbench.read([path], {}, (files) => {
|
||||
importTextureSet(files[0])
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
SharedActions.add('rename', {
|
||||
condition: () => Prop.active_panel == 'textures' && TextureGroup.active_menu_group,
|
||||
@ -579,6 +667,7 @@ BARS.defineActions(function() {
|
||||
new Action('create_material', {
|
||||
icon: 'lightbulb_circle',
|
||||
category: 'textures',
|
||||
condition: () => (!Texture.selected || !Texture.selected.getGroup()?.is_material) && Format.pbr,
|
||||
click() {
|
||||
let texture = Texture.selected;
|
||||
let texture_group = new TextureGroup({is_material: true});
|
||||
@ -604,7 +693,7 @@ BARS.defineActions(function() {
|
||||
new Action('generate_pbr_map', {
|
||||
icon: 'texture_add',
|
||||
category: 'textures',
|
||||
condition: () => Texture.all[0],
|
||||
condition: () => Texture.all[0] && Format.pbr,
|
||||
click() {
|
||||
let texture = Texture.selected ?? Texture.all[0];
|
||||
let texture_group = texture.getGroup();
|
||||
@ -617,7 +706,7 @@ BARS.defineActions(function() {
|
||||
let new_data = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
||||
canvas.style.width = 256 + 'px';
|
||||
canvas.style.height = 256 + 'px';
|
||||
let original_image = new CanvasFrame(texture.canvas);
|
||||
let original_image = new CanvasFrame(texture.canvas, true);
|
||||
original_image.canvas.style.width = 256 + 'px';
|
||||
original_image.canvas.style.height = 256 + 'px';
|
||||
|
||||
@ -683,6 +772,9 @@ BARS.defineActions(function() {
|
||||
|
||||
let output = Math.clamp(Math.lerp(result.out_range[0], result.out_range[1], input_1), 0, 255);
|
||||
|
||||
new_data.data[i+0] = 0;
|
||||
new_data.data[i+1] = 0;
|
||||
new_data.data[i+2] = 0;
|
||||
new_data.data[i+3] = 255;
|
||||
|
||||
switch (result.channel) {
|
||||
@ -715,6 +807,17 @@ BARS.defineActions(function() {
|
||||
width: 564,
|
||||
lines: [preview],
|
||||
form: {
|
||||
channel: {
|
||||
type: 'select',
|
||||
label: 'PBR Channel',
|
||||
options: {
|
||||
//normal: 'menu.texture.pbr_channel.normal',
|
||||
height: 'menu.texture.pbr_channel.height',
|
||||
metalness: 'Metalness',
|
||||
emissive: 'Emissive',
|
||||
roughness: 'Roughness',
|
||||
}
|
||||
},
|
||||
method: {
|
||||
type: 'select',
|
||||
label: 'Source',
|
||||
@ -728,17 +831,6 @@ BARS.defineActions(function() {
|
||||
blue: 'Blue',
|
||||
}
|
||||
},
|
||||
channel: {
|
||||
type: 'select',
|
||||
label: 'PBR Channel',
|
||||
options: {
|
||||
//normal: 'menu.texture.pbr_channel.normal',
|
||||
height: 'menu.texture.pbr_channel.height',
|
||||
metalness: 'Metalness',
|
||||
emissive: 'Emissive',
|
||||
roughness: 'Roughness',
|
||||
}
|
||||
},
|
||||
in_range: {
|
||||
type: 'vector',
|
||||
label: 'Input Range',
|
||||
@ -759,15 +851,53 @@ BARS.defineActions(function() {
|
||||
onConfirm(result) {
|
||||
updateCanvas(result);
|
||||
let textures = [];
|
||||
Undo.initEdit({texture_groups: [texture_group], textures});
|
||||
let pbr_channel = result.channel;
|
||||
let new_texture = new Texture({
|
||||
name: texture.name,
|
||||
pbr_channel,
|
||||
group: texture_group.uuid,
|
||||
}).fromDataURL(canvas.toDataURL()).add(false);
|
||||
textures.push(new_texture);
|
||||
let pbr_channel;
|
||||
switch (result.channel) {
|
||||
case 'height': pbr_channel = result.channel; break;
|
||||
default: pbr_channel = 'mer'; break;
|
||||
}
|
||||
|
||||
let existing_channel_texture = texture_group.getTextures().find(tex => tex.pbr_channel == pbr_channel);
|
||||
|
||||
if (existing_channel_texture && pbr_channel == 'mer') {
|
||||
Undo.initEdit({textures: [existing_channel_texture], bitmap: true});
|
||||
if (!existing_channel_texture.layers_enabled) {
|
||||
existing_channel_texture.activateLayers(false);
|
||||
}
|
||||
let layer = new TextureLayer({
|
||||
name: result.channel,
|
||||
blend_mode: 'add'
|
||||
}, existing_channel_texture);
|
||||
let image_data = canvas.getContext('2d').getImageData(0, 0, canvas.width, canvas.height);
|
||||
layer.setSize(canvas.width, canvas.height);
|
||||
layer.ctx.putImageData(image_data, 0, 0);
|
||||
layer.addForEditing();
|
||||
existing_channel_texture.updateLayerChanges(true);
|
||||
|
||||
} else {
|
||||
Undo.initEdit({texture_groups: texture_group ? [texture_group] : null, textures});
|
||||
|
||||
let main_texture = texture_group?.getTextures().find(t => t.pbr_channel == 'color');
|
||||
let name = main_texture ? main_texture.name : texture.name;
|
||||
name = name.replace('.', `_${pbr_channel}.`);
|
||||
|
||||
let new_texture = new Texture({
|
||||
name,
|
||||
pbr_channel,
|
||||
group: texture_group?.uuid,
|
||||
}).fromDataURL(canvas.toDataURL()).add(false);
|
||||
textures.push(new_texture);
|
||||
|
||||
if (texture_group.material_config) {
|
||||
texture_group.material_config.saved = false;
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
texture_group.updateMaterial();
|
||||
}, 50);
|
||||
Undo.finishEdit('Create PBR map');
|
||||
updateSelection();
|
||||
},
|
||||
onOpen() {
|
||||
updateCanvas(this.getFormResult());
|
||||
|
@ -185,7 +185,7 @@ class Texture {
|
||||
});
|
||||
mat.map = tex;
|
||||
mat.name = this.name;
|
||||
Project.materials[this.uuid] = mat;
|
||||
this.material = mat;
|
||||
|
||||
var size_control = {};
|
||||
|
||||
@ -329,6 +329,12 @@ class Texture {
|
||||
get selection() {
|
||||
return this._static.properties.selection;
|
||||
}
|
||||
get material() {
|
||||
return this._static.properties.material;
|
||||
}
|
||||
set material(material) {
|
||||
this._static.properties.material = material;
|
||||
}
|
||||
getUVWidth() {
|
||||
return Format.per_texture_uv_size ? this.uv_width : Project.texture_width;
|
||||
}
|
||||
@ -891,10 +897,10 @@ class Texture {
|
||||
if (group?.is_material && BarItems.view_mode.value == 'material') {
|
||||
return group.getMaterial();
|
||||
}
|
||||
return Project.materials[this.uuid];
|
||||
return this.material;
|
||||
}
|
||||
getOwnMaterial() {
|
||||
return Project.materials[this.uuid];
|
||||
return this.material;
|
||||
}
|
||||
//Management
|
||||
select(event) {
|
||||
@ -995,7 +1001,6 @@ class Texture {
|
||||
Texture.selected = undefined;
|
||||
}
|
||||
Project.textures.splice(Texture.all.indexOf(this), 1)
|
||||
delete Project.materials[this.uuid];
|
||||
Blockbench.dispatchEvent('update_texture_selection');
|
||||
if (!no_update) {
|
||||
Canvas.updateAllFaces()
|
||||
@ -1783,6 +1788,9 @@ class Texture {
|
||||
this.source = this.canvas.toDataURL('image/png', 1);
|
||||
this.updateImageFromCanvas();
|
||||
}
|
||||
if ((this.pbr_channel == 'mer' || this.pbr_channel == 'height') && this.getGroup()?.is_material && BarItems.view_mode.value == 'material') {
|
||||
this.getGroup().updateMaterial();
|
||||
}
|
||||
this.saved = false;
|
||||
this.syncToOtherProject();
|
||||
}
|
||||
@ -1991,6 +1999,7 @@ class Texture {
|
||||
'adjust_curves',
|
||||
new MenuSeparator('filters'),
|
||||
'limit_to_palette',
|
||||
'split_rgb_into_layers',
|
||||
'clear_unused_texture_space',
|
||||
new MenuSeparator('transform'),
|
||||
'flip_texture_x',
|
||||
@ -2644,6 +2653,9 @@ Interface.definePanels(function() {
|
||||
|
||||
addEventListeners(document, 'mousemove touchmove', move, {passive: false});
|
||||
addEventListeners(document, 'mouseup touchend', off, {passive: false});
|
||||
},
|
||||
closeContextMenu() {
|
||||
if (Menu.open) Menu.open.hide();
|
||||
}
|
||||
},
|
||||
template: `
|
||||
@ -2651,7 +2663,7 @@ Interface.definePanels(function() {
|
||||
v-bind:class="{ selected: texture.selected, multi_selected: texture.multi_selected, particle: texture.particle, use_as_default: texture.use_as_default}"
|
||||
v-bind:texid="texture.uuid"
|
||||
class="texture"
|
||||
@click.stop="texture.select($event)"
|
||||
@click.stop="closeContextMenu();texture.select($event)"
|
||||
@mousedown="highlightTexture($event)"
|
||||
@mouseup="unhighlightTexture($event)"
|
||||
@dblclick="texture.openMenu($event)"
|
||||
|
@ -44,7 +44,10 @@ const UVEditor = {
|
||||
}
|
||||
|
||||
if (Toolbox.selected.id === 'selection_tool') {
|
||||
if (settings.nearest_rectangle_select.value) {
|
||||
if (BarItems.selection_tool.mode == 'lasso') {
|
||||
result.x = mouse_coords[0]/pixel_size;
|
||||
result.y = mouse_coords[1]/pixel_size;
|
||||
} else if (settings.nearest_rectangle_select.value) {
|
||||
result.x = Math.round(mouse_coords[0]/pixel_size*1);
|
||||
result.y = Math.round(mouse_coords[1]/pixel_size*1);
|
||||
} else {
|
||||
@ -254,40 +257,20 @@ const UVEditor = {
|
||||
}
|
||||
this.vue.selection_outline = outline;
|
||||
},
|
||||
focusOnSelection() {
|
||||
let min_x = UVEditor.getUVWidth();
|
||||
let min_y = UVEditor.getUVHeight();
|
||||
let max_x = 0;
|
||||
let max_y = 0;
|
||||
let elements = UVEditor.getMappableElements();
|
||||
elements.forEach(element => {
|
||||
if (element instanceof Cube && element.box_uv) {
|
||||
let size = element.size(undefined, Format.box_uv_float_size != true)
|
||||
min_x = Math.min(min_x, element.uv_offset[0]);
|
||||
min_y = Math.min(min_y, element.uv_offset[1]);
|
||||
max_x = Math.max(max_x, element.uv_offset[0] + (size[0] + size[2]) * 2);
|
||||
max_y = Math.max(max_y, element.uv_offset[1] + size[1] + size[2]);
|
||||
} else {
|
||||
for (let fkey in element.faces) {
|
||||
if (!UVEditor.getSelectedFaces(element, false).includes(fkey)) continue;
|
||||
let face = element.faces[fkey];
|
||||
if (element instanceof Cube) {
|
||||
min_x = Math.min(min_x, face.uv[0], face.uv[2]);
|
||||
min_y = Math.min(min_y, face.uv[1], face.uv[3]);
|
||||
max_x = Math.max(max_x, face.uv[0], face.uv[2]);
|
||||
max_y = Math.max(max_y, face.uv[1], face.uv[3]);
|
||||
} else if (element instanceof Mesh) {
|
||||
face.vertices.forEach(vkey => {
|
||||
if (!face.uv[vkey]) return;
|
||||
min_x = Math.min(min_x, face.uv[vkey][0]);
|
||||
min_y = Math.min(min_y, face.uv[vkey][1]);
|
||||
max_x = Math.max(max_x, face.uv[vkey][0]);
|
||||
max_y = Math.max(max_y, face.uv[vkey][1]);
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
async focusOnSelection(zoom) {
|
||||
if (zoom instanceof Event) {
|
||||
zoom = BarItems.focus_on_selection.keybind.additionalModifierTriggered(zoom, 'zoom');
|
||||
}
|
||||
let [min_x, min_y, max_x, max_y] = this.vue.getSelectedUVBoundingBox();
|
||||
if (zoom) {
|
||||
let width = (max_x-min_x) / UVEditor.getUVWidth();
|
||||
let height = (max_y-min_y) / UVEditor.getUVHeight();
|
||||
let target_zoom_factor = 1/Math.max(width, height);
|
||||
let target_zoom = Math.clamp(UVEditor.zoom, target_zoom_factor * 0.618, Math.max(1, target_zoom_factor * 0.84));
|
||||
UVEditor.setZoom(target_zoom);
|
||||
await new Promise(Vue.nextTick);
|
||||
}
|
||||
|
||||
let pixel_size = UVEditor.inner_width / UVEditor.vue.uv_resolution[0];
|
||||
let focus = [min_x+max_x, min_y+max_y].map(v => v * 0.5 * pixel_size);
|
||||
let {viewport} = UVEditor.vue.$refs;
|
||||
@ -296,7 +279,7 @@ const UVEditor = {
|
||||
scrollLeft: focus[0] + margin[0] - UVEditor.width / 2,
|
||||
scrollTop: focus[1] + margin[1] - UVEditor.height / 2,
|
||||
}, {
|
||||
duration: 100,
|
||||
duration: zoom ? 0 : 100,
|
||||
complete: () => {
|
||||
UVEditor.updateUVNavigator();
|
||||
}
|
||||
@ -797,7 +780,7 @@ const UVEditor = {
|
||||
if (!box) return;
|
||||
|
||||
let uv_viewport = vue.$refs.viewport;
|
||||
if (!uv_viewport || !Project || Blockbench.hasFlag('switching_project') || !uv_viewport.clientWidth || !uv_viewport.scrollLeft) return;
|
||||
if (!uv_viewport || !Project || Blockbench.hasFlag('switching_project') || !uv_viewport.clientWidth) return;
|
||||
let offset = [
|
||||
(uv_viewport.scrollLeft - vue.width/2) / vue.inner_width,
|
||||
(uv_viewport.scrollTop - vue.height/2) / vue.inner_height
|
||||
@ -1294,7 +1277,6 @@ const UVEditor = {
|
||||
Undo.finishEdit('Toggle cullface')
|
||||
},
|
||||
switchTint(event) {
|
||||
var scope = this;
|
||||
var val = UVEditor.getReferenceFace().tint === -1 ? 0 : -1;
|
||||
|
||||
if (event === 0 || event === false) val = event
|
||||
@ -1690,30 +1672,38 @@ const UVEditor = {
|
||||
SharedActions.add('select_all', {
|
||||
condition: () => Prop.active_panel == 'uv' && Modes.edit,
|
||||
run() {
|
||||
Undo.initSelection();
|
||||
UVEditor.selectAll()
|
||||
Undo.finishSelection('Select all UV');
|
||||
}
|
||||
})
|
||||
SharedActions.add('select_all', {
|
||||
condition: () => Prop.active_panel == 'uv' && Modes.paint && UVEditor.texture,
|
||||
run() {
|
||||
Undo.initSelection({texture_selection: true});
|
||||
UVEditor.texture.selection.setOverride(UVEditor.texture.selection.override == true ? false : true);
|
||||
UVEditor.updateSelectionOutline();
|
||||
Undo.finishSelection('Select all');
|
||||
Interface.removeSuggestedModifierKey('alt', 'modifier_actions.drag_to_duplicate');
|
||||
}
|
||||
})
|
||||
SharedActions.add('unselect_all', {
|
||||
condition: () => Prop.active_panel == 'uv' && Modes.edit,
|
||||
run() {
|
||||
Undo.initSelection();
|
||||
UVEditor.getMappableElements().forEach(element => {
|
||||
UVEditor.getSelectedFaces(element, true).empty();
|
||||
})
|
||||
UVEditor.displayTools();
|
||||
Undo.finishSelection('Unselect all UV');
|
||||
}
|
||||
})
|
||||
SharedActions.add('unselect_all', {
|
||||
condition: () => Prop.active_panel == 'uv' && Modes.paint && UVEditor.texture,
|
||||
run() {
|
||||
Undo.initSelection({texture_selection: true});
|
||||
UVEditor.texture.selection.setOverride(false);
|
||||
Undo.finishSelection('Unselect all');
|
||||
UVEditor.updateSelectionOutline();
|
||||
Interface.removeSuggestedModifierKey('alt', 'modifier_actions.drag_to_duplicate');
|
||||
}
|
||||
@ -1721,6 +1711,7 @@ SharedActions.add('unselect_all', {
|
||||
SharedActions.add('invert_selection', {
|
||||
condition: () => Prop.active_panel == 'uv' && Modes.paint && UVEditor.texture,
|
||||
run() {
|
||||
Undo.initSelection({texture_selection: true});
|
||||
let texture = UVEditor.texture;
|
||||
if (texture.selection.is_custom) {
|
||||
texture.selection.forEachPixel((x, y, val, index) => {
|
||||
@ -1730,6 +1721,7 @@ SharedActions.add('invert_selection', {
|
||||
texture.selection.setOverride(!texture.selection.override);
|
||||
}
|
||||
UVEditor.updateSelectionOutline();
|
||||
Undo.finishSelection('Invert selection');
|
||||
}
|
||||
})
|
||||
|
||||
@ -2398,6 +2390,7 @@ Interface.definePanels(function() {
|
||||
active: false,
|
||||
ellipse: false
|
||||
},
|
||||
texture_selection_polygon: [],
|
||||
|
||||
uv_resolution: [16, 16],
|
||||
elements: [],
|
||||
@ -2997,7 +2990,7 @@ Interface.definePanels(function() {
|
||||
}
|
||||
}
|
||||
},
|
||||
drag({event, onDrag, onEnd, onAbort, snap, uv_grid}) {
|
||||
drag({event, onStart, onDrag, onEnd, onAbort, snap, uv_grid}) {
|
||||
if (event.which == 2 || event.which == 3) return;
|
||||
convertTouchEvent(event);
|
||||
let scope = this;
|
||||
@ -3007,6 +3000,7 @@ Interface.definePanels(function() {
|
||||
let viewport = this.$refs.viewport;
|
||||
let initial_scroll_offset = [viewport.scrollLeft, viewport.scrollTop];
|
||||
let original_snap = snap;
|
||||
let on_start_ran = false;
|
||||
function drag(e1) {
|
||||
convertTouchEvent(e1);
|
||||
let step_x, step_y;
|
||||
@ -3030,6 +3024,10 @@ Interface.definePanels(function() {
|
||||
pos[1] = Math.round((e1.clientY - event.clientY + viewport.scrollTop - initial_scroll_offset[1]) / step_y) / snap;
|
||||
|
||||
if (pos[0] != last_pos[0] || pos[1] != last_pos[1]) {
|
||||
if (onStart && !on_start_ran) {
|
||||
on_start_ran = true;
|
||||
onStart();
|
||||
}
|
||||
let applied_difference = onDrag(pos[0] - last_pos[0], pos[1] - last_pos[1], e1)
|
||||
last_pos[0] += applied_difference[0];
|
||||
last_pos[1] += applied_difference[1];
|
||||
@ -3078,78 +3076,82 @@ Interface.definePanels(function() {
|
||||
})
|
||||
|
||||
let overlay_canvas;
|
||||
if (do_move_uv) {
|
||||
Undo.initEdit({
|
||||
elements,
|
||||
uv_only: true,
|
||||
bitmap: true,
|
||||
textures: [this.texture]
|
||||
});
|
||||
|
||||
overlay_canvas = Interface.createElement('canvas', {class: 'move_texture_with_uv'});
|
||||
let ctx = overlay_canvas.getContext('2d');
|
||||
overlay_canvas.width = this.texture.width;
|
||||
overlay_canvas.height = this.texture.height;
|
||||
|
||||
this.texture.edit(canvas => {
|
||||
let tex_ctx = canvas.getContext('2d');
|
||||
ctx.beginPath();
|
||||
tex_ctx.save();
|
||||
tex_ctx.beginPath();
|
||||
UVEditor.getMappableElements().forEach(el => {
|
||||
if (el instanceof Mesh) {
|
||||
for (var fkey in el.faces) {
|
||||
var face = el.faces[fkey];
|
||||
if (!UVEditor.getSelectedFaces(el).includes(fkey)) continue;
|
||||
if (face.vertices.length <= 2 || face.getTexture() !== this.texture) continue;
|
||||
|
||||
let matrix = face.getOccupationMatrix(true, [0, 0]);
|
||||
for (let x in matrix) {
|
||||
for (let y in matrix[x]) {
|
||||
if (!matrix[x][y]) continue;
|
||||
x = parseInt(x); y = parseInt(y);
|
||||
ctx.rect(x, y, 1, 1);
|
||||
tex_ctx.rect(x, y, 1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let factor_x = this.texture.width / UVEditor.getUVWidth();
|
||||
let factor_y = this.texture.height / UVEditor.getUVHeight();
|
||||
for (var fkey in el.faces) {
|
||||
var face = el.faces[fkey];
|
||||
if (!UVEditor.getSelectedFaces(el).includes(fkey) && !el.box_uv) continue;
|
||||
if (face.getTexture() !== this.texture) continue;
|
||||
|
||||
let rect = face.getBoundingRect();
|
||||
let canvasRect = [
|
||||
Math.floor(rect.ax * factor_x),
|
||||
Math.floor(rect.ay * factor_y),
|
||||
Math.ceil(rect.bx * factor_x) - Math.floor(rect.ax * factor_x),
|
||||
Math.ceil(rect.by * factor_y) - Math.floor(rect.ay * factor_y),
|
||||
]
|
||||
ctx.rect(...canvasRect);
|
||||
tex_ctx.rect(...canvasRect);
|
||||
}
|
||||
}
|
||||
})
|
||||
ctx.clip();
|
||||
ctx.drawImage(this.texture.img, 0, 0);
|
||||
tex_ctx.clip();
|
||||
tex_ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
tex_ctx.restore();
|
||||
}, {no_undo: true})
|
||||
|
||||
UVEditor.vue.$refs.frame.append(overlay_canvas);
|
||||
|
||||
} else {
|
||||
Undo.initEdit({elements, uv_only: true});
|
||||
}
|
||||
let started = false;
|
||||
|
||||
this.drag({
|
||||
event,
|
||||
snap: UVEditor.isBoxUV() ? 1 : undefined,
|
||||
onDrag: (diff_x, diff_y) => {
|
||||
if (!started) {
|
||||
started = true;
|
||||
if (do_move_uv) {
|
||||
Undo.initEdit({
|
||||
elements,
|
||||
uv_only: true,
|
||||
bitmap: true,
|
||||
textures: [this.texture]
|
||||
});
|
||||
|
||||
overlay_canvas = Interface.createElement('canvas', {class: 'move_texture_with_uv'});
|
||||
let ctx = overlay_canvas.getContext('2d');
|
||||
overlay_canvas.width = this.texture.width;
|
||||
overlay_canvas.height = this.texture.height;
|
||||
|
||||
this.texture.edit(canvas => {
|
||||
let tex_ctx = canvas.getContext('2d');
|
||||
ctx.beginPath();
|
||||
tex_ctx.save();
|
||||
tex_ctx.beginPath();
|
||||
UVEditor.getMappableElements().forEach(el => {
|
||||
if (el instanceof Mesh) {
|
||||
for (var fkey in el.faces) {
|
||||
var face = el.faces[fkey];
|
||||
if (!UVEditor.getSelectedFaces(el).includes(fkey)) continue;
|
||||
if (face.vertices.length <= 2 || face.getTexture() !== this.texture) continue;
|
||||
|
||||
let matrix = face.getOccupationMatrix(true, [0, 0]);
|
||||
for (let x in matrix) {
|
||||
for (let y in matrix[x]) {
|
||||
if (!matrix[x][y]) continue;
|
||||
x = parseInt(x); y = parseInt(y);
|
||||
ctx.rect(x, y, 1, 1);
|
||||
tex_ctx.rect(x, y, 1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let factor_x = this.texture.width / UVEditor.getUVWidth();
|
||||
let factor_y = this.texture.height / UVEditor.getUVHeight();
|
||||
for (var fkey in el.faces) {
|
||||
var face = el.faces[fkey];
|
||||
if (!UVEditor.getSelectedFaces(el).includes(fkey) && !el.box_uv) continue;
|
||||
if (face.getTexture() !== this.texture) continue;
|
||||
|
||||
let rect = face.getBoundingRect();
|
||||
let canvasRect = [
|
||||
Math.floor(rect.ax * factor_x),
|
||||
Math.floor(rect.ay * factor_y),
|
||||
Math.ceil(rect.bx * factor_x) - Math.floor(rect.ax * factor_x),
|
||||
Math.ceil(rect.by * factor_y) - Math.floor(rect.ay * factor_y),
|
||||
]
|
||||
ctx.rect(...canvasRect);
|
||||
tex_ctx.rect(...canvasRect);
|
||||
}
|
||||
}
|
||||
})
|
||||
ctx.clip();
|
||||
ctx.drawImage(this.texture.img, 0, 0);
|
||||
tex_ctx.clip();
|
||||
tex_ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
tex_ctx.restore();
|
||||
}, {no_undo: true})
|
||||
|
||||
UVEditor.vue.$refs.frame.append(overlay_canvas);
|
||||
|
||||
} else {
|
||||
Undo.initEdit({elements, uv_only: true});
|
||||
}
|
||||
}
|
||||
elements.forEach(element => {
|
||||
if (element instanceof Mesh) {
|
||||
UVEditor.getSelectedFaces(element).forEach(key => {
|
||||
@ -3229,7 +3231,7 @@ Interface.definePanels(function() {
|
||||
},
|
||||
onAbort: () => {
|
||||
if (do_move_uv) {
|
||||
overlay_canvas.remove();
|
||||
if (overlay_canvas) overlay_canvas.remove();
|
||||
}
|
||||
if (face_key && Mesh.selected[0]) {
|
||||
let selected_faces = UVEditor.getSelectedFaces(element, true);
|
||||
@ -3716,6 +3718,22 @@ Interface.definePanels(function() {
|
||||
];
|
||||
return style ? `${margin[1]}px ${margin[0]}px` : margin;
|
||||
},
|
||||
getTextureSelectionPolygon() {
|
||||
return this.texture_selection_polygon.map((point, i) => {
|
||||
let x = point[0] / this.texture.width * this.inner_width;
|
||||
let y = point[1] / this.texture.width * this.inner_width;
|
||||
return `${i?'L':'M'}${x+1} ${y+1}`;
|
||||
}).join(' ');
|
||||
},
|
||||
isSelectionPolygonClosed() {
|
||||
let polygon = this.texture_selection_polygon;
|
||||
if (polygon.length <= 3) return false;
|
||||
let first = polygon[0];
|
||||
let last = polygon.last()
|
||||
let distance = Math.sqrt(Math.pow(first[0]-last[0], 2) + Math.pow(first[1]-last[1], 2));
|
||||
let radius = Blockbench.isTouch ? 12 : 7;
|
||||
return distance < (radius/UVEditor.getPixelSize());
|
||||
},
|
||||
|
||||
startTextureSelection(x, y, event) {
|
||||
let texture = UVEditor.texture;
|
||||
@ -3727,6 +3745,8 @@ Interface.definePanels(function() {
|
||||
let selection_mode = BarItems.selection_tool.mode;
|
||||
let op_mode = BarItems.selection_tool_operation_mode.value;
|
||||
let selection_rect = this.texture_selection_rect;
|
||||
let selection_polygon = this.texture_selection_polygon;
|
||||
let scope = this;
|
||||
let start_x, start_y, calcrect;
|
||||
let layer = texture.selected_layer;
|
||||
let move_with_selection_tool = Toolbox.selected.id == 'selection_tool' && op_mode == 'create' && settings.move_with_selection_tool.value && (clicked_val || layer?.in_limbo)
|
||||
@ -3735,11 +3755,16 @@ Interface.definePanels(function() {
|
||||
&& !event.target.classList.contains('uv_layer_transform_handles');
|
||||
let initial_offset = layer ? layer.offset.slice() : [0, 0];
|
||||
|
||||
if (!create_selection) {
|
||||
x = Math.round(x);
|
||||
y = Math.round(y);
|
||||
}
|
||||
start_x = x;
|
||||
start_y = y;
|
||||
|
||||
if (create_selection) {
|
||||
if (op_mode == 'create') {
|
||||
Undo.initSelection({texture_selection: true});
|
||||
if (op_mode == 'create' && (selection_mode != 'lasso' || selection_polygon.length == 0)) {
|
||||
texture.selection.clear();
|
||||
}
|
||||
|
||||
@ -3804,7 +3829,10 @@ Interface.definePanels(function() {
|
||||
})
|
||||
}
|
||||
UVEditor.updateSelectionOutline();
|
||||
Undo.finishSelection('Select color');
|
||||
return;
|
||||
} else if (selection_mode == 'lasso') {
|
||||
selection_polygon.push([x, y]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3812,11 +3840,18 @@ Interface.definePanels(function() {
|
||||
let started_movement = false;
|
||||
function drag(e1) {
|
||||
|
||||
var {x, y} = UVEditor.getBrushCoordinates(e1, texture);
|
||||
let {x, y} = UVEditor.getBrushCoordinates(e1, texture);
|
||||
if (!create_selection) {
|
||||
x = Math.round(x);
|
||||
y = Math.round(y);
|
||||
}
|
||||
if (last_x == x && last_y == y) return;
|
||||
last_x = x, last_y = y;
|
||||
|
||||
if (create_selection && selection_mode == 'lasso') {
|
||||
selection_polygon.push([x, y]);
|
||||
|
||||
if (create_selection) {
|
||||
} else if (create_selection) {
|
||||
let start_x_here = start_x;
|
||||
let start_y_here = start_y;
|
||||
if (!settings.nearest_rectangle_select.value) {
|
||||
@ -3869,6 +3904,7 @@ Interface.definePanels(function() {
|
||||
} else {
|
||||
Undo.initEdit({layers: [layer], bitmap: true});
|
||||
}
|
||||
selection_polygon.empty();
|
||||
texture.selection.clear();
|
||||
UVEditor.updateSelectionOutline();
|
||||
}
|
||||
@ -3887,10 +3923,11 @@ Interface.definePanels(function() {
|
||||
Blockbench.setCursorTooltip();
|
||||
|
||||
if (create_selection) {
|
||||
if (!calcrect || selection_rect.width == 0 || selection_rect.height == 0) {
|
||||
if ((!calcrect || selection_rect.width == 0 || selection_rect.height == 0) && selection_mode != 'lasso') {
|
||||
if (!texture.selection.hasSelection()) {
|
||||
texture.selection.clear();
|
||||
UVEditor.updateSelectionOutline();
|
||||
Undo.finishSelection('Unselect texture area');
|
||||
}
|
||||
if (TextureLayer.selected?.in_limbo) {
|
||||
TextureLayer.selected.resolveLimbo();
|
||||
@ -3898,7 +3935,7 @@ Interface.definePanels(function() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (op_mode == 'create') {
|
||||
if (op_mode == 'create' && selection_mode != 'lasso') {
|
||||
texture.selection.clear();
|
||||
}
|
||||
if (selection_mode == 'rectangle') {
|
||||
@ -3949,6 +3986,43 @@ Interface.definePanels(function() {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (selection_mode == 'lasso' && scope.isSelectionPolygonClosed()) {
|
||||
selection_polygon.pop();
|
||||
let min_x = Infinity, min_y = Infinity, max_x = 0, max_y = 0;
|
||||
for (let point of selection_polygon) {
|
||||
min_x = Math.min(point[0], min_x);
|
||||
min_y = Math.min(point[1], min_y);
|
||||
max_x = Math.max(point[0], max_x);
|
||||
max_y = Math.max(point[1], max_y);
|
||||
}
|
||||
min_x = Math.clamp(min_x, 0, UVEditor.texture.img.naturalWidth);
|
||||
min_y = Math.clamp(min_y, 0, UVEditor.texture.img.naturalHeight);
|
||||
max_x = Math.clamp(max_x, 0, UVEditor.texture.img.naturalWidth);
|
||||
max_y = Math.clamp(max_y, 0, UVEditor.texture.img.naturalHeight);
|
||||
for (let x = Math.floor(min_x); x < max_x; x++) {
|
||||
for (let y = Math.floor(min_y); y < max_y; y++) {
|
||||
let is_inside = pointInPolygon([x+0.5, y+0.5], selection_polygon);
|
||||
if (!is_inside) continue;
|
||||
switch (op_mode) {
|
||||
case 'create': case 'add': {
|
||||
texture.selection.set(x, y, 1);
|
||||
break;
|
||||
}
|
||||
case 'subtract': {
|
||||
texture.selection.set(x, y, 0);
|
||||
break;
|
||||
}
|
||||
case 'intersect': {
|
||||
if (texture.selection.get(x, y)) {
|
||||
texture.selection.set(x, y, 2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
selection_polygon.empty();
|
||||
}
|
||||
if (op_mode == 'intersect') {
|
||||
for (let x = 0; x < texture.width; x++) {
|
||||
for (let y = 0; y < texture.height; y++) {
|
||||
@ -3964,8 +4038,10 @@ Interface.definePanels(function() {
|
||||
if (!texture.selection.hasSelection()) {
|
||||
texture.selection.clear();
|
||||
}
|
||||
Undo.finishSelection('Select texture area');
|
||||
UVEditor.updateSelectionOutline();
|
||||
Interface.addSuggestedModifierKey('alt', 'modifier_actions.drag_to_duplicate');
|
||||
|
||||
} else if (!started_movement) {
|
||||
if (TextureLayer.selected?.in_limbo) {
|
||||
TextureLayer.selected.resolveLimbo();
|
||||
@ -4046,8 +4122,8 @@ Interface.definePanels(function() {
|
||||
height: this.toPixels(box[3] - box[1], 0),
|
||||
};
|
||||
},
|
||||
focusOnSelection() {
|
||||
UVEditor.focusOnSelection();
|
||||
focusOnSelection(event) {
|
||||
UVEditor.focusOnSelection(event);
|
||||
},
|
||||
showTransparentFaceText() {
|
||||
return UVEditor.getSelectedFaces(this.mappable_elements[0]).length;
|
||||
@ -4127,28 +4203,42 @@ Interface.definePanels(function() {
|
||||
},
|
||||
toggleFaceTint(key, event) {
|
||||
Undo.initEdit({elements: Cube.selected, uv_only: true})
|
||||
UVEditor.switchTint(event)
|
||||
UVEditor.vue.$forceUpdate();
|
||||
let value = UVEditor.getFirstMappableElement()?.faces[key]?.tint === -1 ? 0 : -1;
|
||||
UVEditor.forCubes(cube => {
|
||||
cube.faces[key].tint = value;
|
||||
})
|
||||
this.$forceUpdate();
|
||||
Undo.finishEdit('Toggle face tint')
|
||||
},
|
||||
changeFaceTint(key, event) {
|
||||
Undo.initEdit({elements: Cube.selected, uv_only: true})
|
||||
UVEditor.setTint(event, parseInt(event.target.value));
|
||||
Undo.finishEdit('Toggle face tint');
|
||||
let value = parseInt(event.target.value);
|
||||
UVEditor.forCubes(cube => {
|
||||
cube.faces[key].tint = value;
|
||||
})
|
||||
Undo.finishEdit('Set face tint');
|
||||
},
|
||||
setCullface(key, value) {
|
||||
Undo.initEdit({elements: Cube.selected, uv_only: true})
|
||||
UVEditor.forCubes(obj => {
|
||||
UVEditor.getSelectedFaces(obj).forEach(face => {
|
||||
obj.faces[face].cullface = value;
|
||||
})
|
||||
if (obj.faces[key]) {
|
||||
obj.faces[key].cullface = value;
|
||||
}
|
||||
})
|
||||
Undo.finishEdit(value ? `Set cullface to ${value}` : 'Disable cullface');
|
||||
},
|
||||
startInputMaterialInstance(event) {
|
||||
Undo.initEdit({elements: Cube.selected, uv_only: true})
|
||||
},
|
||||
endInputMaterialInstance(event) {
|
||||
endInputMaterialInstance(event, fkey) {
|
||||
let value = this.mappable_elements[0]?.faces[fkey]?.material_name;
|
||||
if (typeof value == 'string') {
|
||||
for (let element of this.mappable_elements) {
|
||||
if (element.faces[fkey]) {
|
||||
element.faces[fkey].material_name = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
Undo.finishEdit('Change material instances');
|
||||
},
|
||||
showInfoBox(title, text) {
|
||||
@ -4252,7 +4342,7 @@ Interface.definePanels(function() {
|
||||
title="${tl('uv_editor.face_properties.material_instance')}"
|
||||
v-model="mappable_elements[0].faces[key].material_name"
|
||||
@focus="startInputMaterialInstance($event)"
|
||||
@focusout="endInputMaterialInstance($event)"
|
||||
@focusout="endInputMaterialInstance($event, key)"
|
||||
>
|
||||
</template>
|
||||
</li>
|
||||
@ -4443,17 +4533,22 @@ Interface.definePanels(function() {
|
||||
}">
|
||||
</div>
|
||||
|
||||
<svg id="texture_selection_polygon" v-if="texture_selection_polygon.length">
|
||||
<path :d="getTextureSelectionPolygon()" />
|
||||
<circle :cx="texture_selection_polygon[0][0] / texture.width * inner_width + 1" :cy="texture_selection_polygon[0][1] / texture.width * inner_width + 1" r="7" :class="{closed: isSelectionPolygonClosed()}" />
|
||||
</svg>
|
||||
|
||||
<svg id="uv_selection_outline" v-if="mode == 'paint'">
|
||||
<path :d="selection_outline" />
|
||||
<path :d="selection_outline" class="dash_overlay" />
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div class="uv_navigator" @click="focusOnSelection()" v-show="mode == 'uv'">
|
||||
<div class="uv_navigator" @click="focusOnSelection($event)" v-show="mode == 'uv'">
|
||||
<i class="material-icons icon">navigation</i>
|
||||
</div>
|
||||
|
||||
<div class="uv_transparent_face" v-else-if="showTransparentFaceText()">${tl('uv_editor.transparent_face')}</div>
|
||||
<div class="uv_transparent_face" v-if="showTransparentFaceText()">${tl('uv_editor.transparent_face')}</div>
|
||||
</div>
|
||||
|
||||
<div class="uv_layer_limbo_options" v-if="isTransformingLayer()">
|
||||
|
1059
js/undo.js
@ -111,6 +111,7 @@ Object.defineProperty(Array.prototype, "equals", {enumerable: false});
|
||||
//Array Vector
|
||||
Array.prototype.V3_set = function(x, y, z) {
|
||||
if (x instanceof Array) return this.V3_set(...x);
|
||||
if (x instanceof THREE.Vector3) return this.V3_set(x.x, x.y, x.z);
|
||||
if (y === undefined && z === undefined) z = y = x;
|
||||
this[0] = parseFloat(x)||0;
|
||||
this[1] = parseFloat(y)||0;
|
||||
|
156
js/util/json.js
Normal file
@ -0,0 +1,156 @@
|
||||
function compileJSON(object, options = {}) {
|
||||
let indentation = options.indentation;
|
||||
if (typeof indentation !== 'string') {
|
||||
switch (settings.json_indentation.value) {
|
||||
case 'spaces_4': indentation = ' '; break;
|
||||
case 'spaces_2': indentation = ' '; break;
|
||||
case 'tabs': default: indentation = '\t'; break;
|
||||
}
|
||||
}
|
||||
function newLine(tabs) {
|
||||
if (options.small === true) {return '';}
|
||||
let s = '\n';
|
||||
for (let i = 0; i < tabs; i++) {
|
||||
s += indentation;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
function escape(string) {
|
||||
if (string.includes('\\')) {
|
||||
string = string.replace(/\\/g, '\\\\');
|
||||
}
|
||||
if (string.includes('"')) {
|
||||
string = string.replace(/"/g, '\\"');
|
||||
}
|
||||
if (string.includes('\n')) {
|
||||
string = string.replace(/\n|\r\n/g, '\\n');
|
||||
}
|
||||
if (string.includes('\t')) {
|
||||
string = string.replace(/\t/g, '\\t');
|
||||
}
|
||||
return string;
|
||||
}
|
||||
function handleVar(o, tabs, breaks = true) {
|
||||
var out = ''
|
||||
let type = typeof o;
|
||||
if (type === 'string') {
|
||||
//String
|
||||
out += '"' + escape(o) + '"'
|
||||
} else if (type === 'boolean') {
|
||||
//Boolean
|
||||
out += (o ? 'true' : 'false')
|
||||
} else if (o === null || o === Infinity || o === -Infinity) {
|
||||
//Null
|
||||
out += 'null'
|
||||
} else if (type === 'number') {
|
||||
//Number
|
||||
o = (Math.round(o*100000)/100000).toString()
|
||||
if (o == 'NaN') o = null
|
||||
out += o
|
||||
} else if (o instanceof Array) {
|
||||
//Array
|
||||
let has_content = false
|
||||
let multiline = !!o.find(item => typeof item === 'object');
|
||||
if (!multiline) {
|
||||
let length = 0;
|
||||
o.forEach(item => {
|
||||
length += typeof item === 'string' ? (item.length+4) : 3;
|
||||
});
|
||||
if (length > 140) multiline = true;
|
||||
}
|
||||
out += '['
|
||||
for (var i = 0; i < o.length; i++) {
|
||||
var compiled = handleVar(o[i], tabs+1)
|
||||
if (compiled) {
|
||||
if (has_content) {out += ',' + ((options.small || multiline) ? '' : ' ')}
|
||||
if (multiline) {out += newLine(tabs)}
|
||||
out += compiled
|
||||
has_content = true
|
||||
}
|
||||
}
|
||||
if (multiline) {out += newLine(tabs-1)}
|
||||
out += ']'
|
||||
} else if (type === 'object') {
|
||||
//Object
|
||||
breaks = breaks && o.constructor.name !== 'oneLiner';
|
||||
var has_content = false
|
||||
out += '{'
|
||||
for (var key in o) {
|
||||
if (o.hasOwnProperty(key)) {
|
||||
var compiled = handleVar(o[key], tabs+1, breaks)
|
||||
if (compiled) {
|
||||
if (has_content) {out += ',' + (breaks || options.small?'':' ')}
|
||||
if (breaks) {out += newLine(tabs)}
|
||||
out += '"' + escape(key) + '":' + (options.small === true ? '' : ' ')
|
||||
out += compiled
|
||||
has_content = true
|
||||
}
|
||||
}
|
||||
}
|
||||
if (breaks && has_content) {out += newLine(tabs-1)}
|
||||
out += '}'
|
||||
}
|
||||
return out;
|
||||
}
|
||||
let file = handleVar(object, 1);
|
||||
if ((settings.final_newline.value && options.final_newline != false) || options.final_newline == true) {
|
||||
file += '\n';
|
||||
}
|
||||
return file;
|
||||
}
|
||||
function autoParseJSON(data, feedback) {
|
||||
if (data.substr(0, 4) === '<lz>') {
|
||||
data = LZUTF8.decompress(data.substr(4), {inputEncoding: 'StorageBinaryString'})
|
||||
}
|
||||
if (data.charCodeAt(0) === 0xFEFF) {
|
||||
data = data.substr(1)
|
||||
}
|
||||
try {
|
||||
data = JSON.parse(data)
|
||||
} catch (err1) {
|
||||
data = data.replace(/\/\*[^(\*\/)]*\*\/|\/\/.*/g, '')
|
||||
try {
|
||||
data = JSON.parse(data)
|
||||
} catch (err) {
|
||||
if (feedback === false) return;
|
||||
if (data.match(/\n\r?[><]{7}/)) {
|
||||
Blockbench.showMessageBox({
|
||||
title: 'message.invalid_file.title',
|
||||
icon: 'fab.fa-git-alt',
|
||||
message: 'message.invalid_file.merge_conflict'
|
||||
})
|
||||
return;
|
||||
}
|
||||
let error_part = '';
|
||||
function logErrantPart(whole, start, length) {
|
||||
var line = whole.substr(0, start).match(/\n/gm)
|
||||
line = line ? line.length+1 : 1
|
||||
var result = '';
|
||||
var lines = whole.substr(start, length).split(/\n/gm)
|
||||
lines.forEach((s, i) => {
|
||||
result += `#${line+i} ${s}\n`
|
||||
})
|
||||
error_part = result.substr(0, result.length-1) + ' <-- HERE';
|
||||
console.log(error_part);
|
||||
}
|
||||
console.error(err)
|
||||
var length = err.toString().split('at position ')[1]
|
||||
if (length) {
|
||||
length = parseInt(length)
|
||||
var start = limitNumber(length-32, 0, Infinity)
|
||||
|
||||
logErrantPart(data, start, 1+length-start)
|
||||
} else if (err.toString().includes('Unexpected end of JSON input')) {
|
||||
|
||||
logErrantPart(data, data.length-16, 10)
|
||||
}
|
||||
Blockbench.showMessageBox({
|
||||
translateKey: 'invalid_file',
|
||||
icon: 'error',
|
||||
message: tl('message.invalid_file.message', [err]) + (error_part ? `\n\n\`\`\`\n${error_part}\n\`\`\`` : '')
|
||||
})
|
||||
return;
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
@ -81,6 +81,13 @@ Math.getNextPower = function(num, min) {
|
||||
}
|
||||
return i;
|
||||
}
|
||||
Math.signedPow = function(num, power=2) {
|
||||
if (power % 2 == 0) {
|
||||
return Math.pow(num, power) * Math.sign(num);
|
||||
} else {
|
||||
return Math.pow(num, power);
|
||||
}
|
||||
}
|
||||
Math.snapToValues = function(val, snap_points, epsilon = 12) {
|
||||
let snaps = snap_points.slice().sort((a, b) => {
|
||||
return Math.abs(val-a) - Math.abs(val-b)
|
||||
|
@ -409,8 +409,10 @@ var Merge = {
|
||||
}
|
||||
},
|
||||
molang(obj, source, index) {
|
||||
if (['string', 'number'].includes(typeof source[index])) {
|
||||
obj[index] = source[index];
|
||||
if (typeof source[index] == 'string') {
|
||||
obj[index] = source[index].replace(/-?\d\.\d+e-\d\d/g, '0');
|
||||
} else if (typeof source[index] == 'number') {
|
||||
obj[index] = Math.roundTo(source[index], 9).toString();
|
||||
}
|
||||
},
|
||||
boolean(obj, source, index, validate) {
|
||||
@ -489,6 +491,21 @@ Object.defineProperty(String.prototype, 'hashCode', {
|
||||
return hash;
|
||||
}
|
||||
});
|
||||
function exportMolang(input) {
|
||||
if (!input) return 0;
|
||||
if (typeof input == 'string') {
|
||||
if (!isNaN(input)) {
|
||||
let num = parseFloat(input);
|
||||
return isNaN(num) ? 0 : num;
|
||||
} else {
|
||||
return input.replace(/\n/g, '');
|
||||
}
|
||||
} else if (typeof input == 'number') {
|
||||
return input;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// HTML
|
||||
function isNodeUnderCursor(node, event) {
|
||||
@ -656,6 +673,22 @@ function pointInTriangle(pt, v1, v2, v3) {
|
||||
|
||||
return !(has_neg && has_pos);
|
||||
}
|
||||
function pointInPolygon(point, polygon_points) {
|
||||
// ray-casting algorithm based on
|
||||
// https://wrf.ecse.rpi.edu/Research/Short_Notes/pnpoly.html
|
||||
let x = point[0], y = point[1], vs = polygon_points;
|
||||
|
||||
let inside = false;
|
||||
for (let i = 0, j = vs.length - 1; i < vs.length; j = i++) {
|
||||
let xi = vs[i][0], yi = vs[i][1];
|
||||
let xj = vs[j][0], yj = vs[j][1];
|
||||
|
||||
let intersect = ((yi > y) != (yj > y))
|
||||
&& (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
|
||||
if (intersect) inside = !inside;
|
||||
}
|
||||
return inside;
|
||||
}
|
||||
function lineIntersectsTriangle(l1, l2, v1, v2, v3) {
|
||||
return intersectLines(l1, l2, v1, v2) || intersectLines(l1, l2, v2, v3) || intersectLines(l1, l2, v3, v1);
|
||||
}
|
||||
|
@ -242,7 +242,7 @@ new ValidatorCheck('texture_names', {
|
||||
let characters = used_path.replace(/^#/, '').match(/[^a-z0-9._/\\-]/)
|
||||
if (characters) {
|
||||
this.warn({
|
||||
message: `Texture "${used_path}" contains the following invalid characters: "${characters.join('')}". Valid characters are: a-z0-9._/\\-. Uppercase letters are invalid.`,
|
||||
message: `Texture "${used_path}" contains the following invalid characters: "${characters.join('')}". Valid characters are: a-z0-9._/\\-. Uppercase letters and spaces are invalid.`,
|
||||
buttons: [
|
||||
{
|
||||
name: 'Select Texture',
|
||||
|
@ -20,7 +20,7 @@ function initializeWebApp() {
|
||||
if (location.host == 'blockbench-dev.netlify.app') {
|
||||
let button = $(`<a href="https://www.netlify.com/" style="padding: 10px; color: white; cursor: pointer; text-decoration: none; display: block;" target="_blank" rel="noopener">
|
||||
Hosted by
|
||||
<img src="https://www.blockbench.net/_nuxt/74d4819838c06fa271394f626e8c4b16.svg" height="20px" style="vertical-align: text-top;">
|
||||
<img src="./assets/netlify-full-logo-dark.svg" height="20px" style="vertical-align: text-top;">
|
||||
</div>`);
|
||||
button.insertBefore('#start_files');
|
||||
}
|
||||
|
132
lang/cz.json
@ -164,11 +164,6 @@
|
||||
"layout.font.main": "Hlavní font",
|
||||
"layout.font.headline": "Font nadpisu",
|
||||
"about.version": "Verze:",
|
||||
"about.creator": "Tvůrce:",
|
||||
"about.website": "Webová stránka:",
|
||||
"about.vertex_snap": "Vertexové přichytávání (Vertex Snapping) je založené na a pluginu od SirBeneta",
|
||||
"about.icons": "Balíčky ikon:",
|
||||
"about.libraries": "Knihovny:",
|
||||
"settings.category.general": "Všeobecné",
|
||||
"settings.category.preview": "Přehled",
|
||||
"settings.category.grid": "Mřížka",
|
||||
@ -1220,7 +1215,6 @@
|
||||
"camera_angle.true_isometric_right": "True Isometric Right (30°)",
|
||||
"camera_angle.true_isometric_left": "True Isometric Left (30°)",
|
||||
"menu.help.wiki": "Blockbench Wiki",
|
||||
"about.repository": "Repository:",
|
||||
"settings.update_to_prereleases": "Update to Pre-releases",
|
||||
"settings.update_to_prereleases.desc": "Automatically update to Blockbench beta versions to test new features. Pre-release versions can be unstable, don't enable this option if you rely on Blockbench for work or other important projects.",
|
||||
"data.separator.spacer": "Spacer",
|
||||
@ -1607,7 +1601,7 @@
|
||||
"menu.mirror_painting.global.desc": "Enabled mirror painting on the model in global space",
|
||||
"menu.mirror_painting.local": "Local Symmetry",
|
||||
"menu.mirror_painting.local.desc": "Enable mirror painting in local space for each element",
|
||||
"menu.mirror_painting.texture_frames": "Repeat on Animated Texture Frames",
|
||||
"menu.mirror_painting.texture_frames": "Repeat on Flipbook Frames",
|
||||
"menu.mirror_painting.texture_frames.desc": "Mirror paint strokes to every frame of animated textures",
|
||||
"format.bedrock_block.info.size_limit": "Size total size of a block is limited to 30 pixels in all dimensions. The limit can be off-centered in all directions by 7 pixels from the block center.",
|
||||
"format.bedrock_block.info.textures": "Multiple textures can be applied to different cubes in Blockbench, but require additional setup in the behavior pack to work correctly in-game.",
|
||||
@ -1694,7 +1688,7 @@
|
||||
"settings_profile.confirm_delete": "Are you sure you want to delete this settings profile?",
|
||||
"settings_profile.condition.type.selectable": "Manually Selectable",
|
||||
"settings.interface_mode": "UI Mode",
|
||||
"settings.interface_mode.desc": "Interface mode. Restart Blockbench to apply changes",
|
||||
"settings.interface_mode.desc": "Interface mode",
|
||||
"settings.interface_mode.auto": "Automatic",
|
||||
"settings.interface_mode.desktop": "Desktop",
|
||||
"settings.interface_mode.mobile": "Mobile",
|
||||
@ -1818,7 +1812,6 @@
|
||||
"menu.uv.flip_x": "Mirror X",
|
||||
"menu.uv.flip_y": "Mirror Y",
|
||||
"menu.mirror_painting.enabled": "Enabled",
|
||||
"menu.mirror_painting.configure_texture_center": "Configure Texture Center...",
|
||||
"reference_image.position": "Position",
|
||||
"reference_image.size": "Size",
|
||||
"reference_image.rotation": "Rotation",
|
||||
@ -2022,11 +2015,6 @@
|
||||
"action.save_animation_preset.desc": "Save the selected keyframes as an animation preset",
|
||||
"action.animation_onion_skin": "Animation Onion Skin",
|
||||
"action.animation_onion_skin.desc": "Display an wireframe view of a different frame in the animation for reference",
|
||||
"action.animation_onion_skin.off": "Off",
|
||||
"action.animation_onion_skin.select": "Select",
|
||||
"action.animation_onion_skin.previous": "Previous",
|
||||
"action.animation_onion_skin.next": "Next",
|
||||
"action.animation_onion_skin.previous_next": "Previous + Next",
|
||||
"action.apply_animation_preset": "Apply Animation Preset",
|
||||
"action.apply_animation_preset.desc": "Select from a list of animation presets and apply it to the selected bone",
|
||||
"menu.brush_presets.pixel_perfect": "Pixel-perfect Brush",
|
||||
@ -2040,8 +2028,6 @@
|
||||
"settings.final_newline.desc": "Insert a newline character at the end of exported files",
|
||||
"action.crop_layer_to_selection": "Crop Layer to Selection",
|
||||
"action.edit_mode_uv_overlay.desc": "Display the UV map as an overlay in edit mode",
|
||||
"action.animation_onion_skin_selective": "Selective Onion Skin",
|
||||
"action.animation_onion_skin_selective.desc": "Only display onion skin for the selected part of the model",
|
||||
"menu.image": "Image",
|
||||
"menu.texture.discard_changes": "Discard Changes",
|
||||
"menu.texture.discard_changes.desc": "Discard all unsaved changes and load the latest version from the file",
|
||||
@ -2228,5 +2214,117 @@
|
||||
"dialog.blend_transition_edit.extended": "Extended Graph",
|
||||
"message.screenshot_too_large.title": "Screenshot Resolution Issue",
|
||||
"message.screenshot_too_large.message": "The screenshot could not be rendered successfully. Please try again with a lower resolution or without supersampling.",
|
||||
"message.rename_elements.numbering": "You can use special characters to generate sequential numbers: % to get the index of the element within its group, $ to get the index within the selection."
|
||||
"message.rename_elements.numbering": "You can use special characters to generate sequential numbers: % to get the index of the element within its group, $ to get the index within the selection.",
|
||||
"generic.edit_externally": "Edit Externally",
|
||||
"message.settings_require_restart.title": "Restart Required",
|
||||
"message.settings_require_restart.message": "Some settings will only apply after restarting the program.",
|
||||
"message.settings_require_restart.restart_now": "Restart Now",
|
||||
"message.settings_require_restart.restart_later": "Restart Later",
|
||||
"message.classroom_mode.install_plugin": "Cannot install plugins in Classroom Mode",
|
||||
"dialog.collection.export_path": "Export Path",
|
||||
"dialog.collection.select_all": "Select All",
|
||||
"dialog.collection.select_none": "Select None",
|
||||
"dialog.collection.add_with_filter": "Add with Filter",
|
||||
"dialog.collection.remove": "Remove",
|
||||
"dialog.material_config.title": "Material Config",
|
||||
"dialog.material_config.color_value": "Color Value",
|
||||
"dialog.material_config.mer": "Metal-Emissive-Roughness",
|
||||
"dialog.material_config.mer_value": "MER Value",
|
||||
"dialog.material_config.depth_type": "Depth Type",
|
||||
"dialog.create_texture.disable_mirror_uv": "Disable UV Mirroring",
|
||||
"dialog.create_texture.disable_mirror_uv.desc": "Disable the UV Mirror option in Mirror Modeling to preserve separate UVs for each side of the model",
|
||||
"dialog.create_gif.turn.sync_to_anim_length": "Sync to animation length",
|
||||
"settings.category.controls": "Controls",
|
||||
"settings.classroom_mode": "Classroom Mode",
|
||||
"settings.classroom_mode.desc": "Restricts functionality such as installing plugins and removes links to social media",
|
||||
"settings.antialiasing_bleed_fix": "Fix anti-aliasing bleeding",
|
||||
"settings.antialiasing_bleed_fix.desc": "Fixes texture bleeding when using anti-aliasing. Potentially unsupported on older hardware.",
|
||||
"settings.tone_mapping": "Tone Mapping",
|
||||
"settings.tone_mapping.desc": "Approximation method for displaying high dynamic range on a standard screen for PBR rendering.",
|
||||
"settings.audio_scrubbing": "Timline Scrubbing Audio",
|
||||
"settings.audio_scrubbing.desc": "Play short previews of the audio while scrubbing through time timeline",
|
||||
"settings.viewport_rotate_speed": "Viewport Rotate Speed",
|
||||
"settings.viewport_rotate_speed.desc": "Input sensitivity when rotating in the viewport",
|
||||
"settings.viewport_zoom_speed": "Viewport Zoom Speed",
|
||||
"settings.viewport_zoom_speed.desc": "Input sensitivity when zooming in the viewport",
|
||||
"settings.editor_2d_zoom_speed": "2D Editor Zoom Speed",
|
||||
"settings.editor_2d_zoom_speed.desc": "Input sensitivity when zooming in the UV and 2D paint editor",
|
||||
"category.select": "Select",
|
||||
"action.vertex_snap_mode.rotate": "Rotate",
|
||||
"action.export_image": "Export Image",
|
||||
"action.export_image.desc": "Export your texture as an image file",
|
||||
"action.apply_mirror_modeling": "Apply Mirror Modeling",
|
||||
"action.apply_mirror_modeling.desc": "Apply Mirror Modeling to the selection. All selected elements will be copied and flipped across the X axis.",
|
||||
"action.create_collection": "Create Collection",
|
||||
"action.create_collection.desc": "Create a collection out of the outliner selection",
|
||||
"action.set_collection_content_to_selection": "Set Collection Content to Selected",
|
||||
"action.set_collection_content_to_selection.desc": "Set the selected groups and elements as the content of the collection",
|
||||
"action.add_to_collection": "Add Selected to Collection",
|
||||
"action.add_to_collection.desc": "Add the selected groups and elements to the collection",
|
||||
"action.view_mode.material": "Material Preview",
|
||||
"action.create_material": "Create Material",
|
||||
"action.create_material.desc": "Create a new PBR material out of the selected texture",
|
||||
"action.generate_pbr_map": "Generate PBR Map...",
|
||||
"action.generate_pbr_map.desc": "Generate a PBR map (height map or metalness, emissiveness, roughness) from an existing texture",
|
||||
"menu.tools.main_tools": "Toolbox",
|
||||
"menu.view.panels": "Panels",
|
||||
"menu.texture.pbr_channel": "PBR Channel",
|
||||
"menu.texture.pbr_channel.color": "Color",
|
||||
"menu.texture.pbr_channel.normal": "Normal",
|
||||
"menu.texture.pbr_channel.height": "Height",
|
||||
"menu.texture.pbr_channel.mer": "MER (Metalness-Emissive-Roughness)",
|
||||
"menu.texture.pbr_channel.mer_subsurface": "MER Subsurface",
|
||||
"menu.collection.export_project": "Export Project",
|
||||
"menu.collection.export_as": "Export as \"%0\"",
|
||||
"menu.panel.enable": "Enable",
|
||||
"menu.panel.move_to": "Move To",
|
||||
"menu.panel.move_to.left_bar": "Left Sidebar",
|
||||
"menu.panel.move_to.right_bar": "Right Sidebar",
|
||||
"menu.panel.move_to.top": "Top",
|
||||
"menu.panel.move_to.bottom": "Bottom",
|
||||
"menu.panel.move_to.float": "Float",
|
||||
"menu.panel.move_to.hidden": "Hide",
|
||||
"menu.panel.fold": "Collapse",
|
||||
"menu.mirror_painting.texture_center": "Origin",
|
||||
"menu.mirror_modeling.mirror_uv": "Mirror UV",
|
||||
"menu.animation_onion_skin.frames": "Frames",
|
||||
"menu.animation_onion_skin.select": "Select",
|
||||
"menu.animation_onion_skin.previous": "Previous",
|
||||
"menu.animation_onion_skin.next": "Next",
|
||||
"menu.animation_onion_skin.previous_next": "Previous + Next",
|
||||
"menu.animation_onion_skin.count": "Count",
|
||||
"menu.animation_onion_skin.interval": "Interval",
|
||||
"menu.animation_onion_skin_selective": "Selective Onion Skin",
|
||||
"menu.animation_onion_skin_selective.desc": "Only display onion skin for the selected part of the model",
|
||||
"edit.loop_cut.unit": "Unit",
|
||||
"edit.loop_cut.unit.size_units": "Size Units",
|
||||
"edit.loop_cut.unit.percent": "Percent",
|
||||
"edit.extrude_mesh_selection.direction": "Direction",
|
||||
"edit.extrude_mesh_selection.direction.outwards": "Outwards",
|
||||
"edit.extrude_mesh_selection.direction.average": "Average",
|
||||
"edit.extrude_mesh_selection.even_extend": "Even Extend",
|
||||
"edit.vertex_snap.align": "Align",
|
||||
"edit.vertex_snap.align.longest": "Longest Axis",
|
||||
"edit.vertex_snap.align.direction": "Direction from Pivot",
|
||||
"edit.vertex_snap.align.align_axis": "%0 Axis",
|
||||
"edit.vertex_snap.ignore_axis": "Ignore Axis",
|
||||
"codec.common.format": "Format",
|
||||
"codec.image.quality": "Quality",
|
||||
"panel.collections": "Collections",
|
||||
"modifier_actions.always": "Always Enabled",
|
||||
"modifier_actions.unless": "Unless %0",
|
||||
"settings.undo_selections": "Undo Selection",
|
||||
"settings.undo_selections.desc": "Track selection changes as a step in the undo history",
|
||||
"action.focus_on_selection.zoom": "Zoom to fit",
|
||||
"display.reference.tooting": "Horn Tooting",
|
||||
"settings.selection_tolerance": "Selection Tolerance",
|
||||
"settings.selection_tolerance.desc": "Size of the area that can be clicked to select an edge or vertex",
|
||||
"action.delete.keep_vertices": "Keep Edges/Vertices",
|
||||
"menu.mesh": "Mesh",
|
||||
"dialog.material_config.subsurface": "Subsurface Scattering",
|
||||
"dialog.material_config.subsurface_enabled.desc": "Use the MER map alpha channel for subsurface scattering",
|
||||
"settings.pick_combined_color": "Pick Combined Color",
|
||||
"settings.pick_combined_color.desc": "Pick the combined color of all layers at the respective pixel, instead of the color on the active layer",
|
||||
"action.split_rgb_into_layers": "Split RGB Channels into Layers",
|
||||
"action.split_rgb_into_layers.desc": "Split the texture into additive layers, one for each RGB channel"
|
||||
}
|
130
lang/de.json
@ -114,7 +114,7 @@
|
||||
"dialog.select.title": "Auswahl",
|
||||
"dialog.select.group": "In ausgewählter Gruppe",
|
||||
"dialog.select.name": "Name enthält",
|
||||
"dialog.select.random": "Zufall",
|
||||
"dialog.select.random": "Zufallschance (%)",
|
||||
"dialog.select.select": "Auswählen",
|
||||
"dialog.scale.title": "Modell skalieren",
|
||||
"dialog.scale.axis": "Achse",
|
||||
@ -164,11 +164,6 @@
|
||||
"layout.font.main": "Hauptschriftart",
|
||||
"layout.font.headline": "Überschriftenschriftart",
|
||||
"about.version": "Version: ",
|
||||
"about.creator": "Entwickler: ",
|
||||
"about.website": "Webseite: ",
|
||||
"about.vertex_snap": "Der Eckpunktmagnet basiert auf einem Plugin von SirBenet",
|
||||
"about.icons": "Symbolpakete: ",
|
||||
"about.libraries": "Bibliotheken: ",
|
||||
"settings.category.general": "Allgemein",
|
||||
"settings.category.preview": "Vorschau",
|
||||
"settings.category.grid": "Gitter",
|
||||
@ -1220,7 +1215,6 @@
|
||||
"camera_angle.true_isometric_right": "Isometrisch, rechts (30°)",
|
||||
"camera_angle.true_isometric_left": "Isometrisch, links (30°)",
|
||||
"menu.help.wiki": "Blockbench Wiki",
|
||||
"about.repository": "Repository:",
|
||||
"settings.update_to_prereleases": "Auf Vorabversionen aktualisieren",
|
||||
"settings.update_to_prereleases.desc": "Blockbench automatisch auf die neusten Vorabversionen aktualisieren, um neue Funktionen zu testen. Vorabversionen können Fehler beinhalten, aktiviere diese Funktion nicht, wenn du dich für deine Arbeit auf die einwandfreie Funktion von Blockbench verlassen musst.",
|
||||
"data.separator.spacer": "Abstandhalter",
|
||||
@ -1818,7 +1812,6 @@
|
||||
"menu.uv.flip_x": "X spiegeln",
|
||||
"menu.uv.flip_y": "Y spiegeln",
|
||||
"menu.mirror_painting.enabled": "Aktiviert",
|
||||
"menu.mirror_painting.configure_texture_center": "Zentrum in Textur einstellen ...",
|
||||
"reference_image.position": "Position",
|
||||
"reference_image.size": "Größe",
|
||||
"reference_image.rotation": "Drehung",
|
||||
@ -2022,11 +2015,6 @@
|
||||
"action.save_animation_preset.desc": "Speichere die ausgewählten Keyframes als Animationsvorlage",
|
||||
"action.animation_onion_skin": "Animationszwiebelschalen",
|
||||
"action.animation_onion_skin.desc": "Zeige die Vorschau eines anderen Standbildes der Animation als Gitternetz an",
|
||||
"action.animation_onion_skin.off": "Aus",
|
||||
"action.animation_onion_skin.select": "Auswahl",
|
||||
"action.animation_onion_skin.previous": "Voriges",
|
||||
"action.animation_onion_skin.next": "Nächstes",
|
||||
"action.animation_onion_skin.previous_next": "Voriges + Nächstes",
|
||||
"action.apply_animation_preset": "Animationsvorlage anwenden",
|
||||
"action.apply_animation_preset.desc": "Wähle aus einer Liste von Animationsvorlagen und wende die Vorlage auf den ausgewählten Knochen an",
|
||||
"menu.brush_presets.pixel_perfect": "Pixelgenauer Pinsel",
|
||||
@ -2040,8 +2028,6 @@
|
||||
"settings.final_newline.desc": "Füge einen Zeilenumbruch am Ende von exportierten Dateien an",
|
||||
"action.crop_layer_to_selection": "Ebene auf Auswahl zuschneiden",
|
||||
"action.edit_mode_uv_overlay.desc": "Überlagert die UV-Maps der Elemente im Bearbeitungsmodus",
|
||||
"action.animation_onion_skin_selective": "Zwiebelschalen nur für Auswahl",
|
||||
"action.animation_onion_skin_selective.desc": "Zeige die Zwiebelschalenvorschau nur für den ausgewählten Teil des Modells an",
|
||||
"menu.image": "Bild",
|
||||
"menu.texture.discard_changes": "Änderungen verwerfen",
|
||||
"menu.texture.discard_changes.desc": "Verwerfe alle ungespeicherten Änderungen und lade die neuste Version von der Datei",
|
||||
@ -2228,5 +2214,117 @@
|
||||
"dialog.blend_transition_edit.extended": "Erweiterter Graph",
|
||||
"message.screenshot_too_large.title": "Problem mit der Auflösung",
|
||||
"message.screenshot_too_large.message": "Das Bildschirmfoto konnte nicht korrekt aufgezeichnet werden. Versuche es mit einer geringeren Auflösung oder ohne Supersampling.",
|
||||
"message.rename_elements.numbering": "Verwende Sonderzeichen, um eine Zahlenfolge zu generieren: % wird ersetzt durch den Index des Elements in dessen Gruppe, $ wird ersetzt durch den Index des Elements in der Auswahl."
|
||||
"message.rename_elements.numbering": "Verwende Sonderzeichen, um eine Zahlenfolge zu generieren: % wird ersetzt durch den Index des Elements in dessen Gruppe, $ wird ersetzt durch den Index des Elements in der Auswahl.",
|
||||
"generic.edit_externally": "Extern bearbeiten",
|
||||
"message.settings_require_restart.title": "Neustart erforderlich",
|
||||
"message.settings_require_restart.message": "Einige Einstellungen treten erst nach einem Neustart des Programms in Effekt.",
|
||||
"message.settings_require_restart.restart_now": "Jetzt neu starten",
|
||||
"message.settings_require_restart.restart_later": "Später neu starten",
|
||||
"message.classroom_mode.install_plugin": "Plugins können im Klassenzimmermodus nicht installiert werden",
|
||||
"dialog.collection.export_path": "Exportpfad",
|
||||
"dialog.collection.select_all": "Alle auswählen",
|
||||
"dialog.collection.select_none": "Auswahl aufheben",
|
||||
"dialog.collection.add_with_filter": "Mit Filter hinzufügen",
|
||||
"dialog.collection.remove": "Entfernen",
|
||||
"dialog.material_config.title": "Materialkonfiguration",
|
||||
"dialog.material_config.color_value": "Farbwert",
|
||||
"dialog.material_config.mer": "Metallhaftigkeit-Emissivität-Rauheit",
|
||||
"dialog.material_config.mer_value": "MER Wert",
|
||||
"dialog.material_config.depth_type": "Art der Tiefe",
|
||||
"dialog.create_texture.disable_mirror_uv": "UV Spiegelung deaktivieren",
|
||||
"dialog.create_texture.disable_mirror_uv.desc": "Deaktiviert die UV Spiegelung im Gespiegelten Modellieren, um separate UV Maps auf jeder Seite des Modells zu bewahren",
|
||||
"dialog.create_gif.turn.sync_to_anim_length": "Mit Länge der Animation abstimmen",
|
||||
"settings.category.controls": "Steuerung",
|
||||
"settings.classroom_mode": "Klassenzimmermodus",
|
||||
"settings.classroom_mode.desc": "Schränkt Funktionen wie das Installieren von Plugins ein und entfernt Links zu Sozialen Medien",
|
||||
"settings.antialiasing_bleed_fix": "Kantenglättungsartefakte reduzieren",
|
||||
"settings.antialiasing_bleed_fix.desc": "Vermeidet Artefakte durch das Übertreten von Texturen die durch Kantenglättung entstehen",
|
||||
"settings.tone_mapping": "Tonemapping",
|
||||
"settings.tone_mapping.desc": "Annäherungsmethode für die Darstellung von hohem Dynamikumfang auf einem normalen Bildschirm für PBR Effekte.",
|
||||
"settings.audio_scrubbing": "Audiovorschau bei Timelinenavigation",
|
||||
"settings.audio_scrubbing.desc": "Spielt während des Bewegens auf der Timeline kurze Audioschnipsel zur Vorschau ab",
|
||||
"settings.viewport_rotate_speed": "Rotationsgeschwindigkeit bei Navigation",
|
||||
"settings.viewport_rotate_speed.desc": "Empfindlichkeit der Steuerung zur Drehung bei der Navigation im Vorschaufenster",
|
||||
"settings.viewport_zoom_speed": "Zoomgeschwindigkeit bei Navigation",
|
||||
"settings.viewport_zoom_speed.desc": "Empfindlichkeit der Steuerung zum Zoomen bei der Navigation im Vorschaufenster",
|
||||
"settings.editor_2d_zoom_speed": "2D Editor Zoomgeschwindigkeit",
|
||||
"settings.editor_2d_zoom_speed.desc": "Empfindlichkeit der Steuerung beim Zoomen im UV bzw. 2D Editor",
|
||||
"category.select": "Auswahl",
|
||||
"action.vertex_snap_mode.rotate": "Drehen",
|
||||
"action.export_image": "Bild exportieren",
|
||||
"action.export_image.desc": "Exportiere Texturen als Bilddatei",
|
||||
"action.apply_mirror_modeling": "Gespiegeltes Modellieren anwenden",
|
||||
"action.apply_mirror_modeling.desc": "Gespiegeltes Modellieren auf die ausgewählten Elemente anwenden. Die Elemente werden kopiert und auf die andere Seite der X-Achse gespiegelt.",
|
||||
"action.create_collection": "Sammlung erstellen",
|
||||
"action.create_collection.desc": "Erstelle eine Sammlung aus den ausgewählten Elementen",
|
||||
"action.set_collection_content_to_selection": "Auswahl als Sammlungsinhalt festlegen",
|
||||
"action.set_collection_content_to_selection.desc": "Lege die ausgewählten Gruppen und Elemente als Inhalt der Sammlung fest",
|
||||
"action.add_to_collection": "Auswahl zur Sammlung hinzufügen",
|
||||
"action.add_to_collection.desc": "Füge die ausgewählten Gruppen und Elemente zur Sammlung hinzu",
|
||||
"action.view_mode.material": "Materialvorschau",
|
||||
"action.create_material": "Material erstellen",
|
||||
"action.create_material.desc": "Erstelle ein neues PBR Material aus der ausgewählten Textur",
|
||||
"action.generate_pbr_map": "PBR Map generieren...",
|
||||
"action.generate_pbr_map.desc": "Generiere eine PBR Map (Höhenmap, oder Metallhaftigkeit, Emissivität, Rauheit) aus einer bestehenden Textur",
|
||||
"menu.tools.main_tools": "Werkzeugkiste",
|
||||
"menu.view.panels": "Panele",
|
||||
"menu.texture.pbr_channel": "PBR Kanal",
|
||||
"menu.texture.pbr_channel.color": "Farbe",
|
||||
"menu.texture.pbr_channel.normal": "Normale",
|
||||
"menu.texture.pbr_channel.height": "Höhe",
|
||||
"menu.texture.pbr_channel.mer": "MER (Metall-Emission-Rauheit)",
|
||||
"menu.texture.pbr_channel.mer_subsurface": "MER Verdeckte Lichtstreuung",
|
||||
"menu.collection.export_project": "Projekt exportieren",
|
||||
"menu.collection.export_as": "Exportieren als \"%0\"",
|
||||
"menu.panel.enable": "Aktivieren",
|
||||
"menu.panel.move_to": "Verschieben",
|
||||
"menu.panel.move_to.left_bar": "Linke Seitenleiste",
|
||||
"menu.panel.move_to.right_bar": "Rechte Seitenleiste",
|
||||
"menu.panel.move_to.top": "Oben",
|
||||
"menu.panel.move_to.bottom": "Unten",
|
||||
"menu.panel.move_to.float": "Freischwebend",
|
||||
"menu.panel.move_to.hidden": "Verstecken",
|
||||
"menu.panel.fold": "Einklappen",
|
||||
"menu.mirror_painting.texture_center": "Mittelpunkt",
|
||||
"menu.mirror_modeling.mirror_uv": "UV Spiegeln",
|
||||
"menu.animation_onion_skin.frames": "Standbilder",
|
||||
"menu.animation_onion_skin.select": "Auswahl",
|
||||
"menu.animation_onion_skin.previous": "Voriger Frame",
|
||||
"menu.animation_onion_skin.next": "Nächster Frame",
|
||||
"menu.animation_onion_skin.previous_next": "Voriger + Nächster",
|
||||
"menu.animation_onion_skin.count": "Anzahl",
|
||||
"menu.animation_onion_skin.interval": "Intervall",
|
||||
"menu.animation_onion_skin_selective": "Nur Auswahl",
|
||||
"menu.animation_onion_skin_selective.desc": "Die Zwiebelschalenansicht nur für die ausgewählten Elemente des Modells aktivieren",
|
||||
"edit.loop_cut.unit": "Einheit",
|
||||
"edit.loop_cut.unit.size_units": "Größeneinheit",
|
||||
"edit.loop_cut.unit.percent": "Prozent",
|
||||
"edit.extrude_mesh_selection.direction": "Richtung",
|
||||
"edit.extrude_mesh_selection.direction.outwards": "Nach Außen",
|
||||
"edit.extrude_mesh_selection.direction.average": "Durchschnitt",
|
||||
"edit.extrude_mesh_selection.even_extend": "Gleichmäßig",
|
||||
"edit.vertex_snap.align": "Ausrichtung",
|
||||
"edit.vertex_snap.align.longest": "Längste Achse",
|
||||
"edit.vertex_snap.align.direction": "Richtung vom Angelpunkt",
|
||||
"edit.vertex_snap.align.align_axis": "%0-Achse",
|
||||
"edit.vertex_snap.ignore_axis": "Achse ignorieren",
|
||||
"codec.common.format": "Format",
|
||||
"codec.image.quality": "Qualität",
|
||||
"panel.collections": "Sammlungen",
|
||||
"modifier_actions.always": "Immer aktiv",
|
||||
"modifier_actions.unless": "Immer außer %0",
|
||||
"settings.undo_selections": "Auswahl rückgängig machen",
|
||||
"settings.undo_selections.desc": "Auswahlveränderungen im Bearbeitungsverlauf speichern und bei Bedarf rückgängig machen",
|
||||
"action.focus_on_selection.zoom": "Größe einpassen",
|
||||
"display.reference.tooting": "Bockshorn beim Abspielen",
|
||||
"settings.selection_tolerance": "Auswahltoleranz",
|
||||
"settings.selection_tolerance.desc": "Größe des Bereichs der zur Auswahl eines Eckpunktes oder einer Kante angeklickt werden kann",
|
||||
"action.delete.keep_vertices": "Kanten/Eckpunkte behalten",
|
||||
"menu.mesh": "Masche",
|
||||
"dialog.material_config.subsurface": "Volumenstreuung",
|
||||
"dialog.material_config.subsurface_enabled.desc": "Verwende den Transparenzkanal der MER Map für Volumenstreuung",
|
||||
"settings.pick_combined_color": "Farbkombination auswählen",
|
||||
"settings.pick_combined_color.desc": "Mit der Farbpipette die kombinierte Farbe aller Ebenen auswählen, an Stelle von der Farbe der ausgewählten Ebene",
|
||||
"action.split_rgb_into_layers": "RGB Farbkanäle in Ebenen aufteilen",
|
||||
"action.split_rgb_into_layers.desc": "Teile die Textur in eine additive Ebene pro RGB Farbkanal auf"
|
||||
}
|
28
lang/en.json
@ -221,6 +221,8 @@
|
||||
"status_bar.selection.edges": "%0 Edges",
|
||||
"status_bar.selection.vertices": "%0 Vertices",
|
||||
|
||||
"modifier_actions.always": "Always Enabled",
|
||||
"modifier_actions.unless": "Unless %0",
|
||||
"modifier_actions.resize_both_sides": "Resize in both directions",
|
||||
"modifier_actions.resize_one_side": "Resize in one direction",
|
||||
"modifier_actions.draw_line": "Draw line",
|
||||
@ -519,6 +521,8 @@
|
||||
"dialog.material_config.color_value": "Color Value",
|
||||
"dialog.material_config.mer": "Metal-Emissive-Roughness",
|
||||
"dialog.material_config.mer_value": "MER Value",
|
||||
"dialog.material_config.subsurface": "Subsurface Scattering",
|
||||
"dialog.material_config.subsurface_enabled.desc": "Use the MER map alpha channel for subsurface scattering",
|
||||
"dialog.material_config.depth_type": "Depth Type",
|
||||
|
||||
"dialog.edit_texture.preview": "Preview",
|
||||
@ -678,6 +682,8 @@
|
||||
"dialog.create_texture.resolution.desc": "The height and width of the texture",
|
||||
"dialog.create_texture.pixel_density": "Pixel Density",
|
||||
"dialog.create_texture.pixel_density.desc": "The pixel density of the texture, in pixels per meter. The size of the texture map may differ depending on the amount and size of elements.",
|
||||
"dialog.create_texture.disable_mirror_uv": "Disable UV Mirroring",
|
||||
"dialog.create_texture.disable_mirror_uv.desc": "Disable the UV Mirror option in Mirror Modeling to preserve separate UVs for each side of the model",
|
||||
|
||||
"dialog.mirror_painting_texture_center.middle": "Middle",
|
||||
"dialog.mirror_painting_texture_center.custom": "Custom",
|
||||
@ -945,7 +951,7 @@
|
||||
"settings.antialiasing": "Anti-aliasing",
|
||||
"settings.antialiasing.desc": "Toggle anti-aliasing in the preview",
|
||||
"settings.antialiasing_bleed_fix": "Fix anti-aliasing bleeding",
|
||||
"settings.antialiasing_bleed_fix.desc": "Fixes texture bleeding when using anti-aliasing",
|
||||
"settings.antialiasing_bleed_fix.desc": "Fixes texture bleeding when using anti-aliasing. Potentially unsupported on older hardware.",
|
||||
"settings.render_sides": "Render Sides",
|
||||
"settings.tone_mapping": "Tone Mapping",
|
||||
"settings.tone_mapping.desc": "Approximation method for displaying high dynamic range on a standard screen for PBR rendering.",
|
||||
@ -985,6 +991,8 @@
|
||||
"settings.viewport_zoom_speed.desc": "Input sensitivity when zooming in the viewport",
|
||||
"settings.editor_2d_zoom_speed": "2D Editor Zoom Speed",
|
||||
"settings.editor_2d_zoom_speed.desc": "Input sensitivity when zooming in the UV and 2D paint editor",
|
||||
"settings.selection_tolerance": "Selection Tolerance",
|
||||
"settings.selection_tolerance.desc": "Size of the area that can be clicked to select an edge or vertex",
|
||||
"settings.stretch_linked": "Link Stretching",
|
||||
"settings.stretch_linked.desc": "Stretch the cube in all directions with the same value",
|
||||
"settings.auto_keyframe": "Auto Keyframe",
|
||||
@ -1015,6 +1023,8 @@
|
||||
"settings.ground_plane_double_side": "Ground Plane Double-sided",
|
||||
"settings.ground_plane_double_side.desc": "Make the ground plane visible from below",
|
||||
|
||||
"settings.undo_selections": "Undo Selection",
|
||||
"settings.undo_selections.desc": "Track selection changes as a step in the undo history",
|
||||
"settings.undo_limit": "Undo Limit",
|
||||
"settings.undo_limit.desc": "Number of steps you can undo",
|
||||
"settings.local_move": "Move on Relative Axes",
|
||||
@ -1071,6 +1081,8 @@
|
||||
"settings.color_wheel.desc": "Use the color wheel as the main color picker",
|
||||
"settings.pick_color_opacity": "Pick Color Opacity",
|
||||
"settings.pick_color_opacity.desc": "Pick the color opacity with the Color Picker and set it as brush opacity",
|
||||
"settings.pick_combined_color": "Pick Combined Color",
|
||||
"settings.pick_combined_color.desc": "Pick the combined color of all layers at the respective pixel, instead of the color on the active layer",
|
||||
"settings.brush_cursor_2d": "2D Brush Cursor",
|
||||
"settings.brush_cursor_2d.desc": "Display an outline around the brush in the 2D workspace",
|
||||
"settings.brush_cursor_3d": "3D Brush Cursor",
|
||||
@ -1480,6 +1492,7 @@
|
||||
"action.duplicate.desc": "Duplicates the selected elements or group",
|
||||
"action.delete": "Delete",
|
||||
"action.delete.desc": "Deletes the selected elements or group",
|
||||
"action.delete.keep_vertices": "Keep Edges/Vertices",
|
||||
"action.move_to_group": "Move to Group",
|
||||
"action.move_to_group.desc": "Move the selected elements to a different outliner group",
|
||||
"action.sort_outliner": "Sort Outliner",
|
||||
@ -1650,6 +1663,8 @@
|
||||
"action.adjust_curves.desc": "Adjust the brightness curves of the selected texture",
|
||||
"action.limit_to_palette": "Limit to Palette",
|
||||
"action.limit_to_palette.desc": "Limits the colors of the texture to those in the currently loaded palette",
|
||||
"action.split_rgb_into_layers": "Split RGB Channels into Layers",
|
||||
"action.split_rgb_into_layers.desc": "Split the texture into additive layers, one for each RGB channel",
|
||||
"action.clear_unused_texture_space": "Clear Unused Texture Space",
|
||||
"action.clear_unused_texture_space.desc": "Clear parts of the texture that are not UV-mapped to any elements",
|
||||
"action.flip_texture_x": "Flip Horizontally",
|
||||
@ -1752,6 +1767,7 @@
|
||||
"action.focus_on_selection": "Center View on Selection",
|
||||
"action.focus_on_selection.desc": "Align the camera to face the center of the current selection",
|
||||
"action.focus_on_selection.rotate_only": "Rotate only",
|
||||
"action.focus_on_selection.zoom": "Zoom to fit",
|
||||
|
||||
"action.edit_reference_images": "Edit Reference Images",
|
||||
"action.edit_reference_images.desc": "Turn on reference image mode to add or edit reference images and blueprints",
|
||||
@ -1769,7 +1785,7 @@
|
||||
"action.create_texture_group.desc": "Create a group for your textures",
|
||||
"action.create_material": "Create Material",
|
||||
"action.create_material.desc": "Create a new PBR material out of the selected texture",
|
||||
"action.generate_pbr_map": "Generate PBR Map",
|
||||
"action.generate_pbr_map": "Generate PBR Map...",
|
||||
"action.generate_pbr_map.desc": "Generate a PBR map (height map or metalness, emissiveness, roughness) from an existing texture",
|
||||
"action.append_to_template": "Append Elements to Template...",
|
||||
"action.append_to_template.desc": "Add the currently selected elements to the texture template",
|
||||
@ -2020,6 +2036,7 @@
|
||||
"menu.file": "File",
|
||||
"menu.edit": "Edit",
|
||||
"menu.transform": "Transform",
|
||||
"menu.mesh": "Mesh",
|
||||
"menu.uv": "UV",
|
||||
"menu.texture": "Texture",
|
||||
"menu.image": "Image",
|
||||
@ -2118,7 +2135,7 @@
|
||||
"menu.texture.pbr_channel.normal": "Normal",
|
||||
"menu.texture.pbr_channel.height": "Height",
|
||||
"menu.texture.pbr_channel.mer": "MER (Metalness-Emissive-Roughness)",
|
||||
"menu.texture.pbr_channel.mer_subsurface": "MER Sursurface",
|
||||
"menu.texture.pbr_channel.mer_subsurface": "MER Subsurface",
|
||||
"menu.texture.merge_onto_texture": "Merge Onto Texture Above",
|
||||
"menu.texture.edit": "Edit",
|
||||
"menu.texture.edit_externally": "Edit Externally",
|
||||
@ -2189,6 +2206,8 @@
|
||||
"menu.mirror_painting.texture_center": "Origin",
|
||||
"menu.mirror_painting.texture_frames": "Repeat on Flipbook Frames",
|
||||
"menu.mirror_painting.texture_frames.desc": "Mirror paint strokes to every frame of animated textures",
|
||||
|
||||
"menu.mirror_modeling.mirror_uv": "Mirror UV",
|
||||
|
||||
"menu.image_tiled_view.mirrored": "Mirrored Edges",
|
||||
|
||||
@ -2265,7 +2284,7 @@
|
||||
"edit.vertex_snap.align.longest": "Longest Axis",
|
||||
"edit.vertex_snap.align.direction": "Direction from Pivot",
|
||||
"edit.vertex_snap.align.align_axis": "%0 Axis",
|
||||
"edit.vertex_snap.ignore_axis": "Ignore %0 Axis",
|
||||
"edit.vertex_snap.ignore_axis": "Ignore Axis",
|
||||
|
||||
"web.download_app": "Download App",
|
||||
|
||||
@ -2467,6 +2486,7 @@
|
||||
"display.reference.bow": "Charged Bow",
|
||||
"display.reference.crossbow": "Charged Crossbow",
|
||||
"display.reference.eating": "Eating",
|
||||
"display.reference.tooting": "Horn Tooting",
|
||||
"display.reference.block": "Block",
|
||||
"display.reference.frame": "Item Frame",
|
||||
"display.reference.frame_invisible": "Item Frame (Invisible)",
|
||||
|
476
lang/es.json
@ -14,7 +14,7 @@
|
||||
"data.preview": "Previsualización",
|
||||
"data.toolbar": "Barra de herramientas",
|
||||
"data.image": "Imagen",
|
||||
"keys.ctrl": "Control",
|
||||
"keys.ctrl": "Ctrl",
|
||||
"keys.shift": "Shift",
|
||||
"keys.alt": "Alt",
|
||||
"keys.meta": "CMD",
|
||||
@ -62,7 +62,7 @@
|
||||
"message.unsaved_textures.title": "Texturas sin guardar",
|
||||
"message.unsaved_textures.message": "Tu modelo tiene texturas sin guardar. Asegúrate de guardarlas en la carpeta correcta del paquete de recursos",
|
||||
"message.model_clipping.title": "Módelo muy grande",
|
||||
"message.model_clipping.message": "Tu modelo contiene %0 cubos que son más grandes que el límite de 3x3x3 bloques establecido por Minecraft. Este modelo no funcionará en Minecraft.",
|
||||
"message.model_clipping.message": "Tu modelo contiene %0 cubos que son más grandes que el límite de bloques establecido por Minecraft. Este modelo no funcionará en Minecraft.",
|
||||
"message.loose_texture.title": "Importar Textura",
|
||||
"message.loose_texture.message": "La texture importada no forma parte de un Resource Pack. Minecraft sólo puede cargar texturas dentro de una carpeta de textures en un Resource Pack cargado.",
|
||||
"message.loose_texture.change": "Cambiar directorio",
|
||||
@ -81,9 +81,9 @@
|
||||
"message.image_editor.title": "Selecciona un editor de imágenes",
|
||||
"message.image_editor.file": "Seleccionar archivo...",
|
||||
"message.image_editor.exe": "Seleccionar el ejecutable de un editor de imágenes",
|
||||
"message.display_skin.title": "Mostrar Skin",
|
||||
"message.display_skin.title": "Skin de Minecraft",
|
||||
"message.display_skin.message": "Selecciona un archivo de una skin de tu ordenador o escribe el nombre de un jugador",
|
||||
"message.display_skin.upload": "Subir Skin",
|
||||
"message.display_skin.upload": "Seleccionar Archivo",
|
||||
"message.display_skin.reset": "Restablecer",
|
||||
"message.invalid_plugin": "Archivo de plugin inválido, lee la Consola",
|
||||
"message.load_plugin_app": "¿Quieres permitir a este plugin que haga cambios a tu PC? Carga sólo plugins de personas en las que confíes.",
|
||||
@ -94,7 +94,7 @@
|
||||
"dialog.project.title": "Proyecto",
|
||||
"dialog.project.name": "Nombre de Archivo",
|
||||
"dialog.project.parent": "Modelo Padre",
|
||||
"dialog.project.geoname": "Nombre de la Geometría del Mob",
|
||||
"dialog.project.geoname": "Identificador del Modelo",
|
||||
"dialog.project.ao": "Oclusión Ambiental",
|
||||
"dialog.texture.title": "Textura",
|
||||
"dialog.texture.variable": "Variable",
|
||||
@ -114,7 +114,7 @@
|
||||
"dialog.select.title": "Seleccionar",
|
||||
"dialog.select.group": "En el Grupo Seleccionado",
|
||||
"dialog.select.name": "El Nombre Contiene",
|
||||
"dialog.select.random": "Aleatorio",
|
||||
"dialog.select.random": "Oportunidad Aleatoria (%)",
|
||||
"dialog.select.select": "Seleccionar",
|
||||
"dialog.scale.title": "Reescalar Modelo",
|
||||
"dialog.scale.axis": "Ejes",
|
||||
@ -160,15 +160,10 @@
|
||||
"layout.color.light": "Claro",
|
||||
"layout.color.light.desc": "Texto destacado",
|
||||
"layout.color.accent_text": "Acento del texto",
|
||||
"layout.color.accent_text.desc": "Texto en elementos claros o acentuados",
|
||||
"layout.color.accent_text.desc": "Texto sobre fondos con acento",
|
||||
"layout.font.main": "Fuente principal",
|
||||
"layout.font.headline": "Fuente para títulos",
|
||||
"about.version": "Versión:",
|
||||
"about.creator": "Creador:",
|
||||
"about.website": "Página web:",
|
||||
"about.vertex_snap": "El Imán para Vértices está basado en un plugin hecho por SirBenet",
|
||||
"about.icons": "Paquetes de Iconos:",
|
||||
"about.libraries": "Librerías:",
|
||||
"settings.category.general": "General",
|
||||
"settings.category.preview": "Previsualización",
|
||||
"settings.category.grid": "Cuadrícula",
|
||||
@ -178,28 +173,28 @@
|
||||
"settings.category.dialogs": "Diálogos",
|
||||
"settings.category.export": "Exportar",
|
||||
"settings.language": "Lenguaje",
|
||||
"settings.language.desc": "Lenguaje de la interfaz. Reinicia Blockbench para aplicar los cambios.",
|
||||
"settings.language.desc": "Lenguaje de Interfaz",
|
||||
"settings.backup_interval": "Intervalo de Respaldos",
|
||||
"settings.backup_interval.desc": "Intervalo de los respaldos automáticos en minutos",
|
||||
"settings.origin_size": "Marcador de Pivote",
|
||||
"settings.origin_size.desc": "Tamaño del marcador del punto de pivote",
|
||||
"settings.control_size": "Tamaño del control de los ejes",
|
||||
"settings.control_size.desc": "Tamaño de la herramienta de control de los 3 ejes",
|
||||
"settings.display_skin": "Mostrar Skin",
|
||||
"settings.display_skin.desc": "Skin usada para la referencia del modelo de jugador",
|
||||
"settings.control_size": "Transformar el tamaño del artilugio",
|
||||
"settings.control_size.desc": "Tamaño del artilugio de transformación",
|
||||
"settings.display_skin": "Skin de Minecraft",
|
||||
"settings.display_skin.desc": "Skin usada para la referencia del modelo jugador",
|
||||
"settings.shading": "Sombreado",
|
||||
"settings.shading.desc": "Activar sombreado",
|
||||
"settings.shading.desc": "Habilitar sombreado en vista previa",
|
||||
"settings.texture_fps": "FPS de las Texturas Animadas",
|
||||
"settings.texture_fps.desc": "Cuadros por segundo para texturas animadas",
|
||||
"settings.base_grid": "Cuadrícula Pequeña",
|
||||
"settings.base_grid.desc": "Mostrar cuadrícula y ejes pequeños",
|
||||
"settings.large_grid": "Cuadrícula Grande",
|
||||
"settings.large_grid.desc": "Mostrar cuadrícula de 3x3",
|
||||
"settings.full_grid": "Cuadrícula Muy Grande",
|
||||
"settings.full_grid.desc": "Mostar cuadrícula precisa de 3x3",
|
||||
"settings.large_box": "Caja grande",
|
||||
"settings.large_box.desc": "Mostrar los límites de 3x3x3",
|
||||
"settings.display_grid": "Modo de visualización",
|
||||
"settings.large_grid": "Cuadrícula de bloques",
|
||||
"settings.large_grid.desc": "Mostrar cuadrícula de 16x16 bloques",
|
||||
"settings.full_grid": "Cuadrícula de bloques precisa",
|
||||
"settings.full_grid.desc": "Mostrar cuadrícula de bloques con precisión de píxeles",
|
||||
"settings.large_box": "Caja con límite de tamaño",
|
||||
"settings.large_box.desc": "Mostrar límites de tamaño",
|
||||
"settings.display_grid": "Modo de Visualización Cuadrícula",
|
||||
"settings.display_grid.desc": "Mostrar cuadrícula en el modo de visualización",
|
||||
"settings.undo_limit": "Límite de deshacer",
|
||||
"settings.undo_limit.desc": "Número de acciones que puedes deshacer",
|
||||
@ -214,7 +209,7 @@
|
||||
"settings.create_rename": "Renombrar Nuevo Elemento",
|
||||
"settings.create_rename.desc": "Campo de nombre de enfoque al crear nuevo elemento o grupo",
|
||||
"settings.edit_size": "Resolución de la Cuadrícula",
|
||||
"settings.edit_size.desc": "Resolución de la cuadrícula a la que se engancha el cubo",
|
||||
"settings.edit_size.desc": "Resolución de la cuadrícula a la que se ajustan los elementos",
|
||||
"settings.shift_size": "Resolución de Shift",
|
||||
"settings.shift_size.desc": "Resolución de la cuadrícula al mantener Shift",
|
||||
"settings.ctrl_size": "Resolución de Control",
|
||||
@ -222,9 +217,9 @@
|
||||
"settings.negative_size": "Tamaño Negativo",
|
||||
"settings.negative_size.desc": "Permitir a la herramienta de reescalado usar tamaños negativos",
|
||||
"settings.minifiedout": "Exportación minimizada",
|
||||
"settings.minifiedout.desc": "Escribir el archivo JSON en una sola línea",
|
||||
"settings.minifiedout.desc": "Escribir archivos JSON en una línea",
|
||||
"settings.export_groups": "Exportar Grupos en modelos item/bloque de Java",
|
||||
"settings.export_groups.desc": "Guardar grupos en modelos de bloques",
|
||||
"settings.export_groups.desc": "Guardar grupos en archivos JSON de bloques java o modelos de item",
|
||||
"settings.credit": "Comentario de Créditos",
|
||||
"settings.credit.desc": "Añadir un comentario de créditos a archivos exportados",
|
||||
"settings.default_path": "Directorio por defecto de las texturas de Minecraft",
|
||||
@ -255,13 +250,13 @@
|
||||
"action.slider_brush_softness": "Suavidad",
|
||||
"action.slider_brush_softness.desc": "Suavidad del pincel en porcentaje",
|
||||
"action.uv_slider_pos_x": "Mover Horizontal",
|
||||
"action.uv_slider_pos_x.desc": "Mover la selección del UV de todos los cubos seleccionados horizontalmente",
|
||||
"action.uv_slider_pos_x.desc": "Mover horizontalmente todas las caras UV seleccionadas",
|
||||
"action.uv_slider_pos_y": "Mover Vertical",
|
||||
"action.uv_slider_pos_y.desc": "Mover la selección del UV de todos los cubos seleccionados verticalmente",
|
||||
"action.uv_slider_size_x": "Reescalar Horizontal",
|
||||
"action.uv_slider_size_x.desc": "Reescalar la selección del UV de todos los cubos seleccionados horizontalmente",
|
||||
"action.uv_slider_size_y": "Reescalar Vertical",
|
||||
"action.uv_slider_size_y.desc": "Reescalar la selección del UV de todos los cubos seleccionados verticalmente",
|
||||
"action.uv_slider_pos_y.desc": "Mover verticalmente todas las caras UV seleccionadas",
|
||||
"action.uv_slider_size_x": "Tamaño Horizontal",
|
||||
"action.uv_slider_size_x.desc": "Redimensionar horizontalmente todas las caras UV seleccionadas",
|
||||
"action.uv_slider_size_y": "Tamaño Vertical",
|
||||
"action.uv_slider_size_y.desc": "Redimensionar verticalmente todas las caras UV seleccionadas",
|
||||
"action.vertex_snap_mode": "Modo Imán",
|
||||
"action.vertex_snap_mode.desc": "Seleccionar si el Imán para Vertices mueve los elementos a la posición seleccionada o si los reescala",
|
||||
"action.move_tool": "Mover",
|
||||
@ -269,7 +264,7 @@
|
||||
"action.resize_tool": "Reescalar",
|
||||
"action.resize_tool.desc": "Herramienta para seleccionar y reescalar elementos",
|
||||
"action.brush_tool": "Pincel de pintura",
|
||||
"action.brush_tool.desc": "Herramienta para pintar en texturas bitmap en superficies o en el editor de UV",
|
||||
"action.brush_tool.desc": "Pincel de color para dibujar sobre texturas",
|
||||
"action.vertex_snap_tool": "Imán para Vértices",
|
||||
"action.vertex_snap_tool.desc": "Mover un cubo a otro cubo al conectar 2 vértices",
|
||||
"action.swap_tools": "Cambiar Herramientas",
|
||||
@ -280,14 +275,14 @@
|
||||
"action.open_model.desc": "Abre un archivo de modelo de tu ordenador",
|
||||
"action.extrude_texture": "Textura Extruida",
|
||||
"action.extrude_texture.desc": "General un modelo al extender una textura",
|
||||
"action.export_blockmodel": "Exportar Modelo de Bloque",
|
||||
"action.export_blockmodel.desc": "Exporta un modelo de bloque o de ítem",
|
||||
"action.export_blockmodel": "Exportar modelo de bloque/item",
|
||||
"action.export_blockmodel.desc": "Exportar un modelo de bloque o de item de Minecraft Java Edition",
|
||||
"action.export_optifine_part": "Exportar Parte de Optifine",
|
||||
"action.export_optifine_part.desc": "Exportar una sola parte para un modelo de entidad de OptiFine",
|
||||
"action.export_optifine_full": "Exportar a OptiFine JEM",
|
||||
"action.export_optifine_full.desc": "Exportar un modelo completo de entidad de OptiFine",
|
||||
"action.export_obj": "Exportar Modelo OBJ",
|
||||
"action.export_obj.desc": "Exportar a un modelo Wavefront OBJ para renderizar o motores de juego",
|
||||
"action.export_obj.desc": "Exportar un modelo Wavefront OBJ para su renderización",
|
||||
"action.settings_window": "Ajustes...",
|
||||
"action.settings_window.desc": "Abre la ventana de ajustes de Blockbench",
|
||||
"action.plugins_window": "Plugins...",
|
||||
@ -315,33 +310,33 @@
|
||||
"action.outliner_toggle": "Activar Más Opciones",
|
||||
"action.outliner_toggle.desc": "Cambia los botones para más opciones en el Esquema",
|
||||
"action.duplicate": "Duplicar",
|
||||
"action.duplicate.desc": "Duplica los grupos o cubos seleccionados",
|
||||
"action.duplicate.desc": "Duplica los elementos o el grupo seleccionados",
|
||||
"action.delete": "Borrar",
|
||||
"action.delete.desc": "Borra los grupos o cubos seleccionados",
|
||||
"action.delete.desc": "Elimina los elementos o el grupo seleccionados",
|
||||
"action.sort_outliner": "Ordenar Esquema",
|
||||
"action.sort_outliner.desc": "Ordena el esquema alfabéticamente",
|
||||
"action.select_window": "Seleccionar...",
|
||||
"action.select_window.desc": "Busca y selecciona cubos basados en sus propiedades",
|
||||
"action.select_window.desc": "Busca y seleccionar elementos basados en sus propiedades",
|
||||
"action.invert_selection": "Invertir Selección",
|
||||
"action.invert_selection.desc": "Invierte la selección actual de los cubos",
|
||||
"action.invert_selection.desc": "Invertir la selección actual de elementos",
|
||||
"action.select_all": "Seleccionar Todo",
|
||||
"action.select_all.desc": "Selecciona todos los elementos, caras, vértices, o fotogramas",
|
||||
"action.collapse_groups": "Colapsar Grupos",
|
||||
"action.collapse_groups.desc": "Colapsa todos los grupos",
|
||||
"action.collapse_groups.desc": "Contraer todos los grupos del esquema",
|
||||
"action.scale": "Reescalar...",
|
||||
"action.scale.desc": "Reescala los cubos seleccionados",
|
||||
"action.scale.desc": "Escalar los elementos seleccionados",
|
||||
"action.toggle_visibility": "Cambiar Visibilidad",
|
||||
"action.toggle_visibility.desc": "Cambia el ajuste de visibilidad de los cubos seleccionados.",
|
||||
"action.toggle_visibility.desc": "Cambiar la visibilidad de los elementos seleccionados",
|
||||
"action.toggle_export": "Cambiar Exportación",
|
||||
"action.toggle_export.desc": "Cambia el ajuste de exportación de los cubos seleccionados",
|
||||
"action.toggle_export.desc": "Cambia el ajuste de exportación de los elementos seleccionados",
|
||||
"action.toggle_autouv": "Cambiar Auto UV",
|
||||
"action.toggle_autouv.desc": "Cambia el ajuste de Auto UV de los cubos seleccionados",
|
||||
"action.toggle_autouv.desc": "Cambia el ajuste de Auto UV de los elementos seleccionados",
|
||||
"action.toggle_shade": "Cambiar Sombreado",
|
||||
"action.toggle_shade.desc": "Cambia el ajuste de sombreado de los cubos seleccionados",
|
||||
"action.toggle_shade.desc": "Cambia el ajuste de sombreado de los elementos seleccionados",
|
||||
"action.rename": "Renombrar",
|
||||
"action.rename.desc": "Cambia el nombre de los cubos seleccionados",
|
||||
"action.rename.desc": "Cambia el nombre de los elementos seleccionados",
|
||||
"action.add_display_preset": "Nueva Plantilla",
|
||||
"action.add_display_preset.desc": "Añade una nueva plantilla de ajustes de visualización",
|
||||
"action.add_display_preset.desc": "Añadir un nuevo pre-ajuste de visualización",
|
||||
"action.fullscreen": "Pantalla Completa",
|
||||
"action.fullscreen.desc": "Cambia el modo de pantalla completa",
|
||||
"action.zoom_in": "Hacer zoom",
|
||||
@ -400,8 +395,8 @@
|
||||
"menu.texture.file": "Archivo",
|
||||
"menu.texture.refresh": "Refrescar",
|
||||
"menu.texture.change": "Cambiar Archivo",
|
||||
"menu.texture.folder": "Abrir en Carpeta",
|
||||
"menu.texture.edit": "Editar Externamente",
|
||||
"menu.texture.folder": "Mostrar en el Explorador de archivos",
|
||||
"menu.texture.edit": "Editar",
|
||||
"menu.texture.export": "Guardar Como",
|
||||
"menu.texture.save": "Guardar",
|
||||
"menu.texture.properties": "Propiedades",
|
||||
@ -465,7 +460,7 @@
|
||||
"display.reference.baby_zombie": "Zombie bebé",
|
||||
"display.reference.armor_stand_small": "Armor Stand Pequeño",
|
||||
"display.reference.monitor": "Normal",
|
||||
"display.reference.bow": "Arco",
|
||||
"display.reference.bow": "Arco Cargado",
|
||||
"display.reference.block": "Bloque",
|
||||
"display.reference.frame": "Marco de Ítems",
|
||||
"display.reference.inventory_nine": "3x3",
|
||||
@ -488,7 +483,7 @@
|
||||
"action.change_textures_folder.desc": "Cambia la carpeta que en la que se guardan todas las texturas",
|
||||
"menu.texture.particle": "Usar para Partículas",
|
||||
"message.update_notification.title": "No fue posible Instalar la Actualización",
|
||||
"message.update_notification.message": "Una nueva versión está disponible. ¡Active Actualizaciones Automáticas para actualizar!",
|
||||
"message.update_notification.message": "Una nueva versión de Blockbench está disponible. ¡Active Actualizaciones Automáticas para actualizar!",
|
||||
"message.untextured": "La superficie no tiene una textura",
|
||||
"dialog.toolbar_edit.title": "Personalizar Barra de Herramientas",
|
||||
"keybindings.reset": "Resetear",
|
||||
@ -509,7 +504,7 @@
|
||||
"action.uv_mirror_x.desc": "Invierte el UV de esta cara en el eje X",
|
||||
"action.uv_mirror_y": "Invertir UV en Y",
|
||||
"action.uv_mirror_y.desc": "Invierte el UV de esta cara en el eje Y",
|
||||
"action.uv_transparent": "Cara Transparente",
|
||||
"action.uv_transparent": "Eliminar cara",
|
||||
"action.uv_transparent.desc": "Convierte la cara actual en transparente",
|
||||
"action.uv_reset": "Resetear Cara",
|
||||
"action.uv_reset.desc": "Resetea la cara actual",
|
||||
@ -555,7 +550,7 @@
|
||||
"action.move_right": "Mover Hacia Derecha",
|
||||
"action.move_right.desc": "Mueve los cubos seleccionados hacia la derecha relativo al ángulo actual de la cámara",
|
||||
"action.move_forth": "Mover Hacia Delante",
|
||||
"action.move_forth.desc": "Mueve los cubos seleccionados hacia delante relativo al ángulo actual de la cámara",
|
||||
"action.move_forth.desc": "Mueva los elementos seleccionados hacia adelante en relación con el ángulo actual de la cámara",
|
||||
"action.move_back": "Mover Hacia Atrás",
|
||||
"action.move_back.desc": "Mueve los cubos seleccionados hacia atrás relativo al ángulo actual de la cámara",
|
||||
"layout.color.wireframe": "Estructura",
|
||||
@ -584,7 +579,7 @@
|
||||
"action.delete_keyframes": "Eliminar Fotogramas Clave",
|
||||
"action.delete_keyframes.desc": "Elimina todos los fotogramas clave seleccionados",
|
||||
"menu.animation": "Animación",
|
||||
"menu.animation.loop": "Repetición",
|
||||
"menu.animation.loop": "Modo de bucle",
|
||||
"menu.animation.override": "Sobreescribir",
|
||||
"menu.animation.anim_time_update": "Actualizar Variable",
|
||||
"message.display_skin_model.title": "Modelo de Skin",
|
||||
@ -600,9 +595,9 @@
|
||||
"dialog.create_gif.title": "Grabar GIF",
|
||||
"dialog.create_gif.length": "Duración",
|
||||
"dialog.create_gif.fps": "FPS",
|
||||
"dialog.create_gif.play": "Empezar Animación",
|
||||
"dialog.create_gif.play": "Reproducir Animación",
|
||||
"category.animation": "Animación",
|
||||
"action.record_model_gif": "Grabar GIF",
|
||||
"action.record_model_gif": "Grabar GIF...",
|
||||
"action.record_model_gif.desc": "Graba un GIF animado de este modelo desde este ángulo",
|
||||
"display.mirror": "Invertir",
|
||||
"data.separator": "Separador",
|
||||
@ -616,8 +611,8 @@
|
||||
"mode.paint": "Pintar",
|
||||
"mode.display": "Mostrar",
|
||||
"mode.animate": "Animar",
|
||||
"status_bar.recording_gif": "Grabando GIF",
|
||||
"status_bar.processing_gif": "Procesando GIF",
|
||||
"status_bar.recording_gif": "Grabando",
|
||||
"status_bar.processing_gif": "Procesando",
|
||||
"settings.backup_retain": "Mantenimiento de Respaldos",
|
||||
"settings.backup_retain.desc": "Ajustar cuanto tiempo Blockbench mantiene respaldos viejos en días",
|
||||
"action.rotate_tool": "Rotar",
|
||||
@ -636,7 +631,7 @@
|
||||
"menu.preview.perspective.reset": "Resetear Cámara",
|
||||
"action.fill_mode": "Modo de Llenado",
|
||||
"action.fill_mode.face": "Cara",
|
||||
"action.fill_mode.color": "Color",
|
||||
"action.fill_mode.color": "Colores",
|
||||
"action.toggle_mirror_uv": "Invertir UV",
|
||||
"action.toggle_mirror_uv.desc": "Activa el invertido de UV en el eje X de los cubos seleccionados",
|
||||
"menu.texture.blank": "Aplicar a Caras sin Textura",
|
||||
@ -678,7 +673,7 @@
|
||||
"action.element_colors.desc": "Muestra los colores de cubo en el borde",
|
||||
"texture.error.file": "Archivo no encontrado",
|
||||
"texture.error.parent": "Archivo de textura proveído por el modelo padre",
|
||||
"message.recover_backup.title": "Recuperar Modelo",
|
||||
"message.recover_backup.title": "Recuperar Modelos",
|
||||
"message.recover_backup.message": "Blockbench fue cerrado sin guardar. ¿Quieres recuperar el modelo?",
|
||||
"message.invalid_session.title": "Token de Sesión Inválido",
|
||||
"message.invalid_session.message": "La sesión a la que estas intentando entrar ha expirado o el token proveído es inválido.",
|
||||
@ -723,7 +718,7 @@
|
||||
"format.java_block": "Item/Bloque de Java",
|
||||
"format.java_block.desc": "Modelo de bloque o item para la edición Java.",
|
||||
"format.bedrock": "Entidad de Bedrock",
|
||||
"format.bedrock.desc": "Modelo para la edición Bedrock.",
|
||||
"format.bedrock.desc": "Modelo de Minecraft Bedrock Edition para entidades y objetos acoplables",
|
||||
"format.bedrock_old": "Modelo Antiguo de Bedrock",
|
||||
"format.bedrock_old.desc": "Modelo de entidad de las ediciones de Bedrock anteriores a 1.12",
|
||||
"format.modded_entity": "Entidad de Mod",
|
||||
@ -767,7 +762,7 @@
|
||||
"action.remove_blank_faces.desc": "Elimina todas las caras sin textura de la selección",
|
||||
"web.download_app": "Descargar Aplicación",
|
||||
"uv_editor.turned": "Mapeado Girado",
|
||||
"display.reference.crossbow": "Ballesta",
|
||||
"display.reference.crossbow": "Ballesta Cargada",
|
||||
"dialog.settings.search_results": "Resultados de Búsqueda",
|
||||
"settings.animation_snap": "Imán de Animación",
|
||||
"settings.animation_snap.desc": "Intervalo del imán para fotogramas clave en la línea de tiempo de la animación en pasos por segundo. Esto puede ser modificado para cada animación. El valor por defecto es 24.",
|
||||
@ -806,9 +801,9 @@
|
||||
"message.removed_faces": "Eliminadas %0 caras",
|
||||
"dialog.sketchfab_uploader.draft": "Borrador",
|
||||
"action.slider_pos": "Mover %0",
|
||||
"action.slider_pos.desc": "Mover cubos en el eje %0",
|
||||
"action.slider_pos.desc": "Mover elementos en el eje %0",
|
||||
"action.slider_size": "Tamaño %0",
|
||||
"action.slider_size.desc": "Redimensionar cubos en el eje %0",
|
||||
"action.slider_size.desc": "Redimensionar elementos en el eje %0",
|
||||
"action.slider_rotation": "Rotar %0",
|
||||
"action.slider_rotation.desc": "Rotar cubos en el eje %0",
|
||||
"action.slider_origin": "Pivote %0",
|
||||
@ -890,7 +885,7 @@
|
||||
"format.skin.desc": "Editar las skins de entidades y jugadores",
|
||||
"message.sketchfab.setup_guide": "¿Quieres aprender a preparar modelos en Sketchfab? Lee %0",
|
||||
"dialog.skin.title": "Crear Skin",
|
||||
"dialog.skin.model": "Skin",
|
||||
"dialog.skin.model": "Modelo",
|
||||
"dialog.skin.texture": "Textura (Opcional)",
|
||||
"action.toggle_skin_layer": "Cambiar Capa de Skin",
|
||||
"action.toggle_skin_layer.desc": "Cambia la capa del gorro y de la ropa en el modelo de skin",
|
||||
@ -1075,7 +1070,7 @@
|
||||
"settings.motion_trails": "Senderos de movimiento",
|
||||
"settings.motion_trails.desc": "Mostrar senderos de movimiento en el editor de animación",
|
||||
"settings.antialiasing": "Anti-aliasing",
|
||||
"settings.antialiasing.desc": "Modificar el anti-aliassing en la vista previa. Debes reiniciar Blockbench para aplicar los cambios",
|
||||
"settings.antialiasing.desc": "Alternar el anti-aliasing en la vista previa",
|
||||
"action.timeline_frame_back": "Avanza un fotograma atras",
|
||||
"action.timeline_frame_forth": "Avanza un fotograma adelante",
|
||||
"panel.bone.ik": "Cinemáticas inversas (Experimental)",
|
||||
@ -1083,7 +1078,7 @@
|
||||
"settings.particle_tick_rate.desc": "Efectos de partículas en la tasa de tic por segundo. El defecto es 30",
|
||||
"action.lock_motion_trail": "Bloquear el rastro de movimiento",
|
||||
"action.lock_motion_trail.desc": "Bloquear el rastro de movimiento en el grupo seleccionado",
|
||||
"menu.animation_file.unload": "Descargar archivo de animación",
|
||||
"menu.animation_file.unload": "Descargar archivo",
|
||||
"data.null_object": "Objeto Nulo",
|
||||
"status_bar.toggle_sidebar": "Mostrarbarralateral",
|
||||
"message.load_plugin_failed.title": "Falló al cargar el plugin",
|
||||
@ -1103,7 +1098,7 @@
|
||||
"settings.ctrl_shift_size": "Resolución de Control + Shift",
|
||||
"settings.ctrl_shift_size.desc": "Resolución del mapa mientras mantienes presionado control y shift",
|
||||
"settings.hardware_acceleration": "Aceleración de Hardware",
|
||||
"settings.hardware_acceleration.desc": "Subcontrato en tareas de renderizado a la tarjeta gráfica. Reinicia Blockbench para aplicar los cambios",
|
||||
"settings.hardware_acceleration.desc": "Subcontratar tareas de renderizado a la tarjeta gráfica",
|
||||
"action.explode_skin_model": "Expandir Modelo de Skin",
|
||||
"action.explode_skin_model.desc": "Alternar a una vista de explosión que le permite editar caras cubiertas",
|
||||
"action.export_minecraft_skin": "Exportar Skin de Minecraft",
|
||||
@ -1180,7 +1175,7 @@
|
||||
"action.load_keymap.cinema4d.desc": "Mapa de Teclas para usuarios que están familiarizados con los controles de Cinema 4D",
|
||||
"action.load_keymap.maya.desc": "Mapa de Teclas para usuarios que estan familiarizados con los controles de Autodek Maya",
|
||||
"action.import_keymap": "Importar Mapa de Teclas",
|
||||
"action.import_keymap.desc": "Importar atajos de teclado como un archivo .bbkeymap",
|
||||
"action.import_keymap.desc": "Importar atajos de teclado a un archivo .bbkeymap",
|
||||
"action.export_keymap": "Exportar Mapa de Teclas",
|
||||
"action.export_keymap.desc": "Exportar los actuales atajos de teclado como un archivo .bbkeymap",
|
||||
"action.edit_history": "Editar Historial...",
|
||||
@ -1220,7 +1215,6 @@
|
||||
"camera_angle.true_isometric_right": "Isométrico correcto derecho (30 grados)",
|
||||
"camera_angle.true_isometric_left": "Isométrico correcto izquierdo (30 grados)",
|
||||
"menu.help.wiki": "Wiki de BlockBench",
|
||||
"about.repository": "Repositorio:",
|
||||
"settings.update_to_prereleases": "Actualizar a una versión Preliminar",
|
||||
"settings.update_to_prereleases.desc": "Actualiza automáticamente a una versión beta de Blockbench para probar nuevas características. Las versiones Preliminares pueden ser inestables, no actives esta opción si confía en Blockbench para el trabajo u otros proyectos importantes.",
|
||||
"data.separator.spacer": "Espaciador",
|
||||
@ -1235,7 +1229,7 @@
|
||||
"message.invalid_link": "Link del Modelo Inválido o Expirado",
|
||||
"message.default_textures.current": "Ruta actual",
|
||||
"message.update_after_restart": "La actualización será instalada después del próximo reinicio",
|
||||
"message.copy_paste_tool_viewport": "Este objeto solo puede usarse en el panel UV",
|
||||
"message.copy_paste_tool_viewport": "Esta herramienta sólo puede utilizarse en el editor 2D",
|
||||
"dialog.project.shadow_size": "Tamaño de la Sombra",
|
||||
"dialog.find_replace.target": "Objetivo",
|
||||
"dialog.find_replace.target.element_names": "Nombres de los Elementos",
|
||||
@ -1252,22 +1246,22 @@
|
||||
"dialog.add_primitive.shape.cylinder": "Cilindro",
|
||||
"dialog.add_primitive.shape.sphere": "Esfera",
|
||||
"dialog.add_primitive.shape.torus": "Toro",
|
||||
"dialog.add_primitive.shape.cube": "Cubo",
|
||||
"dialog.add_primitive.shape.cube": "Cuboide",
|
||||
"dialog.add_primitive.shape.pyramid": "Pirámide",
|
||||
"dialog.add_primitive.diameter": "Diámetro",
|
||||
"dialog.add_primitive.height": "Peso",
|
||||
"dialog.add_primitive.sides": "Lados",
|
||||
"dialog.add_primitive.minor_diameter": "Espesor",
|
||||
"dialog.add_primitive.minor_sides": "Lador Menores",
|
||||
"dialog.create_texture.combine_polys": "Combinar Caras",
|
||||
"dialog.create_texture.combine_polys.desc": "Combinar las caras conectadas en una en la sección UV",
|
||||
"dialog.create_texture.combine_polys": "Combinar islas",
|
||||
"dialog.create_texture.combine_polys.desc": "Combinar caras en islas UV conectadas",
|
||||
"dialog.model_stats.meshes": "Mallas",
|
||||
"dialog.export_private_settings.omit": "Salir",
|
||||
"layout.select": "Seleccionar",
|
||||
"layout.options": "Opciones",
|
||||
"layout.color": "Escama de color",
|
||||
"layout.documentation": "Documentación",
|
||||
"layout.color.bright_ui_text": "Interfaz clara",
|
||||
"layout.color.bright_ui_text": "Texto de interfaz brillante",
|
||||
"layout.color.bright_ui_text.desc": "Texto en fondos claros",
|
||||
"layout.name": "Nombre",
|
||||
"layout.author": "Autor",
|
||||
@ -1339,8 +1333,8 @@
|
||||
"action.split_mesh": "Separar mallas",
|
||||
"action.split_mesh.desc": "Separar las mallas seleccionadas en una nueva malla",
|
||||
"action.merge_vertices": "Combinar vértices",
|
||||
"action.merge_vertices.desc": "Combinar los vértices seleccionados en la posición del primer verted seleccionado",
|
||||
"action.view_mode.normal": "Cara normal",
|
||||
"action.merge_vertices.desc": "Fusionar los vértices seleccionados en la posición del primer vértice seleccionado",
|
||||
"action.view_mode.normal": "Orientación de la cara",
|
||||
"action.snap_uv_to_pixels": "Cambiar UV a píxeles",
|
||||
"action.snap_uv_to_pixels.desc": "Ajusta los vértices UV seleccionados a la cuadrícula de píxeles",
|
||||
"menu.file.import.import_open_project": "Importar proyecto abierto",
|
||||
@ -1436,27 +1430,27 @@
|
||||
"panel.skin_pose.jumping": "Saltando",
|
||||
"panel.skin_pose.aiming": "Apuntando",
|
||||
"edit.loop_cut.direction": "Dirección",
|
||||
"data.texture_mesh": "Texture Mesh",
|
||||
"generic.left": "Left",
|
||||
"generic.right": "Right",
|
||||
"mode.start.quick_setup": "Quick Setup",
|
||||
"data.texture_mesh": "Malla de textura",
|
||||
"generic.left": "Izquierda",
|
||||
"generic.right": "Derecha",
|
||||
"mode.start.quick_setup": "Armado rápido",
|
||||
"mode.start.keymap": "Keymap",
|
||||
"mode.start.quick_setup.more_themes": "More...",
|
||||
"dialog.resize_texture.animation_frames": "Animation Frames",
|
||||
"dialog.export_emission_map.title": "Export Emission Map",
|
||||
"dialog.export_emission_map.format": "Format",
|
||||
"dialog.export_emission_map.format.luminance": "Luminance",
|
||||
"dialog.export_emission_map.format.luminance_inverted": "Luminance Inverted",
|
||||
"dialog.export_emission_map.format.colors": "Colors",
|
||||
"mode.start.quick_setup.more_themes": "Más...",
|
||||
"dialog.resize_texture.animation_frames": "Fotograma de animación",
|
||||
"dialog.export_emission_map.title": "Exportar Emission Map",
|
||||
"dialog.export_emission_map.format": "Formato",
|
||||
"dialog.export_emission_map.format.luminance": "Luminiscencia",
|
||||
"dialog.export_emission_map.format.luminance_inverted": "Luminiscencia invertida",
|
||||
"dialog.export_emission_map.format.colors": "Colores",
|
||||
"dialog.export_emission_map.threshold": "Transparency Threshold",
|
||||
"dialog.export_emission_map.round_up": "Round Up to %0 x %1",
|
||||
"dialog.export_emission_map.flip_y": "Invertir Eje Y",
|
||||
"dialog.select.type": "Element Type",
|
||||
"dialog.select.type": "Tipo de elemento",
|
||||
"dialog.create_texture.max_edge_angle": "Edge Angle Threshold",
|
||||
"dialog.create_texture.max_edge_angle.desc": "The maximum angle between two faces at which they will still be combined",
|
||||
"dialog.create_texture.max_island_angle": "Island Angle Threshold",
|
||||
"dialog.create_texture.max_island_angle.desc": "The maximum angle that can be combined into the same UV island",
|
||||
"settings.mobile_panel_side": "Mobile Panel Side",
|
||||
"settings.mobile_panel_side": "Panel lateral móvil",
|
||||
"settings.mobile_panel_side.desc": "Select which side of the screen panels are displayed on when using Blockbench on in landscape orientation",
|
||||
"settings.obj_face_export_mode": "OBJ Face Export Mode",
|
||||
"settings.obj_face_export_mode.desc": "Choose to let the OBJ exporter convert all faces into tris or quads",
|
||||
@ -1472,22 +1466,22 @@
|
||||
"action.select_seam": "Select UV Seam",
|
||||
"action.select_seam.desc": "Select the UV seam mode for the selected edges",
|
||||
"action.select_seam.auto": "Auto",
|
||||
"action.select_seam.join": "Join",
|
||||
"action.select_seam.divide": "Divide",
|
||||
"action.select_seam.join": "Unir",
|
||||
"action.select_seam.divide": "Dividir",
|
||||
"action.adjust_brightness_contrast": "Ajustar Brillo y Contraste",
|
||||
"action.adjust_brightness_contrast.desc": "Ajusta el brillo y contraste de la textura seleccionada",
|
||||
"action.adjust_saturation_hue": "Adjust Saturation & Hue...",
|
||||
"action.adjust_saturation_hue.desc": "Adjust the saturation and hue of the selected texture",
|
||||
"action.adjust_saturation_hue": "Ajustar saturación y hue...",
|
||||
"action.adjust_saturation_hue.desc": "Ajustar la saturación y el hue de la textura seleccionada",
|
||||
"action.invert_colors": "Invertir Colores",
|
||||
"action.invert_colors.desc": "Invert all colors of the selected texture",
|
||||
"action.adjust_curves": "Adjust Curves...",
|
||||
"action.adjust_curves.desc": "Adjust the brightness curves of the selected texture",
|
||||
"action.invert_colors.desc": "Invertir todos los colores de la textura seleccionada",
|
||||
"action.adjust_curves": "Ajustar curvas...",
|
||||
"action.adjust_curves.desc": "Ajustar las curvas de brillo de la textura seleccionada",
|
||||
"action.flip_texture_x": "Invertir Textura Horizontalmente",
|
||||
"action.flip_texture_y": "Invertir Textura Verticalmente",
|
||||
"action.resize_texture": "Reescalar Textura...",
|
||||
"action.view_mode.uv": "UV Preview",
|
||||
"action.append_to_template": "Append Elements to Template...",
|
||||
"action.append_to_template.desc": "Add the currently selected elements to the texture template",
|
||||
"action.append_to_template": "Añadir elementos a la plantilla...",
|
||||
"action.append_to_template.desc": "Añadir los elementos actualmente seleccionados a la plantilla de textura",
|
||||
"action.move_texture_with_uv": "Mover textura con UV",
|
||||
"action.move_texture_with_uv.desc": "Mueve la textura de la cara al arrastrar las caras UV",
|
||||
"action.timeline_setups": "Configuraciones de Líneas de Tiempo",
|
||||
@ -1496,18 +1490,18 @@
|
||||
"menu.texture": "Textura",
|
||||
"menu.texture.render_mode.default": "Por Defecto",
|
||||
"menu.texture.merge_onto_texture": "Combinar con la Textura Encima",
|
||||
"menu.animation.unload": "Unload",
|
||||
"menu.animation.unload": "Descargar",
|
||||
"panel.timeline": "Línea de Tiempo",
|
||||
"action.pan_tool": "Pan Tool",
|
||||
"action.pan_tool.desc": "Tool to navigate in the viewport and the texture editor",
|
||||
"mode.start.recent.favorite": "Señalar como Favorito",
|
||||
"mode.start.info": "Info",
|
||||
"mode.start.info": "Información",
|
||||
"mode.start.target": "Objetivo",
|
||||
"mode.start.start": "Start",
|
||||
"mode.start.start": "Iniciar",
|
||||
"mode.start.create_new": "Crear Nuevo Modelo",
|
||||
"mode.start.format.informations": "Importante:",
|
||||
"mode.start.format.resources": "Recursos:",
|
||||
"format.free.info.meshes": "In this format, you can create low poly models using cubes and custom shaped meshes.",
|
||||
"format.free.info.meshes": "En este formato, puedes crear modelos low poly usando cubos y mallas con formas personalizadas.",
|
||||
"format.free.info.limitation": "Estos modelos no pueden ser usados en juegos que requieran formatos especializados, como Minecraft.",
|
||||
"format.skin.info.skin": "Este formato está diseñado para crear skins de Minecraft y texturas para entidades.",
|
||||
"format.skin.info.model": "Estos modelos no pueden ser modificados. Para realizar cambios, primero convierta a un formato diferente con **Archivo** > **Convertir Projecto**.",
|
||||
@ -1518,23 +1512,23 @@
|
||||
"format.bedrock_block": "Bloque de Bedrock",
|
||||
"format.bedrock_block.desc": "Modelo de Bloque para Minecraft Bedrock",
|
||||
"format.modded_entity.info.integer_size": "El tamaño de cubos esta limitado a integrales.",
|
||||
"format.modded_entity.info.format": "Models are written in Java code instead of dedicated data structures like all other Blockbench export formats.",
|
||||
"format.modded_entity.info.format": "Los modelos son escritos en código java en vez de estructuras de datos como el resto de formatos de exportación de Blockbench.",
|
||||
"format.optifine_entity.info.optifine_required": "Usuarios sin OptiFine instalado no podrán ver el modelo.",
|
||||
"format.optifine_entity.info.pivots": "Los pivotes de los huesos están bloqueados, es buena idea dejarlos sin modificar.",
|
||||
"format_category.low_poly": "Low-Poly",
|
||||
"format_category.minecraft": "Minecraft",
|
||||
"format_category.other": "Other",
|
||||
"format_category.loaders": "Loaders",
|
||||
"format_category.other": "Otros",
|
||||
"format_category.loaders": "Cargadores",
|
||||
"message.recover_backup.recover": "Recuperar",
|
||||
"message.invalid_characters.title": "Invalid Path",
|
||||
"message.invalid_characters.title": "Trayectoria invalida",
|
||||
"message.invalid_characters.message": "La ruta del archivo importado contiene caracteres inválidos, letras mayúsculas, o espacios. Los caracteres permitidos son: %0",
|
||||
"dialog.share_model.thumbnail": "Miniatura",
|
||||
"dialog.skin.high_res_texture": "Please note that skins with the selected resolution will not work as regular Minecraft skins. Select a lower resolution.",
|
||||
"settings.allow_display_slot_mirror": "Allow Display Slot Mirroring",
|
||||
"settings.allow_display_slot_mirror.desc": "Allow Display slots for Java item models to be mirrored. WARNING: This only works in Minecraft 1.14 or earlier or in special cases.",
|
||||
"action.switch_tabs": "Switch Tabs",
|
||||
"action.switch_tabs": "Intercambiar pestañas",
|
||||
"action.switch_tabs.desc": "Cycle between opened tabs. Hold shift to cycle in the opposite direction.",
|
||||
"action.unselect_all": "Unselect All",
|
||||
"action.unselect_all": "Deseleccionar todo",
|
||||
"action.unselect_all.desc": "Unselect all elements, faces, vertices, or keyframes",
|
||||
"action.save_palette": "Guardar Paleta...",
|
||||
"action.save_palette.desc": "Guarda la paleta de colores actual dentro de Blockbench para uso posterior",
|
||||
@ -1565,7 +1559,7 @@
|
||||
"settings.default_cube_size.desc": "Cambia el tamaño predeterminado del cubo al crear un nuevo cubo",
|
||||
"settings.uniform_keyframe": "Reescalar Fotogramas Uniformemente",
|
||||
"settings.uniform_keyframe.desc": "Establece los fotogramas clave a reescalado uniforme por defecto",
|
||||
"settings.nearest_rectangle_select": "Rectangle Selection: Nearest Edge",
|
||||
"settings.nearest_rectangle_select": "Selección de rectángulo: Borde mas cercano",
|
||||
"settings.nearest_rectangle_select.desc": "Snap rectangle selections to the nearest pixel edge, like in GIMP, instead of entire pixels.",
|
||||
"settings.pick_color_opacity": "Seleccionar Opacidad del Color",
|
||||
"settings.pick_color_opacity.desc": "Selecciona la Opacidad del color con el Seleccionador de Color y la establece como la opacidad del pincel",
|
||||
@ -1584,13 +1578,13 @@
|
||||
"action.blend_mode.color": "Color",
|
||||
"action.blend_mode.behind": "Por Detrás",
|
||||
"action.blend_mode.multiply": "Multiplicar",
|
||||
"action.blend_mode.divide": "Divide",
|
||||
"action.blend_mode.add": "Add",
|
||||
"action.blend_mode.subtract": "Subtract",
|
||||
"action.blend_mode.divide": "Dividir",
|
||||
"action.blend_mode.add": "Añadir",
|
||||
"action.blend_mode.subtract": "Restar",
|
||||
"action.blend_mode.screen": "Pantalla",
|
||||
"action.blend_mode.overlay": "Cubierta",
|
||||
"action.blend_mode.hard_light": "Hard Light",
|
||||
"action.blend_mode.difference": "Difference",
|
||||
"action.blend_mode.difference": "Diferencia",
|
||||
"action.copy_brush": "Pincel de Copia",
|
||||
"action.copy_brush.desc": "Pincel para clonar partes de tu textura o dibujar patrones",
|
||||
"action.validator_window": "Ver Problemas del Modelo...",
|
||||
@ -1612,14 +1606,14 @@
|
||||
"format.bedrock_block.info.size_limit": "Size total size of a block is limited to 30 pixels in all dimensions. The limit can be off-centered in all directions by 7 pixels from the block center.",
|
||||
"format.bedrock_block.info.textures": "Multiple textures can be applied to different cubes in Blockbench, but require additional setup in the behavior pack to work correctly in-game.",
|
||||
"format.image.desc": "Edit images in the 2D image editor",
|
||||
"generic.delete_all": "Delete All",
|
||||
"generic.delete_all": "Eliminar todo",
|
||||
"message.child_model_only.open": "Open Parent",
|
||||
"message.child_model_only.open_with_textures": "Open Parent & Adopt Textures",
|
||||
"dialog.project.credit": "Credit",
|
||||
"dialog.convert_project.create_copy": "Create Copy",
|
||||
"dialog.project.credit": "Credito",
|
||||
"dialog.convert_project.create_copy": "Crear copia",
|
||||
"dialog.texture.frame_time": "Frame Time",
|
||||
"dialog.texture.frame_time.desc": "Set for how long each frame will be visible, in ticks. Each tick is 1/20th of a second.",
|
||||
"dialog.texture.frame_interpolate": "Interpolate",
|
||||
"dialog.texture.frame_interpolate": "Interpolar",
|
||||
"dialog.texture.frame_interpolate.desc": "Interpolate between animation frames by cross-fading to the next frame",
|
||||
"dialog.texture.frame_order_type": "Loop Mode",
|
||||
"dialog.texture.frame_order_type.loop": "Loop",
|
||||
@ -1633,25 +1627,25 @@
|
||||
"dialog.select.mode.add": "Add to Selected",
|
||||
"dialog.select.mode.remove": "Remove from Selected",
|
||||
"dialog.select.mode.in_selection": "Select only from Selected",
|
||||
"dialog.predicate_overrides.model": "Model",
|
||||
"dialog.predicate_overrides.model": "Modelo",
|
||||
"dialog.predicate_overrides.predicates": "Predicates",
|
||||
"dialog.predicate_overrides.variants": "Variants",
|
||||
"dialog.predicate_overrides.start_value": "Start",
|
||||
"dialog.predicate_overrides.variants": "Variantes",
|
||||
"dialog.predicate_overrides.start_value": "Inicio",
|
||||
"dialog.predicate_overrides.add_override": "Add Override",
|
||||
"dialog.predicate_overrides.add_predicate": "Add Predicate",
|
||||
"dialog.predicate_overrides.generate_overrides": "Generate Overrides",
|
||||
"dialog.predicate_overrides.confirm_delete": "Are you sure you want to delete all overrides?",
|
||||
"dialog.predicate_overrides.predicate.angle": "Compass Angle",
|
||||
"dialog.predicate_overrides.predicate.blocking": "Is Blocking",
|
||||
"dialog.predicate_overrides.predicate.broken": "Is Broken",
|
||||
"dialog.predicate_overrides.predicate.angle": "Angulo de la brújula",
|
||||
"dialog.predicate_overrides.predicate.blocking": "Esta bloqueando",
|
||||
"dialog.predicate_overrides.predicate.broken": "Esta roto",
|
||||
"dialog.predicate_overrides.predicate.cast": "Is Cast",
|
||||
"dialog.predicate_overrides.predicate.cooldown": "Cooldown",
|
||||
"dialog.predicate_overrides.predicate.damage": "Damage",
|
||||
"dialog.predicate_overrides.predicate.damaged": "Is Damaged",
|
||||
"dialog.predicate_overrides.predicate.lefthanded": "Is Left-Handed",
|
||||
"dialog.predicate_overrides.predicate.cooldown": "Enfriamiento",
|
||||
"dialog.predicate_overrides.predicate.damage": "Daño",
|
||||
"dialog.predicate_overrides.predicate.damaged": "Esta dañado",
|
||||
"dialog.predicate_overrides.predicate.lefthanded": "Es zurdo",
|
||||
"dialog.predicate_overrides.predicate.pull": "Pull Amount",
|
||||
"dialog.predicate_overrides.predicate.pulling": "Is Pulling",
|
||||
"dialog.predicate_overrides.predicate.charged": "Is Charged",
|
||||
"dialog.predicate_overrides.predicate.charged": "Esta cargado",
|
||||
"dialog.predicate_overrides.predicate.firework": "Has Firework",
|
||||
"dialog.predicate_overrides.predicate.throwing": "Ready to Throw",
|
||||
"dialog.predicate_overrides.predicate.time": "Time of Day",
|
||||
@ -1663,22 +1657,22 @@
|
||||
"settings.model_export_scale.desc": "Factor by which the scale of exported glTF, DAE, and FBX models gets reduced. The default is 16, which converts 16 Blockbench units into 1 meter in the export.",
|
||||
"action.export_fbx": "Export FBX Model",
|
||||
"action.export_fbx.desc": "Export model and animations as fbx file to use it in other 3D applications and game engines",
|
||||
"action.center_lateral": "Center Lateral",
|
||||
"action.center_lateral": "Centro lateral",
|
||||
"action.center_lateral.desc": "Center the selected elements on the X and Z axis",
|
||||
"action.adjust_opacity": "Adjust Opacity...",
|
||||
"action.adjust_opacity.desc": "Adjust the opacity of the selected texture",
|
||||
"action.rotate_texture_cw": "Rotate Clockwise",
|
||||
"action.rotate_texture_ccw": "Rotate Counter-clockwise",
|
||||
"action.adjust_opacity": "Ajustar opacidad",
|
||||
"action.adjust_opacity.desc": "Ajustar la opacidad de la textura seleccionada",
|
||||
"action.rotate_texture_cw": "Rotar en sentido del reloj",
|
||||
"action.rotate_texture_ccw": "Rotar en sentido contra reloj",
|
||||
"action.predicate_overrides": "Edit Predicate Overrides...",
|
||||
"action.predicate_overrides.desc": "Select models to override this model based on selected conditions",
|
||||
"action.auto_set_cullfaces": "Set Cullfaces Automatically",
|
||||
"action.auto_set_cullfaces.desc": "Automatically generate cullfaces to hide faces when they are covered by the neighboring block.",
|
||||
"menu.texture.edit_externally": "Edit Externally",
|
||||
"menu.mirror_painting.texture": "2D Editor Symmetry",
|
||||
"menu.mirror_painting.texture.desc": "Enable mirror painting in 2D space on the image or texture",
|
||||
"menu.texture.edit_externally": "Editar externamente",
|
||||
"menu.mirror_painting.texture": "Simetría del editor 2D",
|
||||
"menu.mirror_painting.texture.desc": "Activar el pintado reflejado en el espacio 2D en la imagen o textura",
|
||||
"menu.animator.rotation_global": "Rotate in Global Space",
|
||||
"uv_editor.face_properties": "Face Properties",
|
||||
"uv_editor.face_properties.material_instance": "Material Instance",
|
||||
"uv_editor.face_properties": "Propiedades de la cara",
|
||||
"uv_editor.face_properties.material_instance": "Instancia material",
|
||||
"uv_editor.tint.info": "Tint can be enabled on a face to tell Minecraft to tint it. In vanilla, tint can only be used by specific blocks such as leaves and redstone dust, and can only have a value of 0.",
|
||||
"uv_editor.cullface.info": "Enabling cullface tells a face on a block to unrender if another full block is placed next to it in the specified direction in your Minecraft world. This can be used to optimize performance.",
|
||||
"uv_editor.material_instance.info": "Material instances can be set to a user-defined name. That name can be used in the block JSON file in the behavior pack to assign a particular texture and material that the face.",
|
||||
@ -1694,7 +1688,7 @@
|
||||
"settings_profile.confirm_delete": "Are you sure you want to delete this settings profile?",
|
||||
"settings_profile.condition.type.selectable": "Manually Selectable",
|
||||
"settings.interface_mode": "UI Mode",
|
||||
"settings.interface_mode.desc": "Interface mode. Restart Blockbench to apply changes",
|
||||
"settings.interface_mode.desc": "Interface mode",
|
||||
"settings.interface_mode.auto": "Automatic",
|
||||
"settings.interface_mode.desktop": "Desktop",
|
||||
"settings.interface_mode.mobile": "Mobile",
|
||||
@ -1818,7 +1812,6 @@
|
||||
"menu.uv.flip_x": "Mirror X",
|
||||
"menu.uv.flip_y": "Mirror Y",
|
||||
"menu.mirror_painting.enabled": "Enabled",
|
||||
"menu.mirror_painting.configure_texture_center": "Configure Texture Center...",
|
||||
"reference_image.position": "Position",
|
||||
"reference_image.size": "Size",
|
||||
"reference_image.rotation": "Rotation",
|
||||
@ -2022,11 +2015,6 @@
|
||||
"action.save_animation_preset.desc": "Save the selected keyframes as an animation preset",
|
||||
"action.animation_onion_skin": "Animation Onion Skin",
|
||||
"action.animation_onion_skin.desc": "Display an wireframe view of a different frame in the animation for reference",
|
||||
"action.animation_onion_skin.off": "Off",
|
||||
"action.animation_onion_skin.select": "Select",
|
||||
"action.animation_onion_skin.previous": "Previous",
|
||||
"action.animation_onion_skin.next": "Next",
|
||||
"action.animation_onion_skin.previous_next": "Previous + Next",
|
||||
"action.apply_animation_preset": "Apply Animation Preset",
|
||||
"action.apply_animation_preset.desc": "Select from a list of animation presets and apply it to the selected bone",
|
||||
"menu.brush_presets.pixel_perfect": "Pixel-perfect Brush",
|
||||
@ -2040,8 +2028,6 @@
|
||||
"settings.final_newline.desc": "Insert a newline character at the end of exported files",
|
||||
"action.crop_layer_to_selection": "Crop Layer to Selection",
|
||||
"action.edit_mode_uv_overlay.desc": "Display the UV map as an overlay in edit mode",
|
||||
"action.animation_onion_skin_selective": "Selective Onion Skin",
|
||||
"action.animation_onion_skin_selective.desc": "Only display onion skin for the selected part of the model",
|
||||
"menu.image": "Image",
|
||||
"menu.texture.discard_changes": "Discard Changes",
|
||||
"menu.texture.discard_changes.desc": "Discard all unsaved changes and load the latest version from the file",
|
||||
@ -2173,18 +2159,18 @@
|
||||
"action.copy.multiple.desc": "Copy all available data individually",
|
||||
"action.paste.multiple": "Paste All",
|
||||
"action.randomize_marker_colors": "Randomize Marker Colors",
|
||||
"action.cube_light_emission": "Light Emission",
|
||||
"action.cube_light_emission.desc": "Change the emissiveness of the selected cubes, as a value between 0 and 15",
|
||||
"action.cube_light_emission": "Emisión de luz",
|
||||
"action.cube_light_emission.desc": "Cambiar la emisividad de los cubos seleccionados, como un valor entre 0 y 15",
|
||||
"action.view_mode.colored_solid": "Solid with Marker Colors",
|
||||
"action.focus_on_selection.rotate_only": "Rotate only",
|
||||
"action.create_texture_group": "Create Texture Group",
|
||||
"action.create_texture_group.desc": "Create a group for your textures",
|
||||
"action.uv_maximize.all_faces": "Affect all faces",
|
||||
"action.retarget_animators": "Retarget Animations",
|
||||
"action.focus_on_selection.rotate_only": "Solo rotación",
|
||||
"action.create_texture_group": "Crear grupo de texturas",
|
||||
"action.create_texture_group.desc": "Crear un grupo para tus texturas",
|
||||
"action.uv_maximize.all_faces": "Afecta todas las caras",
|
||||
"action.retarget_animators": "Reorientar animaciones",
|
||||
"action.retarget_animators.desc": "Select which animator targets which bone or element",
|
||||
"action.merge_animation": "Merge Animation",
|
||||
"action.merge_animation.desc": "Merge the animation into another animation",
|
||||
"action.add_keyframe.reset_values": "With default values",
|
||||
"action.merge_animation": "Mezclar animación",
|
||||
"action.merge_animation.desc": "Mezclar la animación en otra animación",
|
||||
"action.add_keyframe.reset_values": "Con los valores por defecto",
|
||||
"action.set_timeline_range_start": "Set Timeline Range Start",
|
||||
"action.set_timeline_range_start.desc": "Set the start point for a custom playback range in the animation timeline",
|
||||
"action.set_timeline_range_end": "Set Timeline Range End",
|
||||
@ -2192,41 +2178,153 @@
|
||||
"action.disable_timeline_range": "Disable Timeline Range",
|
||||
"action.disable_timeline_range.desc": "Disable the custom playback range in the animation timeline",
|
||||
"menu.texture_group.resolve": "Resolve",
|
||||
"menu.image_tiled_view.mirrored": "Mirrored Edges",
|
||||
"menu.image_onion_skin_view.frame": "Frames",
|
||||
"menu.image_onion_skin_view.frame.last_viewed": "Last Viewed Frame",
|
||||
"menu.image_onion_skin_view.frame.previous": "Previous Frame",
|
||||
"menu.image_onion_skin_view.frame.next": "Next Frame",
|
||||
"menu.image_onion_skin_view.frame.both": "Previous + Next",
|
||||
"menu.image_onion_skin_view.display": "Display",
|
||||
"menu.image_onion_skin_view.display.pixels": "Smaller Pixels",
|
||||
"menu.image_onion_skin_view.display.transparent": "Transparent",
|
||||
"menu.image_onion_skin_view.above": "Display Above",
|
||||
"menu.animation.reload": "Reload",
|
||||
"switches.autouv.alt": "Relative",
|
||||
"display.rotation_pivot": "Rotation Pivot",
|
||||
"display.scale_pivot": "Scale Pivot",
|
||||
"display.reference.fox": "Fox",
|
||||
"display.reference.eating": "Eating",
|
||||
"preview_scene.sky": "Sky",
|
||||
"preview_scene.space": "Space",
|
||||
"preview_scene.minecraft_ocean": "Ocean",
|
||||
"message.import_palette.selection_only": "Selection only",
|
||||
"menu.image_tiled_view.mirrored": "Bordes reflejados",
|
||||
"menu.image_onion_skin_view.frame": "Fotogramas",
|
||||
"menu.image_onion_skin_view.frame.last_viewed": "Fotograma anteriormente visto",
|
||||
"menu.image_onion_skin_view.frame.previous": "Fotograma previo",
|
||||
"menu.image_onion_skin_view.frame.next": "Siguiente fotograma",
|
||||
"menu.image_onion_skin_view.frame.both": "Previo + anterior",
|
||||
"menu.image_onion_skin_view.display": "Mostrar",
|
||||
"menu.image_onion_skin_view.display.pixels": "Pixeles mas pequeños",
|
||||
"menu.image_onion_skin_view.display.transparent": "Transparente",
|
||||
"menu.image_onion_skin_view.above": "Mostrar abajo",
|
||||
"menu.animation.reload": "Recargar",
|
||||
"switches.autouv.alt": "Relativo",
|
||||
"display.rotation_pivot": "Eje de rotación",
|
||||
"display.scale_pivot": "Eje de escala",
|
||||
"display.reference.fox": "Zorro",
|
||||
"display.reference.eating": "Comer",
|
||||
"preview_scene.sky": "Cielo",
|
||||
"preview_scene.space": "Espacio",
|
||||
"preview_scene.minecraft_ocean": "Oceano",
|
||||
"message.import_palette.selection_only": "Solo selección",
|
||||
"dialog.blend_transition_edit.ease_in_out": "Ease-in-out (%0)",
|
||||
"dialog.blend_transition_edit.generate": "Generate...",
|
||||
"dialog.blend_transition_edit.generate.learn_more": "More info and preview",
|
||||
"dialog.blend_transition_edit.generate": "Generar...",
|
||||
"dialog.blend_transition_edit.generate.learn_more": "Mas info y vista previa",
|
||||
"dialog.blend_transition_edit.generate.curve": "Easing Type",
|
||||
"dialog.blend_transition_edit.generate.steps": "Keyframes",
|
||||
"settings.fps_limit": "FPS Limit",
|
||||
"settings.fps_limit": "Limite de FPS",
|
||||
"settings.fps_limit.desc": "Limit how many frames per second Blockbench renders. The actual frame rate is limited to what your device can display.",
|
||||
"settings.outliner_reveal_on_select": "Reveal Elements on Select",
|
||||
"settings.outliner_reveal_on_select.desc": "Reveal elements in the ouliner when selected",
|
||||
"settings.java_export_pivots": "Export Pivots in Java block/item models",
|
||||
"settings.java_export_pivots.desc": "Save pivot points in Java block/item models on cubes without rotation",
|
||||
"animation_controllers.state.blend_transition_curve": "Blend Transition Curve",
|
||||
"menu.slider.reset_vector": "Reset Vector",
|
||||
"dialog.blend_transition_edit.extended": "Extended Graph",
|
||||
"message.screenshot_too_large.title": "Screenshot Resolution Issue",
|
||||
"message.screenshot_too_large.message": "The screenshot could not be rendered successfully. Please try again with a lower resolution or without supersampling.",
|
||||
"message.rename_elements.numbering": "You can use special characters to generate sequential numbers: % to get the index of the element within its group, $ to get the index within the selection."
|
||||
"menu.slider.reset_vector": "Reajustar vector",
|
||||
"dialog.blend_transition_edit.extended": "Grafico extendido",
|
||||
"message.screenshot_too_large.title": "Problema en la resolución de la captura",
|
||||
"message.screenshot_too_large.message": "La captura de pantalla no podrá renderizarse exitosamente. por favor inténtelo otra vez con una resolución mas baja o sin supersampling.",
|
||||
"message.rename_elements.numbering": "You can use special characters to generate sequential numbers: % to get the index of the element within its group, $ to get the index within the selection.",
|
||||
"generic.edit_externally": "Edit Externally",
|
||||
"message.settings_require_restart.title": "Restart Required",
|
||||
"message.settings_require_restart.message": "Some settings will only apply after restarting the program.",
|
||||
"message.settings_require_restart.restart_now": "Restart Now",
|
||||
"message.settings_require_restart.restart_later": "Restart Later",
|
||||
"message.classroom_mode.install_plugin": "Cannot install plugins in Classroom Mode",
|
||||
"dialog.collection.export_path": "Export Path",
|
||||
"dialog.collection.select_all": "Select All",
|
||||
"dialog.collection.select_none": "Select None",
|
||||
"dialog.collection.add_with_filter": "Add with Filter",
|
||||
"dialog.collection.remove": "Remove",
|
||||
"dialog.material_config.title": "Material Config",
|
||||
"dialog.material_config.color_value": "Color Value",
|
||||
"dialog.material_config.mer": "Metal-Emissive-Roughness",
|
||||
"dialog.material_config.mer_value": "MER Value",
|
||||
"dialog.material_config.depth_type": "Depth Type",
|
||||
"dialog.create_texture.disable_mirror_uv": "Disable UV Mirroring",
|
||||
"dialog.create_texture.disable_mirror_uv.desc": "Disable the UV Mirror option in Mirror Modeling to preserve separate UVs for each side of the model",
|
||||
"dialog.create_gif.turn.sync_to_anim_length": "Sync to animation length",
|
||||
"settings.category.controls": "Controls",
|
||||
"settings.classroom_mode": "Classroom Mode",
|
||||
"settings.classroom_mode.desc": "Restricts functionality such as installing plugins and removes links to social media",
|
||||
"settings.antialiasing_bleed_fix": "Fix anti-aliasing bleeding",
|
||||
"settings.antialiasing_bleed_fix.desc": "Fixes texture bleeding when using anti-aliasing. Potentially unsupported on older hardware.",
|
||||
"settings.tone_mapping": "Tone Mapping",
|
||||
"settings.tone_mapping.desc": "Approximation method for displaying high dynamic range on a standard screen for PBR rendering.",
|
||||
"settings.audio_scrubbing": "Timline Scrubbing Audio",
|
||||
"settings.audio_scrubbing.desc": "Play short previews of the audio while scrubbing through time timeline",
|
||||
"settings.viewport_rotate_speed": "Viewport Rotate Speed",
|
||||
"settings.viewport_rotate_speed.desc": "Input sensitivity when rotating in the viewport",
|
||||
"settings.viewport_zoom_speed": "Viewport Zoom Speed",
|
||||
"settings.viewport_zoom_speed.desc": "Input sensitivity when zooming in the viewport",
|
||||
"settings.editor_2d_zoom_speed": "2D Editor Zoom Speed",
|
||||
"settings.editor_2d_zoom_speed.desc": "Input sensitivity when zooming in the UV and 2D paint editor",
|
||||
"category.select": "Select",
|
||||
"action.vertex_snap_mode.rotate": "Rotate",
|
||||
"action.export_image": "Export Image",
|
||||
"action.export_image.desc": "Export your texture as an image file",
|
||||
"action.apply_mirror_modeling": "Apply Mirror Modeling",
|
||||
"action.apply_mirror_modeling.desc": "Apply Mirror Modeling to the selection. All selected elements will be copied and flipped across the X axis.",
|
||||
"action.create_collection": "Create Collection",
|
||||
"action.create_collection.desc": "Create a collection out of the outliner selection",
|
||||
"action.set_collection_content_to_selection": "Set Collection Content to Selected",
|
||||
"action.set_collection_content_to_selection.desc": "Set the selected groups and elements as the content of the collection",
|
||||
"action.add_to_collection": "Add Selected to Collection",
|
||||
"action.add_to_collection.desc": "Add the selected groups and elements to the collection",
|
||||
"action.view_mode.material": "Material Preview",
|
||||
"action.create_material": "Create Material",
|
||||
"action.create_material.desc": "Create a new PBR material out of the selected texture",
|
||||
"action.generate_pbr_map": "Generate PBR Map...",
|
||||
"action.generate_pbr_map.desc": "Generate a PBR map (height map or metalness, emissiveness, roughness) from an existing texture",
|
||||
"menu.tools.main_tools": "Toolbox",
|
||||
"menu.view.panels": "Panels",
|
||||
"menu.texture.pbr_channel": "PBR Channel",
|
||||
"menu.texture.pbr_channel.color": "Color",
|
||||
"menu.texture.pbr_channel.normal": "Normal",
|
||||
"menu.texture.pbr_channel.height": "Height",
|
||||
"menu.texture.pbr_channel.mer": "MER (Metalness-Emissive-Roughness)",
|
||||
"menu.texture.pbr_channel.mer_subsurface": "MER Subsurface",
|
||||
"menu.collection.export_project": "Export Project",
|
||||
"menu.collection.export_as": "Export as \"%0\"",
|
||||
"menu.panel.enable": "Enable",
|
||||
"menu.panel.move_to": "Move To",
|
||||
"menu.panel.move_to.left_bar": "Left Sidebar",
|
||||
"menu.panel.move_to.right_bar": "Right Sidebar",
|
||||
"menu.panel.move_to.top": "Top",
|
||||
"menu.panel.move_to.bottom": "Bottom",
|
||||
"menu.panel.move_to.float": "Float",
|
||||
"menu.panel.move_to.hidden": "Hide",
|
||||
"menu.panel.fold": "Collapse",
|
||||
"menu.mirror_painting.texture_center": "Origin",
|
||||
"menu.mirror_modeling.mirror_uv": "Mirror UV",
|
||||
"menu.animation_onion_skin.frames": "Frames",
|
||||
"menu.animation_onion_skin.select": "Select",
|
||||
"menu.animation_onion_skin.previous": "Previous",
|
||||
"menu.animation_onion_skin.next": "Next",
|
||||
"menu.animation_onion_skin.previous_next": "Previous + Next",
|
||||
"menu.animation_onion_skin.count": "Count",
|
||||
"menu.animation_onion_skin.interval": "Interval",
|
||||
"menu.animation_onion_skin_selective": "Selective Onion Skin",
|
||||
"menu.animation_onion_skin_selective.desc": "Only display onion skin for the selected part of the model",
|
||||
"edit.loop_cut.unit": "Unit",
|
||||
"edit.loop_cut.unit.size_units": "Size Units",
|
||||
"edit.loop_cut.unit.percent": "Percent",
|
||||
"edit.extrude_mesh_selection.direction": "Direction",
|
||||
"edit.extrude_mesh_selection.direction.outwards": "Outwards",
|
||||
"edit.extrude_mesh_selection.direction.average": "Average",
|
||||
"edit.extrude_mesh_selection.even_extend": "Even Extend",
|
||||
"edit.vertex_snap.align": "Align",
|
||||
"edit.vertex_snap.align.longest": "Longest Axis",
|
||||
"edit.vertex_snap.align.direction": "Direction from Pivot",
|
||||
"edit.vertex_snap.align.align_axis": "%0 Axis",
|
||||
"edit.vertex_snap.ignore_axis": "Ignore Axis",
|
||||
"codec.common.format": "Format",
|
||||
"codec.image.quality": "Quality",
|
||||
"panel.collections": "Collections",
|
||||
"modifier_actions.always": "Always Enabled",
|
||||
"modifier_actions.unless": "Unless %0",
|
||||
"settings.undo_selections": "Undo Selection",
|
||||
"settings.undo_selections.desc": "Track selection changes as a step in the undo history",
|
||||
"action.focus_on_selection.zoom": "Zoom to fit",
|
||||
"display.reference.tooting": "Horn Tooting",
|
||||
"settings.selection_tolerance": "Selection Tolerance",
|
||||
"settings.selection_tolerance.desc": "Size of the area that can be clicked to select an edge or vertex",
|
||||
"action.delete.keep_vertices": "Keep Edges/Vertices",
|
||||
"menu.mesh": "Mesh",
|
||||
"dialog.material_config.subsurface": "Subsurface Scattering",
|
||||
"dialog.material_config.subsurface_enabled.desc": "Use the MER map alpha channel for subsurface scattering",
|
||||
"settings.pick_combined_color": "Pick Combined Color",
|
||||
"settings.pick_combined_color.desc": "Pick the combined color of all layers at the respective pixel, instead of the color on the active layer",
|
||||
"action.split_rgb_into_layers": "Split RGB Channels into Layers",
|
||||
"action.split_rgb_into_layers.desc": "Split the texture into additive layers, one for each RGB channel"
|
||||
}
|
128
lang/fr.json
@ -164,11 +164,6 @@
|
||||
"layout.font.main": "Police principale",
|
||||
"layout.font.headline": "Police de titre",
|
||||
"about.version": "Version :",
|
||||
"about.creator": "Créateur :",
|
||||
"about.website": "Site Internet :",
|
||||
"about.vertex_snap": "L'Alignement Vertex est basé sur un plugin de SirBenet",
|
||||
"about.icons": "Packs d'icônes :",
|
||||
"about.libraries": "Bibliothèques :",
|
||||
"settings.category.general": "Général",
|
||||
"settings.category.preview": "Aperçu",
|
||||
"settings.category.grid": "Grille",
|
||||
@ -1220,7 +1215,6 @@
|
||||
"camera_angle.true_isometric_right": "Vraie droite isométrique (30°)",
|
||||
"camera_angle.true_isometric_left": "Vraie gauche isométrique (30°)",
|
||||
"menu.help.wiki": "Wiki Blockbench",
|
||||
"about.repository": "Dépôt :",
|
||||
"settings.update_to_prereleases": "Mettre à jour vers les versions expérimentales",
|
||||
"settings.update_to_prereleases.desc": "Met à jour Blockbench automatiquement vers des versions bêta pour tester les nouvelles fonctionnalités. Les versions expérimentales peuvent être instables, n'activez pas cette option si vous vous servez de Blockbench pour le travail ou d'autres projets importants.",
|
||||
"data.separator.spacer": "Séparateur",
|
||||
@ -1818,7 +1812,6 @@
|
||||
"menu.uv.flip_x": "Miroir X",
|
||||
"menu.uv.flip_y": "Miroir Y",
|
||||
"menu.mirror_painting.enabled": "Activer",
|
||||
"menu.mirror_painting.configure_texture_center": "Configurer le centre de texture...",
|
||||
"reference_image.position": "Position",
|
||||
"reference_image.size": "Taille",
|
||||
"reference_image.rotation": "Rotation",
|
||||
@ -2022,11 +2015,6 @@
|
||||
"action.save_animation_preset.desc": "Save the selected keyframes as an animation preset",
|
||||
"action.animation_onion_skin": "Animation Onion Skin",
|
||||
"action.animation_onion_skin.desc": "Display an wireframe view of a different frame in the animation for reference",
|
||||
"action.animation_onion_skin.off": "Off",
|
||||
"action.animation_onion_skin.select": "Sélectionner",
|
||||
"action.animation_onion_skin.previous": "Précédente",
|
||||
"action.animation_onion_skin.next": "Suivante",
|
||||
"action.animation_onion_skin.previous_next": "Précédente + Suivante",
|
||||
"action.apply_animation_preset": "Apply Animation Preset",
|
||||
"action.apply_animation_preset.desc": "Select from a list of animation presets and apply it to the selected bone",
|
||||
"menu.brush_presets.pixel_perfect": "Pixel-perfect Brush",
|
||||
@ -2040,8 +2028,6 @@
|
||||
"settings.final_newline.desc": "Insert a newline character at the end of exported files",
|
||||
"action.crop_layer_to_selection": "Crop Layer to Selection",
|
||||
"action.edit_mode_uv_overlay.desc": "Display the UV map as an overlay in edit mode",
|
||||
"action.animation_onion_skin_selective": "Selective Onion Skin",
|
||||
"action.animation_onion_skin_selective.desc": "Only display onion skin for the selected part of the model",
|
||||
"menu.image": "Image",
|
||||
"menu.texture.discard_changes": "Discard Changes",
|
||||
"menu.texture.discard_changes.desc": "Discard all unsaved changes and load the latest version from the file",
|
||||
@ -2228,5 +2214,117 @@
|
||||
"dialog.blend_transition_edit.extended": "Extended Graph",
|
||||
"message.screenshot_too_large.title": "Screenshot Resolution Issue",
|
||||
"message.screenshot_too_large.message": "The screenshot could not be rendered successfully. Please try again with a lower resolution or without supersampling.",
|
||||
"message.rename_elements.numbering": "You can use special characters to generate sequential numbers: % to get the index of the element within its group, $ to get the index within the selection."
|
||||
"message.rename_elements.numbering": "You can use special characters to generate sequential numbers: % to get the index of the element within its group, $ to get the index within the selection.",
|
||||
"generic.edit_externally": "Edit Externally",
|
||||
"message.settings_require_restart.title": "Restart Required",
|
||||
"message.settings_require_restart.message": "Some settings will only apply after restarting the program.",
|
||||
"message.settings_require_restart.restart_now": "Restart Now",
|
||||
"message.settings_require_restart.restart_later": "Restart Later",
|
||||
"message.classroom_mode.install_plugin": "Cannot install plugins in Classroom Mode",
|
||||
"dialog.collection.export_path": "Export Path",
|
||||
"dialog.collection.select_all": "Select All",
|
||||
"dialog.collection.select_none": "Select None",
|
||||
"dialog.collection.add_with_filter": "Add with Filter",
|
||||
"dialog.collection.remove": "Remove",
|
||||
"dialog.material_config.title": "Material Config",
|
||||
"dialog.material_config.color_value": "Color Value",
|
||||
"dialog.material_config.mer": "Metal-Emissive-Roughness",
|
||||
"dialog.material_config.mer_value": "MER Value",
|
||||
"dialog.material_config.depth_type": "Depth Type",
|
||||
"dialog.create_texture.disable_mirror_uv": "Disable UV Mirroring",
|
||||
"dialog.create_texture.disable_mirror_uv.desc": "Disable the UV Mirror option in Mirror Modeling to preserve separate UVs for each side of the model",
|
||||
"dialog.create_gif.turn.sync_to_anim_length": "Sync to animation length",
|
||||
"settings.category.controls": "Controls",
|
||||
"settings.classroom_mode": "Classroom Mode",
|
||||
"settings.classroom_mode.desc": "Restricts functionality such as installing plugins and removes links to social media",
|
||||
"settings.antialiasing_bleed_fix": "Fix anti-aliasing bleeding",
|
||||
"settings.antialiasing_bleed_fix.desc": "Fixes texture bleeding when using anti-aliasing. Potentially unsupported on older hardware.",
|
||||
"settings.tone_mapping": "Tone Mapping",
|
||||
"settings.tone_mapping.desc": "Approximation method for displaying high dynamic range on a standard screen for PBR rendering.",
|
||||
"settings.audio_scrubbing": "Timline Scrubbing Audio",
|
||||
"settings.audio_scrubbing.desc": "Play short previews of the audio while scrubbing through time timeline",
|
||||
"settings.viewport_rotate_speed": "Viewport Rotate Speed",
|
||||
"settings.viewport_rotate_speed.desc": "Input sensitivity when rotating in the viewport",
|
||||
"settings.viewport_zoom_speed": "Viewport Zoom Speed",
|
||||
"settings.viewport_zoom_speed.desc": "Input sensitivity when zooming in the viewport",
|
||||
"settings.editor_2d_zoom_speed": "2D Editor Zoom Speed",
|
||||
"settings.editor_2d_zoom_speed.desc": "Input sensitivity when zooming in the UV and 2D paint editor",
|
||||
"category.select": "Select",
|
||||
"action.vertex_snap_mode.rotate": "Rotate",
|
||||
"action.export_image": "Export Image",
|
||||
"action.export_image.desc": "Export your texture as an image file",
|
||||
"action.apply_mirror_modeling": "Apply Mirror Modeling",
|
||||
"action.apply_mirror_modeling.desc": "Apply Mirror Modeling to the selection. All selected elements will be copied and flipped across the X axis.",
|
||||
"action.create_collection": "Create Collection",
|
||||
"action.create_collection.desc": "Create a collection out of the outliner selection",
|
||||
"action.set_collection_content_to_selection": "Set Collection Content to Selected",
|
||||
"action.set_collection_content_to_selection.desc": "Set the selected groups and elements as the content of the collection",
|
||||
"action.add_to_collection": "Add Selected to Collection",
|
||||
"action.add_to_collection.desc": "Add the selected groups and elements to the collection",
|
||||
"action.view_mode.material": "Material Preview",
|
||||
"action.create_material": "Create Material",
|
||||
"action.create_material.desc": "Create a new PBR material out of the selected texture",
|
||||
"action.generate_pbr_map": "Generate PBR Map...",
|
||||
"action.generate_pbr_map.desc": "Generate a PBR map (height map or metalness, emissiveness, roughness) from an existing texture",
|
||||
"menu.tools.main_tools": "Toolbox",
|
||||
"menu.view.panels": "Panels",
|
||||
"menu.texture.pbr_channel": "PBR Channel",
|
||||
"menu.texture.pbr_channel.color": "Color",
|
||||
"menu.texture.pbr_channel.normal": "Normal",
|
||||
"menu.texture.pbr_channel.height": "Height",
|
||||
"menu.texture.pbr_channel.mer": "MER (Metalness-Emissive-Roughness)",
|
||||
"menu.texture.pbr_channel.mer_subsurface": "MER Subsurface",
|
||||
"menu.collection.export_project": "Export Project",
|
||||
"menu.collection.export_as": "Export as \"%0\"",
|
||||
"menu.panel.enable": "Enable",
|
||||
"menu.panel.move_to": "Move To",
|
||||
"menu.panel.move_to.left_bar": "Left Sidebar",
|
||||
"menu.panel.move_to.right_bar": "Right Sidebar",
|
||||
"menu.panel.move_to.top": "Top",
|
||||
"menu.panel.move_to.bottom": "Bottom",
|
||||
"menu.panel.move_to.float": "Float",
|
||||
"menu.panel.move_to.hidden": "Hide",
|
||||
"menu.panel.fold": "Collapse",
|
||||
"menu.mirror_painting.texture_center": "Origin",
|
||||
"menu.mirror_modeling.mirror_uv": "Mirror UV",
|
||||
"menu.animation_onion_skin.frames": "Frames",
|
||||
"menu.animation_onion_skin.select": "Select",
|
||||
"menu.animation_onion_skin.previous": "Previous",
|
||||
"menu.animation_onion_skin.next": "Next",
|
||||
"menu.animation_onion_skin.previous_next": "Previous + Next",
|
||||
"menu.animation_onion_skin.count": "Count",
|
||||
"menu.animation_onion_skin.interval": "Interval",
|
||||
"menu.animation_onion_skin_selective": "Selective Onion Skin",
|
||||
"menu.animation_onion_skin_selective.desc": "Only display onion skin for the selected part of the model",
|
||||
"edit.loop_cut.unit": "Unit",
|
||||
"edit.loop_cut.unit.size_units": "Size Units",
|
||||
"edit.loop_cut.unit.percent": "Percent",
|
||||
"edit.extrude_mesh_selection.direction": "Direction",
|
||||
"edit.extrude_mesh_selection.direction.outwards": "Outwards",
|
||||
"edit.extrude_mesh_selection.direction.average": "Average",
|
||||
"edit.extrude_mesh_selection.even_extend": "Even Extend",
|
||||
"edit.vertex_snap.align": "Align",
|
||||
"edit.vertex_snap.align.longest": "Longest Axis",
|
||||
"edit.vertex_snap.align.direction": "Direction from Pivot",
|
||||
"edit.vertex_snap.align.align_axis": "%0 Axis",
|
||||
"edit.vertex_snap.ignore_axis": "Ignore Axis",
|
||||
"codec.common.format": "Format",
|
||||
"codec.image.quality": "Quality",
|
||||
"panel.collections": "Collections",
|
||||
"modifier_actions.always": "Always Enabled",
|
||||
"modifier_actions.unless": "Unless %0",
|
||||
"settings.undo_selections": "Undo Selection",
|
||||
"settings.undo_selections.desc": "Track selection changes as a step in the undo history",
|
||||
"action.focus_on_selection.zoom": "Zoom to fit",
|
||||
"display.reference.tooting": "Horn Tooting",
|
||||
"settings.selection_tolerance": "Selection Tolerance",
|
||||
"settings.selection_tolerance.desc": "Size of the area that can be clicked to select an edge or vertex",
|
||||
"action.delete.keep_vertices": "Keep Edges/Vertices",
|
||||
"menu.mesh": "Mesh",
|
||||
"dialog.material_config.subsurface": "Subsurface Scattering",
|
||||
"dialog.material_config.subsurface_enabled.desc": "Use the MER map alpha channel for subsurface scattering",
|
||||
"settings.pick_combined_color": "Pick Combined Color",
|
||||
"settings.pick_combined_color.desc": "Pick the combined color of all layers at the respective pixel, instead of the color on the active layer",
|
||||
"action.split_rgb_into_layers": "Split RGB Channels into Layers",
|
||||
"action.split_rgb_into_layers.desc": "Split the texture into additive layers, one for each RGB channel"
|
||||
}
|
2912
lang/it.json
408
lang/ja.json
@ -164,11 +164,6 @@
|
||||
"layout.font.main": "メインフォント",
|
||||
"layout.font.headline": "見出しフォント",
|
||||
"about.version": "バージョン:",
|
||||
"about.creator": "クリエイター:",
|
||||
"about.website": "ウェブサイト:",
|
||||
"about.vertex_snap": "Vertex Snapping は SirBenet によって提供されました",
|
||||
"about.icons": "アイコンパック:",
|
||||
"about.libraries": "ライブラリ:",
|
||||
"settings.category.general": "一般",
|
||||
"settings.category.preview": "プレビュー",
|
||||
"settings.category.grid": "グリッド",
|
||||
@ -178,7 +173,7 @@
|
||||
"settings.category.dialogs": "ダイアログ",
|
||||
"settings.category.export": "書き出し",
|
||||
"settings.language": "言語を変更",
|
||||
"settings.language.desc": "変更を適用するには Blockbench を再起動してください。",
|
||||
"settings.language.desc": "インターフェース言語",
|
||||
"settings.backup_interval": "バックアップ",
|
||||
"settings.backup_interval.desc": "バックアップの頻度を変更します",
|
||||
"settings.origin_size": "ピボットマーカー",
|
||||
@ -258,10 +253,10 @@
|
||||
"action.uv_slider_pos_x.desc": "選択したキューブの UV を水平方向に移動します",
|
||||
"action.uv_slider_pos_y": "垂直移動",
|
||||
"action.uv_slider_pos_y.desc": "選択したキューブの UV を垂直方向に移動します",
|
||||
"action.uv_slider_size_x": "水平スケール",
|
||||
"action.uv_slider_size_x.desc": "選択したキューブの UV を水平方向に広げます",
|
||||
"action.uv_slider_size_y": "垂直スケール",
|
||||
"action.uv_slider_size_y.desc": "選択したキューブの UV を垂直方向に広げます",
|
||||
"action.uv_slider_size_x": "水平サイズ",
|
||||
"action.uv_slider_size_x.desc": "選択した UV を水平方向にリサイズします",
|
||||
"action.uv_slider_size_y": "垂直サイズ",
|
||||
"action.uv_slider_size_y.desc": "選択した UV を垂直方向にリサイズします",
|
||||
"action.vertex_snap_mode": "スナップ",
|
||||
"action.vertex_snap_mode.desc": "頂点スナップが選択された位置に移動するか、サイズを変更するかを選択します",
|
||||
"action.move_tool": "移動",
|
||||
@ -324,7 +319,7 @@
|
||||
"action.select_window.desc": "プロパティからエレメントを検索します",
|
||||
"action.invert_selection": "インバート",
|
||||
"action.invert_selection.desc": "選択中のエレメントを反転します",
|
||||
"action.select_all": "全てを選択",
|
||||
"action.select_all": "すべて選択",
|
||||
"action.select_all.desc": "すべてのエレメントを選択します",
|
||||
"action.collapse_groups": "折りたたむ",
|
||||
"action.collapse_groups.desc": "すべてのグループを折りたたみます",
|
||||
@ -616,8 +611,8 @@
|
||||
"mode.paint": "Paint",
|
||||
"mode.display": "Display",
|
||||
"mode.animate": "Animate",
|
||||
"status_bar.recording_gif": "レコーディング GIF",
|
||||
"status_bar.processing_gif": "GIF の加工処理",
|
||||
"status_bar.recording_gif": "レコーディング",
|
||||
"status_bar.processing_gif": "加工処理",
|
||||
"settings.backup_retain": "バックアップ保持期間",
|
||||
"settings.backup_retain.desc": "バックアップを保持する日数を設定します",
|
||||
"action.rotate_tool": "回転",
|
||||
@ -871,7 +866,7 @@
|
||||
"action.timelapse": "タイムラプス...",
|
||||
"action.timelapse.desc": "モデリングプロセスのタイムラプスを記録します",
|
||||
"action.add_keyframe": "キーフレームを追加",
|
||||
"action.add_keyframe.desc": "キーフレームを自動的に追加します。 Shift キーを押すとデフォルト値が表示されます",
|
||||
"action.add_keyframe.desc": "アニメーターにキーフレームを追加します",
|
||||
"action.bring_up_all_animations.desc": "変更されたすべてのアニメーターをタイムラインに組み込みます",
|
||||
"timeline.timeline": "インストラ",
|
||||
"menu.palette.load.default": "デフォルト",
|
||||
@ -989,7 +984,7 @@
|
||||
"action.load_plugin_from_url.desc": "サーバーからプラグインをロードします",
|
||||
"action.cube_counter.desc": "現在のキューブ数とその他の統計を表示します",
|
||||
"action.unlock_everything": "アンロック",
|
||||
"action.unlock_everything.desc": "アウトラインの全てのロックを解除します。",
|
||||
"action.unlock_everything.desc": "アウトラインのすべてのロックを解除します。",
|
||||
"action.load_palette": "パレットをロード",
|
||||
"action.load_palette.desc": "パレットプリセットをロードします",
|
||||
"action.toggle_locked": "トグルロック",
|
||||
@ -997,7 +992,7 @@
|
||||
"action.apply_display_preset": "プリセットを適用",
|
||||
"action.apply_display_preset.desc": "カスタム表示設定のプリセットを適用します",
|
||||
"action.apply_display_preset.here": "スロットに適用",
|
||||
"action.apply_display_preset.everywhere": "全てのスロットに適用",
|
||||
"action.apply_display_preset.everywhere": "すべてのスロットに適用",
|
||||
"action.resolve_keyframe_expressions": "キーフレームを解除",
|
||||
"action.resolve_keyframe_expressions.desc": "選択したキーフレームを解除します",
|
||||
"action.fold_all_animations": "すべてのアニメーターを折りたたむ",
|
||||
@ -1069,13 +1064,13 @@
|
||||
"generic.all": "All",
|
||||
"message.small_face_dimensions.title": "互換性のないフェイス",
|
||||
"message.small_face_dimensions.message": "選択範囲に 1 より小さいフェイスが含まれています。マッピングシステムは、そのしきい値を下回るフェイスを 0 ピクセルと見なします。これらのフェイスのテクスチャは正しく機能しない可能性があります。",
|
||||
"message.small_face_dimensions.face_uv": "このフォーマットでは、各フェイスごとの UV マップをサポートしています。\"ファイル\" > \"プロジェクト...\" に移動し、\"UV モード\" を \"Per-face UV\" に変更してください。",
|
||||
"message.small_face_dimensions.face_uv": "現在のフォーマットは、Per-face UV マップをサポートしています。影響を受けるキューブを右クリックし、「UV Mode 」を 「Per-face UV 」に変更してください。",
|
||||
"dialog.plugins.outdated_client": "新しいバージョンの Blockbench が必要です",
|
||||
"dialog.plugins.outdated_plugin": "このバージョンの Blockbench では動作しません",
|
||||
"settings.motion_trails": "モーショントレイル",
|
||||
"settings.motion_trails.desc": "アニメーションエディタでモーショントレイルを表示します",
|
||||
"settings.antialiasing": "アンチエイリアシング",
|
||||
"settings.antialiasing.desc": "プレビューでアンチエイリアスを切り替えます。 Blockbench を再起動して変更を適用します",
|
||||
"settings.antialiasing.desc": "プレビューでアンチエイリアスを切り替えます",
|
||||
"action.timeline_frame_back": "1フレーム戻る",
|
||||
"action.timeline_frame_forth": "1フレーム進む",
|
||||
"panel.bone.ik": "逆運動学 (IK)",
|
||||
@ -1103,7 +1098,7 @@
|
||||
"settings.ctrl_shift_size": "ダブルステップ",
|
||||
"settings.ctrl_shift_size.desc": "Control + Shift のグリッド間隔を変更します",
|
||||
"settings.hardware_acceleration": "アプリを最適化",
|
||||
"settings.hardware_acceleration.desc": "グラフィックカードを使用し、レンダリングを高速化します。この機能を利用するのには再起動が必要です",
|
||||
"settings.hardware_acceleration.desc": "グラフィックカードを使用し、レンダリングを高速化します",
|
||||
"action.explode_skin_model": "モデルを分離",
|
||||
"action.explode_skin_model.desc": "スキンをバーツごとに分解します",
|
||||
"action.export_minecraft_skin": "Minecraft Skin",
|
||||
@ -1147,7 +1142,7 @@
|
||||
"message.load_keymap": "キーマップをロードしますか? 現在のキーバインドが置き換えられます。",
|
||||
"message.keymap_loaded": "キーマップのロード",
|
||||
"dialog.convert_project.current_format": "現在のフォーマット",
|
||||
"dialog.create_texture.rearrange_uv.desc": "新しい UV アレンジメントを作成して、全てのフェイスに独自のテクスチャを与えます",
|
||||
"dialog.create_texture.rearrange_uv.desc": "新しい UV アレンジメントを作成して、すべてのフェイスに独自のテクスチャを与えます",
|
||||
"dialog.create_texture.power.desc": "オートテクスチャサイズを正方形に固定します。",
|
||||
"dialog.create_texture.double_use.desc": "2つの要素に同じ UV スペースが割り当てられている場合、新しいマップでも維持します",
|
||||
"dialog.create_texture.padding.desc": "テンプレートの間にパディングを追加します",
|
||||
@ -1220,13 +1215,12 @@
|
||||
"camera_angle.true_isometric_right": "等角投影 右( 30°)",
|
||||
"camera_angle.true_isometric_left": "等角投影 左( 30°)",
|
||||
"menu.help.wiki": "Blockbench Wiki",
|
||||
"about.repository": "リポジトリ:",
|
||||
"settings.update_to_prereleases": "プレリリース",
|
||||
"settings.update_to_prereleases.desc": "新機能をいち早く体験するために、Blockbench のプレリリースバージョンに自動的に更新されます。ただし、プレリリースバージョンは不安定な場合があるため、実行中のプロジェクトがある場合はこのオプションを有効にしないでください。",
|
||||
"data.separator.spacer": "スペーサー",
|
||||
"data.separator.linebreak": "改行",
|
||||
"data.setting": "Setting",
|
||||
"generic.select_all": "全てを選択",
|
||||
"generic.select_all": "すべて選択",
|
||||
"generic.select_none": "クリア",
|
||||
"projects.new_tab": "New Tab",
|
||||
"projects.close_tab": "Close Tab",
|
||||
@ -1352,8 +1346,8 @@
|
||||
"settings.vertex_merge_distance.desc": "頂点がマージされる距離を変更します",
|
||||
"settings.show_only_selected_uv": "セレクト UV",
|
||||
"settings.show_only_selected_uv.desc": "選択した UV フェイスのみを UV エディタに表示します",
|
||||
"action.merge_vertices.merge_all": "全てマージ",
|
||||
"action.merge_vertices.merge_all_in_center": "中央に全てマージ",
|
||||
"action.merge_vertices.merge_all": "すべてマージ",
|
||||
"action.merge_vertices.merge_all_in_center": "中央にすべてマージ",
|
||||
"action.merge_vertices.merge_by_distance": "距離マージ",
|
||||
"action.merge_vertices.merge_by_distance_in_center": "中央に距離マージ",
|
||||
"action.uv_rotate_left": "UV を左回転",
|
||||
@ -1362,12 +1356,12 @@
|
||||
"action.uv_rotate_right.desc": "選択した UV フェイスを時計回りに回転します",
|
||||
"menu.uv.display_uv": "UV を表示",
|
||||
"menu.uv.display_uv.selected_faces": "選択したフェイス",
|
||||
"menu.uv.display_uv.selected_elements": "全てのフェイス",
|
||||
"menu.uv.display_uv.selected_elements": "すべてのフェイス",
|
||||
"menu.uv.display_uv.all_elements": "All Faces on All Elements",
|
||||
"menu.paste.face": "UV フェイス",
|
||||
"menu.paste.mesh_selection": "メッシュの選択",
|
||||
"menu.paste.outliner": "エレメント",
|
||||
"uv_editor.show_all_faces": "全てのフェイスを表示",
|
||||
"uv_editor.show_all_faces": "すべてのフェイスを表示",
|
||||
"uv_editor.show_selected_faces": "選択したフェイスを表示",
|
||||
"status_bar.selection.edges": "%0 個のエッジ",
|
||||
"action.selection_mode.edge": "エッジ",
|
||||
@ -1398,8 +1392,8 @@
|
||||
"settings.status_bar_modifier_keys.desc": "状況に応じた修飾キーをステータスバーに表示します",
|
||||
"settings.ground_plane": "グランド",
|
||||
"settings.ground_plane.desc": "モデルの下にグランドを表示します",
|
||||
"settings.preview_paste_behavior": "デフォルトプレビュー",
|
||||
"settings.preview_paste_behavior.desc": "プレビューに貼り付けるときのオプションを変更します",
|
||||
"settings.preview_paste_behavior": "デフォルトビューポート",
|
||||
"settings.preview_paste_behavior.desc": "編集モードでビューポートにペーストする際の動作を選択し、複数のオプションを利用できるようにします",
|
||||
"settings.preview_paste_behavior.always_ask": "常に尋ねる",
|
||||
"action.new_window": "新規ウィンドウ",
|
||||
"action.new_window.desc": "新しい Blockbench ウィンドウを開きます",
|
||||
@ -1607,12 +1601,12 @@
|
||||
"menu.mirror_painting.global.desc": "グローバル空間でミラーペインティングを有効にします",
|
||||
"menu.mirror_painting.local": "ローカル対称性",
|
||||
"menu.mirror_painting.local.desc": "ローカル空間でミラーペインティングを有効にします",
|
||||
"menu.mirror_painting.texture_frames": "アニメーションフレームをリピート",
|
||||
"menu.mirror_painting.texture_frames": "フリップフレームをリピート",
|
||||
"menu.mirror_painting.texture_frames.desc": "すべてのフレームにペイントストロークをミラーリングします",
|
||||
"format.bedrock_block.info.size_limit": "ブロックの合計サイズは 30 ピクセル以内に制限されています。",
|
||||
"format.bedrock_block.info.textures": "Blockbench では、複数のテクスチャをさまざまなキューブに適用できますが、ゲーム内で正しく機能させるには、リソースパックに追加の設定が必要です。",
|
||||
"format.image.desc": "2D 画像エディタ",
|
||||
"generic.delete_all": "全てを削除",
|
||||
"generic.delete_all": "すべて削除",
|
||||
"message.child_model_only.open": "親モデルを開く",
|
||||
"message.child_model_only.open_with_textures": "親モデルからテクスチャを適用します",
|
||||
"dialog.project.credit": "クレジット",
|
||||
@ -1679,7 +1673,7 @@
|
||||
"menu.animator.rotation_global": "グローバルスペースで回転",
|
||||
"uv_editor.face_properties": "プロパティ",
|
||||
"uv_editor.face_properties.material_instance": "マテリアルインスタンス",
|
||||
"uv_editor.tint.info": "チルトを有効にして、Minecraft に色合いを付けます。 ただし、葉やレッドストーンダストなどの特定のブロックでのみ使用でき、値は 0 のみです。",
|
||||
"uv_editor.tint.info": "Tint を有効にすると、Minecraft に色合いを指定できます。バニラでは、色合いは葉っぱやレッドストーンダストなどの特定のブロックにのみ使用できます。",
|
||||
"uv_editor.cullface.info": "カリングを有効にすると、Minecraft ワールド内で別のブロックが隣接した場合、ブロックのレンダリングが解除されます。これにより、ゲーム内のパフォーマンスが最適化されます。",
|
||||
"uv_editor.material_instance.info": "マテリアルインスタンスはリソースパックの block.json ファイルにて、フェイスに特定のテクスチャとマテリアルを割り当てることができます。",
|
||||
"display.reference.frame_invisible": "額縁(透明)",
|
||||
@ -1694,7 +1688,7 @@
|
||||
"settings_profile.confirm_delete": "プロファイルの設定を削除してもよろしいですか?",
|
||||
"settings_profile.condition.type.selectable": "手動で選択",
|
||||
"settings.interface_mode": "UI モード",
|
||||
"settings.interface_mode.desc": "お使いの端末に最適なインターフェースを選択します",
|
||||
"settings.interface_mode.desc": "インターフェースモード",
|
||||
"settings.interface_mode.auto": "オート",
|
||||
"settings.interface_mode.desktop": "デスクトップ",
|
||||
"settings.interface_mode.mobile": "モバイル",
|
||||
@ -1818,7 +1812,6 @@
|
||||
"menu.uv.flip_x": "Mirror X",
|
||||
"menu.uv.flip_y": "Mirror Y",
|
||||
"menu.mirror_painting.enabled": "有効",
|
||||
"menu.mirror_painting.configure_texture_center": "テクスチャセンターを設定...",
|
||||
"reference_image.position": "Position",
|
||||
"reference_image.size": "Size",
|
||||
"reference_image.rotation": "Rotation",
|
||||
@ -1832,7 +1825,7 @@
|
||||
"reference_image.layer.blueprint": "設計図をロック",
|
||||
"reference_image.scope": "スコープ",
|
||||
"reference_image.scope.project": "このプロジェクトのみ",
|
||||
"reference_image.scope.global": "全てのプロジェクト",
|
||||
"reference_image.scope.global": "すべてのプロジェクト",
|
||||
"reference_image.enabled_modes": "モードで有効",
|
||||
"codec.common.encoding": "エンコード",
|
||||
"codec.common.armature": "グループをアマチュアとしてエクスポート",
|
||||
@ -1868,7 +1861,7 @@
|
||||
"dialog.unsaved_work.title": "Unsaved Work",
|
||||
"dialog.unsaved_work.text": "次のプロジェクトには、保存されていない変更が含まれています。 変更を保存しますか?",
|
||||
"dialog.unsaved_work.discard_all": "破棄",
|
||||
"dialog.unsaved_work.save_all": "全て保存",
|
||||
"dialog.unsaved_work.save_all": "すべて保存",
|
||||
"dialog.resize_texture.mode": "モード",
|
||||
"dialog.resize_texture.mode.crop": "トリミング/拡大",
|
||||
"dialog.resize_texture.mode.scale": "スケール",
|
||||
@ -1919,7 +1912,7 @@
|
||||
"action.split_screen.triple_top": "トリプルトップ",
|
||||
"action.split_screen.triple_bottom": "トリプルボトム",
|
||||
"action.uv_project_from_view": "UV プロジェクト",
|
||||
"action.uv_project_from_view.desc": "3D ビューの視点から選択した UV を自動的に生成します",
|
||||
"action.uv_project_from_view.desc": "3D ビューから選択した UV を自動的に生成します",
|
||||
"action.graph_editor_other_graphs": "他のグラフを表示",
|
||||
"action.graph_editor_other_graphs.desc": "選択されていない軸のグラフを表示します",
|
||||
"action.graph_editor_include_other_graphs": "他のグラフを含める",
|
||||
@ -2022,11 +2015,6 @@
|
||||
"action.save_animation_preset.desc": "選択したキーフレームをアニメーションプリセットとして保存します",
|
||||
"action.animation_onion_skin": "アニメートレイヤースキン",
|
||||
"action.animation_onion_skin.desc": "アニメーション中ののワイヤーフレームビューを参照用に表示します",
|
||||
"action.animation_onion_skin.off": "オフ",
|
||||
"action.animation_onion_skin.select": "選択",
|
||||
"action.animation_onion_skin.previous": "戻す",
|
||||
"action.animation_onion_skin.next": "進む",
|
||||
"action.animation_onion_skin.previous_next": "戻す + 進む",
|
||||
"action.apply_animation_preset": "アニメーションプリセットを適用",
|
||||
"action.apply_animation_preset.desc": "アニメーションのプリセットリストから選択して、ボーンに適用します",
|
||||
"menu.brush_presets.pixel_perfect": "パーフェクトピクセルブラシ",
|
||||
@ -2040,8 +2028,6 @@
|
||||
"settings.final_newline.desc": "ファイルの末尾に改行を挿入します",
|
||||
"action.crop_layer_to_selection": "レイヤーを選択範囲にトリミング",
|
||||
"action.edit_mode_uv_overlay.desc": "編集モードで UV マップをオーバーレイとして表示します",
|
||||
"action.animation_onion_skin_selective": "トグルレイヤースキン",
|
||||
"action.animation_onion_skin_selective.desc": "選択したレイヤースキンのみを表示します",
|
||||
"menu.image": "Image",
|
||||
"menu.texture.discard_changes": "元に戻す",
|
||||
"menu.texture.discard_changes.desc": "ファイルから最新バージョンをダウンロードします",
|
||||
@ -2059,65 +2045,65 @@
|
||||
"message.optimize_animation.keyframes_removed": "%0 個の余分なキーフレームを削除しました",
|
||||
"message.optimize_animation.nothing_to_optimize": "すでに最適化されています",
|
||||
"message.duplicate_bone_copy_animation.title": "アニメーションをコピー",
|
||||
"message.duplicate_bone_copy_animation.message": "The duplicated bone is animated in %0 animations. Do you want to copy the keyframes over to the new bone?",
|
||||
"message.auto_fix_mesh_edit.title": "Auto Fix",
|
||||
"message.auto_fix_mesh_edit.revert": "Revert Edit",
|
||||
"message.auto_fix_mesh_edit.overlapping_vertices": "Certain vertices have been moved into the same spot. How would you like to proceed?",
|
||||
"message.auto_fix_mesh_edit.concave_quads": "One or more quad faces are now concave, which can cause issues in UV-mapping and rendering. Blockbench can automatically fix it for you:",
|
||||
"message.auto_fix_mesh_edit.merge_vertices": "Merge Vertices",
|
||||
"message.auto_fix_mesh_edit.split_quads": "Split Quads",
|
||||
"message.duplicate_bone_copy_animation.message": "複製したボーンは %0 でアニメーション化されています。キーフレームを新しいボーンにコピーしますか?",
|
||||
"message.auto_fix_mesh_edit.title": "オートフィックス",
|
||||
"message.auto_fix_mesh_edit.revert": "編集を取り消す",
|
||||
"message.auto_fix_mesh_edit.overlapping_vertices": "いくつかの頂点が同じ場所に移動されました。",
|
||||
"message.auto_fix_mesh_edit.concave_quads": "フェイスが凹状になり、UV マッピングとレンダリングで問題が発生する可能性があります。Blockbench はこれを自動的に修正します:",
|
||||
"message.auto_fix_mesh_edit.merge_vertices": "頂点をマージ",
|
||||
"message.auto_fix_mesh_edit.split_quads": "スプリットクワッド",
|
||||
"message.load_images.add_image": "画像を追加",
|
||||
"dialog.project.modded_entity_entity_class": "Entity Class",
|
||||
"dialog.resize_texture.offset": "Offset",
|
||||
"dialog.animated_texture_editor.code_reference": "Code Reference",
|
||||
"dialog.project.modded_entity_entity_class": "エンティティクラス",
|
||||
"dialog.resize_texture.offset": "オフセット",
|
||||
"dialog.animated_texture_editor.code_reference": "コードリファレンス",
|
||||
"dialog.animated_texture_editor.code_reference.about": "このコードはテクスチャアニメーションを実装するための参考用に作成されたものであり、そのままでは動作しない場合があります。詳細については、ドキュメントを参照してください。",
|
||||
"dialog.animated_texture_editor.code_reference.docs": "Documentation",
|
||||
"dialog.animated_texture_editor.code_reference.docs": "ドキュメント",
|
||||
"dialog.animated_texture_editor.reframe": "リフレーム",
|
||||
"dialog.animated_texture_editor.stride": "フレームサイズ",
|
||||
"dialog.animated_texture_editor.frames": "フレーム数",
|
||||
"dialog.animated_texture_editor.add_frame": "フレームを追加",
|
||||
"dialog.animated_texture_editor.resize_frames": "フレームをリサイズ...",
|
||||
"dialog.animated_texture_editor.apply": "適応",
|
||||
"dialog.add_primitive.edge_size": "Edge Size",
|
||||
"dialog.add_primitive.edge_size": "エッジサイズ",
|
||||
"dialog.change_animation_speed.speed": "スピード",
|
||||
"dialog.change_animation_speed.adjust_snapping": "Adjust Snapping",
|
||||
"dialog.optimize_animation.selection": "Selection",
|
||||
"dialog.change_animation_speed.adjust_snapping": "スナップを調整",
|
||||
"dialog.optimize_animation.selection": "選択",
|
||||
"dialog.optimize_animation.selection.selected_keyframes": "キーフレーム",
|
||||
"dialog.optimize_animation.selection.selected_animation": "アニメーション",
|
||||
"dialog.optimize_animation.selection.all_animations": "全てのアニメーション",
|
||||
"dialog.optimize_animation.thresholds": "Threshold values",
|
||||
"dialog.optimize_animation.selection.all_animations": "すべてのアニメーション",
|
||||
"dialog.optimize_animation.thresholds": "値",
|
||||
"dialog.import_obj.obj": "OBJ ファイル",
|
||||
"dialog.import_obj.mtl": "MTL ファイル",
|
||||
"dialog.import_obj.scale": "スケール",
|
||||
"layout.thumbnail": "Custom Thumbnail CSS",
|
||||
"layout.thumbnail": "カスタムサムネイル CSS",
|
||||
"settings.pixel_grid": "ピクセルグリット",
|
||||
"settings.pixel_grid.desc": "エディットモードで、テクスチャにピクセルグリッドを表示します",
|
||||
"settings.image_editor_grid_size": "画像エディタのグリットサイズ",
|
||||
"settings.image_editor_grid_size.desc": "画像エディタの最大グリットサイズを変更します",
|
||||
"settings.ground_plane_double_side": "Ground Plane Double-sided",
|
||||
"settings.ground_plane_double_side.desc": "Make the ground plane visible from below",
|
||||
"settings.optifine_save_default_texture": "OptiFine JEM: Export selected texture",
|
||||
"settings.optifine_save_default_texture": "OptiFine JEM : テクスチャをエクスポート",
|
||||
"settings.optifine_save_default_texture.desc": "選択したテクスチャをモデルのデフォルトテクスチャとしてエクスポートします",
|
||||
"action.slider_color_select_threshold": "Color Select Threshold",
|
||||
"action.slider_color_select_threshold": "カラー選択しきい値",
|
||||
"action.slider_color_select_threshold.desc": "How close the color of a neighboring pixel has to be to get selected by color or wand select",
|
||||
"action.stretch_tool": "ストレッチ",
|
||||
"action.stretch_tool.desc": "Tool to select and stretch elements",
|
||||
"action.stretch_tool.desc": "要素を引き伸ばします",
|
||||
"action.knife_tool": "ナイフ",
|
||||
"action.knife_tool.desc": "Tool to cut mesh faces into smaller pieces",
|
||||
"action.knife_tool.desc": "メッシュを小さくカットします",
|
||||
"action.duplicate_project": "プロジェクトを複製",
|
||||
"action.duplicate_project.desc": "Creates a copy of the open project",
|
||||
"action.duplicate_project.desc": "進行中のプロジェクトのコピーを作成します",
|
||||
"action.transform_space.parent": "Parent",
|
||||
"action.transform_pivot_space": "Pivot Transform Space",
|
||||
"action.solidify_mesh_selection": "Solidify Faces",
|
||||
"action.solidify_mesh_selection.desc": "Solidify the selected faces of the mesh",
|
||||
"action.solidify_mesh_selection": "ソリット化",
|
||||
"action.solidify_mesh_selection.desc": "選択したフェイスをソリッド化します",
|
||||
"action.animated_texture_editor": "フリップブックアニメーション...",
|
||||
"action.animated_texture_editor.desc": "テクスチャのフリップブックアニメーションを設定、または編集します",
|
||||
"action.center_individual_pivots": "Center Individual Pivots",
|
||||
"action.center_individual_pivots.desc": "Set the pivot point of each selected element to its center",
|
||||
"action.uv_cycle": "Cycle UV",
|
||||
"action.uv_cycle.desc": "Cycle through the order of UV vertices without changing the UV positions",
|
||||
"action.uv_cycle_invert": "Cycle Invert UV",
|
||||
"action.uv_cycle_invert.desc": "Reverse the order of UV vertices without changing the UV positions",
|
||||
"action.center_individual_pivots": "センターピボット",
|
||||
"action.center_individual_pivots.desc": "選択したピボットポイントを中心に設定します",
|
||||
"action.uv_cycle": "サイクル UV",
|
||||
"action.uv_cycle.desc": "UV 頂点の順序を循環します",
|
||||
"action.uv_cycle_invert": "逆サイクル UV",
|
||||
"action.uv_cycle_invert.desc": "UV 頂点の順序を逆にします",
|
||||
"action.slider_animation_controller_speed": "Controller Playback Speed",
|
||||
"action.slider_animation_controller_speed.desc": "アニメーションコントローラの再生速度",
|
||||
"action.optimize_animation": "アニメーションを最適化",
|
||||
@ -2130,103 +2116,215 @@
|
||||
"menu.texture.particle.clear": "パーティクルを使用しない",
|
||||
"menu.texture.use_as_default": "デフォルトに設定",
|
||||
"menu.texture.use_as_default.clear": "デフォルトを解除",
|
||||
"menu.toolbar.overflow": "Toolbar Overflow",
|
||||
"menu.toolbar.overflow": "ツールバーフロー",
|
||||
"edit.solidify_mesh_selection.thickness": "ティックネス",
|
||||
"reference_image.sync_to_timeline": "タイムラインに同期",
|
||||
"reference_image.toggle_playback": "プレイ/ポーズ",
|
||||
"dialog.add_primitive.shape.beveled_cuboid": "Beveled Cuboid",
|
||||
"dialog.ignore_all": "Ignore All",
|
||||
"data.texture_group": "Texture Group",
|
||||
"data.animation": "Animation",
|
||||
"dialog.ignore_all": "すべて無視",
|
||||
"data.texture_group": "テクスチャグループ",
|
||||
"data.animation": "アニメーション",
|
||||
"generic.on": "On",
|
||||
"generic.off": "Off",
|
||||
"format.free.info.3d_printing": "3D Printing",
|
||||
"format.free.info.3d_printing": "3D プリント",
|
||||
"message.invalid_file.merge_conflict": "The file contains unresolved Git merge conflicts.",
|
||||
"dialog.expand_texture_selection.radius": "Amount",
|
||||
"dialog.expand_texture_selection.corner": "Corner Shape",
|
||||
"dialog.expand_texture_selection.corner.round": "Round",
|
||||
"dialog.expand_texture_selection.corner.square": "Square",
|
||||
"dialog.expand_texture_selection.corner.manhattan": "Manhattan",
|
||||
"dialog.merge_animation.merge_target": "Merge into",
|
||||
"dialog.expand_texture_selection.radius": "大きさ",
|
||||
"dialog.expand_texture_selection.corner": "コーナーシェイプ",
|
||||
"dialog.expand_texture_selection.corner.round": "角度",
|
||||
"dialog.expand_texture_selection.corner.square": "四角形",
|
||||
"dialog.expand_texture_selection.corner.manhattan": "マンハッタン",
|
||||
"dialog.merge_animation.merge_target": "マージ",
|
||||
"keybindings.variation_conflict": "Variation conflicts with the main keybinding",
|
||||
"settings.recovery_save_interval": "Recovery Point Save Interval",
|
||||
"settings.recovery_save_interval": "リカバリーポイント間隔",
|
||||
"settings.recovery_save_interval.desc": "Blockbench regularly saves the open project in the background to recover in case of a computer crash. Set the interval in seconds. Set to 0 to disable saving.",
|
||||
"settings.save_view_per_tab": "Save View per Tab",
|
||||
"settings.save_view_per_tab": "タブごとにビューを保存",
|
||||
"settings.save_view_per_tab.desc": "Save the current view angle for each tab separately",
|
||||
"settings.inherit_parent_color": "Inherit Parent Color",
|
||||
"settings.inherit_parent_color.desc": "Set the marker color of a newly created element to the color of the parent instead of a random color",
|
||||
"keybind.preview_select.multi_select": "Multi-select",
|
||||
"keybind.preview_select.group_select": "Group-select",
|
||||
"keybind.preview_select.loop_select": "Loop-select",
|
||||
"action.fill_mode.selection": "Selection",
|
||||
"keybind.preview_select.multi_select": "選択-複数",
|
||||
"keybind.preview_select.group_select": "選択-グループ",
|
||||
"keybind.preview_select.loop_select": "選択-ループ",
|
||||
"action.fill_mode.selection": "選択",
|
||||
"action.fill_mode.selected_elements": "Selected Elements",
|
||||
"action.image_tiled_view": "Tiled View",
|
||||
"action.image_tiled_view.description": "Enable the tiled view in the 2D editor",
|
||||
"action.image_tiled_view": "タイル表示",
|
||||
"action.image_tiled_view.description": "2D エディタでタイル表示を有効にします",
|
||||
"action.image_onion_skin_view": "Image Editor Onion Skin",
|
||||
"action.image_onion_skin_view.description": "Enable the onion skin view in the 2D editor",
|
||||
"action.expand_texture_selection": "Expand Texture Selection",
|
||||
"action.expand_texture_selection.desc": "Expand or shrink the texture selection",
|
||||
"action.switch_tabs.reverse_order": "Reverse order",
|
||||
"action.save_project_incremental": "Save Project With Increment",
|
||||
"action.save_project_incremental.desc": "Saves the current model as a project file with an increment (ex: project_2.bbmodel)",
|
||||
"action.copy.multiple": "Copy All",
|
||||
"action.copy.multiple.desc": "Copy all available data individually",
|
||||
"action.paste.multiple": "Paste All",
|
||||
"action.randomize_marker_colors": "Randomize Marker Colors",
|
||||
"action.cube_light_emission": "Light Emission",
|
||||
"action.cube_light_emission.desc": "Change the emissiveness of the selected cubes, as a value between 0 and 15",
|
||||
"action.image_onion_skin_view.description": "2D エディタでオニオンスキン表示を有効にします",
|
||||
"action.expand_texture_selection": "テクスチャ選択範囲の拡張",
|
||||
"action.expand_texture_selection.desc": "テクスチャの選択範囲を拡大または縮小します",
|
||||
"action.switch_tabs.reverse_order": "逆順",
|
||||
"action.save_project_incremental": "Increment プロジェクトを保存",
|
||||
"action.save_project_incremental.desc": "現在のモデルをプロジェクトファイルとしてインクリメント付きで保存します (ex: project_2.bbmodel)",
|
||||
"action.copy.multiple": "すべてコピー",
|
||||
"action.copy.multiple.desc": "利用可能なすべてのデータを個別にコピーします",
|
||||
"action.paste.multiple": "すべて貼り付け",
|
||||
"action.randomize_marker_colors": "ランダムなマーカーカラー",
|
||||
"action.cube_light_emission": "光源レベル",
|
||||
"action.cube_light_emission.desc": "選択したキューブの発光レベルを 0 ~ 15 の値で変更します,",
|
||||
"action.view_mode.colored_solid": "Solid with Marker Colors",
|
||||
"action.focus_on_selection.rotate_only": "Rotate only",
|
||||
"action.create_texture_group": "Create Texture Group",
|
||||
"action.create_texture_group.desc": "Create a group for your textures",
|
||||
"action.uv_maximize.all_faces": "Affect all faces",
|
||||
"action.retarget_animators": "Retarget Animations",
|
||||
"action.retarget_animators.desc": "Select which animator targets which bone or element",
|
||||
"action.merge_animation": "Merge Animation",
|
||||
"action.merge_animation.desc": "Merge the animation into another animation",
|
||||
"action.add_keyframe.reset_values": "With default values",
|
||||
"action.set_timeline_range_start": "Set Timeline Range Start",
|
||||
"action.set_timeline_range_start.desc": "Set the start point for a custom playback range in the animation timeline",
|
||||
"action.set_timeline_range_end": "Set Timeline Range End",
|
||||
"action.set_timeline_range_end.desc": "Set the end point for a custom playback range in the animation timeline",
|
||||
"action.disable_timeline_range": "Disable Timeline Range",
|
||||
"action.disable_timeline_range.desc": "Disable the custom playback range in the animation timeline",
|
||||
"menu.texture_group.resolve": "Resolve",
|
||||
"action.focus_on_selection.rotate_only": "ローテートのみ",
|
||||
"action.create_texture_group": "テクスチャグループを作成",
|
||||
"action.create_texture_group.desc": "テクスチャごとにグループを作成します",
|
||||
"action.uv_maximize.all_faces": "すべてのフェイスに適用",
|
||||
"action.retarget_animators": "アニメーションをリターゲット",
|
||||
"action.retarget_animators.desc": "アニメーターが新たにターゲットを再選択します",
|
||||
"action.merge_animation": "アニメーションをマージ",
|
||||
"action.merge_animation.desc": "アニメーションを別のアニメーションに結合します",
|
||||
"action.add_keyframe.reset_values": "デフォルト値",
|
||||
"action.set_timeline_range_start": "タイムラインの開始点を設定します",
|
||||
"action.set_timeline_range_start.desc": "アニメーションタイムラインで再生範囲の開始点を設定します",
|
||||
"action.set_timeline_range_end": "タイムラインの終点を設定します",
|
||||
"action.set_timeline_range_end.desc": "アニメーションタイムラインで再生範囲の終点を設定します",
|
||||
"action.disable_timeline_range": "タイムライン範囲を無効",
|
||||
"action.disable_timeline_range.desc": "アニメーションタイムラインのカスタム再生範囲を無効にします",
|
||||
"menu.texture_group.resolve": "確定",
|
||||
"menu.image_tiled_view.mirrored": "Mirrored Edges",
|
||||
"menu.image_onion_skin_view.frame": "Frames",
|
||||
"menu.image_onion_skin_view.frame.last_viewed": "Last Viewed Frame",
|
||||
"menu.image_onion_skin_view.frame.previous": "Previous Frame",
|
||||
"menu.image_onion_skin_view.frame.next": "Next Frame",
|
||||
"menu.image_onion_skin_view.frame.both": "Previous + Next",
|
||||
"menu.image_onion_skin_view.display": "Display",
|
||||
"menu.image_onion_skin_view.frame": "フレーム",
|
||||
"menu.image_onion_skin_view.frame.last_viewed": "前回のフレーム",
|
||||
"menu.image_onion_skin_view.frame.previous": "前のフレーム",
|
||||
"menu.image_onion_skin_view.frame.next": "次のフレーム",
|
||||
"menu.image_onion_skin_view.frame.both": "比較",
|
||||
"menu.image_onion_skin_view.display": "表示",
|
||||
"menu.image_onion_skin_view.display.pixels": "Smaller Pixels",
|
||||
"menu.image_onion_skin_view.display.transparent": "Transparent",
|
||||
"menu.image_onion_skin_view.above": "Display Above",
|
||||
"menu.animation.reload": "Reload",
|
||||
"switches.autouv.alt": "Relative",
|
||||
"display.rotation_pivot": "Rotation Pivot",
|
||||
"display.scale_pivot": "Scale Pivot",
|
||||
"display.reference.fox": "Fox",
|
||||
"display.reference.eating": "Eating",
|
||||
"preview_scene.sky": "Sky",
|
||||
"preview_scene.space": "Space",
|
||||
"preview_scene.minecraft_ocean": "Ocean",
|
||||
"message.import_palette.selection_only": "Selection only",
|
||||
"dialog.blend_transition_edit.ease_in_out": "Ease-in-out (%0)",
|
||||
"dialog.blend_transition_edit.generate": "Generate...",
|
||||
"dialog.blend_transition_edit.generate.learn_more": "More info and preview",
|
||||
"dialog.blend_transition_edit.generate.curve": "Easing Type",
|
||||
"dialog.blend_transition_edit.generate.steps": "Keyframes",
|
||||
"settings.fps_limit": "FPS Limit",
|
||||
"settings.fps_limit.desc": "Limit how many frames per second Blockbench renders. The actual frame rate is limited to what your device can display.",
|
||||
"settings.outliner_reveal_on_select": "Reveal Elements on Select",
|
||||
"settings.outliner_reveal_on_select.desc": "Reveal elements in the ouliner when selected",
|
||||
"settings.java_export_pivots": "Export Pivots in Java block/item models",
|
||||
"settings.java_export_pivots.desc": "Save pivot points in Java block/item models on cubes without rotation",
|
||||
"animation_controllers.state.blend_transition_curve": "Blend Transition Curve",
|
||||
"menu.slider.reset_vector": "Reset Vector",
|
||||
"dialog.blend_transition_edit.extended": "Extended Graph",
|
||||
"message.screenshot_too_large.title": "Screenshot Resolution Issue",
|
||||
"message.screenshot_too_large.message": "The screenshot could not be rendered successfully. Please try again with a lower resolution or without supersampling.",
|
||||
"message.rename_elements.numbering": "You can use special characters to generate sequential numbers: % to get the index of the element within its group, $ to get the index within the selection."
|
||||
"menu.image_onion_skin_view.display.transparent": "透明",
|
||||
"menu.image_onion_skin_view.above": "上部に表示",
|
||||
"menu.animation.reload": "リロード",
|
||||
"switches.autouv.alt": "相対",
|
||||
"display.rotation_pivot": "ピボットローテーション",
|
||||
"display.scale_pivot": "ピボットスケール",
|
||||
"display.reference.fox": "キツネ",
|
||||
"display.reference.eating": "食べる",
|
||||
"preview_scene.sky": "空",
|
||||
"preview_scene.space": "スペース",
|
||||
"preview_scene.minecraft_ocean": "海",
|
||||
"message.import_palette.selection_only": "選択のみ",
|
||||
"dialog.blend_transition_edit.ease_in_out": "イーズインアウト (%0)",
|
||||
"dialog.blend_transition_edit.generate": "生成する...",
|
||||
"dialog.blend_transition_edit.generate.learn_more": "詳細情報とプレビュー",
|
||||
"dialog.blend_transition_edit.generate.curve": "イージングタイプ",
|
||||
"dialog.blend_transition_edit.generate.steps": "キーフレーム",
|
||||
"settings.fps_limit": "フレームレート",
|
||||
"settings.fps_limit.desc": "Blockbench が 1 秒あたりにレンダリングするフレーム数を制限します。実際のフレームレートは、お使いのデバイスによって変動します。",
|
||||
"settings.outliner_reveal_on_select": "エレメントをハイライト",
|
||||
"settings.outliner_reveal_on_select.desc": "選択されたエレメントをハイライト表示します",
|
||||
"settings.java_export_pivots": "java block/item をピボットでエクスポート",
|
||||
"settings.java_export_pivots.desc": "キューブ上の Java ブロック/アイテムモデルのピボットポイントを保存します",
|
||||
"animation_controllers.state.blend_transition_curve": "ブレンド遷移曲線",
|
||||
"menu.slider.reset_vector": "ベクトルをリセット",
|
||||
"dialog.blend_transition_edit.extended": "拡張グラフ",
|
||||
"message.screenshot_too_large.title": "スクリーンショット解像度エラー",
|
||||
"message.screenshot_too_large.message": "スクリーンショットがうまく表示されませんでした。解像度を下げるか、スーパーサンプリングをオフにして再度お試しください。",
|
||||
"message.rename_elements.numbering": "連番を生成する際に、特殊文字を活用することができます: % を使うと、グループのインデックスを取得でき、 $ を使うと、選択範囲のインデックスを取得することが出来ます。",
|
||||
"generic.edit_externally": "Edit Externally",
|
||||
"message.settings_require_restart.title": "再起動が必要です",
|
||||
"message.settings_require_restart.message": "一部の設定は、アプリを再起動したあとに適用されます。",
|
||||
"message.settings_require_restart.restart_now": "今すぐ再起動",
|
||||
"message.settings_require_restart.restart_later": "あとで再起動",
|
||||
"message.classroom_mode.install_plugin": "クラスルームモードではプラグインをインストールできません",
|
||||
"dialog.collection.export_path": "Export Path",
|
||||
"dialog.collection.select_all": "すべて選択",
|
||||
"dialog.collection.select_none": "Select None",
|
||||
"dialog.collection.add_with_filter": "Add with Filter",
|
||||
"dialog.collection.remove": "削除",
|
||||
"dialog.material_config.title": "Material Config",
|
||||
"dialog.material_config.color_value": "Color Value",
|
||||
"dialog.material_config.mer": "Metal-Emissive-Roughness",
|
||||
"dialog.material_config.mer_value": "MER Value",
|
||||
"dialog.material_config.depth_type": "Depth Type",
|
||||
"dialog.create_texture.disable_mirror_uv": "UV ミラーリングを無効",
|
||||
"dialog.create_texture.disable_mirror_uv.desc": "ミラーモデリングの UV ミラーオプションを無効にし、フェイスごとに個別の UV を保存します",
|
||||
"dialog.create_gif.turn.sync_to_anim_length": "Sync to animation length",
|
||||
"settings.category.controls": "コントロール",
|
||||
"settings.classroom_mode": "クラスルームモード",
|
||||
"settings.classroom_mode.desc": "Restricts functionality such as installing plugins and removes links to social media",
|
||||
"settings.antialiasing_bleed_fix": "Fix anti-aliasing bleeding",
|
||||
"settings.antialiasing_bleed_fix.desc": "Fixes texture bleeding when using anti-aliasing. Potentially unsupported on older hardware.",
|
||||
"settings.tone_mapping": "トーンマッピング",
|
||||
"settings.tone_mapping.desc": "PBR レンダリングにハイダイナミックレンジを表示します。",
|
||||
"settings.audio_scrubbing": "Timline Scrubbing Audio",
|
||||
"settings.audio_scrubbing.desc": "Play short previews of the audio while scrubbing through time timeline",
|
||||
"settings.viewport_rotate_speed": "ビューポート回転速度",
|
||||
"settings.viewport_rotate_speed.desc": "Input sensitivity when rotating in the viewport",
|
||||
"settings.viewport_zoom_speed": "ビューポートズーム速度",
|
||||
"settings.viewport_zoom_speed.desc": "Input sensitivity when zooming in the viewport",
|
||||
"settings.editor_2d_zoom_speed": "2D エディタのズーム速度",
|
||||
"settings.editor_2d_zoom_speed.desc": "UV および 2D ペイントエディタでズームするときの速度を変更します",
|
||||
"category.select": "Select",
|
||||
"action.vertex_snap_mode.rotate": "回転",
|
||||
"action.export_image": "画像をエクスポート",
|
||||
"action.export_image.desc": "Export your texture as an image file",
|
||||
"action.apply_mirror_modeling": "Apply Mirror Modeling",
|
||||
"action.apply_mirror_modeling.desc": "Apply Mirror Modeling to the selection. All selected elements will be copied and flipped across the X axis.",
|
||||
"action.create_collection": "Create Collection",
|
||||
"action.create_collection.desc": "Create a collection out of the outliner selection",
|
||||
"action.set_collection_content_to_selection": "Set Collection Content to Selected",
|
||||
"action.set_collection_content_to_selection.desc": "Set the selected groups and elements as the content of the collection",
|
||||
"action.add_to_collection": "Add Selected to Collection",
|
||||
"action.add_to_collection.desc": "Add the selected groups and elements to the collection",
|
||||
"action.view_mode.material": "マテリアルをプレビュー",
|
||||
"action.create_material": "マテリアルを作成",
|
||||
"action.create_material.desc": "Create a new PBR material out of the selected texture",
|
||||
"action.generate_pbr_map": "Generate PBR Map...",
|
||||
"action.generate_pbr_map.desc": "Generate a PBR map (height map or metalness, emissiveness, roughness) from an existing texture",
|
||||
"menu.tools.main_tools": "Toolbox",
|
||||
"menu.view.panels": "Panels",
|
||||
"menu.texture.pbr_channel": "PBR Channel",
|
||||
"menu.texture.pbr_channel.color": "Color",
|
||||
"menu.texture.pbr_channel.normal": "ノーマル",
|
||||
"menu.texture.pbr_channel.height": "Height",
|
||||
"menu.texture.pbr_channel.mer": "MER (Metalness-Emissive-Roughness)",
|
||||
"menu.texture.pbr_channel.mer_subsurface": "MER Subsurface",
|
||||
"menu.collection.export_project": "プロジェクトをエクスポート",
|
||||
"menu.collection.export_as": "Export as \"%0\"",
|
||||
"menu.panel.enable": "Enable",
|
||||
"menu.panel.move_to": "Move to",
|
||||
"menu.panel.move_to.left_bar": "Left Side",
|
||||
"menu.panel.move_to.right_bar": "Right Side",
|
||||
"menu.panel.move_to.top": "Top",
|
||||
"menu.panel.move_to.bottom": "Bottom",
|
||||
"menu.panel.move_to.float": "Float",
|
||||
"menu.panel.move_to.hidden": "Hide",
|
||||
"menu.panel.fold": "Collapse",
|
||||
"menu.mirror_painting.texture_center": "Origin",
|
||||
"menu.mirror_modeling.mirror_uv": "Mirror UV",
|
||||
"menu.animation_onion_skin.frames": "フレーム",
|
||||
"menu.animation_onion_skin.select": "選択",
|
||||
"menu.animation_onion_skin.previous": "前",
|
||||
"menu.animation_onion_skin.next": "次",
|
||||
"menu.animation_onion_skin.previous_next": "前 + 次",
|
||||
"menu.animation_onion_skin.count": "カウント",
|
||||
"menu.animation_onion_skin.interval": "インターバル",
|
||||
"menu.animation_onion_skin_selective": "Selective Onion Skin",
|
||||
"menu.animation_onion_skin_selective.desc": "Only display onion skin for the selected part of the model",
|
||||
"edit.loop_cut.unit": "ユニット",
|
||||
"edit.loop_cut.unit.size_units": "Size Units",
|
||||
"edit.loop_cut.unit.percent": "Percent",
|
||||
"edit.extrude_mesh_selection.direction": "方向",
|
||||
"edit.extrude_mesh_selection.direction.outwards": "外側",
|
||||
"edit.extrude_mesh_selection.direction.average": "平均",
|
||||
"edit.extrude_mesh_selection.even_extend": "Even Extend",
|
||||
"edit.vertex_snap.align": "整列",
|
||||
"edit.vertex_snap.align.longest": "Longest Axis",
|
||||
"edit.vertex_snap.align.direction": "Direction from Pivot",
|
||||
"edit.vertex_snap.align.align_axis": "%0 軸",
|
||||
"edit.vertex_snap.ignore_axis": "%0 軸を無視",
|
||||
"codec.common.format": "Format",
|
||||
"codec.image.quality": "クオリティ",
|
||||
"panel.collections": "Collections",
|
||||
"modifier_actions.always": "常に有効",
|
||||
"modifier_actions.unless": "%0 を除く",
|
||||
"settings.undo_selections": "巻き戻し選択",
|
||||
"settings.undo_selections.desc": "巻き戻した変更を、ステップごとに追跡します",
|
||||
"action.focus_on_selection.zoom": "ウィンドウにフィット",
|
||||
"display.reference.tooting": "角笛を吹く",
|
||||
"settings.selection_tolerance": "Selection Tolerance",
|
||||
"settings.selection_tolerance.desc": "Size of the area that can be clicked to select an edge or vertex",
|
||||
"action.delete.keep_vertices": "Keep Edges/Vertices",
|
||||
"menu.mesh": "メッシュ",
|
||||
"dialog.material_config.subsurface": "Subsurface Scattering",
|
||||
"dialog.material_config.subsurface_enabled.desc": "Use the MER map alpha channel for subsurface scattering",
|
||||
"settings.pick_combined_color": "Pick Combined Color",
|
||||
"settings.pick_combined_color.desc": "Pick the combined color of all layers at the respective pixel, instead of the color on the active layer",
|
||||
"action.split_rgb_into_layers": "Split RGB Channels into Layers",
|
||||
"action.split_rgb_into_layers.desc": "Split the texture into additive layers, one for each RGB channel"
|
||||
}
|
132
lang/ko.json
@ -164,11 +164,6 @@
|
||||
"layout.font.main": "주 폰트",
|
||||
"layout.font.headline": "헤드라인 폰트",
|
||||
"about.version": "버전:",
|
||||
"about.creator": "제작자:",
|
||||
"about.website": "웹사이트:",
|
||||
"about.vertex_snap": "꼭짓점 맞춤 기능 제작 : SirBenet",
|
||||
"about.icons": "아이콘 팩:",
|
||||
"about.libraries": "라이브러리",
|
||||
"settings.category.general": "일반",
|
||||
"settings.category.preview": "미리보기",
|
||||
"settings.category.grid": "격자",
|
||||
@ -517,7 +512,7 @@
|
||||
"action.cullface.desc": "선택한 모델의 측면이 덮인 경우 이 면에 대한 렌더링 비활성화",
|
||||
"action.auto_cullface": "후면 제거 키기",
|
||||
"action.auto_cullface.desc": "이 표면의 후면 제거를 자체로 설정",
|
||||
"action.face_tint": "옅은 색",
|
||||
"action.face_tint": "색조",
|
||||
"action.face_tint.desc": "현재 표면에 대한 색조 옵션을 사용 가능으로 설정",
|
||||
"menu.toolbar.edit": "사용자 정의",
|
||||
"menu.toolbar.reset": "초기화",
|
||||
@ -1220,7 +1215,6 @@
|
||||
"camera_angle.true_isometric_right": "트루 아이소메트릭 오른쪽 (30°)",
|
||||
"camera_angle.true_isometric_left": "트루 아이소메트릭 왼쪽 (30°)",
|
||||
"menu.help.wiki": "Blockbench 위키",
|
||||
"about.repository": "레포지토리:",
|
||||
"settings.update_to_prereleases": "사전 릴리즈로 업데이트",
|
||||
"settings.update_to_prereleases.desc": "새로운 기능을 테스트하기 위해 블록벤치 베타 버전을 자동으로 업데이트합니다. 사전 릴리스 버전은 불안정할 수 있으며, 작업 또는 기타 중요한 프로젝트에 대해 Blockbench에 의존할 경우 이 옵션을 사용하지 마십시오.",
|
||||
"data.separator.spacer": "스페이서",
|
||||
@ -1818,7 +1812,6 @@
|
||||
"menu.uv.flip_x": "X 반전",
|
||||
"menu.uv.flip_y": "Y 반전",
|
||||
"menu.mirror_painting.enabled": "켜짐",
|
||||
"menu.mirror_painting.configure_texture_center": "텍스쳐 센터 구성...",
|
||||
"reference_image.position": "위치",
|
||||
"reference_image.size": "크기",
|
||||
"reference_image.rotation": "회전",
|
||||
@ -2022,11 +2015,6 @@
|
||||
"action.save_animation_preset.desc": "Save the selected keyframes as an animation preset",
|
||||
"action.animation_onion_skin": "Animation Onion Skin",
|
||||
"action.animation_onion_skin.desc": "Display an wireframe view of a different frame in the animation for reference",
|
||||
"action.animation_onion_skin.off": "Off",
|
||||
"action.animation_onion_skin.select": "Select",
|
||||
"action.animation_onion_skin.previous": "Previous",
|
||||
"action.animation_onion_skin.next": "Next",
|
||||
"action.animation_onion_skin.previous_next": "Previous + Next",
|
||||
"action.apply_animation_preset": "Apply Animation Preset",
|
||||
"action.apply_animation_preset.desc": "Select from a list of animation presets and apply it to the selected bone",
|
||||
"menu.brush_presets.pixel_perfect": "Pixel-perfect Brush",
|
||||
@ -2040,8 +2028,6 @@
|
||||
"settings.final_newline.desc": "Insert a newline character at the end of exported files",
|
||||
"action.crop_layer_to_selection": "Crop Layer to Selection",
|
||||
"action.edit_mode_uv_overlay.desc": "Display the UV map as an overlay in edit mode",
|
||||
"action.animation_onion_skin_selective": "Selective Onion Skin",
|
||||
"action.animation_onion_skin_selective.desc": "Only display onion skin for the selected part of the model",
|
||||
"menu.image": "Image",
|
||||
"menu.texture.discard_changes": "Discard Changes",
|
||||
"menu.texture.discard_changes.desc": "Discard all unsaved changes and load the latest version from the file",
|
||||
@ -2102,7 +2088,7 @@
|
||||
"action.slider_color_select_threshold.desc": "How close the color of a neighboring pixel has to be to get selected by color or wand select",
|
||||
"action.stretch_tool": "Stretch",
|
||||
"action.stretch_tool.desc": "Tool to select and stretch elements",
|
||||
"action.knife_tool": "Knife Tool",
|
||||
"action.knife_tool": "나이프 도구",
|
||||
"action.knife_tool.desc": "Tool to cut mesh faces into smaller pieces",
|
||||
"action.duplicate_project": "Duplicate Project",
|
||||
"action.duplicate_project.desc": "Creates a copy of the open project",
|
||||
@ -2228,5 +2214,117 @@
|
||||
"dialog.blend_transition_edit.extended": "Extended Graph",
|
||||
"message.screenshot_too_large.title": "Screenshot Resolution Issue",
|
||||
"message.screenshot_too_large.message": "The screenshot could not be rendered successfully. Please try again with a lower resolution or without supersampling.",
|
||||
"message.rename_elements.numbering": "You can use special characters to generate sequential numbers: % to get the index of the element within its group, $ to get the index within the selection."
|
||||
"message.rename_elements.numbering": "You can use special characters to generate sequential numbers: % to get the index of the element within its group, $ to get the index within the selection.",
|
||||
"generic.edit_externally": "Edit Externally",
|
||||
"message.settings_require_restart.title": "Restart Required",
|
||||
"message.settings_require_restart.message": "Some settings will only apply after restarting the program.",
|
||||
"message.settings_require_restart.restart_now": "Restart Now",
|
||||
"message.settings_require_restart.restart_later": "Restart Later",
|
||||
"message.classroom_mode.install_plugin": "Cannot install plugins in Classroom Mode",
|
||||
"dialog.collection.export_path": "Export Path",
|
||||
"dialog.collection.select_all": "Select All",
|
||||
"dialog.collection.select_none": "Select None",
|
||||
"dialog.collection.add_with_filter": "Add with Filter",
|
||||
"dialog.collection.remove": "Remove",
|
||||
"dialog.material_config.title": "Material Config",
|
||||
"dialog.material_config.color_value": "Color Value",
|
||||
"dialog.material_config.mer": "Metal-Emissive-Roughness",
|
||||
"dialog.material_config.mer_value": "MER Value",
|
||||
"dialog.material_config.depth_type": "Depth Type",
|
||||
"dialog.create_texture.disable_mirror_uv": "Disable UV Mirroring",
|
||||
"dialog.create_texture.disable_mirror_uv.desc": "Disable the UV Mirror option in Mirror Modeling to preserve separate UVs for each side of the model",
|
||||
"dialog.create_gif.turn.sync_to_anim_length": "Sync to animation length",
|
||||
"settings.category.controls": "Controls",
|
||||
"settings.classroom_mode": "Classroom Mode",
|
||||
"settings.classroom_mode.desc": "Restricts functionality such as installing plugins and removes links to social media",
|
||||
"settings.antialiasing_bleed_fix": "Fix anti-aliasing bleeding",
|
||||
"settings.antialiasing_bleed_fix.desc": "Fixes texture bleeding when using anti-aliasing. Potentially unsupported on older hardware.",
|
||||
"settings.tone_mapping": "Tone Mapping",
|
||||
"settings.tone_mapping.desc": "Approximation method for displaying high dynamic range on a standard screen for PBR rendering.",
|
||||
"settings.audio_scrubbing": "Timline Scrubbing Audio",
|
||||
"settings.audio_scrubbing.desc": "Play short previews of the audio while scrubbing through time timeline",
|
||||
"settings.viewport_rotate_speed": "Viewport Rotate Speed",
|
||||
"settings.viewport_rotate_speed.desc": "Input sensitivity when rotating in the viewport",
|
||||
"settings.viewport_zoom_speed": "Viewport Zoom Speed",
|
||||
"settings.viewport_zoom_speed.desc": "Input sensitivity when zooming in the viewport",
|
||||
"settings.editor_2d_zoom_speed": "2D Editor Zoom Speed",
|
||||
"settings.editor_2d_zoom_speed.desc": "Input sensitivity when zooming in the UV and 2D paint editor",
|
||||
"category.select": "Select",
|
||||
"action.vertex_snap_mode.rotate": "Rotate",
|
||||
"action.export_image": "Export Image",
|
||||
"action.export_image.desc": "Export your texture as an image file",
|
||||
"action.apply_mirror_modeling": "Apply Mirror Modeling",
|
||||
"action.apply_mirror_modeling.desc": "Apply Mirror Modeling to the selection. All selected elements will be copied and flipped across the X axis.",
|
||||
"action.create_collection": "Create Collection",
|
||||
"action.create_collection.desc": "Create a collection out of the outliner selection",
|
||||
"action.set_collection_content_to_selection": "Set Collection Content to Selected",
|
||||
"action.set_collection_content_to_selection.desc": "Set the selected groups and elements as the content of the collection",
|
||||
"action.add_to_collection": "Add Selected to Collection",
|
||||
"action.add_to_collection.desc": "Add the selected groups and elements to the collection",
|
||||
"action.view_mode.material": "Material Preview",
|
||||
"action.create_material": "Create Material",
|
||||
"action.create_material.desc": "Create a new PBR material out of the selected texture",
|
||||
"action.generate_pbr_map": "Generate PBR Map...",
|
||||
"action.generate_pbr_map.desc": "Generate a PBR map (height map or metalness, emissiveness, roughness) from an existing texture",
|
||||
"menu.tools.main_tools": "Toolbox",
|
||||
"menu.view.panels": "Panels",
|
||||
"menu.texture.pbr_channel": "PBR Channel",
|
||||
"menu.texture.pbr_channel.color": "Color",
|
||||
"menu.texture.pbr_channel.normal": "Normal",
|
||||
"menu.texture.pbr_channel.height": "Height",
|
||||
"menu.texture.pbr_channel.mer": "MER (Metalness-Emissive-Roughness)",
|
||||
"menu.texture.pbr_channel.mer_subsurface": "MER Subsurface",
|
||||
"menu.collection.export_project": "Export Project",
|
||||
"menu.collection.export_as": "Export as \"%0\"",
|
||||
"menu.panel.enable": "Enable",
|
||||
"menu.panel.move_to": "Move To",
|
||||
"menu.panel.move_to.left_bar": "Left Sidebar",
|
||||
"menu.panel.move_to.right_bar": "Right Sidebar",
|
||||
"menu.panel.move_to.top": "Top",
|
||||
"menu.panel.move_to.bottom": "Bottom",
|
||||
"menu.panel.move_to.float": "Float",
|
||||
"menu.panel.move_to.hidden": "Hide",
|
||||
"menu.panel.fold": "Collapse",
|
||||
"menu.mirror_painting.texture_center": "Origin",
|
||||
"menu.mirror_modeling.mirror_uv": "Mirror UV",
|
||||
"menu.animation_onion_skin.frames": "Frames",
|
||||
"menu.animation_onion_skin.select": "Select",
|
||||
"menu.animation_onion_skin.previous": "Previous",
|
||||
"menu.animation_onion_skin.next": "Next",
|
||||
"menu.animation_onion_skin.previous_next": "Previous + Next",
|
||||
"menu.animation_onion_skin.count": "Count",
|
||||
"menu.animation_onion_skin.interval": "Interval",
|
||||
"menu.animation_onion_skin_selective": "Selective Onion Skin",
|
||||
"menu.animation_onion_skin_selective.desc": "Only display onion skin for the selected part of the model",
|
||||
"edit.loop_cut.unit": "Unit",
|
||||
"edit.loop_cut.unit.size_units": "Size Units",
|
||||
"edit.loop_cut.unit.percent": "Percent",
|
||||
"edit.extrude_mesh_selection.direction": "Direction",
|
||||
"edit.extrude_mesh_selection.direction.outwards": "Outwards",
|
||||
"edit.extrude_mesh_selection.direction.average": "Average",
|
||||
"edit.extrude_mesh_selection.even_extend": "Even Extend",
|
||||
"edit.vertex_snap.align": "Align",
|
||||
"edit.vertex_snap.align.longest": "Longest Axis",
|
||||
"edit.vertex_snap.align.direction": "Direction from Pivot",
|
||||
"edit.vertex_snap.align.align_axis": "%0 Axis",
|
||||
"edit.vertex_snap.ignore_axis": "Ignore Axis",
|
||||
"codec.common.format": "Format",
|
||||
"codec.image.quality": "Quality",
|
||||
"panel.collections": "Collections",
|
||||
"modifier_actions.always": "Always Enabled",
|
||||
"modifier_actions.unless": "Unless %0",
|
||||
"settings.undo_selections": "Undo Selection",
|
||||
"settings.undo_selections.desc": "Track selection changes as a step in the undo history",
|
||||
"action.focus_on_selection.zoom": "Zoom to fit",
|
||||
"display.reference.tooting": "Horn Tooting",
|
||||
"settings.selection_tolerance": "Selection Tolerance",
|
||||
"settings.selection_tolerance.desc": "Size of the area that can be clicked to select an edge or vertex",
|
||||
"action.delete.keep_vertices": "Keep Edges/Vertices",
|
||||
"menu.mesh": "Mesh",
|
||||
"dialog.material_config.subsurface": "Subsurface Scattering",
|
||||
"dialog.material_config.subsurface_enabled.desc": "Use the MER map alpha channel for subsurface scattering",
|
||||
"settings.pick_combined_color": "Pick Combined Color",
|
||||
"settings.pick_combined_color.desc": "Pick the combined color of all layers at the respective pixel, instead of the color on the active layer",
|
||||
"action.split_rgb_into_layers": "Split RGB Channels into Layers",
|
||||
"action.split_rgb_into_layers.desc": "Split the texture into additive layers, one for each RGB channel"
|
||||
}
|
128
lang/nl.json
@ -164,11 +164,6 @@
|
||||
"layout.font.main": "Hoofd lettertype",
|
||||
"layout.font.headline": "Opschriftlettertype",
|
||||
"about.version": "Versie:",
|
||||
"about.creator": "Maker:",
|
||||
"about.website": "Website:",
|
||||
"about.vertex_snap": "Vertex Snapping is gebaseerd op een plug-in door SirBenet",
|
||||
"about.icons": "Icon Pakketten:",
|
||||
"about.libraries": "Bibliotheken:",
|
||||
"settings.category.general": "Algemeen:",
|
||||
"settings.category.preview": "Voorvertooning",
|
||||
"settings.category.grid": "Rooster",
|
||||
@ -1220,7 +1215,6 @@
|
||||
"camera_angle.true_isometric_right": "Rechts Isometrisch (30°)",
|
||||
"camera_angle.true_isometric_left": "Links Isometrisch (30°)",
|
||||
"menu.help.wiki": "Blockbench Wiki",
|
||||
"about.repository": "Repository:",
|
||||
"settings.update_to_prereleases": "Update naar Pre-releases",
|
||||
"settings.update_to_prereleases.desc": "Automatisch updaten naar Blockbench beta versies om nieuwe functies te testen. Pre-release versies kunnen onstabiel zijn, schakel deze optie niet in als u vertrouwt op Blockbench voor werk of andere belangrijke projecten.",
|
||||
"data.separator.spacer": "Afstandhouder",
|
||||
@ -1818,7 +1812,6 @@
|
||||
"menu.uv.flip_x": "Spiegel X",
|
||||
"menu.uv.flip_y": "Spiegel Y",
|
||||
"menu.mirror_painting.enabled": "Ingeschakeld",
|
||||
"menu.mirror_painting.configure_texture_center": "Configureer Textuur Centrum...",
|
||||
"reference_image.position": "Positie",
|
||||
"reference_image.size": "Grootte",
|
||||
"reference_image.rotation": "Rotatie",
|
||||
@ -2022,11 +2015,6 @@
|
||||
"action.save_animation_preset.desc": "Save the selected keyframes as an animation preset",
|
||||
"action.animation_onion_skin": "Animation Onion Skin",
|
||||
"action.animation_onion_skin.desc": "Display an wireframe view of a different frame in the animation for reference",
|
||||
"action.animation_onion_skin.off": "Off",
|
||||
"action.animation_onion_skin.select": "Select",
|
||||
"action.animation_onion_skin.previous": "Previous",
|
||||
"action.animation_onion_skin.next": "Next",
|
||||
"action.animation_onion_skin.previous_next": "Previous + Next",
|
||||
"action.apply_animation_preset": "Apply Animation Preset",
|
||||
"action.apply_animation_preset.desc": "Select from a list of animation presets and apply it to the selected bone",
|
||||
"menu.brush_presets.pixel_perfect": "Pixel-perfect Brush",
|
||||
@ -2040,8 +2028,6 @@
|
||||
"settings.final_newline.desc": "Insert a newline character at the end of exported files",
|
||||
"action.crop_layer_to_selection": "Crop Layer to Selection",
|
||||
"action.edit_mode_uv_overlay.desc": "Display the UV map as an overlay in edit mode",
|
||||
"action.animation_onion_skin_selective": "Selective Onion Skin",
|
||||
"action.animation_onion_skin_selective.desc": "Only display onion skin for the selected part of the model",
|
||||
"menu.image": "Image",
|
||||
"menu.texture.discard_changes": "Discard Changes",
|
||||
"menu.texture.discard_changes.desc": "Discard all unsaved changes and load the latest version from the file",
|
||||
@ -2228,5 +2214,117 @@
|
||||
"dialog.blend_transition_edit.extended": "Extended Graph",
|
||||
"message.screenshot_too_large.title": "Screenshot Resolution Issue",
|
||||
"message.screenshot_too_large.message": "The screenshot could not be rendered successfully. Please try again with a lower resolution or without supersampling.",
|
||||
"message.rename_elements.numbering": "You can use special characters to generate sequential numbers: % to get the index of the element within its group, $ to get the index within the selection."
|
||||
"message.rename_elements.numbering": "You can use special characters to generate sequential numbers: % to get the index of the element within its group, $ to get the index within the selection.",
|
||||
"generic.edit_externally": "Edit Externally",
|
||||
"message.settings_require_restart.title": "Restart Required",
|
||||
"message.settings_require_restart.message": "Some settings will only apply after restarting the program.",
|
||||
"message.settings_require_restart.restart_now": "Restart Now",
|
||||
"message.settings_require_restart.restart_later": "Restart Later",
|
||||
"message.classroom_mode.install_plugin": "Cannot install plugins in Classroom Mode",
|
||||
"dialog.collection.export_path": "Export Path",
|
||||
"dialog.collection.select_all": "Select All",
|
||||
"dialog.collection.select_none": "Select None",
|
||||
"dialog.collection.add_with_filter": "Add with Filter",
|
||||
"dialog.collection.remove": "Remove",
|
||||
"dialog.material_config.title": "Material Config",
|
||||
"dialog.material_config.color_value": "Color Value",
|
||||
"dialog.material_config.mer": "Metal-Emissive-Roughness",
|
||||
"dialog.material_config.mer_value": "MER Value",
|
||||
"dialog.material_config.depth_type": "Depth Type",
|
||||
"dialog.create_texture.disable_mirror_uv": "Disable UV Mirroring",
|
||||
"dialog.create_texture.disable_mirror_uv.desc": "Disable the UV Mirror option in Mirror Modeling to preserve separate UVs for each side of the model",
|
||||
"dialog.create_gif.turn.sync_to_anim_length": "Sync to animation length",
|
||||
"settings.category.controls": "Controls",
|
||||
"settings.classroom_mode": "Classroom Mode",
|
||||
"settings.classroom_mode.desc": "Restricts functionality such as installing plugins and removes links to social media",
|
||||
"settings.antialiasing_bleed_fix": "Fix anti-aliasing bleeding",
|
||||
"settings.antialiasing_bleed_fix.desc": "Fixes texture bleeding when using anti-aliasing. Potentially unsupported on older hardware.",
|
||||
"settings.tone_mapping": "Tone Mapping",
|
||||
"settings.tone_mapping.desc": "Approximation method for displaying high dynamic range on a standard screen for PBR rendering.",
|
||||
"settings.audio_scrubbing": "Timline Scrubbing Audio",
|
||||
"settings.audio_scrubbing.desc": "Play short previews of the audio while scrubbing through time timeline",
|
||||
"settings.viewport_rotate_speed": "Viewport Rotate Speed",
|
||||
"settings.viewport_rotate_speed.desc": "Input sensitivity when rotating in the viewport",
|
||||
"settings.viewport_zoom_speed": "Viewport Zoom Speed",
|
||||
"settings.viewport_zoom_speed.desc": "Input sensitivity when zooming in the viewport",
|
||||
"settings.editor_2d_zoom_speed": "2D Editor Zoom Speed",
|
||||
"settings.editor_2d_zoom_speed.desc": "Input sensitivity when zooming in the UV and 2D paint editor",
|
||||
"category.select": "Select",
|
||||
"action.vertex_snap_mode.rotate": "Rotate",
|
||||
"action.export_image": "Export Image",
|
||||
"action.export_image.desc": "Export your texture as an image file",
|
||||
"action.apply_mirror_modeling": "Apply Mirror Modeling",
|
||||
"action.apply_mirror_modeling.desc": "Apply Mirror Modeling to the selection. All selected elements will be copied and flipped across the X axis.",
|
||||
"action.create_collection": "Create Collection",
|
||||
"action.create_collection.desc": "Create a collection out of the outliner selection",
|
||||
"action.set_collection_content_to_selection": "Set Collection Content to Selected",
|
||||
"action.set_collection_content_to_selection.desc": "Set the selected groups and elements as the content of the collection",
|
||||
"action.add_to_collection": "Add Selected to Collection",
|
||||
"action.add_to_collection.desc": "Add the selected groups and elements to the collection",
|
||||
"action.view_mode.material": "Material Preview",
|
||||
"action.create_material": "Create Material",
|
||||
"action.create_material.desc": "Create a new PBR material out of the selected texture",
|
||||
"action.generate_pbr_map": "Generate PBR Map...",
|
||||
"action.generate_pbr_map.desc": "Generate a PBR map (height map or metalness, emissiveness, roughness) from an existing texture",
|
||||
"menu.tools.main_tools": "Toolbox",
|
||||
"menu.view.panels": "Panels",
|
||||
"menu.texture.pbr_channel": "PBR Channel",
|
||||
"menu.texture.pbr_channel.color": "Color",
|
||||
"menu.texture.pbr_channel.normal": "Normal",
|
||||
"menu.texture.pbr_channel.height": "Height",
|
||||
"menu.texture.pbr_channel.mer": "MER (Metalness-Emissive-Roughness)",
|
||||
"menu.texture.pbr_channel.mer_subsurface": "MER Subsurface",
|
||||
"menu.collection.export_project": "Export Project",
|
||||
"menu.collection.export_as": "Export as \"%0\"",
|
||||
"menu.panel.enable": "Enable",
|
||||
"menu.panel.move_to": "Move To",
|
||||
"menu.panel.move_to.left_bar": "Left Sidebar",
|
||||
"menu.panel.move_to.right_bar": "Right Sidebar",
|
||||
"menu.panel.move_to.top": "Top",
|
||||
"menu.panel.move_to.bottom": "Bottom",
|
||||
"menu.panel.move_to.float": "Float",
|
||||
"menu.panel.move_to.hidden": "Hide",
|
||||
"menu.panel.fold": "Collapse",
|
||||
"menu.mirror_painting.texture_center": "Origin",
|
||||
"menu.mirror_modeling.mirror_uv": "Mirror UV",
|
||||
"menu.animation_onion_skin.frames": "Frames",
|
||||
"menu.animation_onion_skin.select": "Select",
|
||||
"menu.animation_onion_skin.previous": "Previous",
|
||||
"menu.animation_onion_skin.next": "Next",
|
||||
"menu.animation_onion_skin.previous_next": "Previous + Next",
|
||||
"menu.animation_onion_skin.count": "Count",
|
||||
"menu.animation_onion_skin.interval": "Interval",
|
||||
"menu.animation_onion_skin_selective": "Selective Onion Skin",
|
||||
"menu.animation_onion_skin_selective.desc": "Only display onion skin for the selected part of the model",
|
||||
"edit.loop_cut.unit": "Unit",
|
||||
"edit.loop_cut.unit.size_units": "Size Units",
|
||||
"edit.loop_cut.unit.percent": "Percent",
|
||||
"edit.extrude_mesh_selection.direction": "Direction",
|
||||
"edit.extrude_mesh_selection.direction.outwards": "Outwards",
|
||||
"edit.extrude_mesh_selection.direction.average": "Average",
|
||||
"edit.extrude_mesh_selection.even_extend": "Even Extend",
|
||||
"edit.vertex_snap.align": "Align",
|
||||
"edit.vertex_snap.align.longest": "Longest Axis",
|
||||
"edit.vertex_snap.align.direction": "Direction from Pivot",
|
||||
"edit.vertex_snap.align.align_axis": "%0 Axis",
|
||||
"edit.vertex_snap.ignore_axis": "Ignore Axis",
|
||||
"codec.common.format": "Format",
|
||||
"codec.image.quality": "Quality",
|
||||
"panel.collections": "Collections",
|
||||
"modifier_actions.always": "Always Enabled",
|
||||
"modifier_actions.unless": "Unless %0",
|
||||
"settings.undo_selections": "Undo Selection",
|
||||
"settings.undo_selections.desc": "Track selection changes as a step in the undo history",
|
||||
"action.focus_on_selection.zoom": "Zoom to fit",
|
||||
"display.reference.tooting": "Horn Tooting",
|
||||
"settings.selection_tolerance": "Selection Tolerance",
|
||||
"settings.selection_tolerance.desc": "Size of the area that can be clicked to select an edge or vertex",
|
||||
"action.delete.keep_vertices": "Keep Edges/Vertices",
|
||||
"menu.mesh": "Mesh",
|
||||
"dialog.material_config.subsurface": "Subsurface Scattering",
|
||||
"dialog.material_config.subsurface_enabled.desc": "Use the MER map alpha channel for subsurface scattering",
|
||||
"settings.pick_combined_color": "Pick Combined Color",
|
||||
"settings.pick_combined_color.desc": "Pick the combined color of all layers at the respective pixel, instead of the color on the active layer",
|
||||
"action.split_rgb_into_layers": "Split RGB Channels into Layers",
|
||||
"action.split_rgb_into_layers.desc": "Split the texture into additive layers, one for each RGB channel"
|
||||
}
|
132
lang/pl.json
@ -164,11 +164,6 @@
|
||||
"layout.font.main": "Główna czcionka",
|
||||
"layout.font.headline": "Czcionka nagłówkowa",
|
||||
"about.version": "Wersja:",
|
||||
"about.creator": "Twórca:",
|
||||
"about.website": "Strona:",
|
||||
"about.vertex_snap": "Przyciąganie wierzchołków jest bazowane na pluginie autorstwa SirBenet",
|
||||
"about.icons": "Paczki ikon:",
|
||||
"about.libraries": "Biblioteki:",
|
||||
"settings.category.general": "Ogólne",
|
||||
"settings.category.preview": "Podgląd",
|
||||
"settings.category.grid": "Siatka",
|
||||
@ -1220,7 +1215,6 @@
|
||||
"camera_angle.true_isometric_right": "Prawdziwy izometryczny prawy (30°)",
|
||||
"camera_angle.true_isometric_left": "Prawdziwy izometryczny lewy (30°)",
|
||||
"menu.help.wiki": "Wiki Blockbencha",
|
||||
"about.repository": "Repozytorium:",
|
||||
"settings.update_to_prereleases": "Aktualizacja do wersji przedpremierowej",
|
||||
"settings.update_to_prereleases.desc": "Automatycznie aktualizuj Blockbench do wersji beta, aby testować nowe funkcje. Wersje przedpremierowe mogą być niestabilne, nie włączaj tej opcji jeśli polegasz na Blockbench w pracy lub innych ważnych projektach.",
|
||||
"data.separator.spacer": "Spacer",
|
||||
@ -1607,7 +1601,7 @@
|
||||
"menu.mirror_painting.global.desc": "Enabled mirror painting on the model in global space",
|
||||
"menu.mirror_painting.local": "Local Symmetry",
|
||||
"menu.mirror_painting.local.desc": "Enable mirror painting in local space for each element",
|
||||
"menu.mirror_painting.texture_frames": "Repeat on Animated Texture Frames",
|
||||
"menu.mirror_painting.texture_frames": "Repeat on Flipbook Frames",
|
||||
"menu.mirror_painting.texture_frames.desc": "Mirror paint strokes to every frame of animated textures",
|
||||
"format.bedrock_block.info.size_limit": "Size total size of a block is limited to 30 pixels in all dimensions. The limit can be off-centered in all directions by 7 pixels from the block center.",
|
||||
"format.bedrock_block.info.textures": "Multiple textures can be applied to different cubes in Blockbench, but require additional setup in the behavior pack to work correctly in-game.",
|
||||
@ -1694,7 +1688,7 @@
|
||||
"settings_profile.confirm_delete": "Are you sure you want to delete this settings profile?",
|
||||
"settings_profile.condition.type.selectable": "Manually Selectable",
|
||||
"settings.interface_mode": "UI Mode",
|
||||
"settings.interface_mode.desc": "Interface mode. Restart Blockbench to apply changes",
|
||||
"settings.interface_mode.desc": "Interface mode",
|
||||
"settings.interface_mode.auto": "Automatic",
|
||||
"settings.interface_mode.desktop": "Desktop",
|
||||
"settings.interface_mode.mobile": "Mobile",
|
||||
@ -1818,7 +1812,6 @@
|
||||
"menu.uv.flip_x": "Mirror X",
|
||||
"menu.uv.flip_y": "Mirror Y",
|
||||
"menu.mirror_painting.enabled": "Enabled",
|
||||
"menu.mirror_painting.configure_texture_center": "Configure Texture Center...",
|
||||
"reference_image.position": "Position",
|
||||
"reference_image.size": "Size",
|
||||
"reference_image.rotation": "Rotation",
|
||||
@ -2022,11 +2015,6 @@
|
||||
"action.save_animation_preset.desc": "Save the selected keyframes as an animation preset",
|
||||
"action.animation_onion_skin": "Animation Onion Skin",
|
||||
"action.animation_onion_skin.desc": "Display an wireframe view of a different frame in the animation for reference",
|
||||
"action.animation_onion_skin.off": "Off",
|
||||
"action.animation_onion_skin.select": "Select",
|
||||
"action.animation_onion_skin.previous": "Previous",
|
||||
"action.animation_onion_skin.next": "Next",
|
||||
"action.animation_onion_skin.previous_next": "Previous + Next",
|
||||
"action.apply_animation_preset": "Apply Animation Preset",
|
||||
"action.apply_animation_preset.desc": "Select from a list of animation presets and apply it to the selected bone",
|
||||
"menu.brush_presets.pixel_perfect": "Pixel-perfect Brush",
|
||||
@ -2040,8 +2028,6 @@
|
||||
"settings.final_newline.desc": "Insert a newline character at the end of exported files",
|
||||
"action.crop_layer_to_selection": "Crop Layer to Selection",
|
||||
"action.edit_mode_uv_overlay.desc": "Display the UV map as an overlay in edit mode",
|
||||
"action.animation_onion_skin_selective": "Selective Onion Skin",
|
||||
"action.animation_onion_skin_selective.desc": "Only display onion skin for the selected part of the model",
|
||||
"menu.image": "Image",
|
||||
"menu.texture.discard_changes": "Discard Changes",
|
||||
"menu.texture.discard_changes.desc": "Discard all unsaved changes and load the latest version from the file",
|
||||
@ -2228,5 +2214,117 @@
|
||||
"dialog.blend_transition_edit.extended": "Extended Graph",
|
||||
"message.screenshot_too_large.title": "Screenshot Resolution Issue",
|
||||
"message.screenshot_too_large.message": "The screenshot could not be rendered successfully. Please try again with a lower resolution or without supersampling.",
|
||||
"message.rename_elements.numbering": "You can use special characters to generate sequential numbers: % to get the index of the element within its group, $ to get the index within the selection."
|
||||
"message.rename_elements.numbering": "You can use special characters to generate sequential numbers: % to get the index of the element within its group, $ to get the index within the selection.",
|
||||
"generic.edit_externally": "Edit Externally",
|
||||
"message.settings_require_restart.title": "Restart Required",
|
||||
"message.settings_require_restart.message": "Some settings will only apply after restarting the program.",
|
||||
"message.settings_require_restart.restart_now": "Restart Now",
|
||||
"message.settings_require_restart.restart_later": "Restart Later",
|
||||
"message.classroom_mode.install_plugin": "Cannot install plugins in Classroom Mode",
|
||||
"dialog.collection.export_path": "Export Path",
|
||||
"dialog.collection.select_all": "Select All",
|
||||
"dialog.collection.select_none": "Select None",
|
||||
"dialog.collection.add_with_filter": "Add with Filter",
|
||||
"dialog.collection.remove": "Remove",
|
||||
"dialog.material_config.title": "Material Config",
|
||||
"dialog.material_config.color_value": "Color Value",
|
||||
"dialog.material_config.mer": "Metal-Emissive-Roughness",
|
||||
"dialog.material_config.mer_value": "MER Value",
|
||||
"dialog.material_config.depth_type": "Depth Type",
|
||||
"dialog.create_texture.disable_mirror_uv": "Disable UV Mirroring",
|
||||
"dialog.create_texture.disable_mirror_uv.desc": "Disable the UV Mirror option in Mirror Modeling to preserve separate UVs for each side of the model",
|
||||
"dialog.create_gif.turn.sync_to_anim_length": "Sync to animation length",
|
||||
"settings.category.controls": "Controls",
|
||||
"settings.classroom_mode": "Classroom Mode",
|
||||
"settings.classroom_mode.desc": "Restricts functionality such as installing plugins and removes links to social media",
|
||||
"settings.antialiasing_bleed_fix": "Fix anti-aliasing bleeding",
|
||||
"settings.antialiasing_bleed_fix.desc": "Fixes texture bleeding when using anti-aliasing. Potentially unsupported on older hardware.",
|
||||
"settings.tone_mapping": "Tone Mapping",
|
||||
"settings.tone_mapping.desc": "Approximation method for displaying high dynamic range on a standard screen for PBR rendering.",
|
||||
"settings.audio_scrubbing": "Timline Scrubbing Audio",
|
||||
"settings.audio_scrubbing.desc": "Play short previews of the audio while scrubbing through time timeline",
|
||||
"settings.viewport_rotate_speed": "Viewport Rotate Speed",
|
||||
"settings.viewport_rotate_speed.desc": "Input sensitivity when rotating in the viewport",
|
||||
"settings.viewport_zoom_speed": "Viewport Zoom Speed",
|
||||
"settings.viewport_zoom_speed.desc": "Input sensitivity when zooming in the viewport",
|
||||
"settings.editor_2d_zoom_speed": "2D Editor Zoom Speed",
|
||||
"settings.editor_2d_zoom_speed.desc": "Input sensitivity when zooming in the UV and 2D paint editor",
|
||||
"category.select": "Select",
|
||||
"action.vertex_snap_mode.rotate": "Rotate",
|
||||
"action.export_image": "Export Image",
|
||||
"action.export_image.desc": "Export your texture as an image file",
|
||||
"action.apply_mirror_modeling": "Apply Mirror Modeling",
|
||||
"action.apply_mirror_modeling.desc": "Apply Mirror Modeling to the selection. All selected elements will be copied and flipped across the X axis.",
|
||||
"action.create_collection": "Create Collection",
|
||||
"action.create_collection.desc": "Create a collection out of the outliner selection",
|
||||
"action.set_collection_content_to_selection": "Set Collection Content to Selected",
|
||||
"action.set_collection_content_to_selection.desc": "Set the selected groups and elements as the content of the collection",
|
||||
"action.add_to_collection": "Add Selected to Collection",
|
||||
"action.add_to_collection.desc": "Add the selected groups and elements to the collection",
|
||||
"action.view_mode.material": "Material Preview",
|
||||
"action.create_material": "Create Material",
|
||||
"action.create_material.desc": "Create a new PBR material out of the selected texture",
|
||||
"action.generate_pbr_map": "Generate PBR Map...",
|
||||
"action.generate_pbr_map.desc": "Generate a PBR map (height map or metalness, emissiveness, roughness) from an existing texture",
|
||||
"menu.tools.main_tools": "Toolbox",
|
||||
"menu.view.panels": "Panels",
|
||||
"menu.texture.pbr_channel": "PBR Channel",
|
||||
"menu.texture.pbr_channel.color": "Color",
|
||||
"menu.texture.pbr_channel.normal": "Normal",
|
||||
"menu.texture.pbr_channel.height": "Height",
|
||||
"menu.texture.pbr_channel.mer": "MER (Metalness-Emissive-Roughness)",
|
||||
"menu.texture.pbr_channel.mer_subsurface": "MER Subsurface",
|
||||
"menu.collection.export_project": "Export Project",
|
||||
"menu.collection.export_as": "Export as \"%0\"",
|
||||
"menu.panel.enable": "Enable",
|
||||
"menu.panel.move_to": "Move To",
|
||||
"menu.panel.move_to.left_bar": "Left Sidebar",
|
||||
"menu.panel.move_to.right_bar": "Right Sidebar",
|
||||
"menu.panel.move_to.top": "Top",
|
||||
"menu.panel.move_to.bottom": "Bottom",
|
||||
"menu.panel.move_to.float": "Float",
|
||||
"menu.panel.move_to.hidden": "Hide",
|
||||
"menu.panel.fold": "Collapse",
|
||||
"menu.mirror_painting.texture_center": "Origin",
|
||||
"menu.mirror_modeling.mirror_uv": "Mirror UV",
|
||||
"menu.animation_onion_skin.frames": "Frames",
|
||||
"menu.animation_onion_skin.select": "Select",
|
||||
"menu.animation_onion_skin.previous": "Previous",
|
||||
"menu.animation_onion_skin.next": "Next",
|
||||
"menu.animation_onion_skin.previous_next": "Previous + Next",
|
||||
"menu.animation_onion_skin.count": "Count",
|
||||
"menu.animation_onion_skin.interval": "Interval",
|
||||
"menu.animation_onion_skin_selective": "Selective Onion Skin",
|
||||
"menu.animation_onion_skin_selective.desc": "Only display onion skin for the selected part of the model",
|
||||
"edit.loop_cut.unit": "Unit",
|
||||
"edit.loop_cut.unit.size_units": "Size Units",
|
||||
"edit.loop_cut.unit.percent": "Percent",
|
||||
"edit.extrude_mesh_selection.direction": "Direction",
|
||||
"edit.extrude_mesh_selection.direction.outwards": "Outwards",
|
||||
"edit.extrude_mesh_selection.direction.average": "Average",
|
||||
"edit.extrude_mesh_selection.even_extend": "Even Extend",
|
||||
"edit.vertex_snap.align": "Align",
|
||||
"edit.vertex_snap.align.longest": "Longest Axis",
|
||||
"edit.vertex_snap.align.direction": "Direction from Pivot",
|
||||
"edit.vertex_snap.align.align_axis": "%0 Axis",
|
||||
"edit.vertex_snap.ignore_axis": "Ignore Axis",
|
||||
"codec.common.format": "Format",
|
||||
"codec.image.quality": "Quality",
|
||||
"panel.collections": "Collections",
|
||||
"modifier_actions.always": "Always Enabled",
|
||||
"modifier_actions.unless": "Unless %0",
|
||||
"settings.undo_selections": "Undo Selection",
|
||||
"settings.undo_selections.desc": "Track selection changes as a step in the undo history",
|
||||
"action.focus_on_selection.zoom": "Zoom to fit",
|
||||
"display.reference.tooting": "Horn Tooting",
|
||||
"settings.selection_tolerance": "Selection Tolerance",
|
||||
"settings.selection_tolerance.desc": "Size of the area that can be clicked to select an edge or vertex",
|
||||
"action.delete.keep_vertices": "Keep Edges/Vertices",
|
||||
"menu.mesh": "Mesh",
|
||||
"dialog.material_config.subsurface": "Subsurface Scattering",
|
||||
"dialog.material_config.subsurface_enabled.desc": "Use the MER map alpha channel for subsurface scattering",
|
||||
"settings.pick_combined_color": "Pick Combined Color",
|
||||
"settings.pick_combined_color.desc": "Pick the combined color of all layers at the respective pixel, instead of the color on the active layer",
|
||||
"action.split_rgb_into_layers": "Split RGB Channels into Layers",
|
||||
"action.split_rgb_into_layers.desc": "Split the texture into additive layers, one for each RGB channel"
|
||||
}
|
136
lang/pt.json
@ -164,11 +164,6 @@
|
||||
"layout.font.main": "Fonte principal",
|
||||
"layout.font.headline": "Fonte de títulos",
|
||||
"about.version": "Versão:",
|
||||
"about.creator": "Criado por:",
|
||||
"about.website": "Página web:",
|
||||
"about.vertex_snap": "O encaixe de vértices é baseado em uma extensão criada por SirBenet",
|
||||
"about.icons": "Pacotes de ícones:",
|
||||
"about.libraries": "Bibliotecas:",
|
||||
"settings.category.general": "Principal",
|
||||
"settings.category.preview": "Pré-visualização",
|
||||
"settings.category.grid": "Grade",
|
||||
@ -227,7 +222,7 @@
|
||||
"settings.export_groups.desc": "Salvar grupos em modelos de bloco ou item",
|
||||
"settings.credit": "Comentário de crédito",
|
||||
"settings.credit.desc": "Adicionar um comentário de crédito aos arquivos exportados",
|
||||
"settings.default_path": "Default Minecraft Textures Path",
|
||||
"settings.default_path": "Caminho Padrão de Texturas do Minecraft",
|
||||
"settings.default_path.desc": "Pasta da qual o Blockbench carrega texturas padrão",
|
||||
"settings.image_editor": "Editor de imagem",
|
||||
"settings.image_editor.desc": "Editor de imagens padrão para editar texturas",
|
||||
@ -1220,7 +1215,6 @@
|
||||
"camera_angle.true_isometric_right": "Habilitar direita isométrica (30°)",
|
||||
"camera_angle.true_isometric_left": "Habilitar esquerda isométrica (30°)",
|
||||
"menu.help.wiki": "Blockbench Wiki",
|
||||
"about.repository": "Repositório:",
|
||||
"settings.update_to_prereleases": "Atualizar para Pré-lançamentos",
|
||||
"settings.update_to_prereleases.desc": "Automatically update to Blockbench beta versions to test new features. Pre-release versions can be unstable, don't enable this option if you rely on Blockbench for work or other important projects.",
|
||||
"data.separator.spacer": "Espaçador",
|
||||
@ -1607,7 +1601,7 @@
|
||||
"menu.mirror_painting.global.desc": "Enabled mirror painting on the model in global space",
|
||||
"menu.mirror_painting.local": "Local Symmetry",
|
||||
"menu.mirror_painting.local.desc": "Enable mirror painting in local space for each element",
|
||||
"menu.mirror_painting.texture_frames": "Repeat on Animated Texture Frames",
|
||||
"menu.mirror_painting.texture_frames": "Repeat on Flipbook Frames",
|
||||
"menu.mirror_painting.texture_frames.desc": "Mirror paint strokes to every frame of animated textures",
|
||||
"format.bedrock_block.info.size_limit": "Size total size of a block is limited to 30 pixels in all dimensions. The limit can be off-centered in all directions by 7 pixels from the block center.",
|
||||
"format.bedrock_block.info.textures": "Multiple textures can be applied to different cubes in Blockbench, but require additional setup in the behavior pack to work correctly in-game.",
|
||||
@ -1694,7 +1688,7 @@
|
||||
"settings_profile.confirm_delete": "Are you sure you want to delete this settings profile?",
|
||||
"settings_profile.condition.type.selectable": "Manually Selectable",
|
||||
"settings.interface_mode": "UI Mode",
|
||||
"settings.interface_mode.desc": "Interface mode. Restart Blockbench to apply changes",
|
||||
"settings.interface_mode.desc": "Interface mode",
|
||||
"settings.interface_mode.auto": "Automatic",
|
||||
"settings.interface_mode.desktop": "Desktop",
|
||||
"settings.interface_mode.mobile": "Mobile",
|
||||
@ -1705,7 +1699,7 @@
|
||||
"action.slider_color_red": "Color Red",
|
||||
"action.slider_color_green": "Color Green",
|
||||
"action.slider_color_blue": "Color Blue",
|
||||
"action.add_animation_controller": "Add Animation Controller",
|
||||
"action.add_animation_controller": "Adicionar Controlador de Animação",
|
||||
"action.add_animation_controller.desc": "Create a blank animation controller",
|
||||
"action.animation_controller_preview_mode": "Controller Preview",
|
||||
"action.animation_controller_preview_mode.paused": "Paused",
|
||||
@ -1818,7 +1812,6 @@
|
||||
"menu.uv.flip_x": "Mirror X",
|
||||
"menu.uv.flip_y": "Mirror Y",
|
||||
"menu.mirror_painting.enabled": "Enabled",
|
||||
"menu.mirror_painting.configure_texture_center": "Configure Texture Center...",
|
||||
"reference_image.position": "Position",
|
||||
"reference_image.size": "Size",
|
||||
"reference_image.rotation": "Rotation",
|
||||
@ -2022,11 +2015,6 @@
|
||||
"action.save_animation_preset.desc": "Save the selected keyframes as an animation preset",
|
||||
"action.animation_onion_skin": "Animation Onion Skin",
|
||||
"action.animation_onion_skin.desc": "Display an wireframe view of a different frame in the animation for reference",
|
||||
"action.animation_onion_skin.off": "Off",
|
||||
"action.animation_onion_skin.select": "Select",
|
||||
"action.animation_onion_skin.previous": "Previous",
|
||||
"action.animation_onion_skin.next": "Next",
|
||||
"action.animation_onion_skin.previous_next": "Previous + Next",
|
||||
"action.apply_animation_preset": "Apply Animation Preset",
|
||||
"action.apply_animation_preset.desc": "Select from a list of animation presets and apply it to the selected bone",
|
||||
"menu.brush_presets.pixel_perfect": "Pixel-perfect Brush",
|
||||
@ -2040,8 +2028,6 @@
|
||||
"settings.final_newline.desc": "Insert a newline character at the end of exported files",
|
||||
"action.crop_layer_to_selection": "Crop Layer to Selection",
|
||||
"action.edit_mode_uv_overlay.desc": "Display the UV map as an overlay in edit mode",
|
||||
"action.animation_onion_skin_selective": "Selective Onion Skin",
|
||||
"action.animation_onion_skin_selective.desc": "Only display onion skin for the selected part of the model",
|
||||
"menu.image": "Image",
|
||||
"menu.texture.discard_changes": "Discard Changes",
|
||||
"menu.texture.discard_changes.desc": "Discard all unsaved changes and load the latest version from the file",
|
||||
@ -2228,5 +2214,117 @@
|
||||
"dialog.blend_transition_edit.extended": "Extended Graph",
|
||||
"message.screenshot_too_large.title": "Screenshot Resolution Issue",
|
||||
"message.screenshot_too_large.message": "The screenshot could not be rendered successfully. Please try again with a lower resolution or without supersampling.",
|
||||
"message.rename_elements.numbering": "You can use special characters to generate sequential numbers: % to get the index of the element within its group, $ to get the index within the selection."
|
||||
"message.rename_elements.numbering": "You can use special characters to generate sequential numbers: % to get the index of the element within its group, $ to get the index within the selection.",
|
||||
"generic.edit_externally": "Edit Externally",
|
||||
"message.settings_require_restart.title": "Restart Required",
|
||||
"message.settings_require_restart.message": "Some settings will only apply after restarting the program.",
|
||||
"message.settings_require_restart.restart_now": "Restart Now",
|
||||
"message.settings_require_restart.restart_later": "Restart Later",
|
||||
"message.classroom_mode.install_plugin": "Cannot install plugins in Classroom Mode",
|
||||
"dialog.collection.export_path": "Export Path",
|
||||
"dialog.collection.select_all": "Select All",
|
||||
"dialog.collection.select_none": "Select None",
|
||||
"dialog.collection.add_with_filter": "Add with Filter",
|
||||
"dialog.collection.remove": "Remove",
|
||||
"dialog.material_config.title": "Material Config",
|
||||
"dialog.material_config.color_value": "Color Value",
|
||||
"dialog.material_config.mer": "Metal-Emissive-Roughness",
|
||||
"dialog.material_config.mer_value": "MER Value",
|
||||
"dialog.material_config.depth_type": "Depth Type",
|
||||
"dialog.create_texture.disable_mirror_uv": "Disable UV Mirroring",
|
||||
"dialog.create_texture.disable_mirror_uv.desc": "Disable the UV Mirror option in Mirror Modeling to preserve separate UVs for each side of the model",
|
||||
"dialog.create_gif.turn.sync_to_anim_length": "Sync to animation length",
|
||||
"settings.category.controls": "Controls",
|
||||
"settings.classroom_mode": "Classroom Mode",
|
||||
"settings.classroom_mode.desc": "Restricts functionality such as installing plugins and removes links to social media",
|
||||
"settings.antialiasing_bleed_fix": "Fix anti-aliasing bleeding",
|
||||
"settings.antialiasing_bleed_fix.desc": "Fixes texture bleeding when using anti-aliasing. Potentially unsupported on older hardware.",
|
||||
"settings.tone_mapping": "Tone Mapping",
|
||||
"settings.tone_mapping.desc": "Approximation method for displaying high dynamic range on a standard screen for PBR rendering.",
|
||||
"settings.audio_scrubbing": "Timline Scrubbing Audio",
|
||||
"settings.audio_scrubbing.desc": "Play short previews of the audio while scrubbing through time timeline",
|
||||
"settings.viewport_rotate_speed": "Viewport Rotate Speed",
|
||||
"settings.viewport_rotate_speed.desc": "Input sensitivity when rotating in the viewport",
|
||||
"settings.viewport_zoom_speed": "Viewport Zoom Speed",
|
||||
"settings.viewport_zoom_speed.desc": "Input sensitivity when zooming in the viewport",
|
||||
"settings.editor_2d_zoom_speed": "2D Editor Zoom Speed",
|
||||
"settings.editor_2d_zoom_speed.desc": "Input sensitivity when zooming in the UV and 2D paint editor",
|
||||
"category.select": "Select",
|
||||
"action.vertex_snap_mode.rotate": "Rotate",
|
||||
"action.export_image": "Export Image",
|
||||
"action.export_image.desc": "Export your texture as an image file",
|
||||
"action.apply_mirror_modeling": "Apply Mirror Modeling",
|
||||
"action.apply_mirror_modeling.desc": "Apply Mirror Modeling to the selection. All selected elements will be copied and flipped across the X axis.",
|
||||
"action.create_collection": "Create Collection",
|
||||
"action.create_collection.desc": "Create a collection out of the outliner selection",
|
||||
"action.set_collection_content_to_selection": "Set Collection Content to Selected",
|
||||
"action.set_collection_content_to_selection.desc": "Set the selected groups and elements as the content of the collection",
|
||||
"action.add_to_collection": "Add Selected to Collection",
|
||||
"action.add_to_collection.desc": "Add the selected groups and elements to the collection",
|
||||
"action.view_mode.material": "Material Preview",
|
||||
"action.create_material": "Create Material",
|
||||
"action.create_material.desc": "Create a new PBR material out of the selected texture",
|
||||
"action.generate_pbr_map": "Generate PBR Map...",
|
||||
"action.generate_pbr_map.desc": "Generate a PBR map (height map or metalness, emissiveness, roughness) from an existing texture",
|
||||
"menu.tools.main_tools": "Toolbox",
|
||||
"menu.view.panels": "Panels",
|
||||
"menu.texture.pbr_channel": "PBR Channel",
|
||||
"menu.texture.pbr_channel.color": "Color",
|
||||
"menu.texture.pbr_channel.normal": "Normal",
|
||||
"menu.texture.pbr_channel.height": "Height",
|
||||
"menu.texture.pbr_channel.mer": "MER (Metalness-Emissive-Roughness)",
|
||||
"menu.texture.pbr_channel.mer_subsurface": "MER Subsurface",
|
||||
"menu.collection.export_project": "Export Project",
|
||||
"menu.collection.export_as": "Export as \"%0\"",
|
||||
"menu.panel.enable": "Enable",
|
||||
"menu.panel.move_to": "Move To",
|
||||
"menu.panel.move_to.left_bar": "Left Sidebar",
|
||||
"menu.panel.move_to.right_bar": "Right Sidebar",
|
||||
"menu.panel.move_to.top": "Top",
|
||||
"menu.panel.move_to.bottom": "Bottom",
|
||||
"menu.panel.move_to.float": "Float",
|
||||
"menu.panel.move_to.hidden": "Hide",
|
||||
"menu.panel.fold": "Collapse",
|
||||
"menu.mirror_painting.texture_center": "Origin",
|
||||
"menu.mirror_modeling.mirror_uv": "Mirror UV",
|
||||
"menu.animation_onion_skin.frames": "Frames",
|
||||
"menu.animation_onion_skin.select": "Select",
|
||||
"menu.animation_onion_skin.previous": "Previous",
|
||||
"menu.animation_onion_skin.next": "Next",
|
||||
"menu.animation_onion_skin.previous_next": "Previous + Next",
|
||||
"menu.animation_onion_skin.count": "Count",
|
||||
"menu.animation_onion_skin.interval": "Interval",
|
||||
"menu.animation_onion_skin_selective": "Selective Onion Skin",
|
||||
"menu.animation_onion_skin_selective.desc": "Only display onion skin for the selected part of the model",
|
||||
"edit.loop_cut.unit": "Unit",
|
||||
"edit.loop_cut.unit.size_units": "Size Units",
|
||||
"edit.loop_cut.unit.percent": "Percent",
|
||||
"edit.extrude_mesh_selection.direction": "Direction",
|
||||
"edit.extrude_mesh_selection.direction.outwards": "Outwards",
|
||||
"edit.extrude_mesh_selection.direction.average": "Average",
|
||||
"edit.extrude_mesh_selection.even_extend": "Even Extend",
|
||||
"edit.vertex_snap.align": "Align",
|
||||
"edit.vertex_snap.align.longest": "Longest Axis",
|
||||
"edit.vertex_snap.align.direction": "Direction from Pivot",
|
||||
"edit.vertex_snap.align.align_axis": "%0 Axis",
|
||||
"edit.vertex_snap.ignore_axis": "Ignore Axis",
|
||||
"codec.common.format": "Format",
|
||||
"codec.image.quality": "Quality",
|
||||
"panel.collections": "Collections",
|
||||
"modifier_actions.always": "Always Enabled",
|
||||
"modifier_actions.unless": "Unless %0",
|
||||
"settings.undo_selections": "Undo Selection",
|
||||
"settings.undo_selections.desc": "Track selection changes as a step in the undo history",
|
||||
"action.focus_on_selection.zoom": "Zoom to fit",
|
||||
"display.reference.tooting": "Horn Tooting",
|
||||
"settings.selection_tolerance": "Selection Tolerance",
|
||||
"settings.selection_tolerance.desc": "Size of the area that can be clicked to select an edge or vertex",
|
||||
"action.delete.keep_vertices": "Keep Edges/Vertices",
|
||||
"menu.mesh": "Mesh",
|
||||
"dialog.material_config.subsurface": "Subsurface Scattering",
|
||||
"dialog.material_config.subsurface_enabled.desc": "Use the MER map alpha channel for subsurface scattering",
|
||||
"settings.pick_combined_color": "Pick Combined Color",
|
||||
"settings.pick_combined_color.desc": "Pick the combined color of all layers at the respective pixel, instead of the color on the active layer",
|
||||
"action.split_rgb_into_layers": "Split RGB Channels into Layers",
|
||||
"action.split_rgb_into_layers.desc": "Split the texture into additive layers, one for each RGB channel"
|
||||
}
|
1784
lang/ru.json
156
lang/sv.json
@ -164,11 +164,6 @@
|
||||
"layout.font.main": "Huvudtypsnitt",
|
||||
"layout.font.headline": "Rubrikstypsnitt",
|
||||
"about.version": "Version:",
|
||||
"about.creator": "Skapare:",
|
||||
"about.website": "Hemsida:",
|
||||
"about.vertex_snap": "Vortex Snapping är baserat på ett plugin av SirBenet",
|
||||
"about.icons": "Ikonpaket:",
|
||||
"about.libraries": "Bibliotek:",
|
||||
"settings.category.general": "Allmän",
|
||||
"settings.category.preview": "Förhansvisning",
|
||||
"settings.category.grid": "Rutnät",
|
||||
@ -488,7 +483,7 @@
|
||||
"action.change_textures_folder.desc": "Ändra mapp som alla texturer sparas i",
|
||||
"menu.texture.particle": "Använd för partiklar",
|
||||
"message.update_notification.title": "En uppdatering är tillgänglig ",
|
||||
"message.update_notification.message": "Den nya Blockbench versionen \"%0\" är tillgänglig. Vill du installera den nu?",
|
||||
"message.update_notification.message": "En ny Blockbench uppdatering är tillgänglig. Sätt på \"Uppdatera automatiskt\" i inställningar för att uppdatera!",
|
||||
"message.untextured": "Denna ytan har ingen textur",
|
||||
"dialog.toolbar_edit.title": "Anpassa verktygsfältet",
|
||||
"keybindings.reset": "Återställ",
|
||||
@ -963,7 +958,7 @@
|
||||
"menu.help.developer": "Utvecklare",
|
||||
"menu.help.developer.dev_tools": "Open Dev Tools",
|
||||
"menu.help.developer.reset_storage": "Factory Reset",
|
||||
"menu.help.developer.reset_storage.confirm": "Are you sure you want to reset Blockbench to factory settings? This will delete all custom settings, keybindings and installed plugins.",
|
||||
"menu.help.developer.reset_storage.confirm": "Är du säker på att du vill fabriksåterställa Blockbenchs inställningar? Om du gör detta kommer alla valda inställningar, kortkommandon och plugins att återställas.",
|
||||
"menu.help.developer.cache_reload": "Cache Reload",
|
||||
"menu.preview.orthographic": "Orthographic",
|
||||
"menu.preview.save_angle": "Spara Vinkel...",
|
||||
@ -1018,8 +1013,8 @@
|
||||
"settings.category.application": "Application",
|
||||
"settings.streamer_mode": "Streamerläge",
|
||||
"settings.streamer_mode.desc": "Hides sensitive information like recent models",
|
||||
"settings.automatic_updates": "Automatic Updates",
|
||||
"settings.automatic_updates.desc": "Automatically download new versions and keep Blockbench up-to-date",
|
||||
"settings.automatic_updates": "Uppdatera automatiskt",
|
||||
"settings.automatic_updates.desc": "Laddar automatiskt ned nya uppdateringar",
|
||||
"action.rotation_space": "Rotation Space",
|
||||
"action.focus_on_selection": "Center View on Selection",
|
||||
"action.focus_on_selection.desc": "Align the camera to face the center of the current selection",
|
||||
@ -1070,12 +1065,12 @@
|
||||
"message.small_face_dimensions.title": "Incompatible Face Dimensions",
|
||||
"message.small_face_dimensions.message": "The selection contains faces that are smaller than 1 unit in one direction. The Box UV mapping system considers any faces below that threshold as 0 pixels wide. The texture on those faces therefore may not work correctly.",
|
||||
"message.small_face_dimensions.face_uv": "The current format supports per-face UV maps which can handle small face dimensions. Right click the affected cubes and change \"UV Mode\" to \"Per-face UV\".",
|
||||
"dialog.plugins.outdated_client": "Requires a newer version of Blockbench",
|
||||
"dialog.plugins.outdated_plugin": "Plugin is outdated and does not work with this version of Blockbench",
|
||||
"dialog.plugins.outdated_client": "Pluginet behöver en nyare version av Blockbench",
|
||||
"dialog.plugins.outdated_plugin": "Pluginet är utdaterat och kommer inte att fungera med den här versionen av Blockbench",
|
||||
"settings.motion_trails": "Motion Trails",
|
||||
"settings.motion_trails.desc": "Show motion trails in the animation editor",
|
||||
"settings.antialiasing": "Anti-aliasing",
|
||||
"settings.antialiasing.desc": "Toggle anti-aliasing in the preview. Restart Blockbench to apply changes",
|
||||
"settings.antialiasing.desc": "Toggle anti-aliasing in the preview",
|
||||
"action.timeline_frame_back": "Jump 1 Frame Back",
|
||||
"action.timeline_frame_forth": "Jump 1 Frame Forth",
|
||||
"panel.bone.ik": "Inverse Kinematics (Experimental)",
|
||||
@ -1097,13 +1092,13 @@
|
||||
"layout.color.subtle_text": "Subtle Text",
|
||||
"layout.color.subtle_text.desc": "Secondary text color with less contrast",
|
||||
"settings.interface_scale": "Interface Scale",
|
||||
"settings.interface_scale.desc": "Scale of the entire Blockbench interface",
|
||||
"settings.interface_scale.desc": "Hela Blockbenchs gränssnittsskala",
|
||||
"settings.background_rendering": "Background Rendering",
|
||||
"settings.background_rendering.desc": "Update the preview while the window is not focused",
|
||||
"settings.ctrl_shift_size": "Control + Shift Resolution",
|
||||
"settings.ctrl_shift_size.desc": "Resolution of the grid while holding control and shift",
|
||||
"settings.hardware_acceleration": "Hardware Acceleration",
|
||||
"settings.hardware_acceleration.desc": "Outsource rendering tasks to the graphics card. Restart Blockbench to apply changes",
|
||||
"settings.hardware_acceleration.desc": "Låter blockbench utnytja grafikkortet för rendering. Kräver omstart av Blockbench",
|
||||
"action.explode_skin_model": "Explode Skin Model",
|
||||
"action.explode_skin_model.desc": "Toggles an explosion view that allows you to edit covered faces",
|
||||
"action.export_minecraft_skin": "Exportera Minecraft Skin",
|
||||
@ -1143,7 +1138,7 @@
|
||||
"dialog.toolbar_edit.hidden_tools": "Some tools might be hidden because they are not available in the current mode, format, or situation.",
|
||||
"settings.camera_near_plane": "Camera Near Plane",
|
||||
"settings.camera_near_plane.desc": "The minimum distance from the camera where objects render. Higher values decrease Z-fighting. Default is 1.",
|
||||
"mode.start.keymap_preference.desc": "If you are new to Blockbench and you are coming from another 3D program, you can select a keymap to make your transition easier. You can change the keymap or individual keybindings later in the settings.",
|
||||
"mode.start.keymap_preference.desc": "Om du har använt ett annat 3D program innan Blockbench och har svårt att vänja dig kan du använda en \"keymap\" för att göra övergången lättare. I inställningar så kan du ändra varje kortkommando för sig.",
|
||||
"message.load_keymap": "Are you sure you want to load this keymap? This will overwrite your current keybindings.",
|
||||
"message.keymap_loaded": "Keymap loaded",
|
||||
"dialog.convert_project.current_format": "Current Format",
|
||||
@ -1170,7 +1165,7 @@
|
||||
"action.import_settings": "Import Settings",
|
||||
"action.import_settings.desc": "Import a .bbsettings file",
|
||||
"action.export_settings": "Export Settings",
|
||||
"action.export_settings.desc": "Export the Blockbench settings as a .bbsettings file",
|
||||
"action.export_settings.desc": "Exportera dina Blockbench inställningar som en \".bbsettings\" fil",
|
||||
"action.load_keymap": "Load Keymap",
|
||||
"action.load_keymap.default": "Default (Trackpad/Mouse)",
|
||||
"action.load_keymap.mouse": "Default (Mouse)",
|
||||
@ -1220,7 +1215,6 @@
|
||||
"camera_angle.true_isometric_right": "True Isometric Right (30°)",
|
||||
"camera_angle.true_isometric_left": "True Isometric Left (30°)",
|
||||
"menu.help.wiki": "Blockbench Wiki",
|
||||
"about.repository": "Repository:",
|
||||
"settings.update_to_prereleases": "Update to Pre-releases",
|
||||
"settings.update_to_prereleases.desc": "Automatically update to Blockbench beta versions to test new features. Pre-release versions can be unstable, don't enable this option if you rely on Blockbench for work or other important projects.",
|
||||
"data.separator.spacer": "Spacer",
|
||||
@ -1402,7 +1396,7 @@
|
||||
"settings.preview_paste_behavior.desc": "Select the behavior when pasting something into the viewport in Edit mode and multiple options are available",
|
||||
"settings.preview_paste_behavior.always_ask": "Always Ask",
|
||||
"action.new_window": "New Window",
|
||||
"action.new_window.desc": "Opens a new Blockbench window",
|
||||
"action.new_window.desc": "Öppnar ett till Blockbench fönster",
|
||||
"action.export_collada": "Export Collada Model (dae)",
|
||||
"action.export_collada.desc": "Export model and animations as dae file to use it in other 3D applications",
|
||||
"action.paint_mode_uv_overlay": "UV Overlay",
|
||||
@ -1607,7 +1601,7 @@
|
||||
"menu.mirror_painting.global.desc": "Enabled mirror painting on the model in global space",
|
||||
"menu.mirror_painting.local": "Local Symmetry",
|
||||
"menu.mirror_painting.local.desc": "Enable mirror painting in local space for each element",
|
||||
"menu.mirror_painting.texture_frames": "Repeat on Animated Texture Frames",
|
||||
"menu.mirror_painting.texture_frames": "Repeat on Flipbook Frames",
|
||||
"menu.mirror_painting.texture_frames.desc": "Mirror paint strokes to every frame of animated textures",
|
||||
"format.bedrock_block.info.size_limit": "Size total size of a block is limited to 30 pixels in all dimensions. The limit can be off-centered in all directions by 7 pixels from the block center.",
|
||||
"format.bedrock_block.info.textures": "Multiple textures can be applied to different cubes in Blockbench, but require additional setup in the behavior pack to work correctly in-game.",
|
||||
@ -1694,7 +1688,7 @@
|
||||
"settings_profile.confirm_delete": "Are you sure you want to delete this settings profile?",
|
||||
"settings_profile.condition.type.selectable": "Manually Selectable",
|
||||
"settings.interface_mode": "UI Mode",
|
||||
"settings.interface_mode.desc": "Interface mode. Restart Blockbench to apply changes",
|
||||
"settings.interface_mode.desc": "Interface mode",
|
||||
"settings.interface_mode.auto": "Automatic",
|
||||
"settings.interface_mode.desktop": "Desktop",
|
||||
"settings.interface_mode.mobile": "Mobile",
|
||||
@ -1818,7 +1812,6 @@
|
||||
"menu.uv.flip_x": "Mirror X",
|
||||
"menu.uv.flip_y": "Mirror Y",
|
||||
"menu.mirror_painting.enabled": "Enabled",
|
||||
"menu.mirror_painting.configure_texture_center": "Configure Texture Center...",
|
||||
"reference_image.position": "Position",
|
||||
"reference_image.size": "Size",
|
||||
"reference_image.rotation": "Rotation",
|
||||
@ -2022,11 +2015,6 @@
|
||||
"action.save_animation_preset.desc": "Save the selected keyframes as an animation preset",
|
||||
"action.animation_onion_skin": "Animation Onion Skin",
|
||||
"action.animation_onion_skin.desc": "Display an wireframe view of a different frame in the animation for reference",
|
||||
"action.animation_onion_skin.off": "Off",
|
||||
"action.animation_onion_skin.select": "Select",
|
||||
"action.animation_onion_skin.previous": "Previous",
|
||||
"action.animation_onion_skin.next": "Next",
|
||||
"action.animation_onion_skin.previous_next": "Previous + Next",
|
||||
"action.apply_animation_preset": "Apply Animation Preset",
|
||||
"action.apply_animation_preset.desc": "Select from a list of animation presets and apply it to the selected bone",
|
||||
"menu.brush_presets.pixel_perfect": "Pixel-perfect Brush",
|
||||
@ -2040,8 +2028,6 @@
|
||||
"settings.final_newline.desc": "Insert a newline character at the end of exported files",
|
||||
"action.crop_layer_to_selection": "Crop Layer to Selection",
|
||||
"action.edit_mode_uv_overlay.desc": "Display the UV map as an overlay in edit mode",
|
||||
"action.animation_onion_skin_selective": "Selective Onion Skin",
|
||||
"action.animation_onion_skin_selective.desc": "Only display onion skin for the selected part of the model",
|
||||
"menu.image": "Image",
|
||||
"menu.texture.discard_changes": "Discard Changes",
|
||||
"menu.texture.discard_changes.desc": "Discard all unsaved changes and load the latest version from the file",
|
||||
@ -2228,5 +2214,117 @@
|
||||
"dialog.blend_transition_edit.extended": "Extended Graph",
|
||||
"message.screenshot_too_large.title": "Screenshot Resolution Issue",
|
||||
"message.screenshot_too_large.message": "The screenshot could not be rendered successfully. Please try again with a lower resolution or without supersampling.",
|
||||
"message.rename_elements.numbering": "You can use special characters to generate sequential numbers: % to get the index of the element within its group, $ to get the index within the selection."
|
||||
"message.rename_elements.numbering": "You can use special characters to generate sequential numbers: % to get the index of the element within its group, $ to get the index within the selection.",
|
||||
"generic.edit_externally": "Edit Externally",
|
||||
"message.settings_require_restart.title": "Restart Required",
|
||||
"message.settings_require_restart.message": "Some settings will only apply after restarting the program.",
|
||||
"message.settings_require_restart.restart_now": "Restart Now",
|
||||
"message.settings_require_restart.restart_later": "Restart Later",
|
||||
"message.classroom_mode.install_plugin": "Cannot install plugins in Classroom Mode",
|
||||
"dialog.collection.export_path": "Export Path",
|
||||
"dialog.collection.select_all": "Select All",
|
||||
"dialog.collection.select_none": "Select None",
|
||||
"dialog.collection.add_with_filter": "Add with Filter",
|
||||
"dialog.collection.remove": "Remove",
|
||||
"dialog.material_config.title": "Material Config",
|
||||
"dialog.material_config.color_value": "Color Value",
|
||||
"dialog.material_config.mer": "Metal-Emissive-Roughness",
|
||||
"dialog.material_config.mer_value": "MER Value",
|
||||
"dialog.material_config.depth_type": "Depth Type",
|
||||
"dialog.create_texture.disable_mirror_uv": "Disable UV Mirroring",
|
||||
"dialog.create_texture.disable_mirror_uv.desc": "Disable the UV Mirror option in Mirror Modeling to preserve separate UVs for each side of the model",
|
||||
"dialog.create_gif.turn.sync_to_anim_length": "Sync to animation length",
|
||||
"settings.category.controls": "Controls",
|
||||
"settings.classroom_mode": "Classroom Mode",
|
||||
"settings.classroom_mode.desc": "Restricts functionality such as installing plugins and removes links to social media",
|
||||
"settings.antialiasing_bleed_fix": "Fix anti-aliasing bleeding",
|
||||
"settings.antialiasing_bleed_fix.desc": "Fixes texture bleeding when using anti-aliasing. Potentially unsupported on older hardware.",
|
||||
"settings.tone_mapping": "Tone Mapping",
|
||||
"settings.tone_mapping.desc": "Approximation method for displaying high dynamic range on a standard screen for PBR rendering.",
|
||||
"settings.audio_scrubbing": "Timline Scrubbing Audio",
|
||||
"settings.audio_scrubbing.desc": "Play short previews of the audio while scrubbing through time timeline",
|
||||
"settings.viewport_rotate_speed": "Viewport Rotate Speed",
|
||||
"settings.viewport_rotate_speed.desc": "Input sensitivity when rotating in the viewport",
|
||||
"settings.viewport_zoom_speed": "Viewport Zoom Speed",
|
||||
"settings.viewport_zoom_speed.desc": "Input sensitivity when zooming in the viewport",
|
||||
"settings.editor_2d_zoom_speed": "2D Editor Zoom Speed",
|
||||
"settings.editor_2d_zoom_speed.desc": "Input sensitivity when zooming in the UV and 2D paint editor",
|
||||
"category.select": "Select",
|
||||
"action.vertex_snap_mode.rotate": "Rotate",
|
||||
"action.export_image": "Export Image",
|
||||
"action.export_image.desc": "Export your texture as an image file",
|
||||
"action.apply_mirror_modeling": "Apply Mirror Modeling",
|
||||
"action.apply_mirror_modeling.desc": "Apply Mirror Modeling to the selection. All selected elements will be copied and flipped across the X axis.",
|
||||
"action.create_collection": "Create Collection",
|
||||
"action.create_collection.desc": "Create a collection out of the outliner selection",
|
||||
"action.set_collection_content_to_selection": "Set Collection Content to Selected",
|
||||
"action.set_collection_content_to_selection.desc": "Set the selected groups and elements as the content of the collection",
|
||||
"action.add_to_collection": "Add Selected to Collection",
|
||||
"action.add_to_collection.desc": "Add the selected groups and elements to the collection",
|
||||
"action.view_mode.material": "Material Preview",
|
||||
"action.create_material": "Create Material",
|
||||
"action.create_material.desc": "Create a new PBR material out of the selected texture",
|
||||
"action.generate_pbr_map": "Generate PBR Map...",
|
||||
"action.generate_pbr_map.desc": "Generate a PBR map (height map or metalness, emissiveness, roughness) from an existing texture",
|
||||
"menu.tools.main_tools": "Toolbox",
|
||||
"menu.view.panels": "Panels",
|
||||
"menu.texture.pbr_channel": "PBR Channel",
|
||||
"menu.texture.pbr_channel.color": "Color",
|
||||
"menu.texture.pbr_channel.normal": "Normal",
|
||||
"menu.texture.pbr_channel.height": "Height",
|
||||
"menu.texture.pbr_channel.mer": "MER (Metalness-Emissive-Roughness)",
|
||||
"menu.texture.pbr_channel.mer_subsurface": "MER Subsurface",
|
||||
"menu.collection.export_project": "Export Project",
|
||||
"menu.collection.export_as": "Export as \"%0\"",
|
||||
"menu.panel.enable": "Enable",
|
||||
"menu.panel.move_to": "Move To",
|
||||
"menu.panel.move_to.left_bar": "Left Sidebar",
|
||||
"menu.panel.move_to.right_bar": "Right Sidebar",
|
||||
"menu.panel.move_to.top": "Top",
|
||||
"menu.panel.move_to.bottom": "Bottom",
|
||||
"menu.panel.move_to.float": "Float",
|
||||
"menu.panel.move_to.hidden": "Hide",
|
||||
"menu.panel.fold": "Collapse",
|
||||
"menu.mirror_painting.texture_center": "Origin",
|
||||
"menu.mirror_modeling.mirror_uv": "Mirror UV",
|
||||
"menu.animation_onion_skin.frames": "Frames",
|
||||
"menu.animation_onion_skin.select": "Select",
|
||||
"menu.animation_onion_skin.previous": "Previous",
|
||||
"menu.animation_onion_skin.next": "Next",
|
||||
"menu.animation_onion_skin.previous_next": "Previous + Next",
|
||||
"menu.animation_onion_skin.count": "Count",
|
||||
"menu.animation_onion_skin.interval": "Interval",
|
||||
"menu.animation_onion_skin_selective": "Selective Onion Skin",
|
||||
"menu.animation_onion_skin_selective.desc": "Only display onion skin for the selected part of the model",
|
||||
"edit.loop_cut.unit": "Unit",
|
||||
"edit.loop_cut.unit.size_units": "Size Units",
|
||||
"edit.loop_cut.unit.percent": "Percent",
|
||||
"edit.extrude_mesh_selection.direction": "Direction",
|
||||
"edit.extrude_mesh_selection.direction.outwards": "Outwards",
|
||||
"edit.extrude_mesh_selection.direction.average": "Average",
|
||||
"edit.extrude_mesh_selection.even_extend": "Even Extend",
|
||||
"edit.vertex_snap.align": "Align",
|
||||
"edit.vertex_snap.align.longest": "Longest Axis",
|
||||
"edit.vertex_snap.align.direction": "Direction from Pivot",
|
||||
"edit.vertex_snap.align.align_axis": "%0 Axis",
|
||||
"edit.vertex_snap.ignore_axis": "Ignore Axis",
|
||||
"codec.common.format": "Format",
|
||||
"codec.image.quality": "Quality",
|
||||
"panel.collections": "Collections",
|
||||
"modifier_actions.always": "Always Enabled",
|
||||
"modifier_actions.unless": "Unless %0",
|
||||
"settings.undo_selections": "Undo Selection",
|
||||
"settings.undo_selections.desc": "Track selection changes as a step in the undo history",
|
||||
"action.focus_on_selection.zoom": "Zoom to fit",
|
||||
"display.reference.tooting": "Horn Tooting",
|
||||
"settings.selection_tolerance": "Selection Tolerance",
|
||||
"settings.selection_tolerance.desc": "Size of the area that can be clicked to select an edge or vertex",
|
||||
"action.delete.keep_vertices": "Keep Edges/Vertices",
|
||||
"menu.mesh": "Mesh",
|
||||
"dialog.material_config.subsurface": "Subsurface Scattering",
|
||||
"dialog.material_config.subsurface_enabled.desc": "Use the MER map alpha channel for subsurface scattering",
|
||||
"settings.pick_combined_color": "Pick Combined Color",
|
||||
"settings.pick_combined_color.desc": "Pick the combined color of all layers at the respective pixel, instead of the color on the active layer",
|
||||
"action.split_rgb_into_layers": "Split RGB Channels into Layers",
|
||||
"action.split_rgb_into_layers.desc": "Split the texture into additive layers, one for each RGB channel"
|
||||
}
|
966
lang/uk.json
158
lang/vi.json
@ -164,11 +164,6 @@
|
||||
"layout.font.main": "Phông chữ chính",
|
||||
"layout.font.headline": "Phông chữ tiêu đề",
|
||||
"about.version": "Phiên bản:",
|
||||
"about.creator": "Nhà sáng lập:",
|
||||
"about.website": "Website:",
|
||||
"about.vertex_snap": "Tính năng Nối Đỉnh được dựa trên một plugin của SirBenet",
|
||||
"about.icons": "Các gói Icon",
|
||||
"about.libraries": "Thư viện:",
|
||||
"settings.category.general": "Cài đặt chung",
|
||||
"settings.category.preview": "Xem trước",
|
||||
"settings.category.grid": "Lưới đồ thị",
|
||||
@ -298,9 +293,9 @@
|
||||
"action.load_plugin.desc": "Tải một plugin bằng cách nhập tệp nguồn",
|
||||
"action.reload_plugins": "Reload các plugin",
|
||||
"action.reload_plugins.desc": "Tải lại toàn bộ Plugin cho Nhà Phát Triển",
|
||||
"action.undo": "Quay lại",
|
||||
"action.undo": "Hoàn tác",
|
||||
"action.undo.desc": "Quay lại thay đổi trước",
|
||||
"action.redo": "Tiến",
|
||||
"action.redo": "Làm lại",
|
||||
"action.redo.desc": "Quay lại thay đổi cuối",
|
||||
"action.copy": "Sao chép",
|
||||
"action.copy.desc": "Sao chép những đồ vật, mặt hay những điều chỉnh hiển thị đã được chọn",
|
||||
@ -838,7 +833,7 @@
|
||||
"dialog.timelapse.source.interface": "Giao diện",
|
||||
"dialog.timelapse.source.locked": "Góc khóa",
|
||||
"dialog.timelapse.destination": "Thư mục đích",
|
||||
"layout.color.checkerboard": "Bàn cờ",
|
||||
"layout.color.checkerboard": "Nền caro",
|
||||
"layout.color.checkerboard.desc": "Nền của canvas và trình chỉnh sửa UV",
|
||||
"layout.font.code": "Mã phông chữ",
|
||||
"layout.css": "CSS tùy chỉnh",
|
||||
@ -929,10 +924,10 @@
|
||||
"dialog.sketchfab_uploader.animations": "Hoạt ảnh",
|
||||
"dialog.settings.theme": "Chủ đề",
|
||||
"settings.category.interface": "Giao diện",
|
||||
"settings.preview_checkerboard": "Xem trước bàn cờ",
|
||||
"settings.preview_checkerboard.desc": "Chuyển đổi nền bàn cờ đằng sau bản xem trước",
|
||||
"settings.uv_checkerboard": "Chỉnh UV bàn cờ",
|
||||
"settings.uv_checkerboard.desc": "Chuyển đổi nền bàn cờ phía sau trình chỉnh sửa UV",
|
||||
"settings.preview_checkerboard": "Xem trước nền caro",
|
||||
"settings.preview_checkerboard.desc": "Chuyển đổi nền caro đằng sau bản xem trước",
|
||||
"settings.uv_checkerboard": "Chỉnh UV nền caro",
|
||||
"settings.uv_checkerboard.desc": "Chuyển đổi nền caro phía sau trình chỉnh sửa UV",
|
||||
"category.paint": "Vẽ",
|
||||
"action.fill_mode.color_connected": "Kết nối màu sắc",
|
||||
"action.draw_shape_type": "Loại hình dạng",
|
||||
@ -1220,7 +1215,6 @@
|
||||
"camera_angle.true_isometric_right": "Hình chiếu trục đo phải đúng(30°)",
|
||||
"camera_angle.true_isometric_left": "Hình chiếu trục đo trái đúng(30°)",
|
||||
"menu.help.wiki": "Blockbench Wiki",
|
||||
"about.repository": "Kho lưu trữ:",
|
||||
"settings.update_to_prereleases": "Cập nhật lên bản phát hành trước",
|
||||
"settings.update_to_prereleases.desc": "Tự động cập nhật lên các phiên bản beta của Blockbench để kiểm tra các tính năng mới. Các phiên bản trước khi phát hành có thể không ổn định, không bật tùy chọn này nếu bạn dùng Blockbench cho công việc hoặc các dự án quan trọng khác.",
|
||||
"data.separator.spacer": "Đệm",
|
||||
@ -1253,10 +1247,10 @@
|
||||
"dialog.add_primitive.shape.sphere": "Hình cầu",
|
||||
"dialog.add_primitive.shape.torus": "Hình xuyến",
|
||||
"dialog.add_primitive.shape.cube": "Hình khối",
|
||||
"dialog.add_primitive.shape.pyramid": "Hình kim tự tháp",
|
||||
"dialog.add_primitive.shape.pyramid": "Hình chóp",
|
||||
"dialog.add_primitive.diameter": "Đường kính",
|
||||
"dialog.add_primitive.height": "Chiều cao",
|
||||
"dialog.add_primitive.sides": "Bên",
|
||||
"dialog.add_primitive.sides": "Số mặt bên",
|
||||
"dialog.add_primitive.minor_diameter": "Độ dày",
|
||||
"dialog.add_primitive.minor_sides": "Bên nhỏ",
|
||||
"dialog.create_texture.combine_polys": "liên kết bề mặt",
|
||||
@ -1288,13 +1282,13 @@
|
||||
"action.add_plugin.desc": "Cài đặt plugin từ kiểm soát hành động",
|
||||
"action.remove_plugin": "Xóa plugin khỏi kiểm soát hành động",
|
||||
"action.remove_plugin.desc": "Gỡ cài đặt plugin thông qua Kiểm soát hành động",
|
||||
"action.add_mesh": "Thêm khung lưới",
|
||||
"action.add_mesh": "Thêm lưới",
|
||||
"action.add_mesh.desc": "Thêm một khung lưới mới",
|
||||
"action.add_texture_mesh": "Thêm khung lưới kết cấu",
|
||||
"action.add_texture_mesh": "Thêm lưới kết cấu",
|
||||
"action.add_texture_mesh.desc": "Thêm một khung lưới kết cấu mới",
|
||||
"action.find_replace": "Tìm/Thay thế...",
|
||||
"action.find_replace.desc": "Tìm và thay thế các phần của tên",
|
||||
"action.hide_everything_except_selection": "Ẩn mọi thứ trừ lựa chọn",
|
||||
"action.hide_everything_except_selection": "Ẩn mọi thứ (trừ phần lựa chọn)",
|
||||
"action.hide_everything_except_selection.desc": "Chuyển đổi chế độ hiển thị cho tất cả các phần tử ngoại trừ phần tử đã chọn",
|
||||
"action.transform_space.normal": "Bình thường",
|
||||
"action.selection_mode": "Chế độ lựa chọn",
|
||||
@ -1342,7 +1336,7 @@
|
||||
"action.merge_vertices.desc": "Hợp nhất các đỉnh đã chọn vào vị trí của đỉnh được chọn đầu tiên",
|
||||
"action.view_mode.normal": "Mặt thường",
|
||||
"action.snap_uv_to_pixels": "Khớp UV với điểm ảnh",
|
||||
"action.snap_uv_to_pixels.desc": "Gắn các đỉnh UV đã chọn vào lưới đồ thị điểm ảnh",
|
||||
"action.snap_uv_to_pixels.desc": "Gắn các đỉnh UV đã chọn vào lưới điểm ảnh",
|
||||
"menu.file.import.import_open_project": "Nhập dự án mở",
|
||||
"menu.help.unlock_projects": "Mở khóa tất cả các dự án",
|
||||
"status_bar.selection.faces": "%0 mặt",
|
||||
@ -1818,7 +1812,6 @@
|
||||
"menu.uv.flip_x": "Gương X",
|
||||
"menu.uv.flip_y": "Gương Y",
|
||||
"menu.mirror_painting.enabled": "Đã bật",
|
||||
"menu.mirror_painting.configure_texture_center": "Định cấu hình Trung tâm Kết cấu...",
|
||||
"reference_image.position": "Vị trí",
|
||||
"reference_image.size": "Kích thước",
|
||||
"reference_image.rotation": "Xoay",
|
||||
@ -2022,11 +2015,6 @@
|
||||
"action.save_animation_preset.desc": "Lưu các khung hình chính đã chọn làm giá trị cài sẵn hoạt ảnh",
|
||||
"action.animation_onion_skin": "Hoạt hoạ da Onion",
|
||||
"action.animation_onion_skin.desc": "Hiển thị chế độ xem khung dây của một khung khác trong hoạt ảnh để tham khảo",
|
||||
"action.animation_onion_skin.off": "Tắt",
|
||||
"action.animation_onion_skin.select": "Lựa chọn",
|
||||
"action.animation_onion_skin.previous": "Trước",
|
||||
"action.animation_onion_skin.next": "Tiếp",
|
||||
"action.animation_onion_skin.previous_next": "Trước + Tiếp",
|
||||
"action.apply_animation_preset": "Áp dụng giá trị cài sẵn hoạt ảnh",
|
||||
"action.apply_animation_preset.desc": "Chọn từ danh sách các giá trị cài sẵn hoạt ảnh và áp dụng nó cho xương đã chọn",
|
||||
"menu.brush_presets.pixel_perfect": "Cọ vẽ Pixel hoàn hảo",
|
||||
@ -2040,8 +2028,6 @@
|
||||
"settings.final_newline.desc": "Chèn ký tự dòng mới vào cuối tệp đã xuất",
|
||||
"action.crop_layer_to_selection": "Cắt lớp để chọn",
|
||||
"action.edit_mode_uv_overlay.desc": "Hiển thị bản đồ UV dưới dạng lớp phủ trong chế độ chỉnh sửa",
|
||||
"action.animation_onion_skin_selective": "Chọn lọc da Onion",
|
||||
"action.animation_onion_skin_selective.desc": "Chỉ hiển thị da onion cho phần đã chọn của mô hình",
|
||||
"menu.image": "Hình ảnh",
|
||||
"menu.texture.discard_changes": "Loại bỏ những thay đổi",
|
||||
"menu.texture.discard_changes.desc": "Hủy bỏ tất cả các thay đổi chưa được lưu và tải phiên bản mới nhất từ tệp",
|
||||
@ -2090,7 +2076,7 @@
|
||||
"dialog.import_obj.mtl": "Tệp MTL",
|
||||
"dialog.import_obj.scale": "Tỉ lệ",
|
||||
"layout.thumbnail": "Tùy chỉnh hình thu nhỏ CSS",
|
||||
"settings.pixel_grid": "Lưới đồ thị điểm ảnh",
|
||||
"settings.pixel_grid": "Lưới điểm ảnh",
|
||||
"settings.pixel_grid.desc": "Hiển thị lưới đồ thị kết cấu điểm ảnh trên các phần tử trong chế độ chỉnh sửa",
|
||||
"settings.image_editor_grid_size": "Kích thước lưới đồ thị của công cụ chỉnh sửa ảnh",
|
||||
"settings.image_editor_grid_size.desc": "Kích thước lưới đồ thị lớn trong công cụ chỉnh sửa ảnh 2D",
|
||||
@ -2106,7 +2092,7 @@
|
||||
"action.knife_tool.desc": "Công cụ để cắt các mặt khung lưới thành các miếng nhỏ hơn",
|
||||
"action.duplicate_project": "Nhân bản dự án",
|
||||
"action.duplicate_project.desc": "Tạo một bản sao của dự án",
|
||||
"action.transform_space.parent": "Phụ huynh",
|
||||
"action.transform_space.parent": "Gốc",
|
||||
"action.transform_pivot_space": "Tâm quay thay đổi không gian",
|
||||
"action.solidify_mesh_selection": "Làm đông đặc các mặt",
|
||||
"action.solidify_mesh_selection.desc": "Làm đông đặc các mặt được chọn của khung lưới",
|
||||
@ -2228,5 +2214,117 @@
|
||||
"dialog.blend_transition_edit.extended": "Đồ thị được mở rộng",
|
||||
"message.screenshot_too_large.title": "Screenshot Resolution Issue",
|
||||
"message.screenshot_too_large.message": "The screenshot could not be rendered successfully. Please try again with a lower resolution or without supersampling.",
|
||||
"message.rename_elements.numbering": "You can use special characters to generate sequential numbers: % to get the index of the element within its group, $ to get the index within the selection."
|
||||
"message.rename_elements.numbering": "You can use special characters to generate sequential numbers: % to get the index of the element within its group, $ to get the index within the selection.",
|
||||
"generic.edit_externally": "Edit Externally",
|
||||
"message.settings_require_restart.title": "Restart Required",
|
||||
"message.settings_require_restart.message": "Some settings will only apply after restarting the program.",
|
||||
"message.settings_require_restart.restart_now": "Restart Now",
|
||||
"message.settings_require_restart.restart_later": "Restart Later",
|
||||
"message.classroom_mode.install_plugin": "Cannot install plugins in Classroom Mode",
|
||||
"dialog.collection.export_path": "Export Path",
|
||||
"dialog.collection.select_all": "Select All",
|
||||
"dialog.collection.select_none": "Select None",
|
||||
"dialog.collection.add_with_filter": "Add with Filter",
|
||||
"dialog.collection.remove": "Remove",
|
||||
"dialog.material_config.title": "Material Config",
|
||||
"dialog.material_config.color_value": "Color Value",
|
||||
"dialog.material_config.mer": "Metal-Emissive-Roughness",
|
||||
"dialog.material_config.mer_value": "MER Value",
|
||||
"dialog.material_config.depth_type": "Depth Type",
|
||||
"dialog.create_texture.disable_mirror_uv": "Disable UV Mirroring",
|
||||
"dialog.create_texture.disable_mirror_uv.desc": "Disable the UV Mirror option in Mirror Modeling to preserve separate UVs for each side of the model",
|
||||
"dialog.create_gif.turn.sync_to_anim_length": "Sync to animation length",
|
||||
"settings.category.controls": "Controls",
|
||||
"settings.classroom_mode": "Classroom Mode",
|
||||
"settings.classroom_mode.desc": "Restricts functionality such as installing plugins and removes links to social media",
|
||||
"settings.antialiasing_bleed_fix": "Fix anti-aliasing bleeding",
|
||||
"settings.antialiasing_bleed_fix.desc": "Fixes texture bleeding when using anti-aliasing. Potentially unsupported on older hardware.",
|
||||
"settings.tone_mapping": "Tone Mapping",
|
||||
"settings.tone_mapping.desc": "Approximation method for displaying high dynamic range on a standard screen for PBR rendering.",
|
||||
"settings.audio_scrubbing": "Timline Scrubbing Audio",
|
||||
"settings.audio_scrubbing.desc": "Play short previews of the audio while scrubbing through time timeline",
|
||||
"settings.viewport_rotate_speed": "Viewport Rotate Speed",
|
||||
"settings.viewport_rotate_speed.desc": "Input sensitivity when rotating in the viewport",
|
||||
"settings.viewport_zoom_speed": "Viewport Zoom Speed",
|
||||
"settings.viewport_zoom_speed.desc": "Input sensitivity when zooming in the viewport",
|
||||
"settings.editor_2d_zoom_speed": "2D Editor Zoom Speed",
|
||||
"settings.editor_2d_zoom_speed.desc": "Input sensitivity when zooming in the UV and 2D paint editor",
|
||||
"category.select": "Select",
|
||||
"action.vertex_snap_mode.rotate": "Rotate",
|
||||
"action.export_image": "Export Image",
|
||||
"action.export_image.desc": "Export your texture as an image file",
|
||||
"action.apply_mirror_modeling": "Apply Mirror Modeling",
|
||||
"action.apply_mirror_modeling.desc": "Apply Mirror Modeling to the selection. All selected elements will be copied and flipped across the X axis.",
|
||||
"action.create_collection": "Create Collection",
|
||||
"action.create_collection.desc": "Create a collection out of the outliner selection",
|
||||
"action.set_collection_content_to_selection": "Set Collection Content to Selected",
|
||||
"action.set_collection_content_to_selection.desc": "Set the selected groups and elements as the content of the collection",
|
||||
"action.add_to_collection": "Add Selected to Collection",
|
||||
"action.add_to_collection.desc": "Add the selected groups and elements to the collection",
|
||||
"action.view_mode.material": "Material Preview",
|
||||
"action.create_material": "Create Material",
|
||||
"action.create_material.desc": "Create a new PBR material out of the selected texture",
|
||||
"action.generate_pbr_map": "Generate PBR Map...",
|
||||
"action.generate_pbr_map.desc": "Generate a PBR map (height map or metalness, emissiveness, roughness) from an existing texture",
|
||||
"menu.tools.main_tools": "Toolbox",
|
||||
"menu.view.panels": "Panels",
|
||||
"menu.texture.pbr_channel": "PBR Channel",
|
||||
"menu.texture.pbr_channel.color": "Color",
|
||||
"menu.texture.pbr_channel.normal": "Normal",
|
||||
"menu.texture.pbr_channel.height": "Height",
|
||||
"menu.texture.pbr_channel.mer": "MER (Metalness-Emissive-Roughness)",
|
||||
"menu.texture.pbr_channel.mer_subsurface": "MER Subsurface",
|
||||
"menu.collection.export_project": "Export Project",
|
||||
"menu.collection.export_as": "Export as \"%0\"",
|
||||
"menu.panel.enable": "Enable",
|
||||
"menu.panel.move_to": "Move To",
|
||||
"menu.panel.move_to.left_bar": "Left Sidebar",
|
||||
"menu.panel.move_to.right_bar": "Right Sidebar",
|
||||
"menu.panel.move_to.top": "Top",
|
||||
"menu.panel.move_to.bottom": "Bottom",
|
||||
"menu.panel.move_to.float": "Float",
|
||||
"menu.panel.move_to.hidden": "Hide",
|
||||
"menu.panel.fold": "Collapse",
|
||||
"menu.mirror_painting.texture_center": "Origin",
|
||||
"menu.mirror_modeling.mirror_uv": "Mirror UV",
|
||||
"menu.animation_onion_skin.frames": "Frames",
|
||||
"menu.animation_onion_skin.select": "Select",
|
||||
"menu.animation_onion_skin.previous": "Previous",
|
||||
"menu.animation_onion_skin.next": "Next",
|
||||
"menu.animation_onion_skin.previous_next": "Previous + Next",
|
||||
"menu.animation_onion_skin.count": "Count",
|
||||
"menu.animation_onion_skin.interval": "Interval",
|
||||
"menu.animation_onion_skin_selective": "Selective Onion Skin",
|
||||
"menu.animation_onion_skin_selective.desc": "Only display onion skin for the selected part of the model",
|
||||
"edit.loop_cut.unit": "Unit",
|
||||
"edit.loop_cut.unit.size_units": "Size Units",
|
||||
"edit.loop_cut.unit.percent": "Percent",
|
||||
"edit.extrude_mesh_selection.direction": "Direction",
|
||||
"edit.extrude_mesh_selection.direction.outwards": "Outwards",
|
||||
"edit.extrude_mesh_selection.direction.average": "Average",
|
||||
"edit.extrude_mesh_selection.even_extend": "Even Extend",
|
||||
"edit.vertex_snap.align": "Align",
|
||||
"edit.vertex_snap.align.longest": "Longest Axis",
|
||||
"edit.vertex_snap.align.direction": "Direction from Pivot",
|
||||
"edit.vertex_snap.align.align_axis": "%0 Axis",
|
||||
"edit.vertex_snap.ignore_axis": "Ignore Axis",
|
||||
"codec.common.format": "Format",
|
||||
"codec.image.quality": "Quality",
|
||||
"panel.collections": "Collections",
|
||||
"modifier_actions.always": "Always Enabled",
|
||||
"modifier_actions.unless": "Unless %0",
|
||||
"settings.undo_selections": "Undo Selection",
|
||||
"settings.undo_selections.desc": "Track selection changes as a step in the undo history",
|
||||
"action.focus_on_selection.zoom": "Zoom to fit",
|
||||
"display.reference.tooting": "Horn Tooting",
|
||||
"settings.selection_tolerance": "Selection Tolerance",
|
||||
"settings.selection_tolerance.desc": "Size of the area that can be clicked to select an edge or vertex",
|
||||
"action.delete.keep_vertices": "Keep Edges/Vertices",
|
||||
"menu.mesh": "Mesh",
|
||||
"dialog.material_config.subsurface": "Subsurface Scattering",
|
||||
"dialog.material_config.subsurface_enabled.desc": "Use the MER map alpha channel for subsurface scattering",
|
||||
"settings.pick_combined_color": "Pick Combined Color",
|
||||
"settings.pick_combined_color.desc": "Pick the combined color of all layers at the respective pixel, instead of the color on the active layer",
|
||||
"action.split_rgb_into_layers": "Split RGB Channels into Layers",
|
||||
"action.split_rgb_into_layers.desc": "Split the texture into additive layers, one for each RGB channel"
|
||||
}
|
140
lang/zh.json
@ -164,11 +164,6 @@
|
||||
"layout.font.main": "字体",
|
||||
"layout.font.headline": "标题字体",
|
||||
"about.version": "版本:",
|
||||
"about.creator": "作者:",
|
||||
"about.website": "网址:",
|
||||
"about.vertex_snap": "基于 SirBenet 顶点捕捉的插件功能",
|
||||
"about.icons": "图标包:",
|
||||
"about.libraries": "库:",
|
||||
"settings.category.general": "常规",
|
||||
"settings.category.preview": "预览",
|
||||
"settings.category.grid": "网格",
|
||||
@ -324,7 +319,7 @@
|
||||
"action.select_window.desc": "根据属性搜索并选择块",
|
||||
"action.invert_selection": "反选",
|
||||
"action.invert_selection.desc": "反向选择所选块",
|
||||
"action.select_all": "全选",
|
||||
"action.select_all": "选择全部",
|
||||
"action.select_all.desc": "选择所有元素、面、顶点或关键帧",
|
||||
"action.collapse_groups": "折叠分组",
|
||||
"action.collapse_groups.desc": "折叠大纲视图中所有分组",
|
||||
@ -1219,8 +1214,7 @@
|
||||
"camera_angle.common_isometric_left": "等距左(2:1)",
|
||||
"camera_angle.true_isometric_right": "真等距右(30°)",
|
||||
"camera_angle.true_isometric_left": "真等距左(30°)",
|
||||
"menu.help.wiki": "Blockbench Wiki",
|
||||
"about.repository": "储存库:",
|
||||
"menu.help.wiki": "Blockbench 维基",
|
||||
"settings.update_to_prereleases": "更新至预发布版",
|
||||
"settings.update_to_prereleases.desc": "自动更新至 beta 版本的 Blockbench 以测试新功能。预发布版本可能不稳定,如果您依赖 Blockbench 工作或其他重要项目,请不要启用此选项。",
|
||||
"data.separator.spacer": "间隔",
|
||||
@ -1521,7 +1515,7 @@
|
||||
"format.modded_entity.info.format": "模型是用 Java 代码编写的,而不是像所有其他 Blockbench 导出格式那样的专用数据结构。",
|
||||
"format.optifine_entity.info.optifine_required": "未安装 OptiFine 的用户将看不到该模型。",
|
||||
"format.optifine_entity.info.pivots": "骨骼枢轴被锁定,因此最好不要触碰它们。",
|
||||
"format_category.low_poly": "Low-Poly",
|
||||
"format_category.low_poly": "低多边形",
|
||||
"format_category.minecraft": "Minecraft",
|
||||
"format_category.other": "其他",
|
||||
"format_category.loaders": "加载程序",
|
||||
@ -1818,7 +1812,6 @@
|
||||
"menu.uv.flip_x": "反转 X 轴",
|
||||
"menu.uv.flip_y": "反转 Y 轴",
|
||||
"menu.mirror_painting.enabled": "启用",
|
||||
"menu.mirror_painting.configure_texture_center": "配置纹理中心...",
|
||||
"reference_image.position": "位置",
|
||||
"reference_image.size": "尺寸",
|
||||
"reference_image.rotation": "旋转",
|
||||
@ -2022,11 +2015,6 @@
|
||||
"action.save_animation_preset.desc": "将所选的关键帧保存为动画预设",
|
||||
"action.animation_onion_skin": "动画洋葱皮",
|
||||
"action.animation_onion_skin.desc": "展示动画其他帧的线框作为参考",
|
||||
"action.animation_onion_skin.off": "关闭",
|
||||
"action.animation_onion_skin.select": "选取",
|
||||
"action.animation_onion_skin.previous": "上一个",
|
||||
"action.animation_onion_skin.next": "下一个",
|
||||
"action.animation_onion_skin.previous_next": "上一个 + 下一个",
|
||||
"action.apply_animation_preset": "应用动画映射",
|
||||
"action.apply_animation_preset.desc": "选择动画映射并应用于所选骨骼",
|
||||
"menu.brush_presets.pixel_perfect": "完美像素笔刷",
|
||||
@ -2040,8 +2028,6 @@
|
||||
"settings.final_newline.desc": "在导出文件的末尾增加一个换行符",
|
||||
"action.crop_layer_to_selection": "将图层裁切至选区内",
|
||||
"action.edit_mode_uv_overlay.desc": "在编辑模式中将 UV 映射覆盖进行展示",
|
||||
"action.animation_onion_skin_selective": "选择性洋葱皮",
|
||||
"action.animation_onion_skin_selective.desc": "只为模型已选中的区域展示洋葱皮",
|
||||
"menu.image": "图像",
|
||||
"menu.texture.discard_changes": "撤销更改",
|
||||
"menu.texture.discard_changes.desc": "撤销全部未保存更改并从文件中加载最新版本",
|
||||
@ -2134,7 +2120,7 @@
|
||||
"edit.solidify_mesh_selection.thickness": "粗细度",
|
||||
"reference_image.sync_to_timeline": "对齐于时间轴",
|
||||
"reference_image.toggle_playback": "播放/停止",
|
||||
"dialog.add_primitive.shape.beveled_cuboid": "使立方体改为斜面",
|
||||
"dialog.add_primitive.shape.beveled_cuboid": "斜角方形",
|
||||
"dialog.ignore_all": "忽略所有",
|
||||
"data.texture_group": "纹理组",
|
||||
"data.animation": "动画",
|
||||
@ -2226,7 +2212,119 @@
|
||||
"animation_controllers.state.blend_transition_curve": "混合过渡曲线",
|
||||
"menu.slider.reset_vector": "重置向量",
|
||||
"dialog.blend_transition_edit.extended": "扩展图表",
|
||||
"message.screenshot_too_large.title": "Screenshot Resolution Issue",
|
||||
"message.screenshot_too_large.message": "The screenshot could not be rendered successfully. Please try again with a lower resolution or without supersampling.",
|
||||
"message.rename_elements.numbering": "You can use special characters to generate sequential numbers: % to get the index of the element within its group, $ to get the index within the selection."
|
||||
"message.screenshot_too_large.title": "截屏分辨率问题",
|
||||
"message.screenshot_too_large.message": "屏幕截图无法成功渲染。请使用较低的分辨率或不进行超采样重试。",
|
||||
"message.rename_elements.numbering": "你可以使用特殊字符生成序列号:% 获取元素组内的索引,$ 获取所选内容中的索引。",
|
||||
"generic.edit_externally": "外部编辑",
|
||||
"message.settings_require_restart.title": "需要重启",
|
||||
"message.settings_require_restart.message": "一些设置需要重新启动程序以生效。",
|
||||
"message.settings_require_restart.restart_now": "立即重启",
|
||||
"message.settings_require_restart.restart_later": "以后重启",
|
||||
"message.classroom_mode.install_plugin": "不会教室模式在安装插件",
|
||||
"dialog.collection.export_path": "导出路径",
|
||||
"dialog.collection.select_all": "选择全部",
|
||||
"dialog.collection.select_none": "无选择",
|
||||
"dialog.collection.add_with_filter": "使用过滤添加",
|
||||
"dialog.collection.remove": "移除",
|
||||
"dialog.material_config.title": "材质设置",
|
||||
"dialog.material_config.color_value": "颜色值",
|
||||
"dialog.material_config.mer": "金属、自发光、粗糙度",
|
||||
"dialog.material_config.mer_value": "MER 值",
|
||||
"dialog.material_config.depth_type": "深度类型",
|
||||
"dialog.create_texture.disable_mirror_uv": "禁用 UV 镜像",
|
||||
"dialog.create_texture.disable_mirror_uv.desc": "禁用镜像建模中的 UV 镜像选项,为模型的每一侧保留单独的 UV",
|
||||
"dialog.create_gif.turn.sync_to_anim_length": "同步到动画长度",
|
||||
"settings.category.controls": "控制",
|
||||
"settings.classroom_mode": "教室模式",
|
||||
"settings.classroom_mode.desc": "限制安装插件等功能并删除指向社交媒体的链接",
|
||||
"settings.antialiasing_bleed_fix": "修复抗锯齿渗出",
|
||||
"settings.antialiasing_bleed_fix.desc": "修复使用抗锯齿时的纹理渗出问题",
|
||||
"settings.tone_mapping": "色调映射",
|
||||
"settings.tone_mapping.desc": "用于在标准屏幕上显示 HDR 以进行 PBR 渲染的近似方法。",
|
||||
"settings.audio_scrubbing": "在时间轴上试听音频",
|
||||
"settings.audio_scrubbing.desc": "播放音频的简短预览,同时拖动时间轴",
|
||||
"settings.viewport_rotate_speed": "视口旋转速度",
|
||||
"settings.viewport_rotate_speed.desc": "在视口中旋转时的灵敏度",
|
||||
"settings.viewport_zoom_speed": "视口缩放速度",
|
||||
"settings.viewport_zoom_speed.desc": "在视口中缩放时的输入灵敏度",
|
||||
"settings.editor_2d_zoom_speed": "2D 编辑器缩放速度",
|
||||
"settings.editor_2d_zoom_speed.desc": "在 UV 和 2D 绘制编辑器中放大时的灵敏度",
|
||||
"category.select": "选择",
|
||||
"action.vertex_snap_mode.rotate": "旋转",
|
||||
"action.export_image": "导出图像",
|
||||
"action.export_image.desc": "将纹理导出为图像文件",
|
||||
"action.apply_mirror_modeling": "应用镜像建模",
|
||||
"action.apply_mirror_modeling.desc": "将镜像建模应用于所选内容。所有选定的元素都将被复制并沿 X 轴翻转。",
|
||||
"action.create_collection": "创建集合",
|
||||
"action.create_collection.desc": "从大纲视图选择中创建集合",
|
||||
"action.set_collection_content_to_selection": "将集合内容设置为选定对象",
|
||||
"action.set_collection_content_to_selection.desc": "Set the selected groups and elements as the content of the collection",
|
||||
"action.add_to_collection": "添加选东西择到的集合",
|
||||
"action.add_to_collection.desc": "Add the selected groups and elements to the collection",
|
||||
"action.view_mode.material": "材质预览",
|
||||
"action.create_material": "创建材质",
|
||||
"action.create_material.desc": "从选定纹理中创建新的 PBR 材质",
|
||||
"action.generate_pbr_map": "生成 PBR 贴图",
|
||||
"action.generate_pbr_map.desc": "从现有纹理生成 PBR 贴图(高度贴图或金属度、发光度、粗糙度)",
|
||||
"menu.tools.main_tools": "工具箱",
|
||||
"menu.view.panels": "面板",
|
||||
"menu.texture.pbr_channel": "PBR 通道",
|
||||
"menu.texture.pbr_channel.color": "颜色",
|
||||
"menu.texture.pbr_channel.normal": "法线贴图",
|
||||
"menu.texture.pbr_channel.height": "凹凸贴图",
|
||||
"menu.texture.pbr_channel.mer": "MER (金属度-自发光-粗糙度)",
|
||||
"menu.texture.pbr_channel.mer_subsurface": "MER Subsurface",
|
||||
"menu.collection.export_project": "导出项目",
|
||||
"menu.collection.export_as": "导出为 “%0\"",
|
||||
"menu.panel.enable": "启用",
|
||||
"menu.panel.move_to": "移到",
|
||||
"menu.panel.move_to.left_bar": "左屏侧边栏",
|
||||
"menu.panel.move_to.right_bar": "右屏侧边栏",
|
||||
"menu.panel.move_to.top": "上屏",
|
||||
"menu.panel.move_to.bottom": "下屏",
|
||||
"menu.panel.move_to.float": "窗口",
|
||||
"menu.panel.move_to.hidden": "隐藏",
|
||||
"menu.panel.fold": "折叠",
|
||||
"menu.mirror_painting.texture_center": "原点",
|
||||
"menu.mirror_modeling.mirror_uv": "镜像 UV",
|
||||
"menu.animation_onion_skin.frames": "帧",
|
||||
"menu.animation_onion_skin.select": "选择",
|
||||
"menu.animation_onion_skin.previous": "上一个",
|
||||
"menu.animation_onion_skin.next": "下一个",
|
||||
"menu.animation_onion_skin.previous_next": "上一个 + 下一个",
|
||||
"menu.animation_onion_skin.count": "数量",
|
||||
"menu.animation_onion_skin.interval": "间隔",
|
||||
"menu.animation_onion_skin_selective": "选择性洋葱皮",
|
||||
"menu.animation_onion_skin_selective.desc": "仅显示模型选定部分的洋葱皮",
|
||||
"edit.loop_cut.unit": "Unit",
|
||||
"edit.loop_cut.unit.size_units": "Size Units",
|
||||
"edit.loop_cut.unit.percent": "百分之",
|
||||
"edit.extrude_mesh_selection.direction": "方向",
|
||||
"edit.extrude_mesh_selection.direction.outwards": "Outwards",
|
||||
"edit.extrude_mesh_selection.direction.average": "平均",
|
||||
"edit.extrude_mesh_selection.even_extend": "均匀拓展",
|
||||
"edit.vertex_snap.align": "对齐",
|
||||
"edit.vertex_snap.align.longest": "最长轴",
|
||||
"edit.vertex_snap.align.direction": "Direction from Pivot",
|
||||
"edit.vertex_snap.align.align_axis": "轴 %0",
|
||||
"edit.vertex_snap.ignore_axis": "忽略 轴",
|
||||
"codec.common.format": "格式",
|
||||
"codec.image.quality": "品质",
|
||||
"panel.collections": "集合",
|
||||
"modifier_actions.always": "始终启用",
|
||||
"modifier_actions.unless": "除非 %0",
|
||||
"settings.undo_selections": "撤消选择",
|
||||
"settings.undo_selections.desc": "将所选内容更改作为撤消历史记录中的一个步骤进行跟踪",
|
||||
"action.focus_on_selection.zoom": "Zoom to fit",
|
||||
"display.reference.tooting": "Horn Tooting",
|
||||
"settings.selection_tolerance": "Selection Tolerance",
|
||||
"settings.selection_tolerance.desc": "Size of the area that can be clicked to select an edge or vertex",
|
||||
"action.delete.keep_vertices": "Keep Edges/Vertices",
|
||||
"menu.mesh": "网格",
|
||||
"dialog.material_config.subsurface": "Subsurface Scattering",
|
||||
"dialog.material_config.subsurface_enabled.desc": "Use the MER map alpha channel for subsurface scattering",
|
||||
"settings.pick_combined_color": "Pick Combined Color",
|
||||
"settings.pick_combined_color.desc": "Pick the combined color of all layers at the respective pixel, instead of the color on the active layer",
|
||||
"action.split_rgb_into_layers": "Split RGB Channels into Layers",
|
||||
"action.split_rgb_into_layers.desc": "Split the texture into additive layers, one for each RGB channel"
|
||||
}
|
1089
lang/zh_tw.json
@ -5,11 +5,11 @@ class CanvasFrame {
|
||||
/**
|
||||
*
|
||||
* @param {Number|HTMLCanvasElement|HTMLImageElement} [a] Image source
|
||||
* @param {Number} [b]
|
||||
* @param {Number|Boolean} [b]
|
||||
*/
|
||||
constructor(a, b) {
|
||||
if (a && a.nodeName == 'CANVAS') {
|
||||
if (a.getContext('2d')) {
|
||||
if (a.getContext('2d') && b !== true) {
|
||||
this.canvas = a;
|
||||
} else {
|
||||
this.createCanvas(a.width, a.height)
|
||||
|