This commit is contained in:
JannisX11 2020-03-04 20:56:17 +01:00
parent 70b211a9da
commit 15e2407324
73 changed files with 7093 additions and 52126 deletions

View File

@ -1,8 +1,11 @@
[!] Before you report an issue, check if if has already been reported. Also check if you are using the latest version of Blockbench.
[!] Prefix the title of your issue with [Issue] or [Suggestion]
[!] If you are having an issue, please press "Ctrl + Shift + i" and click on console. If there are any error messages, please attach a screenshot of it to your issue.
[!] If you are having an issue, please press "Ctrl + Shift + i" and click on console. If there are any (red) error messages, please attach a screenshot of the console to your issue.
Supply the following information:
For issues, please provide the following informations:
- Detailed description of your issue
- Model format in which the issue occurs
For issues that are related to installation, opening/closing, import/export or other platform specific actions, please provide these informations:
- Blockbench variant (Webapp/Desktop)
- Operating System

View File

@ -70,6 +70,11 @@
margin-bottom: 4px;
height: auto;
}
.dialog_bar::after {
content: "";
clear: both;
display: block;
}
.dialog_bar.narrow {
min-height: 30px;
}
@ -485,15 +490,6 @@
margin-left: 1px;
margin-right: 8px;
}
label.in_toolbar {
text-align: left;
color: var(--color-text);
padding: 8px;
padding-top: 3px;
padding-bottom: 0;
min-width: 155px;
margin-right: 8px;
}
/*PE Import Dialog*/
#pe_list {

View File

@ -84,7 +84,7 @@
input.medium_width {
width: 64px;
}
.checkerboard {
.checkerboard, .checkerboard_trigger .checkerboard_target {
--color-checker_offset: rgba(0, 0, 0, 0.16);
background-color: var(--color-checkerboard) !important;
background-image: linear-gradient(45deg, var(--color-checkerboard) 25%, transparent 25%),
@ -94,6 +94,10 @@
background-size: 30px 30px;
background-position: 0 0, 0 15px, 15px -15px, -15px 0px;
}
body[mode=start] div#center.checkerboard {
background-image: none;
background-color: var(--color-dark) !important;
}
/*General*/
canvas.preview {
@ -104,7 +108,8 @@
margin-right: 5px;
}
.toolbar_label {
margin-top: 4px;
padding: 2px;
margin-left: 4px;
}
.bar {
height: 30px;
@ -156,12 +161,15 @@
right: 0;
top: 420px;
z-index: 100;
min-width: 100px;
max-width: 200px;
min-width: 150px;
max-width: 250px;
width: min-content;
padding: 0 12px;
background-color: var(--color-bright_ui);
color: var(--color-accent_text);
box-shadow: 0 0 2px black;
text-align: center;
overflow-wrap: break-word;
cursor: default;
pointer-events: none;
}
@ -264,7 +272,7 @@
padding: 0 8px;
padding-top: 2px;
display: inline-block;
height: 100%;
height: 29px;
font-weight: normal;
}
li.menu_bar_point.opened {
@ -335,7 +343,7 @@
}
.tool {
height: 30px;
width: 38px;
width: 36px;
margin-left: 1px;
margin-right: 1px;
background: transparent;
@ -362,6 +370,9 @@
.tool.widget.bar_text {
padding: 2px 3px;
}
.tool.has_label {
width: auto;
}
.tool:hover {
color: var(--color-light);
@ -424,11 +435,11 @@
padding-right: 5px;
padding-top: 2px;
color: var(--color-accent_text);
margin-top: 32px;
margin-top: 30px;
display: none;
background: var(--color-bright_ui);
white-space: nowrap;
z-index: 125;
z-index: 18;
box-shadow: 0 0.4px 3.5px rgba(0, 0, 0, 0.6);
}
.tool:hover > .tooltip:not(:hover) {
@ -457,8 +468,8 @@
margin-top: -28px;
}
.contextMenu li {
height: 32px;
padding: 5px;
height: 30px;
padding: 4px;
padding-left: 34px;
padding-right: 8px;
}
@ -474,18 +485,18 @@
text-rendering: auto;
-webkit-font-smoothing: antialiased;
float: right;
margin-top: 2px;
margin-right: -12px;
pointer-events: none;
}
.contextMenu li.focused, .contextMenu li.parent.opened {
background-color: var(--color-accent);
}
.contextMenu li i {
float: left;
margin-bottom: -5px;
margin-top: 1px;
margin-top: 1px;
margin-right: 4px;
margin-left: -28px;
pointer-events: none;
}
.contextMenu li img {
cursor: default;
@ -522,6 +533,12 @@
#start_screen h3 {
margin: 0;
}
#start_screen .bar.next_to_title {
margin-top: -40px;
margin-right: -12px;
position: relative;
float: right;
}
#start_screen .recent_project {
margin: 2px 0;
display: flex;
@ -549,6 +566,34 @@
background: linear-gradient(90deg, transparent, var(--color-ui));
}
#start_screen .recent_project.thumbnail {
width: 242px;
height: 150px;
width: 168px;
height: 128px;
position: relative;
float: left;
background-color: var(--color-back);
margin: 1px;
background-size: 150px;
background-repeat: no-repeat;
}
#start_screen .recent_project.thumbnail:hover {
background-color: var(--color-ui);
}
#start_screen .recent_project.thumbnail .recent_project_name {
font-size: 1em;
overflow-x: hidden;
flex-shrink: 1;
flex-grow: 1;
height: 24px;
right: 6px;
left: 6px;
bottom: 0;
position: absolute;
}
#start_screen > content {
display: block;
margin-top: 40px;
@ -631,10 +676,10 @@
color: var(--color-light);
}
#start-files left {
width: 40%;
width: 36%;
}
#start-files right {
width: 60%;
width: 64%;
border-left: 1px solid var(--color-border);
}
#start_screen left > ul {

View File

@ -482,6 +482,13 @@
font-size: 15px;
float: right;
}
#cubes_list .outliner_object i.icon-open-state {
opacity: 0.7;
}
#cubes_list .outliner_object i.icon-open-state:hover {
opacity: 1;
}
.outliner_object i.ec_0 {
color: #A2EBFF; /*light_blue*/
}
@ -840,7 +847,7 @@
color: var(--color-light);
}
#timeline_body li > .animator_channel_bar .channel_head {
padding-left: 34px;
padding-left: 16px;
}
.channel_head .text_button {
width: 26px;
@ -852,6 +859,9 @@
.animator_channel_bar .channel_head .text_button {
float: right;
}
.animator_channel_bar .channel_head .text_button .channel_mute {
font-size: 11pt;
}
.animator.selected .animator_head_bar {
background-color: var(--color-selected);
}
@ -962,13 +972,8 @@
cursor: move;
box-sizing: border-box;
z-index: 1;
box-shadow: 0 0 0 1.5px var(--color-text);
}
#uv_frame:hover #uv_size {
box-shadow: 0 0 0 1.5px white;
}
#uv_frame:hover #uv_size.dark_frame {
box-shadow: 0 0 0 1.5px black;
box-shadow: 0 0 0 1.5px #ffffff;
mix-blend-mode: difference;
}
.uv_size_handle {
position: absolute;
@ -1034,6 +1039,53 @@
left: 1px;
}
#texture_selection_rect {
position: absolute;
pointer-events: none;
border: 1px dashed white;
mix-blend-mode: difference;
}
#texture_pasting_overlay {
position: absolute;
}
#texture_pasting_overlay::before {
content: "";
display: block;
position: absolute;
border: 1px dashed white;
pointer-events: none;
z-index: 6;
width: 100%;
height: 100%;
}
#texture_pasting_overlay > canvas {
box-shadow: 1px 1px 20px black;
cursor: move;
z-index: 5;
float: left;
}
#texture_pasting_overlay > div.control {
background-color: var(--color-bright_ui);
position: absolute;
box-shadow: 1px 1px 15px rgba(0, 0, 0, 0.5);
width: 30px;
height: 30px;
bottom: -30px;
width: max-content;
}
#texture_pasting_overlay > div.control > div {
width: 30px;
height: 30px;
padding: 3px;
float: left;
color: var(--color-accent_text);
text-align: center;
}
#texture_pasting_overlay > div.control > div:hover {
background-color: var(--color-accent);
color: var(--color-accent_text);
}
/*Edit Session UI*/
#chat {
z-index: 16;

View File

@ -152,6 +152,12 @@
-moz-osx-font-smoothing: grayscale;
}
.icon-gizmo:before {
content: "\e922";
}
.icon-gltf:before {
content: "\e923";
}
.icon-format_bedrock_legacy:before {
content: "\e91a";
}
@ -257,6 +263,7 @@
.material-icons {
font-family: 'Material Icons';
font-weight: normal;
@ -275,7 +282,7 @@
}
i.fa_big {
font-size: 15pt;
height: 28px;
height: 22px;
width: 22px;
text-align: center;
vertical-align: text-top;
@ -398,8 +405,6 @@
outline: none;
}
button {
height: 30px;
width: 40px;
border: none;
background: var(--color-button);
display: inline-block;
@ -407,7 +412,7 @@
vertical-align: middle;
cursor: default;
outline: none;
height: 35px;
height: 32px;
min-width: 100px;
width: auto;
color: var(--color-text);
@ -450,6 +455,9 @@
select:hover{
color: var(--color-light);
}
select:focus{
text-decoration: underline;
}
select option {
-webkit-appearance: none;
background-color: var(--color-back);
@ -467,6 +475,34 @@
resize: none;
outline: none;
}
bb-select {
display: block;
position: relative;
background-color: var(--color-button);
text-align: left;
height: 30px;
min-width: 50px;
padding-top: 4px;
padding-left: 10px;
padding-right: 28px;
color: var(--color-text);
}
bb-select:hover{
color: var(--color-light);
}
bb-select::before {
content: "\f0d7";
font-family: 'Font Awesome 5 Free';
font-weight: 900;
display: block;
position: absolute;
height: 12px;
width: 16px;
pointer-events: none;
right: 6px;
top: 3px;
}
input[type="number"]::-webkit-outer-spin-button, input[type="number"]::-webkit-inner-spin-button, {
-webkit-appeareance: none;
}
@ -499,6 +535,9 @@
font-family: 'Font Awesome 5 Free';
font-weight: 600;
}
input[type=checkbox]:focus, input[type=radio]:focus {
color: var(--color-light);
}
input[type=checkbox][disabled=disabled] {
opacity: 0.6;
}

View File

@ -312,7 +312,6 @@ See http://bgrins.github.io/spectrum/themes/ for instructions.
.sp-input-container {
float: left;
width: 64%;
margin-bottom: 4px;
margin-top: -3px;
}
.sp-input {
@ -459,6 +458,9 @@ See http://bgrins.github.io/spectrum/themes/ for instructions.
vertical-align: middle;
text-decoration:none;
}
.sp-choose {
vertical-align: middle;
}

Binary file not shown.

View File

@ -41,4 +41,6 @@
<glyph unicode="&#xe91f;" glyph-name="format_hytale" d="M407.713 284.215l-360.873-102.021 465.16-199.354 465.16 199.354-269.309 76.965-138.439-100.065zM612.456 286.415v-14.147l13.498 10.253zM568.958 574.713l-120.146-0.822-0.754-268.17-109.968 84.054v343.252l-51.828 102.165 160.98 15.113 0.385-171.803 120.546 0.613 0.816 170.844 163.017-15.331-51.408-104.126-0.913-439.617-110.722-83.72z" />
<glyph unicode="&#xe920;" glyph-name="format_java" d="M312.184 248.184l-266.422-66.606 466.24-199.816 466.24 199.816-266.422 66.606c-66.606-66.606-333.028-66.606-399.634 0zM513.040 799.76c-66.606 0-199.816-33.302-199.816-99.908v-333.028c-0.52-150.382 399.634-152.984 399.634 0v32.262c199.816 0 199.816 266.422 0 266.422v34.344c0 66.606-133.212 99.908-199.816 99.908zM513.040 752.799c73.568 0 133.209-25.452 133.212-56.849-0.003-31.397-59.644-56.849-133.212-56.849s-133.209 25.452-133.212 56.849c0.003 31.397 59.644 56.849 133.212 56.849zM712.858 598.904c133.212 0 133.212-133.212 0-133.212z" />
<glyph unicode="&#xe921;" glyph-name="format_optifine" d="M267.243 358.349v35.469h-75.113v292.109h75.113v75.113h146.054v-75.113h70.942v-292.109h-70.942v-70.942h-146.054zM413.297 539.873v146.054h-146.054v-292.109h146.054zM559.351 541.96v219.084h292.109v-75.113h-221.167v-70.942h146.054v-75.113h-146.054v-216.996h-70.942zM512 308.868l-486.956-139.097 486.956-208.731 486.956 208.731z" />
<glyph unicode="&#xe922;" glyph-name="gizmo" d="M465.852-31.801c-120.58 7.681-257.502 16.277-372.249 23.495-33.232 2.090-60.945 3.894-61.584 4.009s15.903 16.604 36.76 36.643c101.976 97.942 182.841 175.579 287.215 275.796 15.121 6.719 26.21 5.487 37.779 0.291 23.908-10.791 51.186-40.829 73.57-81.017 4.757-8.541 9.142-15.542 9.742-15.559 0.817-0.024 121.885 43.468 130.561 46.901 0.833 0.33 1.403 0.917 1.267 1.305-0.244 0.696-168.016 127.989-171.262 129.941-3.16-1.893-14.938-12.757-18.247-15.456-24.814-20.168-49.73-32.216-74.296-35.926-21.812-3.487-46.708 1.958-63.859 15.302-66.135 118.892-75.883 135.209-151.103 292.686 98.993 0.453 197.986 0.906 296.979 1.358 21.359-3.166 39.092-10.393 51.46-23.057 15.562-15.997 24.417-37.367 26.601-64.185 2.047-25.147-2.756-56.092-12.698-81.818-2.382-6.164-4.216-11.701-4.075-12.305 50.597-39.182 95.45-71.965 150.656-113.11 12.382-9.23 22.739-16.556 23.013-16.282 0.719 0.719 3.491 98.007 2.814 98.781-0.311 0.356-4.672 1.425-9.692 2.377-15.208 2.883-38.374 10.357-54.142 17.468-29.642 13.368-49.408 29.637-59.807 49.225-7.088 13.344-7.696 25.508-5.202 36.090 2.025 8.572 3.633 12.021 26.718 57.289 53.272 104.17 107.428 210.564 157.031 307.498 11.748 22.957 12.082 23.496 13.091 21.127 95.828-224.68 162.7-383.013 165.206-391.159 4.691-14.872 2.472-26.18-2.685-37.183-6.157-13.093-14.519-22.148-30.27-32.781-21.964-14.827-55.3-26.655-87.619-31.088-7.522-1.032-14.093-2.134-14.603-2.45-0.623-0.385-2.301-31.507-5.107-94.732-2.298-51.787-4.61-96.82-5.137-100.073-2.312-14.26-12.126-27.85-24.868-34.435-1.401-0.724-50.837-19.449-109.858-41.612s-107.586-40.555-107.92-40.873c1.080-8.923 3.568-18.809 4.91-26.739 9.738-57.871 3.007-102.297-18-118.809-9.258-7.288-18.848-7.502-31.089-6.93z" />
<glyph unicode="&#xe923;" glyph-name="gltf" d="M451.659 239.907c18.98 21.281 29.009 52.387 29.009 94.281v234.082h-40.081v-36.622h-0.489c-7.6 14.183-18.144 24.817-31.671 31.916-13.527 7.085-28.379 10.634-44.543 10.634-22.104 0-40.75-4.205-55.923-12.614s-27.389-19.224-36.622-32.417c-9.245-13.193-15.842-27.711-19.803-43.553s-5.941-31.35-5.941-46.523c0-17.488 2.392-34.076 7.175-49.738 4.783-15.675 11.959-29.447 21.526-41.328s21.448-21.281 35.632-28.212c14.183-6.931 30.848-10.39 49.995-10.39 7.921 0 15.919 0.99 24.007 2.97s15.675 4.861 22.773 8.667c7.085 3.793 13.437 8.577 19.057 14.35 5.606 5.774 10.223 12.614 13.862 20.536h0.977v-16.819c0-14.518-1.402-27.711-4.205-39.592s-7.342-22.027-13.605-30.437c-6.275-8.41-14.196-15.006-23.75-19.803-9.567-4.783-21.281-7.175-35.13-7.175-6.931 0-14.196 0.746-21.77 2.225-2.739 0.54-5.401 1.196-7.985 1.967-2.816 0.99-5.606 2.006-8.371 3.035-0.257 0.103-0.514 0.219-0.772 0.334v-0.051c-108.721 40.621-180.255 109.634-180.255 187.957 0 124.923 181.978 226.186 406.467 226.186 125.052 0 237.181-28.482 311.749-77.912-81.396 82.824-227.318 141.023-394.174 141.048-255.53 0.051-462.698-129.45-462.724-289.246-0.013-109.068 96.505-204.056 239.045-253.396 114.328-3.909 172.359 17.308 206.538 55.64zM434.402 409.901c-2.803-11.882-7.175-22.516-13.116-31.916s-13.772-16.999-23.506-22.76c-9.734-5.774-21.526-8.667-35.387-8.667s-25.409 2.88-34.642 8.667c-9.245 5.761-16.665 13.36-22.271 22.76-5.619 9.4-9.567 19.867-11.882 31.427-2.315 11.547-3.459 23.094-3.459 34.642 0 12.203 1.402 23.917 4.205 35.143 2.803 11.213 7.252 21.114 13.36 29.691 6.095 8.577 13.939 15.418 23.506 20.536s21.114 7.677 34.642 7.677c13.193 0 24.406-2.649 33.651-7.921 9.233-5.285 16.742-12.293 22.516-21.037s9.978-18.555 12.614-29.447c2.636-10.891 3.961-21.95 3.961-33.163 0.013-11.869-1.389-23.75-4.192-35.632zM471.179 215.784c-24.239-22.001-67.547-47.128-126.531-56.99 39.489-6.867 81.1-10.531 124.075-10.544 166.187-0.039 311.723 57.98 393.325 140.225-74.555-49.134-186.234-77.089-310.836-77.089-29.588 0.013-52.232 1.054-80.033 4.398zM727.056 311.685h-60.385v203.439h-75.764v51.731h211.926v-51.731h-75.764v-203.439zM894.645 311.685h-60.398v255.17h186.44v-51.731h-126.042v-47.745h110.329v-51.731h-110.329zM515.799 630.429h42.061v-318.011h-42.061z" />
</font></defs></svg>

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Binary file not shown.

View File

@ -20,16 +20,16 @@
<style type="text/css" id="theme_css"></style>
</head>
<body spellcheck="false">
<div id="loading_error_message" style="display: none;">
<div>An error occurred while loading Blockbench</div>
<button onclick="Blockbench.reload()" class="large" style="margin-right: auto; margin-left: auto;">Reload</button>
<button onclick="window.close()" class="large" style="margin-right: auto; margin-left: auto;">Quit</button>
</div>
<script>
if (typeof module === 'object') {window.module = module; module = undefined;}//jQuery Fix
const isApp = typeof require !== 'undefined';
const appVersion = '3.3.1';
const appVersion = '3.4.0';
</script>
<div id="loading_error_message" style="display: none;">
<div>An error occurred while loading Blockbench</div>
<button onclick="isApp ? Blockbench.reload() : window.location.reload(true)" class="large" style="margin-right: auto; margin-left: auto;">Reload</button>
<button onclick="window.close()" class="large" style="margin-right: auto; margin-left: auto;">Quit</button>
</div>
<script src="lib/vue.min.js"></script>
<script src="lib/vue_sortable.js"></script>
<script src="lib/jquery.js"></script>
@ -44,8 +44,9 @@
<script src="lib/peer.min.js"></script>
<script src="lib/marked.min.js"></script>
<script src="lib/spectrum.js"></script>
<script src="lib/three.js"></script>
<script src="lib/three.min.js"></script>
<script src="lib/three_custom.js"></script>
<script src="lib/GLTFExporter.js"></script>
<!--script src="lib/fik.min.js"></script-->
<script src="lib/molang.js"></script>
<script src="js/preview/OrbitControls.js"></script>
@ -85,6 +86,7 @@
<script src="js/texturing/uv.js"></script>
<script src="js/interface/interface.js"></script>
<script src="js/texturing/painter.js"></script>
<script src="js/texturing/texture_generator.js"></script>
<script src="js/texturing/color.js"></script>
<script src="js/display_mode.js"></script>
<script src="js/animations.js"></script>
@ -96,6 +98,7 @@
<script src="js/io/bedrock.js"></script>
<script src="js/io/bedrock_old.js"></script>
<script src="js/io/obj.js"></script>
<script src="js/io/gltf.js"></script>
<script src="js/io/modded_entity.js"></script>
<script src="js/io/optifine_jem.js"></script>
<script src="js/io/optifine_jpm.js"></script>
@ -353,12 +356,20 @@
<input type="number" id="scaling_origin_y" class="dark_bordered medium_width" oninput="scaleAll()">
<label for="scaling_origin_z" class="inline_label tl">Z</label>
<input type="number" id="scaling_origin_z" class="dark_bordered medium_width" oninput="scaleAll()">
<div class="tool" style="float: none" onclick="setScaleAllPivot('origin')">
<div class="tooltip tl">dialog.scale.element_pivot</div>
<i class="material-icons">center_focus_strong</i>
</div>
<div class="tool" style="float: none" onclick="setScaleAllPivot('selection')">
<div class="tooltip tl">dialog.scale.selection_center</div>
<i class="material-icons">filter_tilt_shift</i>
</div>
</div>
<label class="tl">dialog.scale.scale</label>
<div class="dialog_bar" style="height: 32px;">
<input type="range" id="model_scale_range" value="1" min="0" max="4" step="0.02" oninput="modelScaleSync()">
<input type="number" class="f_left" id="model_scale_label" min="0" max="4" step="0.02" value="1" oninput="modelScaleSync(true)">
<input type="number" class="f_left dark_bordered" id="model_scale_label" min="0" max="4" step="0.02" value="1" oninput="modelScaleSync(true)">
</div>
<div class="dialog_bar narrow" id="scaling_clipping_warning"></div>
@ -459,7 +470,7 @@
<div class="dialog_bar borderless tab_bar" id="settings_tab_bar">
<div class="tl tab open" id="setting" onclick="setSettingsTab('setting')">dialog.settings.settings</div>
<div class="tl tab" id="keybindings" onclick="setSettingsTab('keybindings')">dialog.settings.keybinds</div>
<div class="tl tab" id="layout_settings" onclick="setSettingsTab('layout_settings')">dialog.settings.layout</div>
<div class="tl tab" id="layout_settings" onclick="setSettingsTab('layout_settings')">dialog.settings.theme</div>
<div class="tl tab" id="credits" onclick="setSettingsTab('credits')">dialog.settings.about</div>
</div>
@ -547,7 +558,7 @@
</div>
<div id="layout_settings" class="hidden tab_content">
<h2 class="tl i_b">dialog.settings.layout</h2>
<h2 class="tl i_b">dialog.settings.theme</h2>
<div class="bar next_to_title" id="layout_title_bar"></div>
<div class="y_scrollable" id="theme_editor">
<div id="color_wrapper">
@ -714,7 +725,7 @@
v-on:click="mode.select()"
>{{ mode.name }}</li>
</ul>
</div id="main_toolbar">
</div>
<div id="left_bar" class="sidebar">
<div id="uv" class="panel selection_only">
<div class="bar next_to_title" id="uv_title_bar">
@ -947,12 +958,15 @@
<input type="radio" name="tab" id="radio_color_palette" value="palette" v-model="open_tab">
<label class="tl" for="radio_color_palette">panel.color.palette</label>
<input type="radio" name="tab" id="radio_color_both" value="both" v-model="open_tab">
<label class="tl" for="radio_color_both">panel.color.both</label>
</div>
<div v-show="open_tab == 'picker'">
<div v-show="open_tab == 'picker' || open_tab == 'both'">
<input id="main_colorpicker">
<div class="toolbar_wrapper color_picker"></div>
</div>
<div v-show="open_tab == 'palette'">
<div v-show="open_tab == 'palette' || open_tab == 'both'">
<div class="toolbar_wrapper palette"></div>
<ul id="palette_list" class="list" v-sortable="{onUpdate: sort, onEnd: drop, fallbackTolerance: 10}" @contextmenu="ColorPanel.menu.open($event)">
<li
@ -1047,6 +1061,16 @@
</div>
<div class="animator_channel_bar" v-bind:style="{width: (size*length + head_width)+'px'}" v-for="channel in animator.channels" v-if="animator.expanded && (!focus_channel || channel == focus_channel)">
<div class="channel_head" v-bind:style="{left: scroll_left+'px', width: head_width+'px'}">
<div class="text_button" v-on:click.stop="animator.toggleMuted(channel)">
<template v-if="channel === 'sound'">
<i class="channel_mute fas fa-volume-mute" v-if="animator.muted[channel]"></i>
<i class="channel_mute fas fa-volume-up" v-else></i>
</template>
<template v-else-if="channel !== 'timeline'">
<i class="channel_mute fas fa-eye-slash" v-if="animator.muted[channel]"></i>
<i class="channel_mute fas fa-eye" v-else></i>
</template>
</div>
<span>{{ tl('timeline.'+channel) }}</span>
<div class="text_button" v-on:click.stop="animator.createKeyframe(null, Timeline.time, channel, true)">
<i class="material-icons">add</i>
@ -1081,6 +1105,12 @@
<section id="start-files">
<left>
<h2 class="tl">mode.start.new</h2>
<div class="bar next_to_title" id="uv_title_bar">
<div class="tool" onclick="Blockbench.openLink('https://blockbench.net/quickstart/')">
<div class="tooltip tl">menu.help.quickstart</div>
<i class="fa_big fas fa-directions"></i>
</div>
</div>
<ul>
<li v-for="format in formats" v-if="format.show_on_start_screen" v-on:click="format.new()">
<span class="icon_wrapper f_left" v-html="Blockbench.getIconNode(format.icon).outerHTML"></span>
@ -1091,7 +1121,7 @@
</left>
<right>
<h2 class="tl">mode.start.recent</h2>
<ul>
<ul v-if="true">
<li v-on:click="openProject(project, $event)" v-for="project in recent" v-bind:title="project.path" class="recent_project">
<span class="icon_wrapper" v-html="Blockbench.getIconNode(project.icon).outerHTML"></span>
<span class="recent_project_name">{{ project.name }}</span>
@ -1099,6 +1129,13 @@
</li>
<div v-if="recent.length == 0">{{ tl('mode.start.no_recents') }}</div>
</ul>
<ul v-else>
<li v-on:click="openProject(project, $event)" v-for="project in recent" v-bind:title="project.path" class="recent_project thumbnail" :style="{'background-image': `url('${project.thumbnail}')`}">
<span class="recent_project_name">{{ project.name }}</span>
</li>
<div v-if="recent.length == 0">{{ tl('mode.start.no_recents') }}</div>
</ul>
<button class="tl" style="margin-top: 20px;" onclick="BarItems.open_model.trigger()">action.open_model</button>
</right>
</section>

View File

@ -288,6 +288,10 @@ class GeneralAnimator {
this.expanded = false;
this.selected = false;
this.uuid = uuid || guid();
this.muted = {};
this.channels.forEach(channel => {
this.muted[channel] = false;
})
}
select() {
var scope = this;
@ -369,6 +373,9 @@ class GeneralAnimator {
result = before ? before : this.createKeyframe(null, Timeline.time, channel, false, false);
return {before, result};
}
toggleMuted(channel) {
this.muted[channel] = !this.muted[channel];
}
scrollTo() {
var el = $(`#timeline_body_inner > li[uuid=${this.uuid}]`).get(0)
if (el) {
@ -604,9 +611,9 @@ class BoneAnimator extends GeneralAnimator {
if (!this.doRender()) return;
this.getGroup()
this.displayRotation(this.interpolate(time, 'rotation'))
this.displayPosition(this.interpolate(time, 'position'))
this.displayScale(this.interpolate(time, 'scale'))
if (!this.muted.rotation) this.displayRotation(this.interpolate(time, 'rotation'))
if (!this.muted.position) this.displayPosition(this.interpolate(time, 'position'))
if (!this.muted.scale) this.displayScale(this.interpolate(time, 'scale'))
}
}
BoneAnimator.prototype.channels = ['rotation', 'position', 'scale']
@ -630,25 +637,27 @@ class EffectAnimator extends GeneralAnimator {
return this;
}
displayFrame() {
this.sound.forEach(kf => {
var diff = kf.time - Timeline.time;
if (diff >= 0 && diff < (1/60) * (Timeline.playback_speed/100)) {
if (kf.file && !kf.cooldown) {
var media = new Audio(kf.file);
media.volume = Math.clamp(settings.volume.value/100, 0, 1);
media.play();
Timeline.playing_sounds.push(media);
media.onended = function() {
Timeline.playing_sounds.remove(media);
}
if (!this.muted.sound) {
this.sound.forEach(kf => {
var diff = kf.time - Timeline.time;
if (diff >= 0 && diff < (1/60) * (Timeline.playback_speed/100)) {
if (kf.file && !kf.cooldown) {
var media = new Audio(kf.file);
media.volume = Math.clamp(settings.volume.value/100, 0, 1);
media.play();
Timeline.playing_sounds.push(media);
media.onended = function() {
Timeline.playing_sounds.remove(media);
}
kf.cooldown = true;
setTimeout(() => {
delete kf.cooldown;
}, 400)
}
}
})
kf.cooldown = true;
setTimeout(() => {
delete kf.cooldown;
}, 400)
}
}
})
}
}
}
EffectAnimator.prototype.channels = ['particle', 'sound', 'timeline']
@ -781,7 +790,7 @@ class Keyframe {
this.set(l, negate(this.get(l)))
}
}
} else if (this.channel == 'position' || this.channel == 'scale') {
} else if (this.channel == 'position') {
let l = getAxisLetter(axis)
this.set(l, negate(this.get(l)))
}
@ -1156,11 +1165,11 @@ const Animator = {
selected.length = 0
Canvas.updateAllBones()
if (quad_previews.enabled) {
quad_previews.enabled_before = true
}
main_preview.fullscreen()
main_preview.setNormalCamera()
//if (quad_previews.enabled) {
// quad_previews.enabled_before = true
//}
//main_preview.fullscreen()
//main_preview.setNormalCamera()
$('body').addClass('animation_mode')
if (!Animator.timeline_node) {
@ -1189,12 +1198,12 @@ const Animator = {
Timeline.pause()
Animator.open = false;
$('body').removeClass('animation_mode')
resizeWindow()
updateInterface()
//resizeWindow()
//updateInterface()
Toolbars.element_origin.toPlace()
if (quad_previews.enabled_before) {
openQuadView()
}
//if (quad_previews.enabled_before) {
// openQuadView()
//}
Canvas.updateAllBones()
},
showDefaultPose(no_matrix_update) {
@ -1206,7 +1215,6 @@ const Animator = {
if (!no_matrix_update) group.mesh.updateMatrixWorld()
})
console.trace('default')
},
preview() {
Animator.showDefaultPose(true);
@ -1864,6 +1872,7 @@ const Timeline = {
Timeline.start()
} else {
Timeline.pause()
Animator.preview()
}
}
},
@ -2057,6 +2066,10 @@ BARS.defineActions(function() {
new NumSlider('slider_animation_length', {
category: 'animation',
condition: () => Animator.open && Animator.selected,
getInterval(event) {
if (event && event.shiftKey) return 1;
return 1/Math.clamp(settings.animation_snap.value, 1, 120)
},
get: function() {
return Animator.selected.length
},
@ -2107,6 +2120,10 @@ BARS.defineActions(function() {
new NumSlider('slider_keyframe_time', {
category: 'animation',
condition: () => Animator.open && Timeline.selected.length,
getInterval(event) {
if (event && event.shiftKey) return 1;
return 1/Math.clamp(settings.animation_snap.value, 1, 120)
},
get: function() {
return Timeline.selected[0] ? Timeline.selected[0].time : 0
},
@ -2319,7 +2336,7 @@ BARS.defineActions(function() {
icon: 'flag',
category: 'animation',
condition: {modes: ['animate']},
keybind: new Keybind({key: 77}),
keybind: new Keybind({ctrl: true, key: 77}),
click: function (event) {
if (!Animator.selected) {
Blockbench.showQuickMessage('message.no_animation_selected')

296
js/api.js
View File

@ -51,6 +51,11 @@ const Blockbench = {
} else if (icon instanceof HTMLElement) {
//Node
node = icon
} else if (icon === null) {
//Node
node = document.createElement('i');
node.classList.add('fa_big', 'icon');
} else if (icon.substr(0, 2) === 'fa') {
//Font Awesome
node = document.createElement('i');
@ -330,132 +335,136 @@ const Blockbench = {
var results = [];
var result_count = 0;
var i = 0;
while (i < input.files.length) {
(function() {
var file = input.files[i]
var reader = new FileReader()
reader.i = i
reader.onloadend = function() {
if (reader.result.byteLength) {
var arr = new Uint8Array(reader.result)
var targa_loader = new Targa()
targa_loader.load(arr)
var result = targa_loader.getDataURL()
} else {
var result = reader.result
}
results[this.i] = {
name: file.name,
path: file.name,
content: result
}
result_count++;
if (result_count === input.files.length) {
cb(results)
}
}
let readtype = options.readtype;
if (typeof readtype == 'function') {
readtype = readtype(file.name);
}
if (readtype === 'image') {
if (pathToExtension(file.name) === 'tga') {
reader.readAsArrayBuffer(file)
} else {
reader.readAsDataURL(file)
}
} else if (readtype === 'buffer') {
reader.readAsArrayBuffer(file)
} else /*text*/ {
reader.readAsText(file)
}
i++;
})()
}
Blockbench.read(input.files, options, cb)
}).click()
}
},
read(paths, options, cb) {
if (!isApp || paths == undefined) return false;
if (typeof paths == 'string') paths = [paths];
read(files, options, cb) {
if (files == undefined) return false;
if (typeof files == 'string') files = [files];
var results = [];
var result_count = 0;
var i = 0;
var errant;
while (i < paths.length) {
(function() {
var this_i = i;
var file = paths[i]
let readtype = options.readtype;
if (typeof readtype == 'function') {
readtype = readtype(file);
}
if (isApp) {
while (i < files.length) {
(function() {
var this_i = i;
var file = files[i]
let readtype = options.readtype;
if (typeof readtype == 'function') {
readtype = readtype(file);
}
if (readtype === 'image') {
//
var extension = pathToExtension(file)
if (extension === 'tga') {
var targa_loader = new Targa()
targa_loader.open(file, () => {
if (readtype === 'image') {
//
var extension = pathToExtension(file)
if (extension === 'tga') {
var targa_loader = new Targa()
targa_loader.open(file, () => {
results[this_i] = {
name: pathToName(file, true),
path: file,
content: targa_loader.getDataURL()
}
result_count++;
if (result_count === files.length) {
cb(results)
}
})
} else {
results[this_i] = {
name: pathToName(file, true),
path: file
}
result_count++;
if (result_count === files.length) {
cb(results)
}
}
} else /*text*/ {
var load = function (err, data) {
if (err) {
console.log(err)
if (!errant && options.errorbox !== false) {
Blockbench.showMessageBox({
translateKey: 'file_not_found',
icon: 'error_outline'
})
}
errant = true
return;
}
if ((readtype != 'buffer' && readtype != 'binary') && data.charCodeAt(0) === 0xFEFF) {
data = data.substr(1)
}
results[this_i] = {
name: pathToName(file, true),
path: file,
content: targa_loader.getDataURL()
content: data
}
result_count++;
if (result_count === paths.length) {
if (result_count === files.length) {
cb(results)
}
})
}
if (readtype === 'buffer' || readtype === 'binary') {
fs.readFile(file, load);
} else {
fs.readFile(file, 'utf8', load);
}
}
})()
i++;
}
} else {
while (i < files.length) {
(function() {
var file = files[i]
var reader = new FileReader()
reader.i = i
reader.onloadend = function() {
} else {
results[this_i] = {
name: pathToName(file, true),
path: file
if (reader.result.byteLength && pathToExtension(file.name) === 'tga') {
var arr = new Uint8Array(reader.result)
var targa_loader = new Targa()
targa_loader.load(arr)
var result = targa_loader.getDataURL()
} else {
var result = reader.result
}
results[this.i] = {
name: file.name,
path: file.name,
content: result
}
result_count++;
if (result_count === paths.length) {
if (result_count === files.length) {
cb(results)
}
}
} else /*text*/ {
var load = function (err, data) {
if (err) {
console.log(err)
if (!errant && options.errorbox !== false) {
Blockbench.showMessageBox({
translateKey: 'file_not_found',
icon: 'error_outline'
})
}
errant = true
return;
}
if (readtype != 'buffer' && data.charCodeAt(0) === 0xFEFF) {
data = data.substr(1)
}
results[this_i] = {
name: pathToName(file, true),
path: file,
content: data
}
result_count++;
if (result_count === paths.length) {
cb(results)
}
let readtype = options.readtype;
if (typeof readtype == 'function') {
readtype = readtype(file.name);
}
if (readtype === 'buffer') {
fs.readFile(file, load);
} else {
fs.readFile(file, 'utf8', load);
if (readtype === 'image') {
if (pathToExtension(file.name) === 'tga') {
reader.readAsArrayBuffer(file)
} else {
reader.readAsDataURL(file)
}
} else if (readtype === 'buffer' || readtype === 'binary') {
reader.readAsArrayBuffer(file)
} else /*text*/ {
reader.readAsText(file)
}
}
})()
i++;
i++;
})()
}
}
},
export(options, cb) {
@ -484,7 +493,7 @@ const Blockbench = {
download.click();
if (Blockbench.browser === 'firefox') document.body.removeChild(download);
} else if (options.savetype === 'zip' || options.savetype === 'buffer') {
} else if (options.savetype === 'zip' || options.savetype === 'buffer' || options.savetype === 'binary') {
saveAs(options.content, file_name)
} else {
@ -546,13 +555,12 @@ const Blockbench = {
options.custom_writer(options.content, file_path)
} else {
//text or buffer
//text or binary
fs.writeFileSync(file_path, options.content)
if (cb) {
cb(file_path)
}
}
},
//Flags
addFlag(flag) {
@ -640,77 +648,17 @@ document.body.ondrop = function(event) {
var result_count = 0;
var i = 0;
var errant;
while (i < fileNames.length) {
if (isApp) {
if (handler.readtype === 'image') {
var path = fileNames[i].path
//
results[i] = {
name: pathToName(path, true),
path: path
}
result_count++;
if (result_count === fileNames.length) {
handler.cb(results, event)
}
} else /*text*/ {
(function() {
var path = fileNames[i].path
var this_i = i;
var data;
try {
data = fs.readFileSync(path, 'utf-8')
} catch (err) {
console.log(err)
if (!errant && handler.errorbox !== false) {
Blockbench.showMessageBox({
translateKey: 'file_not_found',
icon: 'error_outline'
})
}
errant = true
}
if (data) {
results[this_i] = {
name: pathToName(path, true),
path: path,
content: data
}
result_count++;
if (result_count === fileNames.length) {
handler.cb(results, event)
}
}
})()
}
} else {
(function() {
var file = fileNames[i]
var reader = new FileReader()
reader.i = i
reader.onloadend = function() {
results[this.i] = {
name: file.name,
path: file.name,
content: reader.result
}
result_count++;
if (result_count === fileNames.length) {
handler.cb(results, event)
}
}
if (handler.readtype === 'image') {
reader.readAsDataURL(file)
} else /*text*/ {
reader.readAsText(file)
}
})()
var paths = []
if (isApp) {
for (var file of fileNames) {
paths.push(file.path)
}
i++;
} else {
paths = fileNames
}
Blockbench.read(paths, handler, (content) => {
handler.cb(content, event)
})
})
}
document.body.ondragenter = function(event) {
@ -762,7 +710,7 @@ function forDragHandlers(event, cb) {
el = parent
}
}
handler.extensions.includes( pathToExtension(event.dataTransfer.files[0].name))
handler.extensions.includes( pathToExtension(event.dataTransfer.files[0].name).toLowerCase())
var name = event.dataTransfer.files[0].name;
if (el && handler.extensions.filter(ex => {
return name.substr(-ex.length) == ex;

View File

@ -100,6 +100,10 @@ function updateNslideValues() {
BarItems.slider_size_z.update()
BarItems.slider_inflate.update()
if (!Project.box_uv) {
BarItems.slider_face_tint.update()
}
}
if (selected.length || (Format.bone_rig && Group.selected)) {
BarItems.slider_origin_x.update()
@ -142,7 +146,7 @@ function setProjectResolution(width, height, modify_uv) {
]
function shiftCube(cube, axis) {
if (Project.box_uv) {
obj.uv_offset[axis] *= multiplier[axis];
cube.uv_offset[axis] *= multiplier[axis];
} else {
for (var face in cube.faces) {
var uv = cube.faces[face];
@ -238,7 +242,7 @@ function selectAll() {
elements.forEach(obj => {
obj.selectLow()
})
updateSelection()
TickUpdates.selection = true;
} else {
unselectAll()
}
@ -251,7 +255,7 @@ function unselectAll() {
Group.all.forEach(function(s) {
s.selected = false
})
updateSelection()
TickUpdates.selection = true;
}
function createSelection() {
if ($('#selgen_new').is(':checked')) {
@ -346,7 +350,7 @@ class Mode extends KeybindItem {
} else {
BarItems.move_tool.select()
}
updateSelection()
TickUpdates.selection = true;
}
trigger() {
if (Condition(this.condition)) {
@ -403,11 +407,15 @@ BARS.defineActions(function() {
BarItems.slider_color_s.update();
BarItems.slider_color_v.update();
$('.UVEditor').find('#uv_size').hide()
three_grid.visible = false;
},
onUnselect: () => {
Cube.all.forEach(cube => {
Canvas.buildGridBox(cube)
})
$('.UVEditor').find('#uv_size').show();
three_grid.visible = true;
},
})
new Mode({
@ -447,7 +455,7 @@ BARS.defineActions(function() {
setInterval(function() {
if (Outliner.root.length || textures.length) {
try {
var model = Codecs.project.compile();
var model = Codecs.project.compile({compressed: true});
localStorage.setItem('backup_model', model)
} catch (err) {
console.log('Unable to create backup. ', err)
@ -457,33 +465,37 @@ setInterval(function() {
//Misc
const TickUpdates = {
Run() {
if (TickUpdates.outliner) {
delete TickUpdates.outliner;
loadOutlinerDraggable()
}
if (TickUpdates.selection) {
delete TickUpdates.selection;
updateSelection()
}
if (TickUpdates.main_uv) {
delete TickUpdates.main_uv;
main_uv.loadData()
}
if (TickUpdates.texture_list) {
delete TickUpdates.texture_list;
loadTextureDraggable();
}
if (TickUpdates.keyframes) {
delete TickUpdates.keyframes;
Vue.nextTick(Timeline.update)
}
if (TickUpdates.keyframe_selection) {
delete TickUpdates.keyframe_selection;
Vue.nextTick(updateKeyframeSelection)
}
if (TickUpdates.keybind_conflicts) {
delete TickUpdates.keybind_conflicts;
updateKeybindConflicts();
try {
if (TickUpdates.outliner) {
delete TickUpdates.outliner;
loadOutlinerDraggable()
}
if (TickUpdates.selection) {
delete TickUpdates.selection;
updateSelection()
}
if (TickUpdates.main_uv) {
delete TickUpdates.main_uv;
main_uv.loadData()
}
if (TickUpdates.texture_list) {
delete TickUpdates.texture_list;
loadTextureDraggable();
}
if (TickUpdates.keyframes) {
delete TickUpdates.keyframes;
Vue.nextTick(Timeline.update)
}
if (TickUpdates.keyframe_selection) {
delete TickUpdates.keyframe_selection;
Vue.nextTick(updateKeyframeSelection)
}
if (TickUpdates.keybind_conflicts) {
delete TickUpdates.keybind_conflicts;
updateKeybindConflicts();
}
} catch (err) {
console.error(err);
}
}
}

View File

@ -35,10 +35,11 @@ BARS.setupVue()
MenuBar.setup()
translateUI()
console.log('Blockbench ' + appVersion + (isApp
console.log('%cBlockbench ' + appVersion + (isApp
? (' Desktop (' + Blockbench.operating_system +')')
: (' Web ('+capitalizeFirstLetter(Blockbench.browser)+')')
))
: (' Web ('+capitalizeFirstLetter(Blockbench.browser)+')')),
'background-color: #3e90ff; color: black; padding: 4px;'
)
var startups = parseInt(localStorage.getItem('startups')||0);
localStorage.setItem('startups', startups+1);

View File

@ -1,33 +1,50 @@
const Clipbench = {
elements: [],
getCopyType(paste) {
var p = Prop.active_panel;
var text = window.getSelection()+'';
types: {
text: 'text',
face_dialog: 'face_dialog',
display_slot: 'display_slot',
keyframe: 'keyframe',
face: 'face',
texture: 'texture',
outliner: 'outliner',
texture_selection: 'texture_selection',
},
getCopyType(mode, check) {
// mode: 1 = copy, 2 = paste
let p = Prop.active_panel;
let text;
if (!check) {
text = window.getSelection()+'';
}
if (text) {
return 'text';
return Clipbench.types.text;
}
if (Painter.selection.canvas && Toolbox.selected.id == 'copy_paste_tool') {
return Clipbench.types.texture_selection;
}
if (open_dialog == 'uv_dialog') {
return 'face_dialog'
return Clipbench.types.face_dialog
}
if (display_mode) {
return 'display_slot'
return Clipbench.types.display_slot
}
if (Animator.open && Timeline.animators.length && (Timeline.selected.length || paste)) {
return 'keyframe'
if (Animator.open && Timeline.animators.length && (Timeline.selected.length || mode === 2)) {
return Clipbench.types.keyframe
}
if ((p == 'uv' || p == 'preview') && Modes.edit) {
return 'face';
return Clipbench.types.face;
}
if (p == 'textures' && isApp && (textures.selected || paste)) {
return 'texture';
if (p == 'textures' && isApp && (textures.selected || mode === 2)) {
return Clipbench.types.texture;
}
if (p == 'outliner' && Modes.edit) {
return 'outliner';
return Clipbench.types.outliner;
}
},
copy(event, cut) {
switch (Clipbench.getCopyType()) {
switch (Clipbench.getCopyType(1)) {
case 'text':
Clipbench.setText(window.getSelection()+'');
break;
@ -69,10 +86,13 @@ const Clipbench = {
}
},
paste(event) {
switch (Clipbench.getCopyType(true)) {
switch (Clipbench.getCopyType(2)) {
case 'text':
Clipbench.setText(window.getSelection()+'');
break;
case 'texture_selection':
main_uv.addPastingOverlay();
break;
case 'face_dialog':
uv_dialog.paste(event)
break;
@ -185,7 +205,7 @@ BARS.defineActions(function() {
icon: 'fa-copy',
category: 'edit',
work_in_dialog: true,
condition: () => Clipbench.getCopyType(),
condition: () => Clipbench.getCopyType(1, true),
keybind: new Keybind({key: 67, ctrl: true, shift: null}),
click: function (event) {Clipbench.copy(event)}
})
@ -193,7 +213,7 @@ BARS.defineActions(function() {
icon: 'fa-cut',
category: 'edit',
work_in_dialog: true,
condition: () => Clipbench.getCopyType(),
condition: () => Clipbench.getCopyType(1, true),
keybind: new Keybind({key: 88, ctrl: true, shift: null}),
click: function (event) {Clipbench.copy(event, true)}
})
@ -201,7 +221,7 @@ BARS.defineActions(function() {
icon: 'fa-clipboard',
category: 'edit',
work_in_dialog: true,
condition: () => Clipbench.getCopyType(true),
condition: () => Clipbench.getCopyType(2, true),
keybind: new Keybind({key: 86, ctrl: true, shift: null}),
click: function (event) {Clipbench.paste(event)}
})

View File

@ -2,6 +2,7 @@ const electron = require('electron').remote;
const {clipboard, shell, nativeImage} = require('electron');
const app = electron.app;
const fs = require('fs');
const NodeBuffer = require('buffer');
const zlib = require('zlib');
const exec = require('child_process').exec;
const originalFs = require('original-fs');
@ -113,12 +114,17 @@ function addRecentProject(data) {
}
i--;
}
recent_projects.splice(0, 0, {
let project = {
name: data.name,
path: data.path,
icon: data.icon,
day: new Date().dayOfYear()
})
}
// main_preview.screenshot({width: 200, height: 120}, url => {
// project.thumbnail = url;
// updateRecentProjects()
// })
recent_projects.splice(0, 0, project)
app.addRecentDocument(data.path)
if (recent_projects.length > Math.clamp(settings.recent_projects.value, 0, 256)) {
recent_projects.pop()

View File

@ -1415,6 +1415,13 @@ window.displayReferenceObjects = {
}
DisplayMode.slots = displayReferenceObjects.slots
const display_angle_preset = {
projection: 'perspective',
position: [-80, 40, -30],
target: [0, 8, 0],
default: true
}
enterDisplaySettings = function() { //Enterung Display Setting Mode, changes the scene etc
display_mode = true;
@ -1428,8 +1435,7 @@ enterDisplaySettings = function() { //Enterung Display Setting Mode, changes th
quad_previews.enabled_before = true
}
display_preview.fullscreen()
display_preview.setNormalCamera()
display_preview.camPers.position.set(-80, 40, -30)
display_preview.loadAnglePreset(display_angle_preset)
display_preview.camPers.setFocalLength(45)
$('body').addClass('display_mode')
@ -1599,7 +1605,7 @@ function loadDisp(key) { //Loads The Menu and slider values, common for all Radi
display_slot = key
if (key !== 'gui' && display_preview.isOrtho === true) {
display_preview.setNormalCamera()
display_preview.loadAnglePreset(display_angle_preset)
}
display_preview.controls.enabled = true;
ground_animation = false;
@ -1618,54 +1624,76 @@ function loadDisp(key) { //Loads The Menu and slider values, common for all Radi
}
DisplayMode.loadThirdRight = function() { //Loader
loadDisp('thirdperson_righthand')
display_preview.camPers.position.set(-44, 40, -44)
display_preview.controls.target.set(0, 14, 0)
display_preview.loadAnglePreset({
position: [-44, 40, -44],
target: [0, 14, 0],
focal_length: 45,
})
displayReferenceObjects.bar(['player', 'zombie', 'baby_zombie', 'armor_stand', 'armor_stand_small'])
}
DisplayMode.loadThirdLeft = function() { //Loader
loadDisp('thirdperson_lefthand')
display_preview.camPers.position.set(-44, 40, -44)
display_preview.controls.target.set(0, 14, 0)
display_preview.loadAnglePreset({
position: [-44, 40, -44],
target: [0, 14, 0],
focal_length: 45,
})
displayReferenceObjects.bar(['player', 'zombie', 'baby_zombie', 'armor_stand', 'armor_stand_small'])
}
DisplayMode.loadFirstRight = function() { //Loader
loadDisp('firstperson_righthand')
display_preview.camPers.setFocalLength(12)
display_preview.camPers.position.set(0, 0, 32.4)
display_preview.controls.target.set(0,0,0)
display_preview.loadAnglePreset({
position: [0, 0, 32.4],
target: [0, 0, 0],
focal_length: 12,
})
display_preview.controls.enabled = false
displayReferenceObjects.bar(['monitor', 'bow', 'crossbow'])
$('.single_canvas_wrapper').append('<div id="display_crosshair"></div>')
}
DisplayMode.loadFirstLeft = function() { //Loader
loadDisp('firstperson_lefthand')
display_preview.camPers.setFocalLength(12)
display_preview.camPers.position.set(0, 0, 32.4)
display_preview.controls.target.set(0,0,0)
display_preview.loadAnglePreset({
position: [0, 0, 32.4],
target: [0, 0, 0],
focal_length: 12,
})
display_preview.controls.enabled = false
displayReferenceObjects.bar(['monitor', 'bow', 'crossbow'])
$('.single_canvas_wrapper').append('<div id="display_crosshair"></div>')
}
DisplayMode.loadHead = function() { //Loader
loadDisp('head')
display_preview.camPers.position.set(-30, 40, -30)
display_preview.controls.target.set(0, 22, 0)
display_preview.loadAnglePreset({
position: [-30, 40, -30],
target: [0, 22, 0],
focal_length: 45,
})
displayReferenceObjects.bar(['player', 'zombie', 'baby_zombie', 'armor_stand', 'armor_stand_small'])
}
DisplayMode.loadGUI = function() { //Loader
loadDisp('gui')
setDisplayArea(0, 0, 0, 0, 0, 0, 0.4, 0.4, 0.4)
display_preview.camOrtho.zoom = 1
display_preview.controls.target.set(0,0,0)
display_preview.setOrthographicCamera(2)
display_preview.camOrtho.position.set(0,0,32)
display_preview.loadAnglePreset({
projection: 'orthographic',
position: [0, 0, 32],
target: [0, 0, 0],
locked_angle: 2,
zoom: 1,
})
displayReferenceObjects.bar(['inventory_nine', 'inventory_full', 'hud'])
BarItems.gui_light.set(Project.front_gui_light ? 'front' : 'side');
}
DisplayMode.loadGround = function() { //Loader
loadDisp('ground')
display_preview.camPers.position.set(-40, 37, -40)
display_preview.controls.target.set(0, 11, 0)
display_preview.loadAnglePreset({
position: [-40, 37, -40],
target: [0, 11, 0],
focal_length: 45,
})
setDisplayArea(0, 12, 0, 0, 0, 0, 1, 1, 1)
ground_animation = true;
ground_timer = 0
@ -1673,8 +1701,11 @@ DisplayMode.loadGround = function() { //Loader
}
DisplayMode.loadFixed = function() { //Loader
loadDisp('fixed')
display_preview.camPers.position.set(-24, 18, -50)
display_preview.controls.target.set(0, 1, -5)
display_preview.loadAnglePreset({
position: [-24, 18, -50],
target: [0, 1, -5],
focal_length: 45,
})
setDisplayArea(0, 0, -8.5, 0, 0, 0, 0.5, 0.5, 0.5)
displayReferenceObjects.bar(['frame'])
}

View File

@ -59,7 +59,8 @@ class BarItem {
}
$(action.node).attr('title', action.description)
if (in_bar) {
$(action.node).prepend('<label class="f_left in_toolbar">'+action.name+':</label>')
$(action.node).prepend('<label class="f_left toolbar_label">'+action.name+':</label>')
$(this.node).addClass('has_label')
} else {
$(action.node).prepend('<div class="tooltip">'+action.name+'</div>')
.on('mouseenter', function() {
@ -175,12 +176,14 @@ class Action extends BarItem {
//Node
this.click = data.click
this.icon_node = Blockbench.getIconNode(this.icon, this.color)
this.icon_states = data.icon_states;
this.node = $(`<div class="tool ${this.id}"></div>`).get(0)
this.nodes = [this.node]
this.menus = [];
this.menu_node = $(`<li title="${this.description||''}">${this.name}</li>`).get(0)
this.menu_node = $(`<li>${this.name}</li>`).get(0)
$(this.node).add(this.menu_node).append(this.icon_node)
this.addLabel()
this.addLabel(data.label)
this.updateHoverTitle()
$(this.node).click(function(e) {scope.trigger(e)})
if (data.linked_setting) {
@ -213,6 +216,21 @@ class Action extends BarItem {
}
return false;
}
updateHoverTitle() {
var text = this.description || '';
if (this.keybind.label) {
if (text) {
text = `${text} (${this.keybind.label})`;
} else {
text = this.keybind.label;
}
}
this.menu_node.title = text;
this.nodes.forEach(node => {
node.title = text;
});
return this;
}
setIcon(icon) {
var scope = this;
this.icon = icon
@ -225,10 +243,16 @@ class Action extends BarItem {
}
toggleLinkedSetting(change) {
if (this.linked_setting && settings[this.linked_setting]) {
let setting = settings[this.linked_setting];
if (change !== false) {
settings[this.linked_setting].value = !settings[this.linked_setting].value
setting.value = !setting.value
}
this.setIcon(settings[this.linked_setting].value ? 'check_box' : 'check_box_outline_blank')
if (this.icon_states) {
this.setIcon(setting.value ? this.icon_states[1] : this.icon_states[0]);
} else {
this.setIcon(setting.value ? 'check_box' : 'check_box_outline_blank');
}
if (setting.onChange) setting.onChange(setting.value)
}
}
delete() {
@ -236,8 +260,7 @@ class Action extends BarItem {
for (var i = this.menus.length-1; i >= 0; i--) {
var m = this.menus[i]
if (m.menu) {
m.path += (m.path ? '.' : '') + this.id;
m.menu.removeAction(m.path)
m.menu.deleteItem(this)
}
}
}
@ -258,6 +281,7 @@ class Tool extends Action {
this.cursor = data.cursor;
this.selectCubes = data.selectCubes !== false;
this.paintTool = data.paintTool;
this.brushTool = data.brushTool;
this.transformerMode = data.transformerMode;
this.animation_channel = data.animation_channel;
this.allowWireframe = data.allowWireframe !== false;
@ -300,7 +324,7 @@ class Tool extends Action {
$('#preview').css('cursor', (this.cursor ? this.cursor : 'default'))
$('.tool.sel').removeClass('sel')
$('.tool.'+this.id).addClass('sel')
updateSelection()
TickUpdates.selection = true;
return this;
}
trigger(event) {
@ -359,8 +383,16 @@ class NumSlider extends Widget {
} else {
this.interval = function(event) {
event = event||0;
return canvasGridSize(event.shiftKey, event.ctrlOrCmd);
};
if (!event.shiftKey && !event.ctrlKey) {
return 1
} else if (event.ctrlKey && event.shiftKey) {
return 0.025
} else if (event.ctrlKey) {
return 0.1
} else if (event.shiftKey) {
return 0.25
}
}
}
if (typeof data.getInterval === 'function') {
this.interval = data.getInterval;
@ -667,37 +699,60 @@ class BarSelect extends Widget {
var scope = this;
this.type = 'select'
this.icon = 'list'
this.node = $('<div class="tool widget bar_select"><div class="bar_select_wrapper"><select></select></div></div>').get(0)
this.node = $('<div class="tool widget bar_select"><bb-select></bb-select></div>').get(0)
var select = $(this.node).find('bb-select')
if (data.width) {
$(this.node).children('select').css('width', data.width+'px')
select.css('width', data.width+'px')
}
select.click(event => {
scope.open(event)
});
this.value = data.value
this.values = []
var select = $(this.node).find('select')
this.values = [];
this.options = data.options;
if (data.options) {
for (var key in data.options) {
if (!this.value) {
this.value = key
}
var name = data.options[key]
if (name === true) {
name = tl('action.'+this.id+'.'+key)
}
select.append(`<option id="${key}" ${key == this.value ? 'selected' : ''}>${name}</option>`)
this.values.push(key);
}
}
this.set(this.value)
this.addLabel()
if (typeof data.onChange === 'function') {
this.onChange = data.onChange
}
$(this.node).find('select').change(function(event) {
scope.change(event)
})
$(this.node).on('mousewheel', event => {
scope.trigger(event.originalEvent);
})
}
open(event) {
let scope = this;
let items = [];
for (var key in this.options) {
let val = this.options[key];
if (val) {
(function() {
var save_key = key;
items.push({
name: scope.getNameFor(key),
icon: val.icon || ((scope.value == save_key) ? 'far.fa-dot-circle' : 'far.fa-circle'),
condition: val.condition,
click: (e) => {
scope.set(save_key);
if (scope.onChange) {
scope.onChange(scope, e);
}
}
})
})()
}
}
let menu = new Menu(items);
menu.node.style['min-width'] = this.node.clientWidth+'px';
menu.open(this.node, this);
}
trigger(event) {
if (!event) event = 0;
var scope = this;
@ -712,18 +767,24 @@ class BarSelect extends Widget {
}
var index = this.values.indexOf(this.value)
if (event.type === 'mousewheel' || event.type === 'wheel') {
index += event.deltaY < 0 ? -1 : 1;
} else {
index++;
if (index >= this.values.length) index = 0;
}
if (index >= 0 && index < this.values.length) {
this.set(this.values[index]);
if (this.onChange) {
this.onChange(this, event);
function advance() {
if (event.type === 'mousewheel' || event.type === 'wheel') {
index += event.deltaY < 0 ? -1 : 1;
} else {
index++;
if (index >= scope.values.length) index = 0;
}
}
for (var i = 0; i < 40; i++) {
advance()
if (index < 0 || index >= this.values.length) return;
let opt = this.options[this.values[index]];
if (opt && Condition(opt.condition)) break;
}
this.set(this.values[index]);
if (this.onChange) {
this.onChange(this, event);
}
scope.uses++;
return true;
@ -737,9 +798,18 @@ class BarSelect extends Widget {
}
return this;
}
set(id) {
this.value = id
$(this.nodes).find('option#'+id).prop('selected', true).siblings().prop('selected', false);
getNameFor(key) {
let val = this.options[key];
let name = tl(val === true || (val && val.name === true)
? ('action.'+this.id+'.'+key)
: (val.name || val)
);
return name;
}
set(key) {
this.value = key;
let name = this.getNameFor(key);
$(this.node).find('bb-select').text(name)
return this;
}
get() {
@ -842,6 +912,7 @@ class Toolbar {
constructor(data) {
var scope = this;
this.children = [];
this.condition_cache = [];
if (data) {
this.id = data.id
this.narrow = !!data.narrow
@ -912,6 +983,7 @@ class Toolbar {
})
BARS.list.currentBar = this.children;
showDialog('toolbar_edit');
$('#toolbar_edit #action_search_bar').val('');
return this;
}
add(action, position) {
@ -945,6 +1017,23 @@ class Toolbar {
}
update() {
var scope = this;
//scope.condition_cache.empty();
let needsUpdate = scope.condition_cache.length !== scope.children.length;
scope.condition_cache.length = scope.children.length;
this.children.forEach(function(item, i) {
let value = null;
if (typeof item === 'object') {
value = !!Condition(item.condition)
}
if (!needsUpdate && value !== scope.condition_cache[i]) {
needsUpdate = true;
}
scope.condition_cache[i] = value;
})
if (!needsUpdate) return this;
var content = $(this.node).find('.content')
content.find('> .tool').detach()
var separators = content.find('> .toolbar_separator').detach()
@ -954,7 +1043,7 @@ class Toolbar {
if (typeof item === 'string') {
var last = content.find('> :last-child')
if (last.length === 0 || last.hasClass('toolbar_separator') || i == scope.children.length-1) {
return
return this;
}
var sep = separators[sep_nr]
if (sep) {
@ -964,7 +1053,7 @@ class Toolbar {
content.append('<div class="toolbar_separator"></div>')
}
} else if (typeof item === 'object') {
if (BARS.condition( item.condition )) {
if (scope.condition_cache[i]) {
content.append(item.getNode())
item.toolbars.safePush(scope)
} else {
@ -1052,7 +1141,7 @@ const BARS = {
//Tools
new Tool('move_tool', {
icon: 'fas.fa-hand-paper',
icon: 'icon-gizmo',
category: 'tools',
selectFace: true,
transformerMode: 'translate',
@ -1148,7 +1237,7 @@ const BARS = {
category: 'file',
condition: () => isApp,
click: function (e) {
shell.showItemInFolder(app.getPath('userData')+osfs+'backups'+osfs+'.')
shell.openItem(app.getPath('userData')+osfs+'backups')
}
})
new Action('settings_window', {
@ -1166,8 +1255,12 @@ const BARS = {
new Action('reload', {
icon: 'refresh',
category: 'file',
condition: () => Blockbench.hasFlag('dev'),
click: function () {Blockbench.reload()}
condition: isApp,
click: function () {
if (Blockbench.hasFlag('dev') || confirm(tl('message.close_warning.web'))) {
Blockbench.reload()
}
}
})
//Edit Generic
@ -1191,7 +1284,7 @@ const BARS = {
click: function () {
if (Prop.active_panel == 'textures' && textures.selected) {
textures.selected.remove()
} else if (Prop.active_panel == 'color' && ColorPanel.vue._data.open_tab == 'palette') {
} else if (Prop.active_panel == 'color' && ['palette', 'both'].includes(ColorPanel.vue._data.open_tab)) {
if (ColorPanel.vue._data.palette.includes(ColorPanel.vue._data.main_color)) {
ColorPanel.vue._data.palette.remove(ColorPanel.vue._data.main_color)
}
@ -1213,7 +1306,7 @@ const BARS = {
array.forEach(function(s) {
s.remove(false)
})
updateSelection()
TickUpdates.selection = true;
Undo.finishEdit('delete elements')
} else if (Prop.active_panel == 'animations' && Animator.selected) {
@ -1331,15 +1424,6 @@ const BARS = {
default_place: true
})
//update 3.3
if (!Toolbars.outliner.children.includes(BarItems.toggle_skin_layer)) {
Toolbars.outliner.add(BarItems.toggle_skin_layer, -1)
}
//update 3.3.1
if (!Toolbars.outliner.children.includes(BarItems.cube_counter)) {
Toolbars.outliner.add(BarItems.cube_counter)
}
Toolbars.texturelist = new Toolbar({
id: 'texturelist',
children: [
@ -1361,20 +1445,28 @@ const BARS = {
'brush_tool',
'fill_tool',
'eraser',
'color_picker'
'color_picker',
'draw_shape_tool',
'copy_paste_tool'
],
vertical: Blockbench.isMobile,
default_place: true
})
// update 3.4
if (!Toolbars.tools.children.includes(BarItems.draw_shape_tool)) {
Toolbars.tools.add(BarItems.draw_shape_tool, -1)
}
if (!Toolbars.tools.children.includes(BarItems.copy_paste_tool)) {
Toolbars.tools.add(BarItems.copy_paste_tool, -1)
}
Toolbars.element_position = new Toolbar({
id: 'element_position',
children: [
'slider_pos_x',
'slider_pos_y',
'slider_pos_z',
'local_move'
'slider_pos_z'
],
default_place: !Blockbench.isMobile
})
@ -1533,26 +1625,24 @@ const BARS = {
],
default_place: true
})
//update 3.3
if (!Toolbars.timeline.children.includes(BarItems.add_marker)) {
Toolbars.timeline.add(BarItems.add_marker, 3)
}
//Tools
Toolbars.main_tools = new Toolbar({
id: 'main_tools',
children: [
'transform_space'
]
})
Toolbars.brush = new Toolbar({
id: 'brush',
children: [
'brush_mode',
'fill_mode',
'draw_shape_type',
'_',
'slider_brush_size',
'slider_brush_opacity',
'slider_brush_min_opacity',
'slider_brush_softness',
'mirror_painting',
'lock_alpha',
'_',
'painting_grid',
]

View File

@ -85,13 +85,13 @@ function Dialog(settings) {
switch (data.type) {
default:
bar.append(`<input class="dark_bordered half" type="text" id="${form_id}" value="${data.value||''}" placeholder="${data.placeholder||''}">`)
bar.append(`<input class="dark_bordered half focusable_input" type="text" id="${form_id}" value="${data.value||''}" placeholder="${data.placeholder||''}">`)
break;
case 'textarea':
bar.append(`<textarea style="height: ${data.height||150}px;" id="${form_id}"></textarea>`)
bar.append(`<textarea class="focusable_input" style="height: ${data.height||150}px;" id="${form_id}"></textarea>`)
break;
case 'select':
var el = $(`<div class="bar_select half"><select id="${form_id}"></select></div>`)
var el = $(`<div class="bar_select half"><select class="focusable_input" id="${form_id}"></select></div>`)
var sel = el.find('select')
for (var key in data.options) {
var name = tl(data.options[key])
@ -104,7 +104,7 @@ function Dialog(settings) {
for (var key in data.options) {
var name = tl(data.options[key])
el.append(`<div class="form_bar_radio">
<input type="radio" name="${form_id}_radio" id="${key}" ${data.default === key ? 'selected' : ''}>
<input type="radio" class="focusable_input" name="${form_id}_radio" id="${key}" ${data.default === key ? 'selected' : ''}>
<label for="${key}">${name}</label>
</div>`)
}
@ -116,12 +116,13 @@ function Dialog(settings) {
bar.addClass('small_text')
break;
case 'number':
bar.append(`<input class="dark_bordered half" type="number" id="${form_id}" value="${data.value||0}" min="${data.min}" max="${data.max}" step="${data.step||1}">`)
bar.append(`<input class="dark_bordered half focusable_input" type="number" id="${form_id}" value="${data.value||0}" min="${data.min}" max="${data.max}" step="${data.step||1}">`)
break;
case 'color':
if (!data.colorpicker) {
data.colorpicker = new ColorPicker({
id: 'cp_'+form_id,
name: tl(data.label),
label: false,
private: true
})
@ -129,14 +130,14 @@ function Dialog(settings) {
bar.append(data.colorpicker.getNode())
break;
case 'checkbox':
bar.append(`<input type="checkbox" id="${form_id}"${data.value ? ' checked' : ''}>`)
bar.append(`<input type="checkbox" class="focusable_input" id="${form_id}"${data.value ? ' checked' : ''}>`)
break;
case 'file':
case 'folder':
case 'save':
if (data.type == 'folder' && !isApp) break;
var input = $(`<input class="dark_bordered half" type="text" id="${form_id}" value="${data.value||''}" disabled>`);
var input = $(`<input class="dark_bordered half" class="focusable_input" type="text" id="${form_id}" value="${data.value||''}" disabled>`);
bar.append(input);
bar.addClass('form_bar_file');
@ -154,7 +155,6 @@ function Dialog(settings) {
})
bar.on('click', e => {
cl(e.target);
function fileCB(files) {
data.value = files[0].path;
input.val(data.value);
@ -189,7 +189,7 @@ function Dialog(settings) {
case 'folder':
}
if (data.readonly) {
bar.find('input').attr('readonly', 'readonly')
bar.find('input').attr('readonly', 'readonly').removeClass('focusable_input')
}
jq_dialog.append(bar)
}
@ -287,6 +287,9 @@ function Dialog(settings) {
if (this.width) {
jq_dialog.css('width', this.width+'px')
}
let first_focus = jq_dialog.find('.focusable_input').first()
if (first_focus) first_focus.focus()
open_dialog = scope.id
open_interface = scope
Prop.active_panel = 'dialog'

View File

@ -306,6 +306,9 @@ function setupInterface() {
}
$('.edit_session_active').hide()
$('#center').toggleClass('checkerboard', settings.preview_checkerboard.value);
$('#UVEditor_main_uv').toggleClass('checkerboard_trigger', settings.uv_checkerboard.value);
$('.sidebar').droppable({
accept: 'h3',
scope: 'panel',

View File

@ -57,6 +57,10 @@ class Keybind {
Keybinds.save();
TickUpdates.keybind_conflicts = true;
}
if (BarItems[this.action] instanceof Action) {
BarItems[this.action].updateHoverTitle()
}
}
return this;
}
@ -218,9 +222,9 @@ class Keybind {
}
Keybinds.no_overlap = function(k1, k2) {
if (typeof k1.condition !== 'object' || typeof k1.condition !== 'object') return false;
if (k1.condition.modes && k2.condition.modes && k1.condition.modes.overlap(k2.condition.modes) == 0) return true;
if (k1.condition.tools && k2.condition.tools && k1.condition.tools.overlap(k2.condition.tools) == 0) return true;
if (k1.condition.formats && k2.condition.formats && k1.condition.formats.overlap(k2.condition.formats) == 0) return true;
if (k1.condition && k2.condition.modes && k1.condition.modes.overlap(k2.condition.modes) == 0) return true;
if (k1.condition && k2.condition.tools && k1.condition.tools.overlap(k2.condition.tools) == 0) return true;
if (k1.condition && k2.condition.formats && k1.condition.formats.overlap(k2.condition.formats) == 0) return true;
return false;
}
function updateKeybindConflicts() {

View File

@ -64,19 +64,23 @@ function getStringWidth(string, size) {
if (code && Language.options[code]) {
Language.code = code
document.body.parentNode.attributes.lang.value = Language.code;
}
$.ajax({
dataType: "json",
url: 'lang/'+Language+'.json',
async: false,
success: function(data) {
Language.data = data;
}
var request = new XMLHttpRequest();
request.overrideMimeType("application/json");
request.open('GET', 'lang/'+Language+'.json', false);
request.send(null);
if (request.status === 200) {
try {
Language.data = JSON.parse(request.responseText);
} catch (err) {
} finally {
if (!Language.loading_steps) {
Language.loading_steps = true;
} else {
translateUI()
}
}
});
})();
}
})();

View File

@ -153,7 +153,11 @@ class Menu {
entry = $(`<li title="${s.description||''}">${tl(s.name)}</li>`)
entry.prepend(icon)
if (typeof s.click === 'function') {
entry.click(function(e) {s.click(context, e)})
entry.click(function(e) {
if (e.target == this) {
s.click(context, e)
}
})
}
//Submenu
if (typeof s.children == 'function' || typeof s.children == 'object') {
@ -205,7 +209,7 @@ class Menu {
position = scope.label
}
var offset_left = $(position).offset().left;
var offset_top = $(position).offset().top + $(position).height()+3;
var offset_top = $(position).offset().top + $(position).height();
}
if (offset_left > $(window).width() - el_width) {
@ -313,6 +317,21 @@ class Menu {
}
traverse(this.structure, 0)
}
deleteItem(rm_item) {
var scope = this;
function traverse(arr, layer) {
arr.forEachReverse((item, i) => {
if (item === rm_item || item === rm_item.id) {
arr.splice(i, 1)
} else if (item && item.children instanceof Array) {
traverse(item.children)
}
})
}
traverse(this.structure, 0)
rm_item.menus.remove(scope)
}
}
class BarMenu extends Menu {
constructor(id, structure, condition) {
@ -455,9 +474,7 @@ const MenuBar = {
'_',
'select_window',
'select_all',
'invert_selection',
'_',
'local_move',
'invert_selection'
])
new BarMenu('transform', [
'scale',
@ -594,8 +611,9 @@ const MenuBar = {
'zoom_reset'
]},
'_',
'toggle_shading',
'toggle_wireframe',
'toggle_checkerboard',
'preview_checkerboard',
'painting_grid',
'toggle_quad_view',
{name: 'menu.view.screenshot', id: 'screenshot', icon: 'camera_alt', children: [
@ -609,16 +627,35 @@ const MenuBar = {
{name: 'menu.help.discord', id: 'discord', icon: 'fab.fa-discord', click: () => {
Blockbench.openLink('http://discord.blockbench.net');
}},
{name: 'menu.help.quickstart', id: 'discord', icon: 'fas.fa-directions', click: () => {
Blockbench.openLink('https://blockbench.net/quickstart/');
}},
{name: 'menu.help.report_issue', id: 'report_issue', icon: 'bug_report', click: () => {
Blockbench.openLink('https://github.com/JannisX11/blockbench/issues');
}},
{name: 'menu.help.plugin_documentation', id: 'plugin_documentation', icon: 'fa-book', click: () => {
Blockbench.openLink('https://jannisx11.github.io/blockbench-docs/');
}},
'_',
{name: 'menu.help.search_action', description: BarItems.action_control.description, id: 'search_action', icon: 'search', click: ActionControl.select},
'_',
'update_window',
{name: 'menu.help.developer', id: 'developer', icon: 'fas.fa-wrench', children: [
'reload_plugins',
{name: 'menu.help.plugin_documentation', id: 'plugin_documentation', icon: 'fa-book', click: () => {
Blockbench.openLink('https://jannisx11.github.io/blockbench-docs/');
}},
{name: 'menu.help.developer.dev_tools', icon: 'fas.fa-tools', condition: isApp, click: () => {
currentwindow.toggleDevTools()
}},
{name: 'menu.help.developer.reset_storage', icon: 'fas.fa-hdd', click: () => {
if (confirm(tl('menu.help.developer.reset_storage.confirm'))) {
localStorage.clear()
console.log('Cleared Local Storage')
}
}},
{name: 'menu.help.developer.cache_reload', icon: 'cached', condition: !isApp, click: () => {
window.location.reload(true)
}},
'reload',
]},
{name: 'menu.help.donate', id: 'donate', icon: 'fas.fa-hand-holding-usd', click: () => {
Blockbench.openLink('https://blockbench.net/donate/');
}},

View File

@ -78,14 +78,24 @@ const Settings = {
new Setting('recent_projects', {value: 12, max: 128, min: 0, type: 'number', condition: isApp});
new Setting('backup_interval', {value: 10, type: 'number', condition: isApp});
new Setting('backup_retain', {value: 30, type: 'number', condition: isApp});
//Interface
new Setting('origin_size', {category: 'interface', value: 10, type: 'number'});
new Setting('control_size', {category: 'interface', value: 10, type: 'number'});
new Setting('seethrough_outline', {category: 'interface', value: false});
new Setting('outliner_colors', {category: 'interface', value: false});
new Setting('preview_checkerboard', {category: 'interface', value: false, onChange() {
$('#center').toggleClass('checkerboard', settings.preview_checkerboard.value);
}});
new Setting('uv_checkerboard', {category: 'interface', value: false, onChange() {
$('#UVEditor_main_uv').toggleClass('checkerboard_trigger', settings.uv_checkerboard.value);
}});
//Preview
new Setting('origin_size', {category: 'preview', value: 10, type: 'number'});
new Setting('control_size', {category: 'preview', value: 10, type: 'number'});
new Setting('seethrough_outline', {category: 'preview', value: false});
new Setting('brightness', {category: 'preview', value: 50, type: 'number'});
new Setting('shading', {category: 'preview', value: true},);
new Setting('outliner_colors', {category: 'preview', value: false},);
new Setting('shading', {category: 'preview', value: true, onChange() {
setShading()
}});
new Setting('texture_fps', {category: 'preview', value: 2, type: 'number', onChange() {
TextureAnimator.updateSpeed()
}});
@ -94,7 +104,6 @@ const Settings = {
//Edit
new Setting('undo_limit', {category: 'edit', value: 256, type: 'number'});
new Setting('local_move', {category: 'edit', value: true});
new Setting('canvas_unselect', {category: 'edit', value: false});
new Setting('highlight_cubes', {category: 'edit', value: true, onChange() {
updateCubeHighlights();
@ -107,7 +116,11 @@ const Settings = {
new Setting('full_grid', {category: 'grid', value: false});
new Setting('large_box', {category: 'grid', value: false});
new Setting('display_grid', {category: 'grid', value: false});
new Setting('painting_grid',{category: 'grid', value: true});
new Setting('painting_grid',{category: 'grid', value: true, onChange() {
Cube.all.forEach(cube => {
Canvas.buildGridBox(cube)
})
}});
//Snapping
new Setting('edit_size', {category: 'snapping', value: 16, type: 'number'});
@ -196,13 +209,8 @@ const Settings = {
||hasSettingChanged('large_box') || hasSettingChanged('display_grid') || hasSettingChanged('edit_size')) {
buildGrid()
}
if (hasSettingChanged('painting_grid')) {
Cube.all.forEach(cube => {
Canvas.buildGridBox(cube)
})
}
Canvas.outlineMaterial.depthTest = !settings.seethrough_outline.value
if (hasSettingChanged('shading') || hasSettingChanged('brightness')) {
if (hasSettingChanged('brightness')) {
setShading()
}
for (var id in settings) {

View File

@ -5,9 +5,8 @@ var codec = new Codec('project', {
extension: 'bbmodel',
remember: true,
load(model, file) {
var name = pathToName(file.path, true)
newProject(model.meta.type||'free');
var name = pathToName(file.path, true);
if (file.path && isApp && !file.no_file ) {
ModelMeta.save_path = file.path;
ModelMeta.name = pathToName(name, false);
@ -100,6 +99,7 @@ var codec = new Codec('project', {
}
Blockbench.dispatchEvent('save_project', {model});
this.dispatchEvent('compile', {model, options})
if (options.raw) {
return model;
@ -142,6 +142,7 @@ var codec = new Codec('project', {
}
Blockbench.dispatchEvent('load_project', {model, path});
this.dispatchEvent('parse', {model})
Project.name = model.name;
if (model.geo_name) {
@ -178,12 +179,12 @@ var codec = new Codec('project', {
var copy = NonGroup.fromSave(element, true)
for (var face in copy.faces) {
if (!Project.box_uv) {
var texture = textures[element.faces[face].texture]
if (!Format.single_texture) {
var texture = element.faces[face].texture && textures[element.faces[face].texture]
if (texture) {
copy.faces[face].texture = texture.uuid
}
} else if (textures[0]) {
} else if (textures[0] && copy.faces[face].texture !== null) {
copy.faces[face].texture = textures[0].uuid
}
}

View File

@ -220,6 +220,8 @@ function parseGeometry(data) {
data = pe_list_data[0]
}
}
codec.dispatchEvent('parse', {model: data.object});
Project.geometry_name = (data.object.description.identifier && data.object.description.identifier.replace(/^geometry\./, '')) || '';
Project.texture_width = 16;
Project.texture_height = 16;
@ -271,7 +273,7 @@ function parseGeometry(data) {
})
base_cube.origin[0] *= -1;
if (s.origin) {
base_cube.from = s.origin
base_cube.from.V3_set(s.origin)
base_cube.from[0] = -(base_cube.from[0] + s.size[0])
if (s.size) {
base_cube.to[0] = s.size[0] + base_cube.from[0]
@ -433,38 +435,38 @@ var codec = new Codec('bedrock', {
for (var obj of g.children) {
if (obj.export) {
if (obj instanceof Cube) {
var cube = {
var template = {
origin: obj.from.slice(),
size: obj.size(),
inflate: obj.inflate||undefined,
}
if (Project.box_uv) {
cube = new oneLiner(cube);
template = new oneLiner(template);
}
cube.origin[0] = -(cube.origin[0] + cube.size[0])
template.origin[0] = -(template.origin[0] + template.size[0])
if (!obj.rotation.allEqual(0)) {
cube.pivot = obj.origin.slice();
cube.pivot[0] *= -1;
template.pivot = obj.origin.slice();
template.pivot[0] *= -1;
cube.rotation = obj.rotation.slice();
cube.rotation.forEach(function(br, axis) {
if (axis != 2) cube.rotation[axis] *= -1
template.rotation = obj.rotation.slice();
template.rotation.forEach(function(br, axis) {
if (axis != 2) template.rotation[axis] *= -1
})
}
if (Project.box_uv) {
cube.uv = obj.uv_offset;
template.uv = obj.uv_offset;
if (obj.mirror_uv === !bone.mirror) {
cube.mirror = obj.mirror_uv
template.mirror = obj.mirror_uv
}
} else {
cube.uv = {};
template.uv = {};
for (var key in obj.faces) {
var face = obj.faces[key];
if (face.texture !== null) {
cube.uv[key] = new oneLiner({
template.uv[key] = new oneLiner({
uv: [
face.uv[0],
face.uv[1],
@ -475,10 +477,10 @@ var codec = new Codec('bedrock', {
]
});
if (key == 'up') {
cube.uv[key].uv[0] += cube.uv[key].uv_size[0];
cube.uv[key].uv[1] += cube.uv[key].uv_size[1];
cube.uv[key].uv_size[0] *= -1;
cube.uv[key].uv_size[1] *= -1;
template.uv[key].uv[0] += template.uv[key].uv_size[0];
template.uv[key].uv[1] += template.uv[key].uv_size[1];
template.uv[key].uv_size[0] *= -1;
template.uv[key].uv_size[1] *= -1;
}
}
}
@ -488,7 +490,7 @@ var codec = new Codec('bedrock', {
if (mesh) {
visible_box.expandByObject(mesh)
}
cubes.push(cube)
cubes.push(template)
} else if (obj instanceof Locator) {
@ -532,6 +534,7 @@ var codec = new Codec('bedrock', {
if (bones.length) {
entitymodel.bones = bones
}
this.dispatchEvent('compile', {model: main_tag, options});
if (options.raw) {
return main_tag

View File

@ -11,6 +11,7 @@ function parseGeometry(data) {
data = pe_list_data[0]
}
}
codec.dispatchEvent('parse', {model: data.object});
Project.geometry_name = data.name.replace(/^geometry\./, '');
Project.texture_width = data.object.texturewidth || 64;
Project.texture_height = data.object.textureheight || 64;
@ -43,7 +44,7 @@ function parseGeometry(data) {
b.cubes.forEach(function(s) {
var base_cube = new Cube({name: b.name, autouv: 0, color: bi%8})
if (s.origin) {
base_cube.from = s.origin
base_cube.from.V3_set(s.origin);
base_cube.from[0] = -(base_cube.from[0] + s.size[0])
if (s.size) {
base_cube.to[0] = s.size[0] + base_cube.from[0]
@ -166,23 +167,23 @@ var codec = new Codec('bedrock_old', {
if (obj.export) {
if (obj instanceof Cube) {
var cube = new oneLiner()
cube.origin = obj.from.slice()
cube.size = obj.size()
cube.origin[0] = -(cube.origin[0] + cube.size[0])
cube.uv = obj.uv_offset
var template = new oneLiner()
template.origin = obj.from.slice()
template.size = obj.size()
template.origin[0] = -(template.origin[0] + template.size[0])
template.uv = obj.uv_offset
if (obj.inflate && typeof obj.inflate === 'number') {
cube.inflate = obj.inflate
template.inflate = obj.inflate
}
if (obj.mirror_uv === !bone.mirror) {
cube.mirror = obj.mirror_uv
template.mirror = obj.mirror_uv
}
//Visible Bounds
var mesh = obj.mesh
if (mesh) {
visible_box.expandByObject(mesh)
}
cubes.push(cube)
cubes.push(template)
cube_count++;
} else if (obj instanceof Locator) {
@ -226,6 +227,7 @@ var codec = new Codec('bedrock_old', {
if (bones.length) {
entitymodel.bones = bones
}
this.dispatchEvent('compile', {model: entitymodel, options});
if (options.raw) {
return entitymodel

View File

@ -5,13 +5,14 @@
var codec = new Codec('gltf', {
name: 'GLTF Model',
extension: 'gltf',
compile(options = 0, cb) {
compile(options = 0, callback) {
let scope = this;
let exporter = new THREE.GLTFExporter();
let animations = [];
let gl_scene = new THREE.Scene();
gl_scene.name = 'blockbench_export'
scene.children.forEach(object => {
scene.children.forEachReverse(object => {
if (object.isGroup || object.isElement) {
gl_scene.add(object);
}
@ -31,7 +32,8 @@ var codec = new Codec('gltf', {
if (animator[channel] && animator[channel].length) {
let times = [];
let values = [];
animator[channel].forEach(kf => {
let keyframes = animator[channel].slice();
keyframes.forEach(kf => {
times.push(kf.time);
Timeline.time = kf.time;
kf.getFixed().toArray(values, values.length);
@ -59,9 +61,10 @@ var codec = new Codec('gltf', {
}
exporter.parse(gl_scene, (json) => {
cb(JSON.stringify(json));
scope.dispatchEvent('compile', {model: json, options});
callback(JSON.stringify(json));
gl_scene.children.forEach(object => {
gl_scene.children.forEachReverse(object => {
if (object.isGroup || object.isElement) {
scene.add(object);
}
@ -93,7 +96,7 @@ var codec = new Codec('gltf', {
BARS.defineActions(function() {
codec.export_action = new Action({
id: 'export_gltf',
icon: 'fas.fa-ring',
icon: 'icon-gltf',
category: 'file',
click: function () {
codec.export()

View File

@ -77,11 +77,9 @@ class ModelFormat {
}
var center = Format.centered_grid ? 8 : 0;
previews.forEach(preview => {
if (preview.isOrtho) {
preview.setOrthographicCamera(preview.angle);
if (preview.isOrtho && typeof preview.angle == 'number') {
preview.loadAnglePreset(DefaultCameraPresets[preview.angle+1])
}
preview.camOrtho.position.y += center - preview.controls.target.y;
preview.controls.target.set(0, center, 0);
})
updateSelection()
Modes.vue.$forceUpdate()
@ -121,7 +119,7 @@ class ModelFormat {
//Bone Rig
if (!Format.bone_rig && old_format.bone_rig) {
Group.all.forEach(group => {
group.rotation = [0, 0, 0];
group.rotation.V3_set(0, 0, 0);
})
}
if (Format.bone_rig && !old_format.bone_rig) {
@ -145,7 +143,7 @@ class ModelFormat {
//Rotate Cubes
if (!Format.rotate_cubes && old_format.rotate_cubes) {
Cube.all.forEach(cube => {
cube.rotation = [0, 0, 0];
cube.rotation.V3_set(0, 0, 0)
})
}
@ -192,7 +190,7 @@ class ModelFormat {
if (!cube.rotation.allEqual(0)) {
var axis = (cube.rotation_axis && getAxisNumber(cube.rotation_axis)) || 0;
var angle = limitNumber( Math.round(cube.rotation[axis]/22.5)*22.5, -45, 45 );
cube.rotation = [0, 0, 0];
cube.rotation.V3_set(0, 0, 0)
cube.rotation[axis] = angle;
}
})
@ -217,6 +215,7 @@ class Codec {
this.id = id;
Codecs[id] = this;
this.name = data.name || 'Unknown Format';
this.events = {};
Merge.function(this, data, 'load');
Merge.function(this, data, 'compile');
Merge.function(this, data, 'parse');
@ -252,6 +251,7 @@ class Codec {
//Export
compile() {
this.dispatchEvent('compile', {content: ''})
return '';
}
export() {
@ -306,10 +306,27 @@ class Codec {
}
Blockbench.showQuickMessage(tl('message.save_file', [name]));
}
//Events
dispatchEvent(event_name, data) {
var list = this.events[event_name]
if (!list) return;
for (var i = 0; i < list.length; i++) {
if (typeof list[i] === 'function') {
list[i](data)
}
}
}
on(event_name, cb) {
if (!this.events[event_name]) {
this.events[event_name] = []
}
this.events[event_name].safePush(cb)
}
}
//New
function resetProject() {
Blockbench.dispatchEvent('reset_project');
if (Toolbox.selected.id !== 'move_tool') BarItems.move_tool.select();
Format = 0;
elements.length = 0;
@ -648,10 +665,9 @@ function uploadSketchfabModel() {
name: {label: 'dialog.sketchfab_uploader.name'},
description: {label: 'dialog.sketchfab_uploader.description', type: 'textarea'},
tags: {label: 'dialog.sketchfab_uploader.tags', placeholder: 'Tag1 Tag2'},
animations: {label: 'dialog.sketchfab_uploader.animations', value: true, type: 'checkbox', conditions: (Format.animation_mode && Animator.animations.length)},
animations: {label: 'dialog.sketchfab_uploader.animations', value: true, type: 'checkbox', condition: (Format.animation_mode && Animator.animations.length)},
//color: {type: 'color', label: 'dialog.sketchfab_uploader.color'},
draft: {label: 'dialog.sketchfab_uploader.draft', type: 'checkbox'},
// isPublished (draft)
// options.background.color = '#ffffff' (Background Color)
// Category
divider: '_',
private: {label: 'dialog.sketchfab_uploader.private', type: 'checkbox'},
@ -672,6 +688,7 @@ function uploadSketchfabModel() {
data.append('description', formResult.description)
data.append('tags', formResult.tags)
data.append('isPublished', !formResult.draft)
//data.append('background', JSON.stringify({color: formResult.color.toHexString()}))
data.append('private', formResult.private)
data.append('password', formResult.password)
data.append('source', 'blockbench')
@ -714,8 +731,8 @@ function uploadSketchfabModel() {
Blockbench.showMessageBox({
title: tl('message.sketchfab.success'),
message:
`[${formResult.name} on Sketchfab](https://sketchfab.com/models/${response.uid})\n\n&nbsp;\n\n`+
tl('message.sketchfab.setup_guide', '[Sketchfab Setup and Common Issues](https://blockbench.net/2020/01/22/sketchfab-setup-and-common-issues/)'),
`[${formResult.name} on Sketchfab](https://sketchfab.com/models/${response.uid})`, //\n\n&nbsp;\n\n`+
//tl('message.sketchfab.setup_guide', '[Sketchfab Setup and Common Issues](https://blockbench.net/2020/01/22/sketchfab-setup-and-common-issues/)'),
icon: 'icon-sketchfab',
})
},
@ -731,75 +748,6 @@ function uploadSketchfabModel() {
})
dialog.show()
}
/*function uploadPastebinModel() {
if (elements.length === 0) {
return;
}
var dialog = new Dialog({
id: 'sketchfab_uploader',
title: 'dialog.sketchfab_uploader.title',
width: 540,
form: {
token: {label: 'dialog.sketchfab_uploader.token', value: settings.sketchfab_token.value},
about_token: {type: 'text', text: tl('dialog.sketchfab_uploader.about_token', ['[sketchfab.com/settings/password](https://sketchfab.com/settings/password)'])},
name: {label: 'dialog.sketchfab_uploader.name'},
description: {label: 'dialog.sketchfab_uploader.description', type: 'textarea'},
tags: {label: 'dialog.sketchfab_uploader.tags', placeholder: 'Tag1 Tag2'},
draft: {label: 'dialog.sketchfab_uploader.draft', type: 'checkbox'},
// isPublished (draft)
// options.background.color = '#ffffff' (Background Color)
// Category
divider: '_',
private: {label: 'dialog.sketchfab_uploader.private', type: 'checkbox'},
password: {label: 'dialog.sketchfab_uploader.password'},
},
onConfirm: function(formResult) {
if (formResult.token && !formResult.name) {
Blockbench.showQuickMessage('message.sketchfab.name_or_token', 1800)
return;
}
var model = Codecs.project.compile({compressed: true})
var data = new FormData()
data.append('api_option', 'paste');
data.append('api_dev_key', '');
data.append('api_paste_code', model);
data.append('api_paste_private', 1);
data.append('api_paste_name', formResult.name)
data.append('api_paste_expire_date', '40M')
data.append('api_user_key', formResult.user_key)
//settings.sketchfab_token.value = formResult.token
$.ajax({
url: 'https://pastebin.com/api/api_post.php',
data: data,
cache: false,
contentType: false,
processData: false,
type: 'POST',
success: function(response) {
cl(response);
Blockbench.showMessageBox({
title: tl('message.sketchfab.success'),
message: `[${formResult.name} on Sketchfab](https://sketchfab.com/models/${response.uid})`,
icon: 'icon-sketchfab',
})
},
error: function(response) {
cl(response);
Blockbench.showQuickMessage('message.sketchfab.error', 1500)
console.error(response);
}
})
dialog.hide()
}
})
dialog.show()
}*/
//Json
function compileJSON(object, options) {
var output = ''
@ -816,7 +764,7 @@ function compileJSON(object, options) {
var out = ''
if (typeof o === 'string') {
//String
out += '"' + o.replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n').replace(/\t/g, '\\t') + '"'
out += '"' + o.replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n|\r\n/g, '\\n').replace(/\t/g, '\\t') + '"'
} else if (typeof o === 'boolean') {
//Boolean
out += (o ? 'true' : 'false')
@ -827,7 +775,7 @@ function compileJSON(object, options) {
} else if (o === null || o === Infinity || o === -Infinity) {
//Null
out += 'null'
} else if (typeof o === 'object' && o.constructor.name === 'Array') {
} else if (typeof o === 'object' && o instanceof Array) {
//Array
var has_content = false
out += '['
@ -924,11 +872,13 @@ BARS.defineActions(function() {
centered_grid: false,
optional_box_uv: true,
uv_rotation: true,
animation_mode: true,
})
//Project
new Action('project_window', {
icon: 'featured_play_list',
category: 'file',
condition: () => Format,
click: function () {
var dialog = new Dialog({
@ -1156,7 +1106,8 @@ BARS.defineActions(function() {
click: function() {
var archive = new JSZip();
var content = Format.codec.compile()
archive.file((Project.name||'model')+'.json', content)
var name = `${Format.codec.fileName()}.${Format.codec.extension}`
archive.file(name, content)
textures.forEach(tex => {
if (tex.mode === 'bitmap') {
archive.file(pathToName(tex.name) + '.png', tex.source.replace('data:image/png;base64,', ''), {base64: true});

View File

@ -22,8 +22,8 @@ var codec = new Codec('java_block', {
element.name = s.name
}
}
element.from = s.from.slice()
element.to = s.to.slice()
element.from = s.from.slice();
element.to = s.to.slice();
if (s.inflate) {
for (var i = 0; i < 3; i++) {
element.from[i] -= s.inflate;
@ -86,8 +86,8 @@ var codec = new Codec('java_block', {
if (s.faces[face].cullface) {
tag.cullface = s.faces[face].cullface
}
if (s.faces[face].tint) {
tag.tintindex = 0
if (s.faces[face].tint >= 0) {
tag.tintindex = s.faces[face].tint
}
e_faces[face] = tag
}
@ -168,6 +168,14 @@ var codec = new Codec('java_block', {
message: tl('message.model_clipping.message', [largerCubesNr])
})
}
if (options.prevent_dialog !== true && clear_elements.length && ['item/generated', 'item/handheld'].includes(Project.parent)) {
Blockbench.showMessageBox({
translateKey: 'invalid_builtin_parent',
icon: 'info',
message: tl('message.invalid_builtin_parent.message', [Project.parent])
})
Project.parent = '';
}
var blockmodel = {}
if (checkExport('comment', settings.credit.value)) {
@ -218,6 +226,7 @@ var codec = new Codec('java_block', {
blockmodel.groups = groups
}
}
this.dispatchEvent('compile', {model: blockmodel, options});
if (options.raw) {
return blockmodel
} else {
@ -235,6 +244,8 @@ var codec = new Codec('java_block', {
Formats.java_block.select()
Settings.save()
this.dispatchEvent('parse', {model});
var previous_length = add ? elements.length : 0
var previous_texture_length = add ? textures.length : 0
var new_cubes = [];
@ -338,8 +349,8 @@ var codec = new Codec('java_block', {
}
new_face.texture = t.uuid;
}
if (read_face.tintindex !== undefined) {
new_face.tint = true;
if (typeof read_face.tintindex == 'number') {
new_face.tint = read_face.tintindex;
}
}
}

View File

@ -150,10 +150,13 @@ var codec = new Codec('modded_entity', {
'\n modelRenderer.rotateAngleZ = z;'+
'\n }'+
'\n}';
this.dispatchEvent('compile', {model, options});
return model;
},
parse(model, path, add) {
// WIP //
this.dispatchEvent('parse', {model});
var lines = [];
model.split('\n').forEach(l => {
l = l.replace(/\/\*[^(\*\/)]*\*\/|\/\/.*/g, '').trim().replace(/;$/, '');
@ -288,9 +291,8 @@ var codec = new Codec('modded_entity', {
if (parseScheme('$v.addChild($v)', line.replace(/\(this\./g, '('))) {
var child = bones[match[1]], parent = bones[match[0]];
child.addTo(parent);
child.origin[0] += parent.origin[0];
child.origin[1] += parent.origin[1] - 24;
child.origin[2] += parent.origin[2];
child.origin.V3_add(parent.origin)
child.origin[1] -= 24;
child.children.forEach(cube => {
if (cube instanceof Cube) {
cube.from[0] += parent.origin[0]; cube.to[0] += parent.origin[0];

View File

@ -177,6 +177,7 @@ var codec = new Codec('obj', {
mtl: mtlOutput,
images: materials
}
this.dispatchEvent('compile', {model: output, mtl: mtlOutput, images: materials});
return options.all_files ? _obj_export : output;
},
write(content, path) {

View File

@ -15,6 +15,7 @@ var codec = new Codec('optifine_entity', {
entitymodel.models = []
Outliner.root.forEach(function(g) {
if (g instanceof Group == false) return;
//Bone
var bone = {
part: g.name,
@ -129,6 +130,8 @@ var codec = new Codec('optifine_entity', {
entitymodel.models.push(bone)
})
this.dispatchEvent('compile', {entitymodel, options});
if (options.raw) {
return entitymodel
} else {
@ -136,6 +139,7 @@ var codec = new Codec('optifine_entity', {
}
},
parse(model, path) {
this.dispatchEvent('parse', {model});
if (model.textureSize) {
Project.texture_width = parseInt(model.textureSize[0])||16;
Project.texture_height = parseInt(model.textureSize[1])||16;

View File

@ -66,7 +66,7 @@ var part_codec = new Codec('optifine_part', {
if (submodels.length) {
jpm.submodels = submodels
}
this.dispatchEvent('compile', {model: jpm, options});
if (options.raw) {
return jpm
@ -75,6 +75,8 @@ var part_codec = new Codec('optifine_part', {
}
},
parse(model, path, add) {
this.dispatchEvent('parse', {model});
Project.box_uv = false;
var new_cubes = [];
var box_uv_changed = false;

View File

@ -43,20 +43,20 @@ const codec = new Codec('skin_model', {
if (obj.export) {
if (obj instanceof Cube) {
var cube = new oneLiner()
cube.name = obj.name;
if (obj.visibility == false) cube.visibility = false;
cube.origin = obj.from.slice()
cube.size = obj.size()
cube.origin[0] = -(cube.origin[0] + cube.size[0])
cube.uv = obj.uv_offset
var template = new oneLiner()
template.name = obj.name;
if (obj.visibility == false) template.visibility = false;
template.origin = obj.from.slice()
template.size = obj.size()
template.origin[0] = -(template.origin[0] + template.size[0])
template.uv = obj.uv_offset
if (obj.inflate && typeof obj.inflate === 'number') {
cube.inflate = obj.inflate
template.inflate = obj.inflate
}
if (obj.mirror_uv === !bone.mirror) {
cube.mirror = obj.mirror_uv
template.mirror = obj.mirror_uv
}
cubes.push(cube)
cubes.push(template)
cube_count++;
}
@ -71,9 +71,11 @@ const codec = new Codec('skin_model', {
if (bones.length) {
entitymodel.bones = bones
}
this.dispatchEvent('compile', {model: entitymodel, options});
return entitymodel
},
parse(data, resolution, texture_path) {
this.dispatchEvent('parse', {model: data});
Project.geometry_name = data.name;
Project.texture_width = data.texturewidth || 64;
Project.texture_height = data.textureheight || 64;
@ -106,7 +108,7 @@ const codec = new Codec('skin_model', {
b.cubes.forEach(function(s) {
var base_cube = new Cube({name: s.name, visibility: s.visibility, autouv: 0, color: b.color})
if (s.origin) {
base_cube.from = s.origin
base_cube.from.V3_set(s.origin)
base_cube.from[0] = -(base_cube.from[0] + s.size[0])
if (s.size) {
base_cube.to[0] = s.size[0] + base_cube.from[0]
@ -168,7 +170,7 @@ const codec = new Codec('skin_model', {
Canvas.updateAllBones()
setProjectTitle()
if (isApp && Project.geometry_name) {
BedrockEntityManager.initEntity()
//BedrockEntityManager.initEntity()
}
updateSelection()
EditSession.initNewModel()
@ -243,8 +245,13 @@ const skin_dialog = new Dialog({
armor_stand: 'Armor Stand',
bat: 'Bat',
bee: 'Bee',
bell: 'Bell',
blaze: 'Blaze',
boat: 'Boat',
cat: 'Cat',
chest: 'Chest',
chest_right: 'Chest Right',
chest_left: 'Chest Left',
chicken: 'Chicken',
cod: 'Cod',
cow: 'Cow',
@ -253,11 +260,13 @@ const skin_dialog = new Dialog({
enderdragon: 'Ender Dragon',
enderman: 'Enderman',
endermite: 'Endermite',
evocation_fang: 'Evocation Fang',
evoker: 'Evoker',
fox_bedrock: 'Fox (Bedrock)',
fox_java: 'Fox (Java)',
ghast: 'Ghast',
guardian: 'Guardian',
hoglin: 'Hoglin',
horse: 'Horse',
llama: 'Llama',
lavaslime: 'Lava Slime',
@ -267,6 +276,7 @@ const skin_dialog = new Dialog({
parrot: 'Parrot',
phantom: 'Phantom',
pig: 'Pig',
piglin: 'Piglin',
pillager: 'Pillager',
polarbear: 'Polarbear',
pufferfish: 'Pufferfish',
@ -527,14 +537,6 @@ skin_presets.armor_stand = `{
{"name": "head", "origin": [-1, 24, -1], "size": [2, 7, 2], "uv": [0, 0]}
]
},
{
"name": "hat",
"parent": "head",
"pivot": [0, 24, 0],
"cubes": [
{"name": "hat", "origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [32, 0]}
]
},
{
"name": "leftarm",
"parent": "body",
@ -544,11 +546,6 @@ skin_presets.armor_stand = `{
{"name": "leftarm", "origin": [5, 12, -1], "size": [2, 12, 2], "uv": [32, 16]}
]
},
{
"name": "leftitem",
"parent": "leftarm",
"pivot": [6, 15, 1]
},
{
"name": "leftleg",
"parent": "body",
@ -566,11 +563,6 @@ skin_presets.armor_stand = `{
{"name": "rightarm", "origin": [-7, 12, -1], "size": [2, 12, 2], "uv": [24, 0]}
]
},
{
"name": "rightitem",
"parent": "rightarm",
"pivot": [-6, 15, 1]
},
{
"name": "rightleg",
"parent": "body",
@ -729,6 +721,123 @@ skin_presets.bee = `{
}
]
}`;
skin_presets.bell = `{
"name": "bell",
"texturewidth": 32,
"textureheight": 32,
"bones": [
{
"name": "bell",
"pivot": [0, 11, 0],
"cubes": [
{"name": "cube", "origin": [-4, 2, -4], "size": [8, 2, 8], "uv": [0, 13]},
{"name": "cube", "origin": [-3, 4, -3], "size": [6, 7, 6], "uv": [0, 0]}
]
}
]
}`;
skin_presets.blaze = `{
"name": "blaze",
"texturewidth": 64,
"textureheight": 32,
"eyes": [
[9, 11],
[13, 11]
],
"bones": [
{
"name": "upperBodyParts0",
"pivot": [8, 26, -3],
"cubes": [
{"name": "upperBodyParts0", "origin": [8, 18, -3], "size": [2, 8, 2], "uv": [0, 16]}
]
},
{
"name": "upperBodyParts1",
"pivot": [-10, 26, 1],
"cubes": [
{"name": "upperBodyParts1", "origin": [-10, 18, 1], "size": [2, 8, 2], "uv": [0, 16]}
]
},
{
"name": "upperBodyParts2",
"pivot": [1, 26, 8],
"cubes": [
{"name": "upperBodyParts2", "origin": [1, 18, 8], "size": [2, 8, 2], "uv": [0, 16]}
]
},
{
"name": "upperBodyParts3",
"pivot": [-3, 26, -10],
"cubes": [
{"name": "upperBodyParts3", "origin": [-3, 18, -10], "size": [2, 8, 2], "uv": [0, 16]}
]
},
{
"name": "upperBodyParts4",
"pivot": [5, 18, -1],
"cubes": [
{"name": "upperBodyParts4", "origin": [5, 10, -1], "size": [2, 8, 2], "uv": [0, 16]}
]
},
{
"name": "upperBodyParts5",
"pivot": [-7, 18, -1],
"cubes": [
{"name": "upperBodyParts5", "origin": [-7, 10, -1], "size": [2, 8, 2], "uv": [0, 16]}
]
},
{
"name": "upperBodyParts6",
"pivot": [-1, 18, 5],
"cubes": [
{"name": "upperBodyParts6", "origin": [-1, 10, 5], "size": [2, 8, 2], "uv": [0, 16]}
]
},
{
"name": "upperBodyParts7",
"pivot": [-1, 18, -7],
"cubes": [
{"name": "upperBodyParts7", "origin": [-1, 10, -7], "size": [2, 8, 2], "uv": [0, 16]}
]
},
{
"name": "upperBodyParts8",
"pivot": [3, 8, 2],
"cubes": [
{"name": "upperBodyParts8", "origin": [3, 0, 2], "size": [2, 8, 2], "uv": [0, 16]}
]
},
{
"name": "upperBodyParts9",
"pivot": [-5, 8, -4],
"cubes": [
{"name": "upperBodyParts9", "origin": [-5, 0, -4], "size": [2, 8, 2], "uv": [0, 16]}
]
},
{
"name": "upperBodyParts10",
"pivot": [-4, 8, 3],
"cubes": [
{"name": "upperBodyParts10", "origin": [-4, 0, 3], "size": [2, 8, 2], "uv": [0, 16]}
]
},
{
"name": "upperBodyParts11",
"pivot": [2, 8, -5],
"cubes": [
{"name": "upperBodyParts11", "origin": [2, 0, -5], "size": [2, 8, 2], "uv": [0, 16]}
]
},
{
"name": "head",
"pivot": [0, 24, 0],
"cubes": [
{"name": "head", "origin": [-4, 20, -4], "size": [8, 8, 8], "uv": [0, 0]}
]
}
]
}`;
skin_presets.boat = `{
"name": "boat",
"texturewidth": 128,
@ -881,6 +990,57 @@ skin_presets.cat = `{
}
]
}`;
skin_presets.chest = `{
"name": "chest",
"texturewidth": 64,
"textureheight": 64,
"bones": [
{
"name": "chest",
"pivot": [0, 8, 0],
"rotation": [0, 0, -180],
"cubes": [
{"name": "cube", "origin": [-1, 5, 7], "size": [2, 4, 1], "uv": [0, 0]},
{"name": "cube", "origin": [-7, 2, -7], "size": [14, 5, 14], "uv": [0, 0]},
{"name": "cube", "origin": [-7, 6, -7], "size": [14, 10, 14], "uv": [0, 19]}
]
}
]
}`;
skin_presets.chest_left = `{
"name": "bell",
"texturewidth": 64,
"textureheight": 64,
"bones": [
{
"name": "chest",
"pivot": [0, 8, 0],
"rotation": [0, 0, -180],
"cubes": [
{"name": "cube", "origin": [-9, 5, 7], "size": [2, 4, 1], "uv": [0, 0]},
{"name": "cube", "origin": [-8, 2, -7], "size": [15, 5, 14], "uv": [0, 0]},
{"name": "cube", "origin": [-8, 6, -7], "size": [15, 10, 14], "uv": [0, 19]}
]
}
]
}`;
skin_presets.chest_right = `{
"name": "bell",
"texturewidth": 64,
"textureheight": 64,
"bones": [
{
"name": "chest",
"pivot": [0, 8, 0],
"rotation": [0, 0, -180],
"cubes": [
{"name": "cube", "origin": [7, 5, 7], "size": [2, 4, 1], "uv": [0, 0]},
{"name": "cube", "origin": [-7, 2, -7], "size": [15, 5, 14], "uv": [0, 0]},
{"name": "cube", "origin": [-7, 6, -7], "size": [15, 10, 14], "uv": [0, 19]}
]
}
]
}`;
skin_presets.chicken = `{
"name": "chicken",
"texturewidth": 64,
@ -1644,6 +1804,38 @@ skin_presets.endermite = `{
}
]
}`;
skin_presets.evocation_fang = `{
"name": "evocation_fang",
"texturewidth": 64,
"textureheight": 32,
"bones": [
{
"name": "base",
"pivot": [0, 0, 0],
"cubes": [
{"name": "base", "origin": [-5, 0, -5], "size": [10, 12, 10], "uv": [0, 0]}
]
},
{
"name": "upper_jaw",
"parent": "base",
"pivot": [0, 11, 0],
"rotation": [0, 180, -150],
"cubes": [
{"name": "upper_jaw", "origin": [-1.5, -4, -4], "size": [4, 14, 8], "uv": [40, 0], "inflate": 0.01}
]
},
{
"name": "lower_jaw",
"parent": "base",
"pivot": [0, 11, 0],
"rotation": [0, 0, 150],
"cubes": [
{"name": "lower_jaw", "origin": [-1.5, -4, -4], "size": [4, 14, 8], "uv": [40, 0]}
]
}
]
}`
skin_presets.evoker = `{
"name": "evoker",
"texturewidth": 64,
@ -2096,6 +2288,77 @@ skin_presets.guardian = `{
}
]
}`;
skin_presets.hoglin = `{
"name": "hoglin",
"texturewidth": 128,
"textureheight": 128,
"bones": [
{
"name": "head",
"pivot": [0, 19, -13],
"rotation": [50, 0, 0],
"cubes": [
{"name": "head", "origin": [-7, 17, -29], "size": [14, 6, 19], "uv": [1, 42]},
{"name": "head", "origin": [6, 18, -23], "size": [2, 11, 2], "uv": [6, 45]},
{"name": "head", "origin": [-8, 18, -23], "size": [2, 11, 2], "uv": [6, 45]}
]
},
{
"name": "ear_right",
"parent": "head",
"pivot": [-6, 23, -14],
"rotation": [0, 0, -35],
"cubes": [
{"name": "cube", "origin": [-13, 22, -17], "size": [6, 1, 4], "uv": [4, 16]}
]
},
{
"name": "ear_left",
"parent": "head",
"pivot": [6, 23, -14],
"rotation": [0, 0, 35],
"cubes": [
{"name": "cube", "origin": [7, 22, -17], "size": [6, 1, 4], "uv": [4, 21]}
]
},
{
"name": "body",
"pivot": [0, 19, 2],
"cubes": [
{"name": "body", "origin": [-8, 10, -13], "size": [16, 14, 26], "uv": [1, 1]},
{"name": "body", "origin": [0, 21, -16], "size": [0, 10, 21], "uv": [3, 65]}
]
},
{
"name": "leg0",
"pivot": [-5, 11, 10],
"cubes": [
{"name": "leg0", "origin": [-7.5, 0, 7.5], "size": [5, 11, 5], "uv": [51, 43]}
]
},
{
"name": "leg1",
"pivot": [5, 11, 10],
"cubes": [
{"name": "leg1", "origin": [2.5, 0, 7.5], "size": [5, 11, 5], "uv": [72, 43]}
]
},
{
"name": "leg2",
"pivot": [-3.5, 14, -8.5],
"cubes": [
{"name": "leg2", "origin": [-7, 0, -11.5], "size": [6, 14, 6], "uv": [46, 75]}
]
},
{
"name": "leg3",
"pivot": [3.5, 14, -8.5],
"cubes": [
{"name": "leg3", "origin": [1, 0, -11.5], "size": [6, 14, 6], "uv": [71, 75]}
]
}
]
}`
skin_presets.horse = `{
"name": "horse",
"texturewidth": 64,
@ -2650,7 +2913,7 @@ skin_presets.phantom = `{
"name": "phantom",
"eyes": [
[5, 6, 2, 1],
[10, 6, 2, 1],
[10, 6, 2, 1]
],
"texturewidth": 64,
"textureheight": 64,
@ -2785,6 +3048,85 @@ skin_presets.pig = `{
}
]
}`;
skin_presets.piglin = `{
"name": "piglin",
"texturewidth": 128,
"textureheight": 64,
"eyes": [
[10, 11, 1, 1],
[15, 11, 1, 1]
],
"bones": [
{
"name": "Head",
"pivot": [0, 24, 0],
"rotation": [3, 5, 0],
"cubes": [
{"name": "Head", "origin": [-5, 24, -4], "size": [10, 8, 8], "uv": [0, 0]},
{"name": "Head", "origin": [-2, 24, -5], "size": [4, 4, 1], "uv": [31, 1]},
{"name": "Head", "origin": [-3, 24, -5], "size": [1, 2, 1], "uv": [2, 0]},
{"name": "Head", "origin": [2, 24, -5], "size": [1, 2, 1], "uv": [2, 4]}
]
},
{
"name": "LeftEar",
"parent": "Head",
"pivot": [4.5, 30, 0],
"rotation": [0, 0, -25],
"cubes": [
{"name": "Head", "origin": [4.5, 25, -2], "size": [1, 5, 4], "uv": [57, 38]}
]
},
{
"name": "RightEar",
"parent": "Head",
"pivot": [-4.5, 30, 0],
"rotation": [0, 0, 25],
"cubes": [
{"name": "Head", "origin": [-5.5, 25, -2], "size": [1, 5, 4], "uv": [57, 22]}
]
},
{
"name": "Body",
"pivot": [0, 24, 0],
"cubes": [
{"name": "Body", "origin": [-4, 12, -2], "size": [8, 12, 4], "uv": [16, 16]}
]
},
{
"name": "RightArm",
"pivot": [-5, 22, 0],
"rotation": [-10, 0, 0],
"cubes": [
{"name": "Right Arm", "origin": [-8, 12, -2], "size": [4, 12, 4], "uv": [40, 16]}
]
},
{
"name": "LeftArm",
"pivot": [5, 22, 0],
"rotation": [12, 0, 0],
"cubes": [
{"name": "Left Arm", "origin": [4, 12, -2], "size": [4, 12, 4], "uv": [32, 48]}
]
},
{
"name": "RightLeg",
"pivot": [-1.9, 12, 0],
"rotation": [11, 0, 2],
"cubes": [
{"name": "Right Leg", "origin": [-3.9, 0, -2], "size": [4, 12, 4], "uv": [0, 16]}
]
},
{
"name": "LeftLeg",
"pivot": [1.9, 12, 0],
"rotation": [-10, 0, -2],
"cubes": [
{"name": "Left Leg", "origin": [-0.1, 0, -2], "size": [4, 12, 4], "uv": [16, 48]}
]
}
]
}`
skin_presets.pillager = `{
"name": "pillager",
"texturewidth": 64,

View File

@ -30,7 +30,7 @@ class Face {
}
Merge.string(this, object, 'cullface')
Merge.number(this, object, 'rotation')
Merge.boolean(this, object, 'tint')
Merge.number(this, object, 'tint')
if (object.uv) {
Merge.number(this.uv, object.uv, 0)
Merge.number(this.uv, object.uv, 1)
@ -45,11 +45,11 @@ class Face {
this.texture = false;
this.cullface = '';
this.enabled = true;
this.tint = false;
this.tint = -1;
return this;
}
getTexture() {
if (Format.single_texture && Project.box_uv) {
if (Format.single_texture && Project.box_uv && this.texture !== null) {
return textures[0];
}
if (typeof this.texture === 'string') {
@ -69,8 +69,8 @@ class Face {
} else if (tex instanceof Texture) {
copy.texture = textures.indexOf(tex)
}
if (this.tint) {
copy.tint = true;
if (this.tint !== -1) {
copy.tint = this.tint;
}
if (this.cullface) {
copy.cullface = this.cullface;
@ -81,6 +81,14 @@ class Face {
return copy;
}
}
Face.opposite = {
north: 'south',
south: 'north',
east: 'west',
west: 'east',
down: 'up',
up: 'down'
}
class Cube extends NonGroup {
constructor(data, uuid) {
@ -94,11 +102,10 @@ class Cube extends NonGroup {
this.color = Math.floor(Math.random()*8)
this.uv_offset = [0,0]
this.inflate = 0;
this.rotation = [0, 0, 0]
if (Format.centered_grid) {
this.origin = [0, 0, 0]
} else {
this.origin = [8, 8, 8]
this.rotation = [0, 0, 0];
this.origin = [0, 0, 0];
if (!Format.centered_grid) {
this.origin.V3_set(8, 8, 8);
}
this.visibility = true;
this.autouv = 0
@ -150,7 +157,7 @@ class Cube extends NonGroup {
if (object.rotation.angle && object.rotation.axis) {
var axis = getAxisNumber(object.rotation.axis)
if (axis >= 0) {
this.rotation = [0, 0, 0]
this.rotation.V3_set(0)
this.rotation[axis] = object.rotation.angle
}
}
@ -193,7 +200,9 @@ class Cube extends NonGroup {
super.init();
if (Format.single_texture && textures[0]) {
for (var face in this.faces) {
this.faces[face].texture = textures[0].uuid
if (this.faces[face].texture !== null) {
this.faces[face].texture = textures[0].uuid
}
}
}
if (!this.parent || (this.parent === 'root' && Outliner.root.indexOf(this) === -1)) {
@ -290,11 +299,9 @@ class Cube extends NonGroup {
if (!this.rotation.allEqual(0)) el.rotation = this.rotation;
el.origin = this.origin;
if (!this.uv_offset.allEqual(0)) el.uv_offset = this.uv_offset;
if (!meta || !meta.box_uv) {
el.faces = {}
for (var face in this.faces) {
el.faces[face] = this.faces[face].getSaveCopy()
}
el.faces = {}
for (var face in this.faces) {
el.faces[face] = this.faces[face].getSaveCopy()
}
el.uuid = this.uuid
return el;
@ -335,10 +342,10 @@ class Cube extends NonGroup {
case 1: [this.from[2], this.to[2]] = [this.to[2], this.from[2]]; break;
case 2: [this.from[1], this.to[1]] = [this.to[1], this.from[1]]; break;
}
this.from = rotateCoord(this.from, 1, origin)
this.to = rotateCoord(this.to, 1, origin)
this.from.V3_set(rotateCoord(this.from, 1, origin))
this.to.V3_set(rotateCoord(this.to, 1, origin))
if (origin != this.origin) {
this.origin = rotateCoord(this.origin, 1, origin)
this.origin.V3_set(rotateCoord(this.origin, 1, origin))
}
if (!Project.box_uv) {
if (axis === 0) {
@ -483,7 +490,7 @@ class Cube extends NonGroup {
this.moveVector(shift)
this.origin = origin.slice();
this.origin.V3_set(origin);
Canvas.adaptObjectPosition(this)
return this;
@ -677,12 +684,8 @@ class Cube extends NonGroup {
this.mesh.getWorldQuaternion(rotation);
m.applyQuaternion(rotation.inverse());
this.from[0] += m.x;
this.from[1] += m.y;
this.from[2] += m.z;
this.to[0] += m.x;
this.to[1] += m.y;
this.to[2] += m.z;
this.from.V3_add(m.x, m.y, m.z);
this.to.V3_add(m.x, m.y, m.z);
} else {
this.to[axis] += val;

View File

@ -4,10 +4,9 @@ class Group extends OutlinerElement {
super()
this.name = Format.bone_rig ? 'bone' : 'group'
this.children = []
if (Format.centered_grid) {
this.origin = [0, 0, 0];
} else {
this.origin = [8, 8, 8];
this.origin = [0, 0, 0];
if (!Format.centered_grid) {
this.origin.V3_set(8, 8, 8);
}
this.rotation = [0, 0, 0];
this.reset = false;
@ -240,30 +239,22 @@ class Group extends OutlinerElement {
dq.applyQuaternion(q)
shift.sub(dq)
shift.applyQuaternion(q.inverse())
this.origin = origin.slice();
this.origin.V3_set(origin);
function iterateChild(obj) {
if (obj instanceof Group) {
obj.origin[0] += shift.x;
obj.origin[1] += shift.y;
obj.origin[2] += shift.z;
obj.origin.V3_add(shift);
obj.children.forEach(child => iterateChild(child));
} else {
if (obj.movable) {
obj.from[0] += shift.x;
obj.from[1] += shift.y;
obj.from[2] += shift.z;
obj.from.V3_add(shift);
}
if (obj.resizable) {
obj.to[0] += shift.x;
obj.to[1] += shift.y;
obj.to[2] += shift.z;
obj.to.V3_add(shift);
}
if (obj.rotatable) {
obj.origin[0] += shift.x;
obj.origin[1] += shift.y;
obj.origin[2] += shift.z;
obj.origin.V3_add(shift);
}
}
}
@ -310,8 +301,8 @@ class Group extends OutlinerElement {
getChildlessCopy() {
var base_group = new Group();
base_group.name = this.name;
base_group.origin = this.origin.slice();
base_group.rotation = this.rotation.slice();
base_group.origin.V3_set(this.origin);
base_group.rotation.V3_set(this.rotation);
base_group.shade = this.shade;
base_group.reset = this.reset;
base_group.visibility = this.visibility;
@ -335,7 +326,7 @@ class Group extends OutlinerElement {
}
obj.origin = this.origin.slice()
if (this.rotation.join('_') !== '0_0_0') {
if (!this.rotation.allEqual(0)) {
obj.rotation = this.rotation.slice()
}
if (this.reset) {

View File

@ -2,7 +2,7 @@
class Locator extends NonGroup {
constructor(data, uuid) {
super(data, uuid);
this.from = [0, 0, 0];
this.from = new Array().V3_set(0, 0, 0);
this.name = 'locator';
this.export = true;
@ -14,11 +14,7 @@ class Locator extends NonGroup {
Merge.string(this, object, 'name');
this.sanitizeName();
Merge.boolean(this, object, 'export');
if (object.from) {
Merge.number(this.from, object.from, 0);
Merge.number(this.from, object.from, 1);
Merge.number(this.from, object.from, 2);
}
Merge.arrayVector(this, object, 'from');
return this;
}
getUndoCopy() {
@ -75,10 +71,7 @@ class Locator extends NonGroup {
this.parent.mesh.getWorldQuaternion(rotation);
m.applyQuaternion(rotation.inverse());
}
this.from[0] += m.x;
this.from[1] += m.y;
this.from[2] += m.z;
this.from.V3_add(m);
} else {
this.from[axis] += val
}

View File

@ -987,16 +987,6 @@ BARS.defineActions(function() {
Undo.finishEdit('sort_outliner')
}
})
new Action('local_move', {
icon: 'check_box',
category: 'edit',
condition: () => Modes.edit,
linked_setting: 'local_move',
click: function () {
BarItems.local_move.toggleLinkedSetting()
updateSelection()
}
})
new Action('element_colors', {
icon: 'check_box',
category: 'edit',

View File

@ -11,7 +11,7 @@
>` +
//Opener
'<i v-if="node.children && node.children.length > 0 && (!Animator.open || node.children.some(o => o instanceof Group))" v-on:click.stop="toggle(node)" class="icon-open-state fa" :class=\'{"fa-caret-right": !node.isOpen, "fa-caret-down": node.isOpen}\'></i>' +
'<i v-if="node.children && node.children.length > 0 && (!Animator.open || node.children.some(o => o instanceof Group))" v-on:click.stop="toggle(node)" class="icon-open-state fa" :class=\'{"fa-angle-right": !node.isOpen, "fa-angle-down": node.isOpen}\'></i>' +
'<i v-else class="outliner_opener_placeholder"></i>' +
//Main
'<i :class="node.icon + (settings.outliner_colors.value ? \' ec_\'+node.color : \'\')" v-on:dblclick.stop="if (node.children && node.children.length) {node.isOpen = !node.isOpen;}"></i>' +

View File

@ -113,7 +113,9 @@ THREE.OrbitControls = function ( object, preview ) {
if ( scope.autoRotate && state === STATE.NONE ) {
rotateLeft( getAutoRotationAngle() );
let auto_rot_angle = getAutoRotationAngle()
scope.autoRotateProgress += auto_rot_angle;
rotateLeft( auto_rot_angle );
}
@ -455,8 +457,6 @@ THREE.OrbitControls = function ( object, preview ) {
function handleKeyDown( event ) {
//console.log( 'handleKeyDown' );
switch ( event.keyCode ) {
case scope.keys.UP:

View File

@ -59,7 +59,7 @@ const Canvas = {
color: gizmo_colors.wire,
wireframe: true
}),
transparentMaterial: new THREE.MeshBasicMaterial({visible: false}),
transparentMaterial: new THREE.MeshBasicMaterial({visible: false, name: 'invisible'}),
gridMaterial: new THREE.LineBasicMaterial({color: gizmo_colors.grid}),
face_order: ['east', 'west', 'up', 'down', 'south', 'north'],
//Misc
@ -304,31 +304,29 @@ const Canvas = {
updateAllBones() {
Group.all.forEach((obj) => {
let mesh = obj.mesh
if (mesh) {
let bone = obj.mesh
if (bone) {
mesh.rotation.reorder('ZYX')
obj.rotation.forEach(function(n, i) {
mesh.rotation[getAxisLetter(i)] = Math.PI / (180 / n);
})
mesh.position.fromArray(obj.origin)
mesh.scale.x = mesh.scale.y = mesh.scale.z = 1
bone.rotation.reorder('ZYX')
bone.rotation.setFromDegreeArray(obj.rotation);
bone.position.fromArray(obj.origin)
bone.scale.x = bone.scale.y = bone.scale.z = 1
if (obj.parent.type === 'group') {
mesh.position.x -= obj.parent.origin[0]
mesh.position.y -= obj.parent.origin[1]
mesh.position.z -= obj.parent.origin[2]
bone.position.x -= obj.parent.origin[0]
bone.position.y -= obj.parent.origin[1]
bone.position.z -= obj.parent.origin[2]
var parent_mesh = obj.parent.mesh
parent_mesh.add(mesh)
var parent_bone = obj.parent.mesh
parent_bone.add(bone)
} else {
scene.add(mesh)
scene.add(bone)
}
mesh.updateMatrixWorld()
bone.updateMatrixWorld()
mesh.fix_position = mesh.position.clone()
mesh.fix_rotation = mesh.rotation.clone()
bone.fix_position = bone.position.clone()
bone.fix_rotation = bone.rotation.clone()
}
})
},
@ -805,7 +803,7 @@ const Canvas = {
var geometry = new THREE.BufferGeometry();
geometry.addAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) );
geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) );
var lines = new THREE.LineSegments(geometry, new THREE.LineBasicMaterial({color: gizmo_colors.grid}));
lines.geometry.translate(-cube.origin[0], -cube.origin[1], -cube.origin[2]);

View File

@ -19,6 +19,75 @@ var gizmo_colors = {
wire: new THREE.Color(0x576f82),
outline: new THREE.Color(0x3e90ff)
}
const DefaultCameraPresets = [
{
name: 'menu.preview.angle.initial',
projection: 'perspective',
position: [-40, 32, -40],
target: [0, 8, 0],
default: true
},
{
name: 'direction.top',
projection: 'orthographic',
color: 'y',
position: [0, 64, 0],
target: [0, 0, 0],
zoom: 0.5,
locked_angle: 0,
default: true
},
{
name: 'direction.bottom',
projection: 'orthographic',
color: 'y',
position: [0, -64, 0],
target: [0, 0, 0],
zoom: 0.5,
locked_angle: 1,
default: true
},
{
name: 'direction.south',
projection: 'orthographic',
color: 'z',
position: [0, 0, 64],
target: [0, 0, 0],
zoom: 0.5,
locked_angle: 2,
default: true
},
{
name: 'direction.north',
projection: 'orthographic',
color: 'z',
position: [0, 0, -64],
target: [0, 0, 0],
zoom: 0.5,
locked_angle: 3,
default: true
},
{
name: 'direction.east',
projection: 'orthographic',
color: 'x',
position: [64, 0, 0],
target: [0, 0, 0],
zoom: 0.5,
locked_angle: 4,
default: true
},
{
name: 'direction.west',
projection: 'orthographic',
color: 'x',
position: [-64, 0, 0],
target: [0, 0, 0],
zoom: 0.5,
locked_angle: 5,
default: true
}
]
class Preview {
constructor(data) {
@ -34,11 +103,12 @@ class Preview {
this.width = 0;
//Cameras
this.isOrtho = false
this.angle = null;
this.camPers = new THREE.PerspectiveCamera(45, 16 / 9, 1, 30000)
this.camOrtho = new THREE.OrthographicCamera(-600, 600, -400, 400, 0.5, 200);
this.camOrtho = new THREE.OrthographicCamera(-600, 600, -400, 400, -200, 20000);
this.camOrtho.backgroundHandle = [{n: false, a: 'x'}, {n: false, a: 'y'}]
this.camOrtho.axis = null
this.camOrtho.zoom = 0.4
this.camOrtho.zoom = 0.5
this.camPers.preview = this.camOrtho.preview = this;
for (var i = 4; i <= 6; i++) {
this.camPers.layers.enable(i);
@ -78,7 +148,8 @@ class Preview {
}
}
this.resetCamera(true)
this.camPers.position.fromArray(DefaultCameraPresets[0].position)
this.controls.target.fromArray(DefaultCameraPresets[0].target);
//Keybinds
this.controls.mouseButtons.ZOOM = undefined;
@ -155,11 +226,8 @@ class Preview {
var canvas_offset = $(this.canvas).offset()
this.mouse.x = ((event.clientX - canvas_offset.left) / this.width) * 2 - 1;
this.mouse.y = - ((event.clientY - canvas_offset.top) / this.height) * 2 + 1;
if (this.isOrtho === true) {
this.raycaster.setFromCamera( this.mouse, this.camOrtho );
} else {
this.raycaster.setFromCamera( this.mouse, this.camPers );
}
this.raycaster.setFromCamera( this.mouse, this.camera );
var objects = []
scene.traverse(function(s) {
if (s.isElement === true) {
@ -215,104 +283,164 @@ class Preview {
display_mode
? display_scene
: scene,
this.isOrtho
? this.camOrtho
: this.camPers
this.camera
)
}
//Camera
get camera() {
return this.isOrtho ? this.camOrtho : this.camPers;
}
setNormalCamera() {
this.isOrtho = false;
this.camOrtho.axis = null
setProjectionMode(ortho) {
let position = this.camera.position;
this.isOrtho = !!ortho;
this.resize()
this.controls.object = this.camPers;
if (Transformer.camera == this.camOrtho) {
Transformer.camera = this.camPers;
this.controls.object = this.camera;
this.camera.position.copy(position);
if (this.isOrtho) {
this.camera.zoom = 0.5;
this.camOrtho.updateProjectionMatrix()
}
if (Transformer && Transformer.camera !== this.camera) {
Transformer.camera = this.camera;
Transformer.update();
}
this.controls.enableRotate = true;
this.setLockedAngle()
this.controls.updateSceneScale();
this.loadBackground()
return this;
}
setOrthographicCamera(angle) {
this.isOrtho = true;
this.angle = angle
this.controls.object = this.camOrtho;
if (Transformer.camera == this.camPers) {
Transformer.camera = this.camOrtho;
}
this.controls.enableRotate = false;
this.controls.target.set(0, 0, 0);
setNormalCamera() {
//Deprecated
this.setProjectionMode(false)
return this;
}
setLockedAngle(angle) {
if (typeof angle === 'number' && this.isOrtho) {
//Angle
//if (angle === undefined) return;
var dist = 64
switch (angle) {
case 0:
this.camOrtho.axis = 'y'
this.camOrtho.position.set(0,dist,0)
this.camOrtho.backgroundHandle = [{n: false, a: 'x'}, {n: false, a: 'z'}]
break;
case 1:
this.camOrtho.axis = 'y'
this.camOrtho.position.set(0,-dist,0)
this.camOrtho.backgroundHandle = [{n: false, a: 'x'}, {n: true, a: 'z'}]
break;
case 2:
this.camOrtho.axis = 'z'
this.camOrtho.position.set(0,0,dist)
this.camOrtho.backgroundHandle = [{n: false, a: 'x'}, {n: true, a: 'y'}]
break;
case 3:
this.camOrtho.axis = 'z'
this.camOrtho.position.set(0,0,-dist)
this.camOrtho.backgroundHandle = [{n: true, a: 'x'}, {n: true, a: 'y'}]
break;
case 4:
this.camOrtho.axis = 'x'
this.camOrtho.position.set(dist,0,0)
this.camOrtho.backgroundHandle = [{n: true, a: 'z'}, {n: true, a: 'y'}]
break;
case 5:
this.camOrtho.axis = 'x'
this.camOrtho.position.set(-dist,0,0)
this.camOrtho.backgroundHandle = [{n: false, a: 'z'}, {n: true, a: 'y'}]
break;
case undefined:
this.camOrtho.axis = null;
angle = 1;
this.camOrtho.position.copy(this.camPers.position);
this.controls.enableRotate = true;
break;
}
this.loadBackground();
this.angle = angle
this.controls.enableRotate = false;
var layer = getAxisNumber(this.camOrtho.axis)+1;
this.camOrtho.layers.set(0);
this.camOrtho.layers.enable(layer);
for (var i = 1; i <= 3; i++) {
if (i != layer) {
this.camOrtho.layers.enable(i+3);
var dist = 64
switch (angle) {
case 0:
this.camOrtho.axis = 'y'
//this.camOrtho.position.set(0,dist,0)
this.camOrtho.backgroundHandle = [{n: false, a: 'x'}, {n: false, a: 'z'}]
break;
case 1:
this.camOrtho.axis = 'y'
//this.camOrtho.position.set(0,-dist,0)
this.camOrtho.backgroundHandle = [{n: false, a: 'x'}, {n: true, a: 'z'}]
break;
case 2:
this.camOrtho.axis = 'z'
//this.camOrtho.position.set(0,0,dist)
this.camOrtho.backgroundHandle = [{n: false, a: 'x'}, {n: true, a: 'y'}]
break;
case 3:
this.camOrtho.axis = 'z'
//this.camOrtho.position.set(0,0,-dist)
this.camOrtho.backgroundHandle = [{n: true, a: 'x'}, {n: true, a: 'y'}]
break;
case 4:
this.camOrtho.axis = 'x'
//this.camOrtho.position.set(dist,0,0)
this.camOrtho.backgroundHandle = [{n: true, a: 'z'}, {n: true, a: 'y'}]
break;
case 5:
this.camOrtho.axis = 'x'
//this.camOrtho.position.set(-dist,0,0)
this.camOrtho.backgroundHandle = [{n: false, a: 'z'}, {n: true, a: 'y'}]
break;
}
this.loadBackground();
var layer = getAxisNumber(this.camOrtho.axis)+1;
this.camOrtho.layers.set(0);
this.camOrtho.layers.enable(layer);
for (var i = 1; i <= 3; i++) {
if (i != layer) {
this.camOrtho.layers.enable(i+3);
}
}
} else {
this.angle = null;
this.camOrtho.axis = null
this.camOrtho.layers.set(0);
this.camOrtho.layers.enable(4);
this.camOrtho.layers.enable(5);
this.camOrtho.layers.enable(6);
this.resize()
this.controls.enableRotate = true;
this.loadBackground()
}
Transformer.update();
this.resize()
this.controls.updateSceneScale();
this.loadBackground()
return this;
}
resetCamera(init) {
var dis = 40;
this.controls.target.set(0, 8+scene.position.y, 0);
this.camPers.position.set(-dis, dis*0.8, -dis)
if (!init) {
this.setNormalCamera()
loadAnglePreset(preset) {
if (!preset) return;
this.camera.position.fromArray(preset.position);
this.controls.target.fromArray(preset.target);
if (preset.projection !== 'unset') {
this.setProjectionMode(preset.projection == 'orthographic')
}
if (this.isOrtho && preset.zoom) {
this.camera.zoom = preset.zoom;
this.camera.updateProjectionMatrix()
}
if (!this.isOrtho) {
this.camera.setFocalLength(preset.focal_length||45);
}
this.setLockedAngle(preset.locked_angle)
return this;
}
newAnglePreset() {
let scope = this;
let dialog = new Dialog({
id: 'save_angle',
title: 'menu.preview.save_angle',
width: 540,
form: {
name: {label: 'generic.name'},
projection: {label: 'dialog.save_angle.projection', type: 'select', default: 'unset', options: {
unset: 'generic.unset',
perspective: 'dialog.save_angle.projection.perspective',
orthographic: 'dialog.save_angle.projection.orthographic'
}}
},
onConfirm: function(formResult) {
if (!formResult.name) return;
let preset = {
name: formResult.name,
projection: formResult.projection,
position: scope.camera.position.toArray(),
target: scope.controls.target.toArray(),
}
if (this.isOrtho) preset.zoom = this.camOrtho.zoom;
let presets = localStorage.getItem('camera_presets');
try {
presets = JSON.parse(presets)||[]
} catch (err) {
presets = [];
}
presets.push(preset);
localStorage.setItem('camera_presets', JSON.stringify(presets))
dialog.hide()
}
})
dialog.show()
return this;
}
//Orientation
getFacingDirection() {
var vec = new THREE.Vector3()
this.controls.object.getWorldDirection(vec)
@ -389,7 +517,7 @@ class Preview {
Toolbox.selected.onCanvasClick(0)
}
if (this.isOrtho && this.camOrtho.axis || this.movingBackground) {
if (this.angle !== null && this.camOrtho.axis || this.movingBackground) {
this.startSelRect(event)
} else {
return false;
@ -546,7 +674,7 @@ class Preview {
cube.selectLow()
}
})
updateSelection()
TickUpdates.selection = true;
}
stopSelRect(event) {
var scope = this;
@ -578,7 +706,7 @@ class Preview {
} else {
this.background = canvas_scenes.normal
}
} else if (this.isOrtho) {
} else if (this.angle !== null) {
this.background = canvas_scenes['ortho'+this.angle]
} else {
this.background = canvas_scenes.normal
@ -600,10 +728,10 @@ class Preview {
updateBackground() {
if (!this.background) return;
var bg = this.background
var zoom = (this.isOrtho === true && bg.lock === true) ? this.camOrtho.zoom : 1
var zoom = (this.angle !== null && bg.lock === true) ? this.camOrtho.zoom : 1
var pos_x = 0;
var pos_y = 0;
if (this.isOrtho === true && bg.lock !== false) {
if (this.angle !== null && bg.lock !== false) {
pos_x = this.camOrtho.backgroundHandle[0].n === true ? 1 : -1
pos_x *= this.controls.target[this.camOrtho.backgroundHandle[0].a] * zoom * 40
pos_y = this.camOrtho.backgroundHandle[1].n === true ? 1 : -1
@ -748,14 +876,12 @@ class Preview {
}
}
Preview.prototype.menu = new Menu([
{icon: 'photo_camera', name: 'menu.preview.screenshot', click: function(preview) {
preview.screenshot()
}},
'screenshot_model',
{icon: 'icon-player', name: 'settings.display_skin', condition: () => (display_mode && displayReferenceObjects.active.id === 'player'), click: function() {
changeDisplaySkin()
}},
'toggle_checkerboard',
{icon: 'wallpaper', name: 'menu.preview.background', children: function(preview) {
'preview_checkerboard',
{icon: 'wallpaper', name: 'menu.preview.background', children(preview) {
var has_background = !!preview.background.image
return [
{icon: 'folder', name: 'menu.preview.background.load', click: function(preview) {
@ -785,38 +911,60 @@ class Preview {
}},
{
name: 'menu.preview.background.lock',
condition: (has_background && preview.background.lock !== null && preview.isOrtho),
condition: (has_background && preview.background.lock !== null && preview.angle !== null),
icon: preview.background.lock?'check_box':'check_box_outline_blank',
click: function(preview) {
preview.background.lock = !preview.background.lock
preview.updateBackground()
}},
{icon: 'clear', name: 'menu.preview.background.remove', condition: has_background, click: function(preview) {
{icon: 'clear', name: 'generic.remove', condition: has_background, click: function(preview) {
preview.clearBackground()
}}
]
}},
{icon: 'videocam', name: 'menu.preview.perspective', condition: function(preview) {return !preview.movingBackground && !Modes.display}, children: function(preview) {
function getBtn(angle, pers) {
var condition = (pers && !preview.isOrtho)
|| (!pers && angle === preview.angle && preview.isOrtho);
return condition ? 'radio_button_checked' : 'radio_button_unchecked'
}
return [
{icon: getBtn(0, true), name: 'menu.preview.perspective.normal', click: function(preview) {preview.setNormalCamera()}},
'camera_reset',
{icon: getBtn(0), name: 'direction.top', color: 'y', click: function(preview) {preview.setOrthographicCamera(0)}},
{icon: getBtn(1), name: 'direction.bottom', color: 'y', click: function(preview) {preview.setOrthographicCamera(1)}},
{icon: getBtn(2), name: 'direction.south', color: 'z', click: function(preview) {preview.setOrthographicCamera(2)}},
{icon: getBtn(3), name: 'direction.north', color: 'z', click: function(preview) {preview.setOrthographicCamera(3)}},
{icon: getBtn(4), name: 'direction.east', color: 'x', click: function(preview) {preview.setOrthographicCamera(4)}},
{icon: getBtn(5), name: 'direction.west', color: 'x', click: function(preview) {preview.setOrthographicCamera(5)}}
]
'_',
{icon: 'add_a_photo', name: 'menu.preview.save_angle', condition(preview) {return !preview.movingBackground && !Modes.display}, click(preview) {
preview.newAnglePreset()
}},
{icon: 'videocam', name: 'menu.preview.angle', condition(preview) {return !preview.movingBackground && !Modes.display}, children: function(preview) {
var children = [
]
let presets = localStorage.getItem('camera_presets')
presets = (presets && JSON.parse(presets)) || [];
let all_presets = [...DefaultCameraPresets, ...presets];
all_presets.forEach(preset => {
let icon = typeof preset.locked_angle !== 'number' ? 'videocam' : (preset.locked_angle == preview.angle ? 'radio_button_checked' : 'radio_button_unchecked');
children.push({
name: preset.name,
color: preset.color,
id: preset.name,
icon,
click: preset.default ? () => {
preview.loadAnglePreset(preset)
} : null,
children: !preset.default && [
{icon: 'check_circle', name: 'menu.preview.angle.load', click() {
preview.loadAnglePreset(preset)
}},
{icon: 'delete', name: 'generic.delete', click() {
presets.remove(preset)
localStorage.setItem('camera_presets', JSON.stringify(presets))
}}
]
})
})
return children;
}},
{icon: (preview) => (preview.isOrtho ? 'check_box' : 'check_box_outline_blank'), name: 'menu.preview.orthographic', click: function(preview) {
preview.setProjectionMode(!preview.isOrtho);
}},
'_',
{icon: 'widgets', name: 'menu.preview.quadview', condition: function(preview) {return !quad_previews.enabled && !preview.movingBackground && !Modes.display && !Animator.open}, click: function() {
openQuadView()
}},
{icon: 'web_asset', name: 'menu.preview.fullview', condition: function(preview) {return quad_previews.enabled && !preview.movingBackground && !Modes.display}, click: function(preview) {
{icon: 'web_asset', name: 'menu.preview.maximize', condition: function(preview) {return quad_previews.enabled && !preview.movingBackground && !Modes.display}, click: function(preview) {
preview.fullscreen()
}},
{icon: 'cancel', color: 'x', name: 'menu.preview.stop_drag', condition: function(preview) {return preview.movingBackground;}, click: function(preview) {
@ -853,14 +1001,18 @@ const Screencam = {
recording_timelapse: false,
fullScreen(options, cb) {
setTimeout(function() {
currentwindow.capturePage(function(screenshot) {
currentwindow.capturePage().then(function(screenshot) {
var dataUrl = screenshot.toDataURL()
if (!(options && options.width && options.height)) {
Screencam.returnScreenshot(dataUrl, cb)
return;
}
dataUrl = dataUrl.replace('data:image/png;base64,','')
Jimp.read(Buffer.from(dataUrl, 'base64')).then(function(image) {
if (options && options.width && options.height) {
image.contain(options.width, options.height)
}
image.contain(options.width, options.height)
image.getBase64(Jimp.MIME_PNG, function(a, dataUrl){
Screencam.returnScreenshot(dataUrl, cb)
@ -915,47 +1067,35 @@ const Screencam = {
quad_previews.current.screenshot(options, cb)
},
createGif(options, cb) {
if (typeof options !== 'object') {
options = {}
}
/*
var images = [];
var preview = quad_previews.current;
var interval = setInterval(function() {
if (typeof options !== 'object') options = {}
if (!options.length_mode) options.length_mode = 'seconds';
if (!options.length) options.length = 1;
var shot = preview.canvas.toDataURL()
images.push(shot);
if (images.length >= options.length/1000*options.fps) {
clearInterval(interval);
gifshot.createGIF({
images,
frameDuration: 10/options.fps,
progressCallback: cl,
text: 'BLOCKBENCH'
}, obj => {
Screencam.returnScreenshot(obj.image, cb);
})
}
}, 1000/options.fps)
//Does not support transparency
*/
if (!options.length) {
options.length = 1000;
}
var preview = quad_previews.current;
var animation = Animator.selected;
var interval = options.fps ? (1000/options.fps) : 100;
var gif = new GIF({
var frames = 0;
const gif = new GIF({
repeat: options.repeat,
quality: options.quality,
transparent: 0x000000,
background: {r: 30, g: 0, b: 255},
transparent: 0x1e01ff,
});
var frame_count = (options.length/interval);
if (options.turnspeed) {
preview.controls.autoRotate = true;
preview.controls.autoRotateSpeed = options.turnspeed;
preview.controls.autoRotateProgress = 0;
} else if (options.length_mode == 'turntable') {
options.length_mode = 'seconds'
}
if (options.play && animation) {
Timeline.time = 0;
Timeline.start()
if (!animation.length) options.length_mode = 'seconds';
} else if (options.length_mode == 'animation') {
options.length_mode = 'seconds'
}
if (!options.silent) {
@ -963,9 +1103,21 @@ const Screencam = {
gif.on('progress', Blockbench.setProgress);
}
var frames = 0;
function getProgress() {
switch (options.length_mode) {
case 'seconds': return interval*frames/(options.length*1000); break;
case 'frames': return frames/options.length; break;
case 'turntable': return Math.abs(preview.controls.autoRotateProgress) / (2*Math.PI); break;
case 'animation': return Timeline.time / (animation.length-(interval/1000)); break;
}
}
var loop = setInterval(() => {
frames++;
if (getProgress() >= 1) {
endRecording()
return;
}
Canvas.withoutGizmos(function() {
var img = new Image();
preview.render();
@ -974,10 +1126,12 @@ const Screencam = {
gif.addFrame(img, {delay: interval});
}
})
Blockbench.setProgress(interval*frames/options.length);
Blockbench.setProgress(getProgress());
}, interval)
var endTimer = setTimeout(() => {
function endRecording() {
gif.render();
clearInterval(loop)
if (!options.silent) {
@ -989,7 +1143,7 @@ const Screencam = {
if (options.turnspeed) {
preview.controls.autoRotate = false;
}
}, options.length)
}
gif.on('finished', blob => {
var reader = new FileReader();
@ -1202,10 +1356,10 @@ function initCanvas() {
setShading()
quad_previews = {
one: new Preview({id: 'one'}).setOrthographicCamera(0),
one: new Preview({id: 'one'}).loadAnglePreset(DefaultCameraPresets[1]),
two: main_preview,
three: new Preview({id: 'three'}).setOrthographicCamera(2),
four: new Preview({id: 'four'}).setOrthographicCamera(4),
three: new Preview({id: 'three'}).loadAnglePreset(DefaultCameraPresets[3]),
four: new Preview({id: 'four'}).loadAnglePreset(DefaultCameraPresets[5]),
current: main_preview
}
@ -1260,6 +1414,7 @@ function initCanvas() {
rot_origin.rotation.reorder('ZYX')
rot_origin.base_scale = new THREE.Vector3(1, 1, 1);
rot_origin.no_export = true;
setupGrid = true;
@ -1441,10 +1596,10 @@ function buildGrid() {
});
scene.add(Canvas.side_grids.z)
Canvas.side_grids.z.name = 'side_grid_y'
Canvas.side_grids.z.name = 'side_grid_z'
Canvas.side_grids.z.visible = !Modes.display;
Canvas.side_grids.z.rotation.z = Math.PI/2;
Canvas.side_grids.z.rotation.y = 1.6
Canvas.side_grids.z.rotation.y = Math.PI/2
Canvas.side_grids.z.position.y = Format.centered_grid ? 8 : 0;
Canvas.side_grids.z.children.forEach(el => {
el.layers.set(3)
@ -1466,17 +1621,32 @@ BARS.defineActions(function() {
Blockbench.showQuickMessage('message.wireframe.' + (Prop.wireframe ? 'enabled' : 'disabled'))
}
})
new Action('toggle_checkerboard', {
icon: 'fa-chess-board',
new Action('preview_checkerboard', {
name: tl('settings.preview_checkerboard'),
description: tl('settings.preview_checkerboard.desc'),
category: 'view',
linked_setting: 'preview_checkerboard',
keybind: new Keybind({key: 84}),
click: function () {
if (Prop.active_panel == 'uv') {
var val = $('#uv_viewport').toggleClass('checkerboard').hasClass('checkerboard');
} else {
var val = $('#center').toggleClass('checkerboard').hasClass('checkerboard');
}
Blockbench.showQuickMessage('message.checkerboard.' + (val ? 'enabled' : 'disabled'))
this.toggleLinkedSetting()
}
})
new Action('uv_checkerboard', {
name: tl('settings.uv_checkerboard'),
description: tl('settings.uv_checkerboard.desc'),
category: 'view',
linked_setting: 'uv_checkerboard',
click: function () {
this.toggleLinkedSetting()
}
})
new Action('toggle_shading', {
name: tl('settings.shading'),
description: tl('settings.shading.desc'),
category: 'view',
linked_setting: 'shading',
click: function () {
this.toggleLinkedSetting()
}
})
@ -1495,6 +1665,12 @@ BARS.defineActions(function() {
title: tl('dialog.create_gif.title'),
draggable: true,
form: {
length_mode: {label: 'dialog.create_gif.length_mode', type: 'select', default: 'seconds', options: {
seconds: 'dialog.create_gif.length_mode.seconds',
frames: 'dialog.create_gif.length_mode.frames',
animation: 'dialog.create_gif.length_mode.animation',
turntable: 'dialog.create_gif.length_mode.turntable',
}},
length: {label: 'dialog.create_gif.length', type: 'number', value: 10, step: 0.25},
fps: {label: 'dialog.create_gif.fps', type: 'number', value: 10},
quality:{label: 'dialog.create_gif.compression', type: 'number', value: 20, min: 1, max: 80},
@ -1502,13 +1678,12 @@ BARS.defineActions(function() {
play: {label: 'dialog.create_gif.play', type: 'checkbox', condition: Animator.open},
},
onConfirm: function(formData) {
if (formData.play) {
Timeline.start()
}
Screencam.createGif({
length: limitNumber(formData.length, 0.1, 240)*1000,
length_mode: formData.length_mode,
length: limitNumber(formData.length, 0.1, 24000),
fps: limitNumber(formData.fps, 0.5, 30),
quality: limitNumber(formData.quality, 0, 30),
play: formData.play,
turnspeed: formData.turn,
}, Screencam.returnScreenshot)
this.hide()
@ -1560,98 +1735,98 @@ BARS.defineActions(function() {
main_preview.toggleFullscreen()
}
})
new Action('camera_reset', {
name: 'menu.preview.perspective.reset',
description: 'menu.preview.perspective.reset',
icon: 'videocam',
new Action('toggle_camera_projection', {
icon: 'switch_video',
category: 'view',
keybind: new Keybind({key: 96}),
click: function () {
quad_previews.current.resetCamera()
}
})
new Action('camera_normal', {
name: 'menu.preview.perspective.normal',
description: 'menu.preview.perspective.normal',
icon: 'videocam',
category: 'view',
condition: _ => !Modes.display,
condition: _ => (!preview.movingBackground || !Modes.display),
keybind: new Keybind({key: 101}),
click: function () {
quad_previews.current.setNormalCamera()
quad_previews.current.setProjectionMode(!quad_previews.current.isOrtho);
}
})
new Action('camera_initial', {
name: tl('action.load_camera_angle', tl('menu.preview.angle.initial')),
description: tl('action.load_camera_angle.desc', tl('menu.preview.angle.initial')),
icon: 'videocam',
color: 'y',
category: 'view',
condition: _ => !Modes.display,
keybind: new Keybind({key: 97}),
click: function () {
quad_previews.current.loadAnglePreset(DefaultCameraPresets[0])
}
})
new Action('camera_top', {
name: 'direction.top',
description: 'direction.top',
name: tl('action.load_camera_angle', tl('direction.top')),
description: tl('action.load_camera_angle.desc', tl('direction.top')),
icon: 'videocam',
color: 'y',
category: 'view',
condition: _ => !Modes.display,
keybind: new Keybind({key: 104}),
click: function () {
quad_previews.current.setOrthographicCamera(0)
quad_previews.current.loadAnglePreset(DefaultCameraPresets[1])
}
})
new Action('camera_bottom', {
name: 'direction.bottom',
description: 'direction.bottom',
name: tl('action.load_camera_angle', tl('direction.bottom')),
description: tl('action.load_camera_angle.desc', tl('direction.bottom')),
icon: 'videocam',
color: 'y',
category: 'view',
condition: _ => !Modes.display,
keybind: new Keybind({key: 98}),
click: function () {
quad_previews.current.setOrthographicCamera(1)
quad_previews.current.loadAnglePreset(DefaultCameraPresets[2])
}
})
new Action('camera_south', {
name: 'direction.south',
description: 'direction.south',
name: tl('action.load_camera_angle', tl('direction.south')),
description: tl('action.load_camera_angle.desc', tl('direction.south')),
icon: 'videocam',
color: 'z',
category: 'view',
condition: _ => !Modes.display,
keybind: new Keybind({key: 100}),
click: function () {
quad_previews.current.setOrthographicCamera(2)
quad_previews.current.loadAnglePreset(DefaultCameraPresets[3])
}
})
new Action('camera_north', {
name: 'direction.north',
description: 'direction.north',
name: tl('action.load_camera_angle', tl('direction.north')),
description: tl('action.load_camera_angle.desc', tl('direction.north')),
icon: 'videocam',
color: 'z',
category: 'view',
condition: _ => !Modes.display,
keybind: new Keybind({key: 102}),
click: function () {
quad_previews.current.setOrthographicCamera(3)
quad_previews.current.loadAnglePreset(DefaultCameraPresets[4])
}
})
new Action('camera_east', {
name: 'direction.east',
description: 'direction.east',
name: tl('action.load_camera_angle', tl('direction.east')),
description: tl('action.load_camera_angle.desc', tl('direction.east')),
icon: 'videocam',
color: 'x',
category: 'view',
condition: _ => !Modes.display,
keybind: new Keybind({key: 103}),
click: function () {
quad_previews.current.setOrthographicCamera(4)
quad_previews.current.loadAnglePreset(DefaultCameraPresets[5])
}
})
new Action('camera_west', {
name: 'direction.west',
description: 'direction.west',
name: tl('action.load_camera_angle', tl('direction.west')),
description: tl('action.load_camera_angle.desc', tl('direction.west')),
icon: 'videocam',
color: 'x',
category: 'view',
condition: _ => !Modes.display,
keybind: new Keybind({key: 105}),
click: function () {
quad_previews.current.setOrthographicCamera(5)
quad_previews.current.loadAnglePreset(DefaultCameraPresets[6])
}
})
})

View File

@ -161,7 +161,7 @@
child.updateMatrix();
var tempGeometry = child.geometry.clone();
tempGeometry.applyMatrix( child.matrix );
tempGeometry.applyMatrix4( child.matrix );
child.geometry = tempGeometry;
child.position.set( 0, 0, 0 );
@ -235,15 +235,15 @@
arrowGeometry.merge( mesh.geometry, mesh.matrix );
var lineXGeometry = new THREE.BufferGeometry();
lineXGeometry.addAttribute( 'position', new THREE.Float32BufferAttribute( [ 0, 0, 0, 1, 0, 0 ], 3 ) );
lineXGeometry.setAttribute( 'position', new THREE.Float32BufferAttribute( [ 0, 0, 0, 1, 0, 0 ], 3 ) );
lineXGeometry.name = 'gizmo_x'
var lineYGeometry = new THREE.BufferGeometry();
lineYGeometry.addAttribute( 'position', new THREE.Float32BufferAttribute( [ 0, 0, 0, 0, 1, 0 ], 3 ) );
lineYGeometry.setAttribute( 'position', new THREE.Float32BufferAttribute( [ 0, 0, 0, 0, 1, 0 ], 3 ) );
lineYGeometry.name = 'gizmo_y'
var lineZGeometry = new THREE.BufferGeometry();
lineZGeometry.addAttribute( 'position', new THREE.Float32BufferAttribute( [ 0, 0, 0, 0, 0, 1 ], 3 ) );
lineZGeometry.setAttribute( 'position', new THREE.Float32BufferAttribute( [ 0, 0, 0, 0, 0, 1 ], 3 ) );
lineZGeometry.name = 'gizmo_z'
this.handleGizmos = {
@ -311,13 +311,13 @@
arrowGeometry.merge( mesh.geometry, mesh.matrix );
var lineXGeometry = new THREE.BufferGeometry();
lineXGeometry.addAttribute( 'position', new THREE.Float32BufferAttribute( [ 0, 0, 0, 1, 0, 0 ], 3 ) );
lineXGeometry.setAttribute( 'position', new THREE.Float32BufferAttribute( [ 0, 0, 0, 1, 0, 0 ], 3 ) );
var lineYGeometry = new THREE.BufferGeometry();
lineYGeometry.addAttribute( 'position', new THREE.Float32BufferAttribute( [ 0, 0, 0, 0, 1, 0 ], 3 ) );
lineYGeometry.setAttribute( 'position', new THREE.Float32BufferAttribute( [ 0, 0, 0, 0, 1, 0 ], 3 ) );
var lineZGeometry = new THREE.BufferGeometry();
lineZGeometry.addAttribute( 'position', new THREE.Float32BufferAttribute( [ 0, 0, 0, 0, 0, 1 ], 3 ) );
lineZGeometry.setAttribute( 'position', new THREE.Float32BufferAttribute( [ 0, 0, 0, 0, 0, 1 ], 3 ) );
this.handleGizmos = {
X: [
@ -411,7 +411,7 @@
}
geometry.addAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) );
geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) );
return geometry;
};
@ -834,6 +834,50 @@
display_gui_rotation.rotation.set(0.2, 0.2, 0);
display_gui_rotation.updateMatrixWorld();
this.getTransformSpace = function() {
if (!selected.length) return;
let input_space = BarItems.transform_space.get()
if (input_space == 'local' && selected[0].rotatable && Toolbox.selected.id !== 'pivot_tool') {
let is_local = true;
if (Format.bone_rig) {
for (var el of selected) {
if (el.parent !== selected[0].parent) {
is_local = false;
break;
}
}
}
if (is_local) {
for (var el of selected) {
if (el.rotation !== selected[0].rotation &&
!(el.rotation instanceof Array && el.rotation.equals(selected[0].rotation))
) {
is_local = false;
break;
}
}
}
if (is_local) return 2;
}
if (input_space !== 'global' && Format.bone_rig) {
// Bone Space
if (Format.bone_rig && Group.selected && Group.selected.parent instanceof Group && Group.selected.matchesSelection()) {
return Group.selected.parent;
}
let bone = selected[0].parent;
for (var el of selected) {
if (el.parent !== bone) {
bone = 0;
break;
}
}
return bone;
}
return 0;
}
this.center = function() {
delete Transformer.rotation_ref;
if (Modes.edit || Toolbox.selected.id == 'pivot_tool') {
@ -867,11 +911,22 @@
Transformer.position.fromArray(center)
}
let space = Transformer.getTransformSpace();
//Rotation
if (rotation_tool) {
if (Toolbox.selected.id === 'rotate_tool') {
Transformer.rotation_ref = rotation_object.mesh.parent;
} else if (Group.selected && !Blockbench.globalMovement) {
} else if (space === 2 || Toolbox.selected.id == 'resize_tool') {
Transformer.rotation_ref = selected[0].mesh;
} else if (space instanceof Group) {
Transformer.rotation_ref = space.mesh;
}
/* else if (Group.selected && !Blockbench.globalMovement) {
Transformer.rotation_ref = rotation_object.mesh;
} else if (Group.selected && Blockbench.globalMovement && Group.selected.parent && Format.bone_rig) {
@ -882,7 +937,7 @@
} else if (!Blockbench.globalMovement && Locator.selected[0]) {
Transformer.rotation_ref = Locator.selected[0].parent.mesh;
}
}*/
}
} else if (Modes.display) {
@ -936,7 +991,7 @@
}
line.scale[axis] = long ? 20000 : 1;
if (Toolbox.selected.transformerMode !== 'rotate') {
line.position[axis] = long ? -10000 : (scope.direction?0:-1);
line.position[axis] = long ? -10000 : ((scope.direction || Toolbox.selected.transformerMode !== 'scale')?0:-1);
} else {
line.base_scale[axis] = long ? 20000 : 1;
}
@ -1193,6 +1248,7 @@
]
var angle = Math.radToDeg( rotations[axisNumber] )
}
let transform_space = Transformer.getTransformSpace()
if (Modes.edit || Toolbox.selected.id == 'pivot_tool') {
@ -1201,6 +1257,7 @@
var snap_factor = canvasGridSize(event.shiftKey, event.ctrlOrCmd)
point[axis] = Math.round( point[axis] / snap_factor ) * snap_factor;
if (originalValue === null) {
originalValue = point[axis];
}
@ -1226,17 +1283,23 @@
})
}
if (!overlapping) {
displayDistance(point[axis] - originalValue);
moveElementsInSpace(difference, axisNumber)
/*
if (_has_groups && Blockbench.globalMovement) {
Group.selected.forEachChild(g => {
g.origin[axisNumber] += difference
}, Group, true)
}
displayDistance(point[axis] - originalValue);
selected.forEach(function(obj, i) {
if (obj.movable) {
obj.move(difference, axisNumber, _has_groups||!Format.bone_rig)
}
})
*/
scope.updateSelection()
}
previousValue = point[axis]
@ -1308,7 +1371,21 @@
}
} else {
var origin = Transformer.rotation_object.origin.slice()
origin[axisNumber] += difference;
if (transform_space == 0) {
let vec = new THREE.Vector3();
vec[axis] = difference;
var rotation = new THREE.Quaternion();
Transformer.rotation_object.mesh.parent.getWorldQuaternion(rotation);
vec.applyQuaternion(rotation.inverse());
origin.V3_add(vec.x, vec.y, vec.z);
} else {
origin[axisNumber] += difference;
}
selected.forEach(obj => {
if (obj.transferOrigin) {
obj.transferOrigin(origin);

View File

@ -38,7 +38,275 @@ onVueSetup(() => {
'#0955a8',
'#126bc3',
'#1782db',
'#339afc'
'#339afc',
'#cd3e00',
'#e65b00',
'#f37800',
'#f89520',
'#fdaf40',
'#02a8c1',
'#0cc3ca',
'#17d1c7',
'#38debd',
'#5be9b7',
],
material: [
'#FFEBEE',
'#FFCDD2',
'#EF9A9A',
'#E57373',
'#EF5350',
'#F44336',
'#E53935',
'#D32F2F',
'#C62828',
'#B71C1C',
'#FCE4EC',
'#F8BBD0',
'#F48FB1',
'#F06292',
'#EC407A',
'#E91E63',
'#D81B60',
'#C2185B',
'#AD1457',
'#880E4F',
'#F3E5F5',
'#E1BEE7',
'#CE93D8',
'#BA68C8',
'#AB47BC',
'#9C27B0',
'#8E24AA',
'#7B1FA2',
'#6A1B9A',
'#4A148C',
'#EDE7F6',
'#D1C4E9',
'#B39DDB',
'#9575CD',
'#7E57C2',
'#673AB7',
'#5E35B1',
'#512DA8',
'#4527A0',
'#311B92',
'#E8EAF6',
'#C5CAE9',
'#9FA8DA',
'#7986CB',
'#5C6BC0',
'#3F51B5',
'#3949AB',
'#303F9F',
'#283593',
'#1A237E',
'#E3F2FD',
'#BBDEFB',
'#90CAF9',
'#64B5F6',
'#42A5F5',
'#2196F3',
'#1E88E5',
'#1976D2',
'#1565C0',
'#0D47A1',
'#E1F5FE',
'#B3E5FC',
'#81D4FA',
'#4FC3F7',
'#29B6F6',
'#03A9F4',
'#039BE5',
'#0288D1',
'#0277BD',
'#01579B',
'#E0F7FA',
'#B2EBF2',
'#80DEEA',
'#4DD0E1',
'#26C6DA',
'#00BCD4',
'#00ACC1',
'#0097A7',
'#00838F',
'#006064',
'#E0F2F1',
'#B2DFDB',
'#80CBC4',
'#4DB6AC',
'#26A69A',
'#009688',
'#00897B',
'#00796B',
'#00695C',
'#004D40',
'#E8F5E9',
'#C8E6C9',
'#A5D6A7',
'#81C784',
'#66BB6A',
'#4CAF50',
'#43A047',
'#388E3C',
'#2E7D32',
'#1B5E20',
'#F1F8E9',
'#DCEDC8',
'#C5E1A5',
'#AED581',
'#9CCC65',
'#8BC34A',
'#7CB342',
'#689F38',
'#558B2F',
'#33691E',
'#F9FBE7',
'#F0F4C3',
'#E6EE9C',
'#DCE775',
'#D4E157',
'#CDDC39',
'#C0CA33',
'#AFB42B',
'#9E9D24',
'#827717',
'#FFFDE7',
'#FFF9C4',
'#FFF59D',
'#FFF176',
'#FFEE58',
'#FFEB3B',
'#FDD835',
'#FBC02D',
'#F9A825',
'#F57F17',
'#FFF8E1',
'#FFECB3',
'#FFE082',
'#FFD54F',
'#FFCA28',
'#FFC107',
'#FFB300',
'#FFA000',
'#FF8F00',
'#FF6F00',
'#FFF3E0',
'#FFE0B2',
'#FFCC80',
'#FFB74D',
'#FFA726',
'#FF9800',
'#FB8C00',
'#F57C00',
'#EF6C00',
'#E65100',
'#FBE9E7',
'#FFCCBC',
'#FFAB91',
'#FF8A65',
'#FF7043',
'#FF5722',
'#F4511E',
'#E64A19',
'#D84315',
'#BF360C',
'#EFEBE9',
'#D7CCC8',
'#BCAAA4',
'#A1887F',
'#8D6E63',
'#795548',
'#6D4C41',
'#5D4037',
'#4E342E',
'#3E2723',
'#FAFAFA',
'#F5F5F5',
'#EEEEEE',
'#E0E0E0',
'#BDBDBD',
'#9E9E9E',
'#757575',
'#616161',
'#424242',
'#212121',
'#ECEFF1',
'#CFD8DC',
'#B0BEC5',
'#90A4AE',
'#78909C',
'#607D8B',
'#546E7A',
'#455A64',
'#37474F',
'#263238',
],
endesga64: [
'#ff0040',
'#131313',
'#1b1b1b',
'#272727',
'#3d3d3d',
'#5d5d5d',
'#858585',
'#b4b4b4',
'#ffffff',
'#c7cfdd',
'#92a1b9',
'#657392',
'#424c6e',
'#2a2f4e',
'#1a1932',
'#0e071b',
'#1c121c',
'#391f21',
'#5d2c28',
'#8a4836',
'#bf6f4a',
'#e69c69',
'#f6ca9f',
'#f9e6cf',
'#edab50',
'#e07438',
'#c64524',
'#8e251d',
'#ff5000',
'#ed7614',
'#ffa214',
'#ffc825',
'#ffeb57',
'#d3fc7e',
'#99e65f',
'#5ac54f',
'#33984b',
'#1e6f50',
'#134c4c',
'#0c2e44',
'#00396d',
'#0069aa',
'#0098dc',
'#00cdf9',
'#0cf1ff',
'#94fdff',
'#fdd2ed',
'#f389f5',
'#db3ffd',
'#7a09fa',
'#3003d9',
'#0c0293',
'#03193f',
'#3b1443',
'#622461',
'#93388f',
'#ca52c9',
'#c85086',
'#f68187',
'#f5555d',
'#ea323c',
'#c42430',
'#891e2b',
'#571c27',
]
}
ColorPanel = Interface.Panels.color = new Panel({
@ -56,9 +324,14 @@ onVueSetup(() => {
'clear_palette',
{name: 'menu.palette.load', id: 'load', icon: 'fa-tasks', children: [
{name: 'menu.palette.load.default', icon: 'bubble_chart', id: 'default', click: () => {
ColorPanel.palette.purge();
ColorPanel.palette.push(...palettes.default);
}}
ColorPanel.palette.splice(0, Infinity, ...palettes.default);
}},
{name: 'Endesga 64', description: 'Pixel art palette created by lospec.com/endesga', icon: 'bubble_chart', id: 'endesga64', click: () => {
ColorPanel.palette.splice(0, Infinity, ...palettes.endesga64);
}},
{name: 'Material', icon: 'bubble_chart', id: 'material', click: () => {
ColorPanel.palette.splice(0, Infinity, ...palettes.material);
}},
]}
])
})
@ -187,7 +460,10 @@ onVueSetup(() => {
ColorPanel.importPalette = function(file) {
if (pathToExtension(file.path) == 'png') {
let extension = pathToExtension(file.path);
if (extension == 'png') {
var img = new Image(file.content);
img.src = file.content || file.path;
img.onload = function() {
@ -196,55 +472,240 @@ onVueSetup(() => {
c.width = img.naturalWidth;
c.height = img.naturalHeight;
ctx.drawImage(img, 0, 0);
ColorPanel.generatePalette(ctx);
ColorPanel.generatePalette(ctx, false);
}
return;
}
var string = file.content;
var colors = [];
var m_hex = string.match(/(#|FF)?[a-fA-F0-9]{6}/g);
if (m_hex) m_hex.forEach(color => {
color = color.substr(-6).toLowerCase();
colors.safePush('#'+color);
})
var m_rgb = string.match(/\(\s*\d{1,3},\s*\d{1,3},\s*\d{1,3}\s*\)/g)
if (m_rgb) m_rgb.forEach(color => {
color = tinycolor('rgb'+color);
colors.safePush(color.toHexString());
})
var m_gpl = string.match(/\n\d{1,3} \d{1,3} \d{1,3}/g)
if (m_gpl) m_gpl.forEach(color => {
color = tinycolor(`rgb(${color.substr(1).replace(/ /g, ',')})`);
colors.safePush(color.toHexString());
})
var m_gpl = string.match(/\n\d{1,3} \d{1,3} \d{1,3}/g)
if (m_gpl) m_gpl.forEach(color => {
color = tinycolor(`rgb(${color.substr(1).replace(/ /g, ',')})`);
colors.safePush(color.toHexString());
})
var dialog = new Dialog({
id: 'palette_import',
title: 'action.import_palette',
width: 400,
form: {
replace: {label: 'message.import_palette.replace_palette', type: 'checkbox', value: true},
},
onConfirm(formData) {
if (formData.replace) {
ColorPanel.palette.purge();
ColorPanel.palette.push(...colors);
} else {
colors.forEach(color => {
ColorPanel.palette.safePush(color);
})
}
dialog.hide();
if (extension === 'ase') {
let colorContents = file.content;
let colorBuffer = Buffer.from(colorContents);
let signature = colorBuffer.toString('utf-8', 0, 4);
let versionMajor = colorBuffer.slice(4, 6).readInt16BE(0);
let versionMin = colorBuffer.slice(6, 8).readInt16BE(0);
let count = colorBuffer.slice(8, 12).readInt32BE(0);
if (colorBuffer.length > 12 && signature !== 'ASEF' && versionMajor !== 1 && versionMin !== 0) {
console.log('Invalid ASE swatch file');
return;
}
let i = 12;
while (i < colorBuffer.length) {
let blockLength;
let blockType = colorBuffer.slice(i, i + 2).readInt16BE(0).toString(16);
i += 2;
// Ignore group start c001, end c002
if (blockType === 'c001') {
blockLength = colorBuffer.slice(i, i + 4).readInt32BE(0);
i += blockLength;
}
if (blockType === 'c002') {
i += 2;
}
// Color entry, start 0001
if (blockType === '1') {
blockLength = colorBuffer.slice(i, i + 4).readInt32BE(0);
let nameLength = colorBuffer.slice(i + 4, i + 6).readUInt16BE(0);
let colorName = '';
let color;
for (let j = 0; j < nameLength * 2 - 2; j += 2) {
colorName += String.fromCodePoint(colorBuffer.slice(i + 6 + j, i + 8 + j).readInt16BE(0));
}
let _i = i + 6 + nameLength * 2;
let colorModel = colorBuffer.slice(_i, _i + 4).toString('utf-8', 0, 4);
_i += 4;
if (colorModel === 'RGB ') {
let r = colorBuffer.slice(_i, _i + 4).readFloatBE(0);
_i += 4;
let g = colorBuffer.slice(_i, _i + 4).readFloatBE(0);
_i += 4;
let b = colorBuffer.slice(_i, _i + 4).readFloatBE(0);
color = new tinycolor({r: r*255, g: g*255, b: b*255})
//nscolor = color.colorWithRGBA(r * 255, g * 255, b * 255, 1.0);
} else if (colorModel === 'CMYK') {
let c = colorBuffer.slice(_i, _i + 4).readFloatBE(0);
_i += 4;
let m = colorBuffer.slice(_i, _i + 4).readFloatBE(0);
_i += 4;
let y = colorBuffer.slice(_i, _i + 4).readFloatBE(0);
_i += 4;
let k = colorBuffer.slice(_i, _i + 4).readFloatBE(0);
//nscolor = color.colorWithCMYKA(c * 100, m * 100, y * 100, k * 100, 1.0);
color = new tinycolor({
r: 255 * (1 - c) * (1 - k),
g: 255 * (1 - m) * (1 - k),
b: 255 * (1 - y) * (1 - k)
})
} else if (colorModel === 'LAB ') {
let l = colorBuffer.slice(_i, _i + 4).readFloatBE(0);
_i += 4;
let a = colorBuffer.slice(_i, _i + 4).readFloatBE(0);
_i += 4;
let b = colorBuffer.slice(_i, _i + 4).readFloatBE(0);
//nscolor = color.colorWithLABA(l * 100, a * 100, b * 100, 1.0);
} else if (colorModel === 'Gray') {
let g = colorBuffer.slice(_i, _i + 4).readFloatBE(0);
color = new tinycolor({r: g*255, g: g*255, b: g*255})
}
colors.push(color.toHexString());
i += blockLength;
}
}
} else if (extension === 'aco') {
let colorContents = file.content;
let colorBuffer = Buffer.from(colorContents);
if (colorBuffer.length < 4) {
UI.message('Invalid ACO file');
return;
}
});
dialog.show();
let version = colorBuffer.slice(0, 2).readUInt16BE(0);
let count = colorBuffer.slice(2, 4).readUInt16BE(0);
// version 1
let i;
if (version === 1 && (colorBuffer.length - 4) / 10 === count) {
i = 4;
while (i < colorBuffer.length) {
let colorSpace = colorBuffer.slice(i, i + 2).readUInt16BE(0);
let r = colorBuffer.slice(i + 2, i + 4).readUInt16BE(0);
let g = colorBuffer.slice(i + 4, i + 6).readUInt16BE(0);
let b = colorBuffer.slice(i + 6, i + 8).readUInt16BE(0);
let z = colorBuffer.slice(i + 8, i + 10).readUInt16BE(0);
if (colorSpace === 0) {
let color = new tinycolor({
r: Math.floor(r/255),
g: Math.floor(g/255),
b: Math.floor(b/255)
})
colors.push(color.toHexString());
}
i += 10;
}
}
// version 2
if (
(version === 2) ||
(
version === 1 &&
colorBuffer.length > count * 10 + 8 &&
colorBuffer.slice(4 + count * 10, 6 + count * 10).readUInt16BE(0) === 2 &&
colorBuffer.slice(6 + count * 10, 8 + count * 10).readUInt16BE(0) === count
)
) {
i = 4 + count * 10 + 4;
if (version === 2) {
i = 4;
}
while (i < colorBuffer.length) {
let colorSpace = colorBuffer.slice(i, i + 2).readUInt16BE(0);
let r = colorBuffer.slice(i + 2, i + 4).readUInt16BE(0);
let g = colorBuffer.slice(i + 4, i + 6).readUInt16BE(0);
let b = colorBuffer.slice(i + 6, i + 8).readUInt16BE(0);
let z = colorBuffer.slice(i + 8, i + 10).readUInt16BE(0);
let colorName = '';
let nameLength = colorBuffer.slice(i + 12, i + 14).readUInt16BE(0);
/*for (let j = 0; j < nameLength * 2 - 2; j += 2) {
colorName += String.fromCodePoint(colorBuffer.slice(i + 14 + j, i + 16 + j).readUInt16BE(0));
}*/
// colorspace: [0: RGB, 1: HSB (hsv), 2: CMYK, 7: Lab, 8: Gray]
if (colorSpace === 0) {
let color = new tinycolor({
r: Math.floor(r/255),
g: Math.floor(g/255),
b: Math.floor(b/255)
})
colors.push(color.toHexString());
}
i += 14 + nameLength * 2;
}
}
} else if (extension === 'act') {
let colorContents = file.content;
let colorBuffer = Buffer.from(colorContents);
let maxLength = Math.min(colorBuffer.length, 768);
if (colorBuffer.length === 772) {
maxLength = colorBuffer[769]*3
}
for (var i = 0; i < maxLength; i += 3) {
let color = new tinycolor({
r: colorBuffer[i+0],
g: colorBuffer[i+1],
b: colorBuffer[i+2]
})
colors.push(color);
}
} else {
var string = file.content;
var m_hex = string.match(/(#|FF)?[a-fA-F0-9]{6}/g);
if (m_hex) m_hex.forEach(color => {
color = color.substr(-6).toLowerCase();
colors.safePush('#'+color);
})
var m_rgb = string.match(/\(\s*\d{1,3},\s*\d{1,3},\s*\d{1,3}\s*\)/g)
if (m_rgb) m_rgb.forEach(color => {
color = tinycolor('rgb'+color);
colors.safePush(color.toHexString());
})
var m_gpl = string.match(/\n\d{1,3} \d{1,3} \d{1,3}/g)
if (m_gpl) m_gpl.forEach(color => {
color = tinycolor(`rgb(${color.substr(1).replace(/ /g, ',')})`);
colors.safePush(color.toHexString());
})
var m_gpl = string.match(/\n\d{1,3} \d{1,3} \d{1,3}/g)
if (m_gpl) m_gpl.forEach(color => {
color = tinycolor(`rgb(${color.substr(1).replace(/ /g, ',')})`);
colors.safePush(color.toHexString());
})
}
if (ColorPanel.palette.length) {
var dialog = new Dialog({
id: 'palette_import',
title: 'action.import_palette',
width: 400,
form: {
replace: {label: 'message.import_palette.replace_palette', type: 'checkbox', value: true},
},
onConfirm(formData) {
if (formData.replace) {
ColorPanel.palette.purge();
ColorPanel.palette.push(...colors);
} else {
colors.forEach(color => {
ColorPanel.palette.safePush(color);
})
}
dialog.hide();
}
});
dialog.show();
} else {
colors.forEach(color => {
ColorPanel.palette.push(color);
})
}
}
ColorPanel.generatePalette = function(source) {
ColorPanel.generatePalette = function(source, process_colors = true) {
var options = {};
if (!source) {
@ -261,7 +722,7 @@ onVueSetup(() => {
form: {
texture: {label: 'data.texture', type: 'select', options, condition: !source},
replace: {label: 'message.import_palette.replace_palette', type: 'checkbox', value: true},
threshold: {label: 'message.import_palette.threshold', type: 'number', value: 10, min: 0, max: 100},
threshold: {label: 'message.import_palette.threshold', type: 'number', value: 10, min: 0, max: 100, condition: process_colors},
},
onConfirm(formData) {
var colors = {};
@ -288,51 +749,54 @@ onVueSetup(() => {
t.count = 1;
}
})
var pots = {gray:[], red:[], orange:[], yellow:[], green:[], blue:[], magenta:[]}
for (var hex in colors) {
var color = colors[hex];
if (Math.abs(color._r - color._g) + Math.abs(color._g - color._b) + Math.abs(color._r - color._b) < 74) {
//gray
pots.gray.push(color);
} else {
var distances = {
red: colorDistance(color, {_r: 250, _g: 0, _b: 0}),
orange: colorDistance(color, {_r: 240, _g: 127, _b: 0})*1.4,
yellow: colorDistance(color, {_r: 265, _g: 240, _b: 0})*1.4,
green: colorDistance(color, {_r: 0, _g: 255, _b: 0}),
blue: colorDistance(color, {_r: 0, _g: 50, _b: 240}),
magenta: colorDistance(color,{_r: 255, _g: 0, _b: 255})*1.4,
if (process_colors) {
var pots = {gray:[], red:[], orange:[], yellow:[], green:[], blue:[], magenta:[]}
for (var hex in colors) {
var color = colors[hex];
if (Math.abs(color._r - color._g) + Math.abs(color._g - color._b) + Math.abs(color._r - color._b) < 74) {
//gray
pots.gray.push(color);
} else {
var distances = {
red: colorDistance(color, {_r: 250, _g: 0, _b: 0}),
orange: colorDistance(color, {_r: 240, _g: 127, _b: 0})*1.4,
yellow: colorDistance(color, {_r: 265, _g: 240, _b: 0})*1.4,
green: colorDistance(color, {_r: 0, _g: 255, _b: 0}),
blue: colorDistance(color, {_r: 0, _g: 50, _b: 240}),
magenta: colorDistance(color,{_r: 255, _g: 0, _b: 255})*1.4,
}
var closest = highestInObject(distances, true);
pots[closest].push(color);
}
var closest = highestInObject(distances, true);
pots[closest].push(color);
}
}
for (var pot in pots) {
pots[pot].sort((a, b) => {
return (a._r + a._g + a._b) - (b._r + b._g + b._b);
})
if (pots[pot].length > 1) {
for (var i = pots[pot].length-2; i >= 0; i--) {
var col = pots[pot][i];
var abv = pots[pot][i+1];
var distance = colorDistance(col, abv);
if (distance < formData.threshold) {
if (col.count < col.count) {
pots[pot].splice(i, 1);
} else {
pots[pot].splice(i+1, 1);
for (var pot in pots) {
pots[pot].sort((a, b) => {
return (a._r + a._g + a._b) - (b._r + b._g + b._b);
})
if (pots[pot].length > 1) {
for (var i = pots[pot].length-2; i >= 0; i--) {
var col = pots[pot][i];
var abv = pots[pot][i+1];
var distance = colorDistance(col, abv);
if (distance < formData.threshold) {
if (col.count < col.count) {
pots[pot].splice(i, 1);
} else {
pots[pot].splice(i+1, 1);
}
}
}
}
pots[pot].forEach(color => {
result_palette.push(color.toHexString());
})
}
} else {
for (var hex in colors) {
result_palette.push(hex);
}
pots[pot].forEach(color => {
result_palette.push(color.toHexString());
})
}
if (formData.replace) {
ColorPanel.palette.purge();
ColorPanel.palette.push(...result_palette);
@ -348,9 +812,16 @@ onVueSetup(() => {
}
Blockbench.addDragHandler('palette', {
extensions: ['bbpalette', 'css', 'txt', 'gpl', 'hex', 'png'],
extensions: ['gpl', 'css', 'txt', 'hex', 'png', 'aco', 'act', 'ase', 'bbpalette'],
readtype: 'text',
readtype: (path) => (pathToExtension(path) == 'png' ? 'image' : 'text'),
readtype: (path) => {
switch (pathToExtension(path)) {
case 'png': return 'image'; break;
case 'ase': return 'binary'; break;
case 'act': return 'binary'; break;
case 'aco': return 'binary'; break;
default: return 'text'; break;
}},
element: '#color',
propagate: true,
}, function(files) {
@ -383,9 +854,16 @@ BARS.defineActions(function() {
category: 'color',
click: function () {
Blockbench.import({
extensions: ['bbpalette', 'css', 'txt', 'gpl', 'hex', 'png'],
extensions: ['gpl', 'css', 'txt', 'hex', 'png', 'aco', 'act', 'ase', 'bbpalette'],
type: 'Blockbench Palette',
readtype: (path) => (pathToExtension(path) == 'png' ? 'image' : 'text'),
readtype: (path) => {
switch (pathToExtension(path)) {
case 'png': return 'image'; break;
case 'ase': return 'binary'; break;
case 'act': return 'binary'; break;
case 'aco': return 'binary'; break;
default: return 'text'; break;
}},
}, function(files) {
if (files && files[0]) {
ColorPanel.importPalette(files[0]);
@ -397,10 +875,15 @@ BARS.defineActions(function() {
icon: 'fas.fa-dice-four',
category: 'color',
click: function () {
let content = 'GIMP Palette\nName: Blockbench palette\nColumns: 10\n';
ColorPanel.palette.forEach(color => {
t = new tinycolor(color);
content += `${t._r}\t${t._g}\t${t._b}\t${color}\n`;
})
Blockbench.export({
extensions: ['bbpalette'],
type: 'Blockbench Palette',
content: ColorPanel.palette.join('\n')
extensions: ['gpl'],
type: 'GPL Palette',
content
}, (path) => {
Blockbench.showQuickMessage(tl('message.save_file', pathToName(path)));
})

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,760 @@
const TextureGenerator = {
background_color: new ColorPicker({
id: 'background_color',
name: 'data.color',
private: true,
}),
face_data: {
up: {c1: '#b4d4e1', c2: '#ecf8fd', place: t => {return {x: t.posx+t.z, y: t.posy, w: t.x, h: t.z}}},
down: {c1: '#536174', c2: '#6e788c', place: t => {return {x: t.posx+t.z+t.x, y: t.posy, w: t.x, h: t.z}}},
east: {c1: '#43e88d', c2: '#7BFFA3', place: t => {return {x: t.posx, y: t.posy+t.z, w: t.z, h: t.y}}},
north: {c1: '#5bbcf4', c2: '#7BD4FF', place: t => {return {x: t.posx+t.z, y: t.posy+t.z, w: t.x, h: t.y}}},
west: {c1: '#f48686', c2: '#FFA7A4', place: t => {return {x: t.posx+t.z+t.x, y: t.posy+t.z, w: t.z, h: t.y}}},
south: {c1: '#f8dd72', c2: '#FFF899', place: t => {return {x: t.posx+t.z+t.x+t.z,y: t.posy+t.z, w: t.x, h: t.y}}},
},
addBitmapDialog() {
var dialog = new Dialog({
id: 'add_bitmap',
title: tl('action.create_texture'),
form: {
name: {label: 'generic.name', value: 'texture'},
folder: {label: 'dialog.create_texture.folder'},
template: {label: 'dialog.create_texture.template', type: 'checkbox', condition: Cube.all.length}
},
onConfirm: function(results) {
results.particle = 'auto';
dialog.hide()
if (results.template) {
var dialog2 = new Dialog({
id: 'texture_template',
title: tl('dialog.create_texture.template'),
form: {
compress: {label: 'dialog.create_texture.compress', type: 'checkbox', value: true, condition: Project.box_uv},
power: {label: 'dialog.create_texture.power', type: 'checkbox', value: true},
double_use: {label: 'dialog.create_texture.double_use', type: 'checkbox', value: true, condition: Project.box_uv},
box_uv: {label: 'dialog.project.box_uv', type: 'checkbox', value: false, condition: !Project.box_uv},
color: {label: 'data.color', type: 'color', colorpicker: TextureGenerator.background_color},
resolution: {label: 'dialog.create_texture.resolution', type: 'select', value: 16, options: {
16: '16',
32: '32',
64: '64',
128: '128',
256: '256',
512: '512',
}},
},
onConfirm: function(results2) {
$.extend(results, results2)
TextureGenerator.addBitmap(results)
dialog2.hide()
}
}).show()
if (TextureGenerator.background_color.get().toHex8() === 'ffffffff') {
TextureGenerator.background_color.set('#00000000')
}
} else {
var dialog2 = new Dialog({
id: 'texture_simple',
title: tl('action.create_texture'),
form: {
color: {label: 'data.color', type: 'color', colorpicker: TextureGenerator.background_color},
resolution: {label: 'dialog.create_texture.resolution', type: 'number', value: 16, min: 16, max: 2048},
},
onConfirm: function(results2) {
$.extend(results, results2)
TextureGenerator.addBitmap(results)
dialog2.hide()
}
}).show()
}
}
}).show()
},
addBitmap(options, after) {
if (typeof options !== 'object') {
options = {}
}
if (isNaN(options.resolution) || !options.resolution) {
options.resolution = 16
}
if (options.color === undefined) {
options.color = new tinycolor().toRgb()
}
if (Format.single_texture) {
options.texture = textures[0]
}
var texture = new Texture({
mode: 'bitmap',
keep_size: true,
res: options.resolution,
name: options.name ? options.name : 'texture',
folder: options.folder ? options.folder : 'block'
})
function makeTexture(dataUrl) {
texture.fromDataURL(dataUrl).add(false)
switch (options.particle) {
case 'auto':
texture.fillParticle();
break;
case true:
texture.enableParticle();
break;
}
if (typeof after === 'function') {
after(texture)
}
if (!options.template) {
Undo.finishEdit('create blank texture', {textures: [texture], bitmap: true})
}
return texture;
}
if (options.template === true) {
Undo.initEdit({
textures: Format.single_texture ? textures : [],
elements: Format.single_texture ? Cube.all : Cube.selected,
uv_only: true,
uv_mode: true
})
if (Project.box_uv || options.box_uv) {
TextureGenerator.generateTemplate(options, makeTexture)
} else {
TextureGenerator.generateFaceTemplate(options, makeTexture)
}
} else {
Undo.initEdit({textures: []})
TextureGenerator.generateBlank(options.resolution, options.resolution, options.color, makeTexture)
}
},
generateBlank(height, width, color, cb) {
var canvas = document.createElement('canvas')
canvas.width = width;
canvas.height = height;
var ctx = canvas.getContext('2d')
ctx.fillStyle = new tinycolor(color).toRgbString()
ctx.fillRect(0, 0, width, height)
cb(canvas.toDataURL())
},
//constructor
boxUVCubeTemplate: function(obj, min_size) {
this.x = obj.size(0, true) || min_size;
this.y = obj.size(1, true) || min_size;
this.z = obj.size(2, true) || min_size;
this.posx = obj.uv_offset[0];
this.posy = obj.uv_offset[1];
this.obj = obj;
this.template_size = (obj.size(2, true) + obj.size(1, true))+ (obj.size(2, true) + obj.size(0, true))*2;
this.height = this.z + this.y;
this.width = 2* (this.x + this.z);
return this;
},
//BoxUV Template
generateTemplate(options, cb) {
var res = options.resolution;
var background_color = options.color;
var texture = options.texture;
var min_size = Project.box_uv ? 0 : 1;
var res_multiple = res / 16
var templates = [];
var doubles = {};
var extend_x = 0;
var extend_y = 0;
var avg_size = 0;
var cubes = Format.single_texture ? Cube.all.slice() : Cube.selected.slice()
var i = cubes.length-1
while (i >= 0) {
let obj = cubes[i]
if (obj.visibility === true) {
var template = new TextureGenerator.boxUVCubeTemplate(obj, min_size);
if (options.double_use && Project.box_uv && textures.length) {
var double_key = [...obj.uv_offset, ...obj.size(undefined, true), ].join('_')
if (doubles[double_key]) {
// improve chances that original is not mirrored
if (doubles[double_key][0].obj.mirror_uv && !obj.mirror_uv) {
templates[templates.indexOf(doubles[double_key][0])] = template;
doubles[double_key].splice(0, 0, template)
} else {
doubles[double_key].push(template)
}
doubles[double_key][0].duplicates = doubles[double_key];
i--;
continue;
} else {
doubles[double_key] = [template]
}
}
templates.push(template)
avg_size += templates[templates.length-1].template_size
}
i--;
}
templates.sort(function(a,b) {
return b.template_size - a.template_size;
})
//Cancel if no cubes
if (templates.length == 0) {
Blockbench.showMessage('No valid cubes', 'center')
return;
}
if (options.compress) {
var fill_map = {}
function occupy(x, y) {
if (!fill_map[x]) fill_map[x] = {}
fill_map[x][y] = true
}
function check(x, y) {
return fill_map[x] && fill_map[x][y]
}
function forTemplatePixel(tpl, sx, sy, cb) {
for (var x = 0; x < tpl.width; x++) {
for (var y = 0; y < tpl.height; y++) {
if (y >= tpl.z || (x >= tpl.z && x < (tpl.z + 2*tpl.x))) {
if (cb(sx+x, sy+y)) return;
}
}
}
}
function place(tpl, x, y) {
var works = true;
forTemplatePixel(tpl, x, y, (tx, ty) => {
if (check(tx, ty)) {
works = false;
return true;
}
})
if (works) {
forTemplatePixel(tpl, x, y, occupy)
tpl.posx = x;
tpl.posy = y;
extend_x = Math.max(extend_x, x + tpl.width);
extend_y = Math.max(extend_y, y + tpl.height);
return true;
}
}
templates.forEach(tpl => {
var vert = extend_x > extend_y;
//Scan for empty spot
for (var line = 0; line < 2e3; line++) {
for (var x = 0; x <= line; x++) {
if (place(tpl, x, line)) return;
}
for (var y = 0; y < line; y++) {
if (place(tpl, line, y)) return;
}
}
})
} else {
//OLD -------------------------------------------
var lines = [[]]
var line_length = Math.sqrt(cubes.length/2)
avg_size /= templates.length
var o = 0
var i = 0
var ox = 0
templates.forEach(function(tpl) {
if (ox >= line_length) {
o = ox = 0
i++
lines[i] = []
}
lines[i][o] = tpl
o++;
ox += tpl.template_size/avg_size
})
lines.forEach(function(temps) {
var x_pos = 0
var y_pos = 0 //Y Position of current area relative to this bone
var filled_x_pos = 0;
var max_height = 0
//Find the maximum height of the line
temps.forEach(function(t) {
max_height = Math.max(max_height, t.height)
})
//Place
temps.forEach(function(t) {
if (y_pos > 0 && (y_pos + t.height) <= max_height) {
//same column
t.posx = x_pos
t.posy = y_pos + extend_y
filled_x_pos = Math.max(filled_x_pos, x_pos+t.width)
y_pos += t.height
} else {
//new column
x_pos = filled_x_pos
y_pos = t.height
t.posx = x_pos
t.posy = extend_y
filled_x_pos = Math.max(filled_x_pos, x_pos+t.width)
}
//size of widest bone
extend_x = Math.max(extend_x, filled_x_pos)
})
extend_y += max_height
})
}
var max_size = Math.max(extend_x, extend_y)
if (options.power) {
max_size = Math.getNextPower(max_size, 16);
} else {
max_size = Math.ceil(max_size/16)*16;
}
if (background_color.getAlpha() != 0) {
background_color = background_color.toRgbString()
}
var canvas = document.createElement('canvas')
canvas.width = canvas.height = max_size*res_multiple;
var ctx = canvas.getContext('2d')
ctx.imageSmoothingEnabled = false;
//Drawing
TextureGenerator.changeProjectResolution(max_size, max_size);
templates.forEach(function(t) {
t.obj.uv_offset[0] = t.posx;
t.obj.uv_offset[1] = t.posy;
//if true, dupes must be flipped
let reverse_flip = t.obj.mirror_uv;
t.obj.mirror_uv = false;
if (t.duplicates) {
t.duplicates.forEach(dupl => {
if (dupl.obj !== t.obj) {
dupl.obj.mirror_uv = dupl.obj.mirror_uv !== reverse_flip;
}
})
}
TextureGenerator.paintCubeBoxTemplate(t.obj, texture, canvas, t);
})
var dataUrl = canvas.toDataURL()
var texture = cb(dataUrl)
if (texture && !Project.single_texture) {
cubes.forEach(function(cube) {
cube.applyTexture(texture, true);
cube.autouv = 0;
})
}
if (options.box_uv && !Project.box_uv) {
Project.box_uv = true;
}
updateSelection()
Undo.finishEdit('create template', {
textures: [texture],
bitmap: true,
elements: cubes,
uv_only: true,
uv_mode: true
})
},
boxUVdrawTemplateRectangle(border_color, color, face, coords, texture, canvas) {
if (typeof background_color === 'string') {
border_color = background_color
color = undefined
}
var res_multiple = canvas.width/Project.texture_width;
var ctx = canvas.getContext('2d');
ctx.fillStyle = border_color;
ctx.fillRect(
coords.x*res_multiple,
coords.y*res_multiple,
coords.w*res_multiple,
coords.h*res_multiple
)
if (coords.w*res_multiple > 2 && coords.h*res_multiple > 2 && color) {
ctx.fillStyle = color
ctx.fillRect(
coords.x * res_multiple + 1,
coords.y * res_multiple + 1,
coords.w * res_multiple - 2,
coords.h * res_multiple - 2
)
}
},
boxUVdrawTexture(face, coords, texture, canvas) {
if (!Format.single_texture) {
if (face.texture === undefined || face.texture === null) return false;
texture = face.getTexture()
}
if (!texture || !texture.img) return false;
var ctx = canvas.getContext('2d');
var res_multiple = canvas.width/Project.texture_width;
ctx.save()
var uv = face.uv.slice();
if (face.direction === 'up') {
uv = [uv[2], uv[3], uv[0], uv[1]]
} else if (face.direction === 'down') {
uv = [uv[2], uv[1], uv[0], uv[3]]
}
var src = getRectangle(uv[0], uv[1], uv[2], uv[3])
var flip = [
uv[0] > uv[2] ? -1 : 1,
uv[1] > uv[3] ? -1 : 1
]
if (flip[0] + flip[1] < 1) {
ctx.scale(flip[0], flip[1])
}
if (face.rotation) {
ctx.rotate(Math.degToRad(face.rotation))
let rot = face.rotation
if (rot <= 180) flip[1] *= -1;
if (rot >= 180) flip[0] *= -1;
while (rot > 0) {
[coords.x, coords.y] = [coords.y, coords.x];
[coords.w, coords.h] = [coords.h, coords.w];
rot -= 90;
}
}
ctx.drawImage(
texture.img,
src.ax/Project.texture_width * texture.img.naturalWidth,
src.ay/Project.texture_height * texture.img.naturalHeight,
src.x /Project.texture_width * texture.img.naturalWidth,
src.y /Project.texture_height * texture.img.naturalHeight,
coords.x*res_multiple*flip[0],
coords.y*res_multiple*flip[1],
coords.w*res_multiple*flip[0],
coords.h*res_multiple*flip[1]
)
ctx.restore()
return true;
},
paintCubeBoxTemplate(cube, texture, canvas, template) {
if (!template) {
template = new TextureGenerator.boxUVCubeTemplate(cube, Project.box_uv ? 0 : 1);
}
for (var face in TextureGenerator.face_data) {
let d = TextureGenerator.face_data[face]
if (!cube.faces[face].texture ||
!TextureGenerator.boxUVdrawTexture(cube.faces[face], d.place(template), texture, canvas)
) {
TextureGenerator.boxUVdrawTemplateRectangle(d.c1, d.c2, cube.faces[face], d.place(template), texture, canvas)
}
}
if (template && template.duplicates) {
template.duplicates.forEach(t_2 => {
t_2.obj.uv_offset[0] = cube.uv_offset[0];
t_2.obj.uv_offset[1] = cube.uv_offset[1];
if (t_2.obj !== cube) {
t_2.obj.mirror_uv = t_2.obj.mirror_uv != cube.mirror_uv;
}
})
}
if (!Project.box_uv) {
var size = cube.size(undefined, true);
size.forEach((n, i) => {
size[i] = n;
})
var face_list = [
{face: 'north', fIndex: 10, from: [size[2], size[2]], size: [size[0], size[1]]},
{face: 'east', fIndex: 0, from: [0, size[2]], size: [size[2], size[1]]},
{face: 'south', fIndex: 8, from: [size[2]*2 + size[0], size[2]], size: [size[0], size[1]]},
{face: 'west', fIndex: 2, from: [size[2] + size[0], size[2]], size: [size[2], size[1]]},
{face: 'up', fIndex: 4, from: [size[2]+size[0], size[2]], size: [-size[0], -size[2]]},
{face: 'down', fIndex: 6, from: [size[2]+size[0]*2, 0], size: [-size[0], size[2]]}
]
face_list.forEach(function(f) {
cube.faces[f.face].uv[0] = (f.from[0] + Math.floor(cube.uv_offset[0]+0.0000001)) / canvas.width * Project.texture_width;
cube.faces[f.face].uv[1] = (f.from[1] + Math.floor(cube.uv_offset[1]+0.0000001)) / canvas.height * Project.texture_height;
cube.faces[f.face].uv[2] = (f.from[0]+f.size[0]+ Math.floor(cube.uv_offset[0]+0.0000001)) / canvas.width * Project.texture_width;
cube.faces[f.face].uv[3] = (f.from[1]+f.size[1]+ Math.floor(cube.uv_offset[1]+0.0000001)) / canvas.height * Project.texture_height;
cube.faces[f.face].rotation = 0;
})
}
},
//Face Template
generateFaceTemplate(options, cb) {
var res_multiple = options.resolution / 16;
var background_color = options.color;
var texture = options.texture;
var face_list = [];
function faceRect(cube, face_key, tex, x, y) {
this.cube = cube;
this.width = Math.abs(x);
this.height = Math.abs(y);
this.width = (this.width >= 0.01 && this.width < 1) ? 1 : Math.round(this.width );
this.height = (this.height >= 0.01 && this.height < 1) ? 1 : Math.round(this.height);
this.size = this.width * this.height;
this.face_key = face_key;
this.texture = tex
this.face = cube.faces[face_key];
face_list.push(this);
}
var cube_array = Format.single_texture ? Cube.all : Cube.selected;
cube_array.forEach(cube => {
var fi = 0;
for (var face_key in cube.faces) {
var face = cube.faces[face_key];
var tex = face.getTexture();
if (tex !== null) {
var x = 0;
var y = 0;
switch (face_key) {
case 'north': x = cube.size(0); y = cube.size(1); break;
case 'east': x = cube.size(2); y = cube.size(1); break;
case 'south': x = cube.size(0); y = cube.size(1); break;
case 'west': x = cube.size(2); y = cube.size(1); break;
case 'up': x = cube.size(0); y = cube.size(2); break;
case 'down': x = cube.size(0); y = cube.size(2); break;
}
new faceRect(cube, face_key, tex, x, y)
}
}
})
if (face_list.length == 0) {
Blockbench.showMessage('No valid cubes', 'center')
return;
}
var extend_x = 0;
var extend_y = 0;
if (true) {
face_list.sort(function(a,b) {
return b.size - a.size;
})
var fill_map = {}
function occupy(x, y) {
if (!fill_map[x]) fill_map[x] = {}
fill_map[x][y] = true
}
function check(x, y) {
return fill_map[x] && fill_map[x][y]
}
function forTemplatePixel(tpl, sx, sy, cb) {
for (var x = 0; x < tpl.width; x++) {
for (var y = 0; y < tpl.height; y++) {
if (cb(sx+x, sy+y)) return;
}
}
}
function place(tpl, x, y) {
var works = true;
forTemplatePixel(tpl, x, y, (tx, ty) => {
if (check(tx, ty)) {
works = false;
return true;
}
})
if (works) {
forTemplatePixel(tpl, x, y, occupy)
tpl.posx = x;
tpl.posy = y;
extend_x = Math.max(extend_x, x + tpl.width);
extend_y = Math.max(extend_y, y + tpl.height);
return true;
}
}
face_list.forEach(tpl => {
var vert = extend_x > extend_y;
//Scan for empty spot
for (var line = 0; line < 2e3; line++) {
for (var x = 0; x <= line; x++) {
if (place(tpl, x, line)) return;
}
for (var y = 0; y < line; y++) {
if (place(tpl, line, y)) return;
}
}
})
}
var max_size = Math.max(extend_x*res_multiple, extend_y*res_multiple)
if (options.power) {
max_size = Math.getNextPower(max_size, 16);
} else {
max_size = Math.ceil(max_size/16)*16;
}
if (background_color.getAlpha() != 0) {
background_color = background_color.toRgbString()
}
var canvas = document.createElement('canvas')
canvas.width = canvas.height = max_size;
var ctx = canvas.getContext('2d')
ctx.imageSmoothingEnabled = false;
function drawTemplateRectangle(border_color, color, face, coords) {
if (typeof background_color === 'string') {
border_color = background_color
color = undefined
}
ctx.fillStyle = border_color
ctx.fillRect(
coords.x*res_multiple,
coords.y*res_multiple,
coords.w*res_multiple,
coords.h*res_multiple
)
if (coords.w*res_multiple > 2 && coords.h*res_multiple > 2 && color) {
ctx.fillStyle = color
ctx.fillRect(
coords.x * res_multiple + 1,
coords.y * res_multiple + 1,
coords.w * res_multiple - 2,
coords.h * res_multiple - 2
)
}
}
function drawTexture(face, coords) {
if (!Format.single_texture) {
if (face.texture === undefined || face.texture === null) return false;
texture = face.getTexture()
} else {
texture = textures[0];
}
if (!texture || !texture.img) return false;
ctx.save()
var uv = face.uv.slice();
if (face.direction === 'up') {
uv = [uv[2], uv[3], uv[0], uv[1]]
} else if (face.direction === 'down') {
uv = [uv[2], uv[1], uv[0], uv[3]]
}
var src = getRectangle(uv[0], uv[1], uv[2], uv[3])
var flip = [
uv[0] > uv[2] ? -1 : 1,
uv[1] > uv[3] ? -1 : 1
]
if (flip[0] + flip[1] < 1) {
ctx.scale(flip[0], flip[1])
}
if (face.rotation) {
ctx.rotate(Math.degToRad(face.rotation))
let rot = face.rotation
if (rot <= 180) flip[1] *= -1;
if (rot >= 180) flip[0] *= -1;
while (rot > 0) {
[coords.x, coords.y] = [coords.y, coords.x];
[coords.w, coords.h] = [coords.h, coords.w];
rot -= 90;
}
}
ctx.drawImage(
texture.img,
src.ax/Project.texture_width * texture.img.naturalWidth,
src.ay/Project.texture_height * texture.img.naturalHeight,
src.x /Project.texture_width * texture.img.naturalWidth,
src.y /Project.texture_height * texture.img.naturalHeight,
coords.x*res_multiple*flip[0],
coords.y*res_multiple*flip[1],
coords.w*res_multiple*flip[0],
coords.h*res_multiple*flip[1]
)
ctx.restore()
return true;
}
//Drawing
face_list.forEach(function(ftemp) {
let cube = ftemp.cube
var pos = {
x: ftemp.posx,
y: ftemp.posy,
w: ftemp.width,
h: ftemp.height
}
var d = TextureGenerator.face_data[ftemp.face_key];
if (!ftemp.texture ||
!drawTexture(ftemp.face, pos)
) {
drawTemplateRectangle(d.c1, d.c2, ftemp.face, pos)
}
var flip_rotation = ftemp.face.rotation % 180 != 0;
ftemp.face.extend({
rotation: 0,
uv: flip_rotation ? [pos.y, pos.x] : [pos.x, pos.y]
})
ftemp.face.uv_size = flip_rotation ? [pos.h, pos.w] : [pos.w, pos.h];
if (ftemp.face_key == 'up') {
[ftemp.face.uv[2], ftemp.face.uv[0]] = [ftemp.face.uv[0], ftemp.face.uv[2]];
[ftemp.face.uv[3], ftemp.face.uv[1]] = [ftemp.face.uv[1], ftemp.face.uv[3]];
}
if (ftemp.face_key == 'down') {
[ftemp.face.uv[2], ftemp.face.uv[0]] = [ftemp.face.uv[0], ftemp.face.uv[2]];
}
})
var dataUrl = canvas.toDataURL()
var texture = cb(dataUrl)
TextureGenerator.changeProjectResolution(max_size / res_multiple, max_size / res_multiple);
if (texture && !Format.single_texture) {
cube_array.forEach(function(cube) {
for (var key in cube.faces) {
if (cube.faces[key].texture !== null) {
cube.faces[key].texture = texture.uuid;
}
}
Canvas.adaptObjectFaces(cube)
Canvas.updateUV(cube)
cube.autouv = 0
})
}
updateSelection()
Undo.finishEdit('create template', {
textures: [texture],
bitmap: true,
elements: cube_array,
uv_only: true,
uv_mode: true
})
},
//Misc
changeProjectResolution(width, height) {
let factor_x = width / Project.texture_width;
let factor_y = height / Project.texture_height;
Project.texture_width = width;
Project.texture_height = height;
if (!Project.box_uv && !Format.single_texture) {
Cube.all.forEach(cube => {
if (cube.selected) return;
for (var key in cube.faces) {
let face = cube.faces[key];
if (face.texture) {
face.uv[0] *= factor_x
face.uv[1] *= factor_y;
face.uv[2] *= factor_x;
face.uv[3] *= factor_y;
}
}
Canvas.updateUV(cube)
})
}
}
}

View File

@ -14,7 +14,6 @@ class Texture {
this.source = ''
this.selected = false
this.show_icon = true
this.dark_box = false
this.error = 0;
//Data
this.img = 0;
@ -69,7 +68,6 @@ class Texture {
var size_control = {};
this.img.onload = function() {
if (!this.src) return;
this.tex.needsUpdate = true;
scope.width = img.naturalWidth;
@ -79,9 +77,6 @@ class Texture {
console.log('Successfully loaded '+scope.name+' from default pack')
}
var average_color = getAverageRGB(this)
scope.dark_box = (average_color.r + average_color.g + average_color.b) >= 383
//Width / Animation
if (img.naturalWidth !== img.naturalHeight && Format.id == 'java_block') {
@ -93,40 +88,43 @@ class Texture {
}
}
if (Project.box_uv && Format.single_texture && !scope.keep_size) {
if (Project.box_uv && Format.single_texture) {
let pw = Project.texture_width;
let ph = Project.texture_height;
let nw = img.naturalWidth;
let nh = img.naturalHeight;
if (!scope.keep_size) {
let pw = Project.texture_width;
let ph = Project.texture_height;
let nw = img.naturalWidth;
let nh = img.naturalHeight;
//texture is unlike project
var unlike = (pw != nw || ph != nh);
//Resolution of this texture has changed
var changed = size_control.old_width && (size_control.old_width != nw || size_control.old_height != nh);
//Resolution could be a multiple of project size
var multi = !(
(pw%nw || ph%nh) &&
(nw%pw || nh%ph)
)
//texture is unlike project
var unlike = (pw != nw || ph != nh);
//Resolution of this texture has changed
var changed = size_control.old_width && (size_control.old_width != nw || size_control.old_height != nh);
//Resolution could be a multiple of project size
var multi = !(
(pw%nw || ph%nh) &&
(nw%pw || nh%ph)
)
if (unlike && changed) {
Blockbench.showMessageBox({
translateKey: 'update_res',
icon: 'photo_size_select_small',
buttons: [tl('message.update_res.update'), tl('dialog.cancel')],
confirm: 0,
cancel: 1
}, function(result) {
if (result === 0) {
setProjectResolution(img.naturalWidth, img.naturalHeight)
if (selected.length) {
main_uv.loadData()
if (unlike && changed) {
Blockbench.showMessageBox({
translateKey: 'update_res',
icon: 'photo_size_select_small',
buttons: [tl('message.update_res.update'), tl('dialog.cancel')],
confirm: 0,
cancel: 1
}, function(result) {
if (result === 0) {
setProjectResolution(img.naturalWidth, img.naturalHeight)
if (selected.length) {
main_uv.loadData()
}
}
}
})
})
}
}
delete scope.keep_size;
size_control.old_width = img.naturalWidth
size_control.old_height = img.naturalHeight
}
@ -201,6 +199,7 @@ class Texture {
Merge.boolean(this, data, 'particle')
Merge.string(this, data, 'mode')
Merge.boolean(this, data, 'saved')
Merge.boolean(this, data, 'keep_size')
if (this.mode === 'bitmap') {
Merge.string(this, data, 'source')
} else if (data.path) {
@ -327,7 +326,7 @@ class Texture {
}
fromDefaultPack() {
if (isApp && settings.default_path && settings.default_path.value) {
if (Project.single_texture) {
if (Format.single_texture) {
var path = BedrockEntityManager.findEntityTexture(Project.geometry_name, 'raw')
if (path) {
this.isDefault = true;
@ -363,6 +362,7 @@ class Texture {
return this;
}
updateSource(dataUrl) {
if (!dataUrl) dataUrl = this.source;
this.source = dataUrl;
this.img.src = dataUrl;
this.updateMaterial();
@ -393,9 +393,8 @@ class Texture {
img.tex.magFilter = THREE.NearestFilter
img.tex.minFilter = THREE.NearestFilter
img.tex.needsUpdate = true;
scope.img = img
Canvas.materials[scope.uuid].map = tex
Canvas.materials[scope.uuid].map = tex
}
return this;
}
@ -440,8 +439,9 @@ class Texture {
if (single) {
tex_version++;
}
this.source = this.source.replace(/\?\d+$/, '?' + tex_version);
this.load();
this.source = this.source.replace(/\?\d+$/, '?' + tex_version)
this.img.src = this.source;
this.updateMaterial();
TickUpdates.main_uv = true;
TickUpdates.texture_list = true;
}
@ -547,6 +547,8 @@ class Texture {
}
})
}
TickUpdates.selection = true;
if (undo) {
Undo.finishEdit('add_texture', {textures: [this]})
}
@ -681,6 +683,101 @@ class Texture {
$('#texture_edit .tool.bitmap_only').show()
}
}
resizeDialog() {
let scope = this;
let dialog = new Dialog({
id: 'resize_texture',
title: 'menu.texture.resize',
form: {
width: {
label: 'dialog.project.width',
type: 'number',
value: this.width,
min: 1
},
height: {
label: 'dialog.project.height',
type: 'number',
value: this.height,
min: 1
},
fill: {label: 'dialog.resize_texture.fill', type: 'select', default: 'transparent', options: {
transparent: 'dialog.resize_texture.fill.transparent',
color: 'dialog.resize_texture.fill.color',
repeat: 'dialog.resize_texture.fill.repeat',
stretch: 'dialog.resize_texture.fill.stretch'
}}
/*
width
height
fill
transparent
color
repeat
stretch
*/
},
onConfirm: function(formResult) {
let old_width = scope.width;
let old_height = scope.height;
scope.edit((canvas) => {
let new_canvas = document.createElement('canvas')
new_canvas.width = formResult.width;
new_canvas.height = formResult.height;
let new_ctx = new_canvas.getContext('2d')
new_ctx.imageSmoothingEnabled = false;
switch (formResult.fill) {
case 'transparent':
new_ctx.drawImage(canvas, 0, 0, scope.width, scope.height);
break;
case 'color':
new_ctx.fillStyle = ColorPanel.get();
new_ctx.fillRect(0, 0, formResult.width, formResult.height)
new_ctx.clearRect(0, 0, scope.width, scope.height)
new_ctx.drawImage(canvas, 0, 0, scope.width, scope.height);
break;
case 'repeat':
for (var x = 0; x < formResult.width; x += scope.width) {
for (var y = 0; y < formResult.height; y += scope.height) {
new_ctx.drawImage(canvas, x, y, scope.width, scope.height);
}
}
break;
case 'stretch':
new_ctx.drawImage(canvas, 0, 0, formResult.width, formResult.height);
break;
}
if (Painter.current && Painter.current.canvas) {
delete Painter.current.canvas;
}
scope.keep_size = true;
if (formResult.fill !== 'stretch' && Format.single_texture) {
Undo.current_save.uv_mode = {
box_uv: Project.box_uv,
width: Project.texture_width,
height: Project.texture_height
}
Undo.current_save.aspects.uv_mode = true;
Project.texture_width = Project.texture_width * (formResult.width / old_width);
Project.texture_height = Project.texture_height * (formResult.height / old_height);
Canvas.updateAllUVs()
}
return new_canvas
})
dialog.hide()
}
})
dialog.show()
return this;
}
//Export
javaTextureLink() {
var link = this.name.replace(/\.png$/, '')
@ -808,6 +905,12 @@ class Texture {
}
},
'_',
{
icon: 'photo_size_select_large',
name: 'menu.texture.resize',
click(texture) {texture.resizeDialog()}
},
'_',
{
icon: 'edit',
name: 'menu.texture.edit',

View File

@ -5,6 +5,7 @@ class UVEditor {
this.size = 320;
this.zoom = 1;
this.grid = 1;
this.max_zoom = 16;
this.auto_grid = true;
this.texture = false;
this.headline = headline
@ -24,7 +25,7 @@ class UVEditor {
if (this.jquery.main) {
this.jquery.main.detach()
}
this.jquery.main = $('<div class="UVEditor" id="UVEditor_'+scope.id+'"></div>')
this.jquery.main = $('<div class="UVEditor" id="UVEditor_' + scope.id + '"></div>')
if (this.headline) {
this.jquery.main.append('<div class="uv_headline"><div class="uv_title">'+capitalizeFirstLetter(scope.id)+'</div><div class="tool"><i class="material-icons">fullscreen</i><div class="tooltip">Fullscreen</div></div></div>')
this.jquery.main.find('div.uv_headline > .tool').click(function() {
@ -35,7 +36,7 @@ class UVEditor {
uv_dialog.select(scope.id, event)
})
}
this.jquery.viewport = $('<div id="uv_viewport"></div>')
this.jquery.viewport = $('<div id="uv_viewport" class="checkerboard_target"></div>')
this.jquery.transform_info = $('<div class="uv_transform_info"></div>')
this.jquery.main.append(this.jquery.transform_info)
this.jquery.main.append(this.jquery.viewport)
@ -79,7 +80,7 @@ class UVEditor {
get: function() {
if (Project.box_uv && Cube.selected[0]) {
return trimFloatNumber(Cube.selected[0].uv_offset[0])
} else {
} else if (Cube.selected[0]) {
var face_uv = Cube.selected[0].faces[scope.face].uv
if (face_uv) {
return trimFloatNumber(face_uv[0])
@ -102,7 +103,7 @@ class UVEditor {
get: function() {
if (Project.box_uv && Cube.selected[0]) {
return trimFloatNumber(Cube.selected[0].uv_offset[1])
} else {
} else if (Cube.selected[0]) {
var face_uv = Cube.selected[0].faces[scope.face].uv
if (face_uv) {
return trimFloatNumber(face_uv[1])
@ -206,8 +207,8 @@ class UVEditor {
p.left = limitNumber(p.left, 0, scope.inner_width-scope.jquery.size.width()+1);
p.top = limitNumber(p.top, 0, scope.inner_height-scope.jquery.size.height()+1);
p.left = p.left - p.left % (scope.inner_width / main_uv.getResolution(0) / scope.grid);
p.top = p.top - p.top % (scope.inner_height / main_uv.getResolution(1) / scope.grid);
p.left = p.left - p.left % (scope.inner_width / scope.getResolution(0) / scope.grid);
p.top = p.top - p.top % (scope.inner_height / scope.getResolution(1) / scope.grid);
scope.save();
scope.displaySliders();
@ -262,14 +263,14 @@ class UVEditor {
this.jquery.viewport.on('mousedown touchstart', function(event) {
if (Toolbox.selected.paintTool && (event.which === 1 || (event.touches && event.touches.length == 1))) {
scope.startBrush(event)
scope.startPaintTool(event)
}
})
this.jquery.viewport.on('mousewheel', function(e) {
if (e.ctrlOrCmd) {
var n = (event.deltaY < 0) ? 0.1 : -0.1;
n *= scope.zoom
var number = limitNumber(scope.zoom + n, 1.0, 4.0)
var number = limitNumber(scope.zoom + n, 1, scope.max_zoom)
if (Math.abs(number - scope.zoom) > 0.001) {
this.scrollLeft += (scope.inner_width * n / 2) * (event.offsetX / scope.jquery.frame.width());
this.scrollTop += (scope.inner_width * n / 2) * (event.offsetY / scope.jquery.frame.height());
@ -305,15 +306,16 @@ class UVEditor {
//Paint brush outline
var brush_outline = $('<div id="uv_brush_outline"></div>');
scope.jquery.frame.on('mouseenter mousemove', e => {
if (Modes.paint && (['brush_tool', 'eraser'].includes(Toolbox.selected.id))) {
if (Modes.paint && Toolbox.selected.brushTool) {
scope.jquery.frame.append(brush_outline);
var pixel_size = main_uv.getPixelSize();
var pixel_size = scope.inner_width / (scope.texture ? scope.texture.width : Project.texture_width);
//pos
let left = (0.5 + Math.floor(e.offsetX / pixel_size)) * pixel_size;
let top = (0.5 + Math.floor(e.offsetY / pixel_size)) * pixel_size;
let offset = BarItems.slider_brush_size.get()%2 == 0 && Toolbox.selected.brushTool ? 0.5 : 0;
let left = (0.5 - offset + Math.floor(e.offsetX / pixel_size + offset)) * pixel_size;
let top = (0.5 - offset + Math.floor(e.offsetY / pixel_size + offset)) * pixel_size;
brush_outline.css('left', left+'px').css('top', top+'px');
//size
var radius = (BarItems.slider_brush_size.get()-0.5) * pixel_size;
var radius = (BarItems.slider_brush_size.get()/2) * pixel_size;
brush_outline.css('padding', radius+'px').css('margin', (-radius)+'px');
}
})
@ -340,12 +342,21 @@ class UVEditor {
convertTouchEvent(event);
var multiplier = (Project.box_uv && tex) ? tex.width/Project.texture_width : 1
var pixel_size = scope.inner_width / tex.width
return {
x: Math.floor(event.offsetX/scope.getPixelSize()*multiplier),
y: Math.floor(event.offsetY/scope.getPixelSize()*multiplier)
if (Toolbox.selected.id === 'copy_paste_tool') {
return {
x: Math.round(event.offsetX/pixel_size*1),
y: Math.round(event.offsetY/pixel_size*1)
}
} else {
let offset = BarItems.slider_brush_size.get()%2 == 0 && Toolbox.selected.brushTool ? 0.5 : 0;
return {
x: Math.floor(event.offsetX/pixel_size*1 + offset),
y: Math.floor(event.offsetY/pixel_size*1 + offset)
}
}
}
startBrush(event) {
startPaintTool(event) {
var scope = this;
Painter.active_uv_editor = scope;
@ -353,25 +364,27 @@ class UVEditor {
if (texture) {
var coords = scope.getBrushCoordinates(event, texture)
Painter.startBrush(texture, coords.x, coords.y, undefined, event)
if (Toolbox.selected.id !== 'copy_paste_tool') {
Painter.startPaintTool(texture, coords.x, coords.y, undefined, event)
} else {
this.startSelection(texture, coords.x, coords.y, event)
}
}
if (Toolbox.selected.id !== 'color_picker' && texture) {
addEventListeners(scope.jquery.frame.get(0), 'mousemove touchmove', scope.moveBrush, false );
addEventListeners(scope.jquery.frame.get(0), 'mousemove touchmove', scope.movePaintTool, false );
addEventListeners(document, 'mouseup touchend', scope.stopBrush, false );
}
}
moveBrush(event) {
movePaintTool(event) {
var scope = Painter.active_uv_editor;
var texture = scope.getTexture()
if (!texture) {
Blockbench.showQuickMessage('message.untextured')
} else {
var x, y, new_face;
x = scope.getBrushCoordinates(event, texture).x
y = scope.getBrushCoordinates(event, texture).y
var new_face;
var {x, y} = scope.getBrushCoordinates(event, texture);
if (texture.img.naturalWidth + texture.img.naturalHeight == 0) return;
if (x === Painter.current.x && y === Painter.current.y) {
return
}
@ -380,18 +393,209 @@ class UVEditor {
Painter.current.y = y
Painter.current.face = scope.face
new_face = true;
if (texture !== Painter.current.texture) {
if (texture !== Painter.current.texture && Undo.current_save) {
Undo.current_save.addTexture(texture)
}
}
Painter.drawBrushLine(texture, x, y, event, new_face)
if (Toolbox.selected.id !== 'copy_paste_tool') {
Painter.movePaintTool(texture, x, y, event, new_face)
} else {
scope.dragSelection(texture, x, y, event)
}
}
}
stopBrush(event) {
var scope = Painter.active_uv_editor;
removeEventListeners( scope.jquery.frame.get(0), 'mousemove touchmove', scope.moveBrush, false );
removeEventListeners( scope.jquery.frame.get(0), 'mousemove touchmove', scope.movePaintTool, false );
removeEventListeners( document, 'mouseup touchend', scope.stopBrush, false );
Painter.stopBrush()
if (Toolbox.selected.id !== 'copy_paste_tool') {
Painter.stopPaintTool()
} else {
scope.stopSelection()
}
}
// Copy Paste Tool
startSelection(texture, x, y, event) {
if (Painter.selection.overlay && event.target && event.target.id === 'uv_frame') {
this.removePastingOverlay()
}
delete Painter.selection.calcrect;
if (!Painter.selection.overlay) {
this.jquery.frame.find('#texture_selection_rect').detach();
let rect = $(`<div id="texture_selection_rect"></div>`);
this.jquery.frame.append(rect)
Painter.selection.rect = rect;
Painter.selection.start_x = x;
Painter.selection.start_y = y;
} else {
Painter.selection.start_x = Painter.selection.x;
Painter.selection.start_y = Painter.selection.y;
Painter.selection.start_event = event;
}
}
dragSelection(texture, x, y, event) {
let m = this.inner_width / this.texture.width;
if (!Painter.selection.overlay) {
let calcrect = getRectangle(Painter.selection.start_x, Painter.selection.start_y, x, y)
Painter.selection.calcrect = calcrect;
Painter.selection.x = calcrect.ax;
Painter.selection.y = calcrect.ay;
Painter.selection.rect
.css('left', calcrect.ax*m + 'px')
.css('top', calcrect.ay*m + 'px')
.css('width', calcrect.x *m + 'px')
.css('height', calcrect.y *m + 'px')
} else if (this.texture && Painter.selection.canvas) {
Painter.selection.x = Painter.selection.start_x + Math.round((event.clientX - Painter.selection.start_event.clientX) / m);
Painter.selection.y = Painter.selection.start_y + Math.round((event.clientY - Painter.selection.start_event.clientY) / m);
Painter.selection.x = Math.clamp(Painter.selection.x, 0, this.texture.width-Painter.selection.canvas.width)
Painter.selection.y = Math.clamp(Painter.selection.y, 0, this.texture.height-Painter.selection.canvas.height)
this.updatePastingOverlay()
}
}
stopSelection() {
if (Painter.selection.rect) {
Painter.selection.rect.detach()
}
if (Painter.selection.overlay || !Painter.selection.calcrect) return;
if (Painter.selection.calcrect.x == 0 || Painter.selection.calcrect.y == 0) return;
let calcrect = Painter.selection.calcrect;
var canvas = document.createElement('canvas')
var ctx = canvas.getContext('2d');
canvas.width = calcrect.x;
canvas.height = calcrect.y;
ctx.drawImage(this.texture.img, -calcrect.ax, -calcrect.ay)
if (isApp) {
let image = nativeImage.createFromDataURL(canvas.toDataURL())
clipboard.writeImage(image)
}
Painter.selection.canvas = canvas;
this.addPastingOverlay();
}
addPastingOverlay() {
if (Painter.selection.overlay) return;
let scope = this;
let overlay = $(`<div id="texture_pasting_overlay">
<div class="control">
<div class="button_place" title="${tl('uv_editor.copy_paste_tool.place')}"><i class="material-icons">check_circle</i></div>
<div class="button_cut" title="${tl('uv_editor.copy_paste_tool.cut')}"><i class="fas fa-cut"></i></div>
<div class="button_mirror_x" title="${tl('uv_editor.copy_paste_tool.mirror_x')}"><i class="icon-mirror_x icon"></i></div>
<div class="button_mirror_y" title="${tl('uv_editor.copy_paste_tool.mirror_y')}"><i class="icon-mirror_y icon"></i></div>
<div class="button_rotate" title="${tl('uv_editor.copy_paste_tool.rotate')}"><i class="material-icons">rotate_right</i></div>
</div>
</div>`)
open_interface = {
confirm() {
scope.removePastingOverlay()
if (scope.texture) {
scope.texture.edit((canvas) => {
var ctx = canvas.getContext('2d');
ctx.drawImage(Painter.selection.canvas, Painter.selection.x, Painter.selection.y)
})
}
},
hide() {
scope.removePastingOverlay()
}
}
overlay.find('.button_place').click(open_interface.confirm);
//overlay.find('.button_cancel').click(open_interface.hide);
function getCanvasCopy() {
var temp_canvas = document.createElement('canvas')
var temp_ctx = temp_canvas.getContext('2d');
temp_canvas.width = Painter.selection.canvas.width;
temp_canvas.height = Painter.selection.canvas.height;
temp_ctx.drawImage(Painter.selection.canvas, 0, 0)
return temp_canvas
}
overlay.find('.button_cut').click(e => {
scope.removePastingOverlay()
scope.texture.edit((canvas) => {
var ctx = canvas.getContext('2d');
ctx.clearRect(Painter.selection.x, Painter.selection.y, Painter.selection.canvas.width, Painter.selection.canvas.height);
})
})
overlay.find('.button_mirror_x').click(e => {
let temp_canvas = getCanvasCopy()
let ctx = Painter.selection.canvas.getContext('2d');
ctx.save();
ctx.translate(ctx.canvas.width, 0);
ctx.scale(-1, 1);
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.drawImage(temp_canvas, ctx.canvas.width, 0, -ctx.canvas.width, ctx.canvas.height);
ctx.restore();
})
overlay.find('.button_mirror_y').click(e => {
let temp_canvas = getCanvasCopy()
let ctx = Painter.selection.canvas.getContext('2d');
ctx.save();
ctx.translate(0, ctx.canvas.height);
ctx.scale(1, -1);
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.drawImage(temp_canvas, 0, ctx.canvas.height, ctx.canvas.width, -ctx.canvas.height);
ctx.restore();
})
overlay.find('.button_rotate').click(e => {
let temp_canvas = getCanvasCopy()
let ctx = Painter.selection.canvas.getContext('2d');
[ctx.canvas.width, ctx.canvas.height] = [ctx.canvas.height, ctx.canvas.width]
ctx.save();
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.translate(ctx.canvas.width/2,ctx.canvas.height/2);
ctx.rotate(Math.PI/2);
ctx.drawImage(temp_canvas,-temp_canvas.width/2,-temp_canvas.height/2);
//ctx.rotate(-Math.PI/2);
ctx.restore();
scope.updateSize()
})
overlay.append(Painter.selection.canvas)
Painter.selection.overlay = overlay;
this.jquery.frame.append(overlay)
Painter.selection.x = Math.clamp(Painter.selection.x, 0, this.texture.width-Painter.selection.canvas.width)
Painter.selection.y = Math.clamp(Painter.selection.y, 0, this.texture.height-Painter.selection.canvas.height)
this.updateSize()
function hideOverlay(event) {
if (!Painter.selection.overlay) {
removeEventListeners(document, 'mousedown touchstart', hideOverlay)
} else if (Painter.selection.overlay.has(event.target).length == 0) {
scope.removePastingOverlay()
}
}
addEventListeners(document, 'mousedown touchstart', hideOverlay)
}
removePastingOverlay() {
Painter.selection.overlay.detach();
delete Painter.selection.overlay;
open_interface = false;
}
updatePastingOverlay() {
let m = this.inner_width/this.texture.width
$(Painter.selection.canvas)
.css('width', Painter.selection.canvas.width * m)
.css('height', Painter.selection.canvas.height * m)
Painter.selection.overlay
.css('left', Painter.selection.x * m)
.css('top', Painter.selection.y * m);
return this;
}
//Get
get inner_width() {
@ -442,7 +646,7 @@ class UVEditor {
for (var id in this.sliders) {
this.sliders[id].setWidth(size/(Project.box_uv?2:4)-1)
}
if (!cancel_load) {
if (!cancel_load && old_size !== size) {
this.loadData();
} else {
this.updateSize();
@ -492,6 +696,9 @@ class UVEditor {
} else {
this.img.style.objectPosition = `0 0`;
}
if (Painter.selection.overlay && this.texture) {
this.updatePastingOverlay()
}
if (this.zoom > 1) {
this.jquery.viewport.css('overflow', 'scroll scroll')
@ -509,9 +716,6 @@ class UVEditor {
}
return this;
}
setFrameColor(black) {
this.jquery.size.toggleClass('dark_frame', black === true)
}
setToMainSlot() {
var scope = this;
$('.panel#uv').append(this.jquery.main)
@ -546,8 +750,8 @@ class UVEditor {
}
var matches = [];
var face_match;
var u = event.offsetX / main_uv.inner_width * this.getResolution(0);
var v = event.offsetY / main_uv.inner_height * this.getResolution(1);
var u = event.offsetX / this.inner_width * this.getResolution(0);
var v = event.offsetY / this.inner_height * this.getResolution(1);
Cube.all.forEach(cube => {
for (var face in cube.faces) {
var uv = cube.faces[face].uv
@ -564,8 +768,6 @@ class UVEditor {
if (!Project.box_uv) {
main_uv.setFace(face_match);
}
//if (!event.ctrlOrCmd && !event.shiftKey) {
//}
selected.empty();
matches.forEach(s => {
selected.safePush(s)
@ -671,12 +873,10 @@ class UVEditor {
main_uv.img.src = '';
this.img.style.display = 'none';
this.texture = false;
this.setFrameColor()
} else {
this.img.src = tex.source;
this.img.style.display = 'block';
this.texture = tex;
this.setFrameColor(tex.dark_box);
if (!Project.box_uv && this.auto_grid) {
this.grid = tex.width / Project.texture_width;
}
@ -870,7 +1070,8 @@ class UVEditor {
if (!Cube.selected.length) return;
var face = Cube.selected[0].faces[this.face]
BarItems.cullface.set(face.cullface||'off')
BarItems.face_tint.setIcon(face.tint ? 'check_box' : 'check_box_outline_blank')
BarItems.face_tint.setIcon(face.tint !== -1 ? 'check_box' : 'check_box_outline_blank')
BarItems.slider_face_tint.update()
}
updateDragHandle() {
var pos = this.jquery.size.position()
@ -1156,9 +1357,7 @@ class UVEditor {
var val = BarItems.cullface.get()
if (val === 'off') val = false
this.forCubes(obj => {
if (val) {
obj.faces[scope.face].cullface = val || '';
}
obj.faces[scope.face].cullface = val || '';
})
if (val) {
this.message('uv_editor.cullface_on')
@ -1169,19 +1368,27 @@ class UVEditor {
}
switchTint(event) {
var scope = this;
var val = !Cube.selected[0].faces[scope.face].tint
var val = Cube.selected[0].faces[scope.face].tint === -1 ? 0 : -1;
if (event === true || event === false) val = event
if (event === 0 || event === false) val = event
this.forCubes(obj => {
obj.faces[scope.face].tint = val
})
if (val) {
if (val !== -1) {
this.message('uv_editor.tint_on')
} else {
this.message('uv_editor.tint_off')
}
this.displayTools()
}
setTint(event, val) {
var scope = this;
this.forCubes(obj => {
obj.faces[scope.face].tint = val
})
this.displayTools()
}
rotate() {
var scope = this;
var value = parseInt(BarItems.uv_rotation.get())
@ -1335,7 +1542,7 @@ class UVEditor {
'zoom_out',
'zoom_reset'
]},
'toggle_checkerboard',
'uv_checkerboard',
'_',
'copy',
'paste',
@ -1478,6 +1685,7 @@ class UVEditor {
}}
])
function switchBoxUV(state) {
BARS.updateConditions()
if (state) {
@ -1572,19 +1780,19 @@ const uv_dialog = {
uv_dialog.selection = []
uv_dialog.updateSelection()
},
forSelection: function(cb, event) {
forSelection: function(cb, event, ...args) {
if (open_dialog === false) {
main_uv[cb](event)
main_uv[cb](event, ...args)
} else if (uv_dialog.single) {
uv_dialog.editors.single[cb]()
uv_dialog.editors.single[cb](...args)
} else {
if (uv_dialog.selection.length > 0) {
uv_dialog.selection.forEach(function(s) {
uv_dialog.editors[s][cb]()
uv_dialog.editors[s][cb](...args)
})
} else {
uv_dialog.allFaces.forEach(function(s) {
uv_dialog.editors[s][cb]()
uv_dialog.editors[s][cb](...args)
})
}
}
@ -1963,6 +2171,29 @@ BARS.defineActions(function() {
Undo.finishEdit('tint')
}
})
new NumSlider('slider_face_tint', {
category: 'uv',
condition: () => !Project.box_uv && Cube.selected.length,
getInterval(event) {
return 1;
},
get: function() {
return Cube.selected[0] && Cube.selected[0].faces[main_uv.face].tint
},
change: function(modify) {
let number = Math.clamp(Math.round(modify(this.get())), -1)
uv_dialog.forSelection('setTint', event, number)
},
onBefore: function() {
Undo.initEdit({elements: Cube.selected, uv_only: true})
},
onAfter: function() {
Undo.finishEdit('set face tint')
}
})
new Action('toggle_uv_overlay', {
condition: () => Project.box_uv,
icon: 'crop_landscape',//'crop_landscape'

View File

@ -16,7 +16,7 @@ function origin2geometry() {
position.forEach(function(p, pi) {
position[pi] = p / Group.selected.children.length
})
Group.selected.origin = position
Group.selected.origin.V3_set(position)
} else if (Cube.selected) {
Undo.initEdit({elements: Cube.selected})
@ -47,12 +47,6 @@ function getSelectionCenter() {
selected.forEach(obj => {
var m = obj.mesh
if (m) {
var pos = obj.getWorldCenter()
center[0] += pos.x
center[1] += pos.y
center[2] += pos.z
} else if (!m && obj.from) {
var pos = obj.getWorldCenter();
center[0] += pos.x
center[1] += pos.y
@ -70,7 +64,7 @@ function getSelectionCenter() {
return center;
}
function isMovementGlobal() {
if (selected.length === 0 || (!settings.local_move.value && Toolbox.selected.id !== 'resize_tool')) {
if (selected.length === 0 || (Toolbox.selected.id !== 'resize_tool')) {
return true;
}
if (Format.rotate_cubes) {
@ -158,18 +152,9 @@ function moveCubesRelative(difference, index, event) { //Multiple
if (event) {
difference *= canvasGridSize(event.shiftKey, event.ctrlOrCmd);
}
if (_has_groups && Blockbench.globalMovement) {
Group.selected.forEachChild(g => {
g.origin[axes[index]] += difference
}, Group, true)
}
moveElementsInSpace(difference, axes[index])
Cube.selected.forEach(cube => {
cube.move(difference, axes[index], _has_groups||!Format.bone_rig)
})
Canvas.updatePositions()
Undo.finishEdit('move')
}
//Rotate
@ -387,9 +372,7 @@ const Vertexsnap = {
cube_pos.applyQuaternion(q);
}
if (Format.rotate_cubes) {
obj.origin[0] += cube_pos.getComponent(0);
obj.origin[1] += cube_pos.getComponent(1);
obj.origin[2] += cube_pos.getComponent(2);
obj.origin.V3_add(cube_pos);
}
var in_box = obj.moveVector(cube_pos.toArray());
if (!in_box && Format.canvas_limit && !settings.deactivate_size_limit.value) {
@ -503,9 +486,9 @@ function modelScaleSync(label) {
function cancelScaleAll() {
selected.forEach(function(obj) {
if (obj === undefined) return;
if (obj.from) obj.from = obj.before.from;
if (obj.to) obj.to = obj.before.to;
if (obj.origin) obj.origin = obj.before.origin;
if (obj.from) obj.from.V3_set(obj.before.from);
if (obj.to) obj.to.V3_set(obj.before.to);
if (obj.origin) obj.origin.V3_set(obj.before.origin);
delete obj.before
if (Project.box_uv) {
Canvas.updateUV(obj)
@ -522,6 +505,18 @@ function cancelScaleAll() {
Canvas.updatePositions()
hideDialog()
}
function setScaleAllPivot(mode) {
if (mode === 'selection') {
var center = getSelectionCenter()
} else {
var center = Cube.selected[0] && Cube.selected[0].origin;
}
if (center) {
$('input#scaling_origin_x').val(center[0]);
$('input#scaling_origin_y').val(center[1]);
$('input#scaling_origin_z').val(center[2]);
}
}
function scaleAllSelectOverflow() {
cancelScaleAll()
selected.length = 0;
@ -557,6 +552,85 @@ function centerCubes(axis, update) {
Canvas.updatePositions()
}
}
//Move
function moveElementsInSpace(difference, axis) {
let space = Transformer.getTransformSpace()
let group = Format.bone_rig && Group.selected && Group.selected.matchesSelection() && Group.selected;
var group_m;
if (group) {
if (space === 0) {
group_m = new THREE.Vector3();
group_m[getAxisLetter(axis)] = difference;
var rotation = new THREE.Quaternion();
group.mesh.parent.getWorldQuaternion(rotation);
group_m.applyQuaternion(rotation.inverse());
group.forEachChild(g => {
g.origin.V3_add(group_m.x, group_m.y, group_m.z);
}, Group, true)
} else if (space === 2) {
group_m = new THREE.Vector3();
group_m[getAxisLetter(axis)] = difference;
var rotation = new THREE.Quaternion();
group.mesh.getWorldQuaternion(rotation);
group_m.applyQuaternion(rotation);
group.forEachChild(g => {
g.origin.V3_add(group_m.x, group_m.y, group_m.z);
}, Group, true)
} else {
group.forEachChild(g => {
g.origin[axis] += difference
}, Group, true)
}
}
selected.forEach(el => {
if (space == 2 && !group_m) {
if (el.movable) el.from[axis] += difference;
if (el.resizable) el.to[axis] += difference;
} else if (space instanceof Group) {
if (el.movable) el.from[axis] += difference;
if (el.resizable) el.to[axis] += difference;
if (el.rotatable) el.origin[axis] += difference;
} else {
if (group_m) {
var m = group_m
} else {
var m = new THREE.Vector3();
m[getAxisLetter(axis)] = difference;
var rotation = new THREE.Quaternion();
if (el.mesh) {
el.mesh.getWorldQuaternion(rotation);
} else if (el.parent instanceof Group) {
el.parent.mesh.getWorldQuaternion(rotation);
}
m.applyQuaternion(rotation.inverse());
}
if (el.movable) el.from.V3_add(m.x, m.y, m.z);
if (el.resizable) el.to.V3_add(m.x, m.y, m.z);
if (group) {
if (el.rotatable) el.origin.V3_add(m.x, m.y, m.z);
}
}
if (el instanceof Cube) {
el.mapAutoUV()
Canvas.adaptObjectPosition(el);
}
})
TickUpdates.selection = true;
}
//Rotate
function getRotationInterval(event) {
if (Format.rotation_limit) {
@ -626,7 +700,7 @@ function rotateOnAxis(modify, axis) {
}*/
Cube.selected.forEach(function(obj, i) {
if (obj.rotation.allEqual(0)) {
obj.origin = origin.slice()
obj.origin.V3_set(origin)
}
var obj_val = modify(obj.rotation[axis]);
obj_val = Math.trimDeg(obj_val)
@ -651,6 +725,25 @@ function rotateOnAxis(modify, axis) {
}
BARS.defineActions(function() {
new BarSelect('transform_space', {
condition: () => Modes.edit,
category: 'transform',
options: {
global: true,
bone: {condition: () => Format.bone_rig, name: true},
local: true
},
onChange() {
updateSelection();
}
})
let grid_locked_interval = function(event) {
event = event||0;
return canvasGridSize(event.shiftKey, event.ctrlOrCmd);
}
function moveOnAxis(modify, axis) {
selected.forEach(function(obj, i) {
if (obj.movable) {
@ -679,7 +772,9 @@ BARS.defineActions(function() {
name: tl('action.slider_pos', ['X']),
description: tl('action.slider_pos.desc', ['X']),
color: 'x',
category: 'transform',
condition: () => (selected.length && Modes.edit),
getInterval: grid_locked_interval,
get: function() {
return selected[0].from[0]
},
@ -697,7 +792,9 @@ BARS.defineActions(function() {
name: tl('action.slider_pos', ['Y']),
description: tl('action.slider_pos.desc', ['Y']),
color: 'y',
category: 'transform',
condition: () => (selected.length && Modes.edit),
getInterval: grid_locked_interval,
get: function() {
return selected[0].from[1]
},
@ -715,7 +812,9 @@ BARS.defineActions(function() {
name: tl('action.slider_pos', ['Z']),
description: tl('action.slider_pos.desc', ['Z']),
color: 'z',
category: 'transform',
condition: () => (selected.length && Modes.edit),
getInterval: grid_locked_interval,
get: function() {
return selected[0].from[2]
},
@ -742,7 +841,9 @@ BARS.defineActions(function() {
name: tl('action.slider_size', ['X']),
description: tl('action.slider_size.desc', ['X']),
color: 'x',
category: 'transform',
condition: () => (Cube.selected.length && Modes.edit),
getInterval: grid_locked_interval,
get: function() {
return Cube.selected[0].to[0] - Cube.selected[0].from[0]
},
@ -760,7 +861,9 @@ BARS.defineActions(function() {
name: tl('action.slider_size', ['Y']),
description: tl('action.slider_size.desc', ['Y']),
color: 'y',
category: 'transform',
condition: () => (Cube.selected.length && Modes.edit),
getInterval: grid_locked_interval,
get: function() {
return Cube.selected[0].to[1] - Cube.selected[0].from[1]
},
@ -778,7 +881,9 @@ BARS.defineActions(function() {
name: tl('action.slider_size', ['Z']),
description: tl('action.slider_size.desc', ['Z']),
color: 'z',
category: 'transform',
condition: () => (Cube.selected.length && Modes.edit),
getInterval: grid_locked_interval,
get: function() {
return Cube.selected[0].to[2] - Cube.selected[0].from[2]
},
@ -794,7 +899,9 @@ BARS.defineActions(function() {
})
//Inflate
new NumSlider('slider_inflate', {
category: 'transform',
condition: function() {return Cube.selected.length && Modes.edit},
getInterval: grid_locked_interval,
get: function() {
return Cube.selected[0].inflate
},
@ -826,6 +933,7 @@ BARS.defineActions(function() {
name: tl('action.slider_rotation', ['X']),
description: tl('action.slider_rotation.desc', ['X']),
color: 'x',
category: 'transform',
condition: () => (Modes.edit && getRotationObject()),
get: function() {
if (Format.bone_rig && Group.selected) {
@ -851,6 +959,7 @@ BARS.defineActions(function() {
name: tl('action.slider_rotation', ['Y']),
description: tl('action.slider_rotation.desc', ['Y']),
color: 'y',
category: 'transform',
condition: () => (Modes.edit && getRotationObject()),
get: function() {
if (Format.bone_rig && Group.selected) {
@ -876,6 +985,7 @@ BARS.defineActions(function() {
name: tl('action.slider_rotation', ['Z']),
description: tl('action.slider_rotation.desc', ['Z']),
color: 'z',
category: 'transform',
condition: () => (Modes.edit && getRotationObject()),
get: function() {
if (Format.bone_rig && Group.selected) {
@ -930,7 +1040,9 @@ BARS.defineActions(function() {
name: tl('action.slider_origin', ['X']),
description: tl('action.slider_origin.desc', ['X']),
color: 'x',
category: 'transform',
condition: () => (Modes.edit || Modes.animate) && getRotationObject(),
getInterval: grid_locked_interval,
get: function() {
if (Format.bone_rig && Group.selected) {
return Group.selected.origin[0];
@ -953,7 +1065,9 @@ BARS.defineActions(function() {
name: tl('action.slider_origin', ['Y']),
description: tl('action.slider_origin.desc', ['Y']),
color: 'y',
category: 'transform',
condition: () => (Modes.edit || Modes.animate) && getRotationObject(),
getInterval: grid_locked_interval,
get: function() {
if (Format.bone_rig && Group.selected) {
return Group.selected.origin[1];
@ -976,7 +1090,9 @@ BARS.defineActions(function() {
name: tl('action.slider_origin', ['Z']),
description: tl('action.slider_origin.desc', ['Z']),
color: 'z',
category: 'transform',
condition: () => (Modes.edit || Modes.animate) && getRotationObject(),
getInterval: grid_locked_interval,
get: function() {
if (Format.bone_rig && Group.selected) {
return Group.selected.origin[2];
@ -999,6 +1115,7 @@ BARS.defineActions(function() {
new Action('scale', {
icon: 'settings_overscan',
category: 'transform',
condition: () => (Modes.edit && selected.length),
click: function () {
$('#model_scale_range, #model_scale_label').val(1)
$('#scaling_clipping_warning').text('')

View File

@ -300,11 +300,10 @@ var Undo = {
var tex = Undo.getItemByUUID(textures, uuid)
if (tex) {
var require_reload = tex.mode !== save.textures[uuid].mode;
tex.extend(save.textures[uuid]).updateMaterial()
tex.extend(save.textures[uuid]).updateSource()
tex.keep_size = true;
if (require_reload || reference.textures[uuid] === true) {
tex.load()
} else {
tex.updateMaterial()
}
}
} else {

View File

@ -168,6 +168,10 @@ Math.trimDeg = function(a) {
Math.isPowerOfTwo = function(x) {
return (x > 1) && ((x & (x - 1)) == 0);
}
Math._numbertype = 'number';
Math.isNumber = function(x) {
return typeof x == Math._numbertype;
}
Math.randomab = function(a, b) {
return a + Math.random()*(b-a);
}
@ -379,6 +383,53 @@ Array.prototype.overlap = function(arr2) {
return count;
}
//Array Vector
Array.prototype.V3_set = function(x, y, z) {
if (x instanceof Array) return this.V3_set(...x);
if (y === undefined && z === undefined) z = y = x;
this[0] = parseFloat(x)||0;
this[1] = parseFloat(y)||0;
this[2] = parseFloat(z)||0;
return this;
}
Array.prototype.V3_add = function(x, y, z) {
if (x instanceof Array) return this.V3_add(...x);
if (x instanceof THREE.Vector3) return this.V3_add(x.x, x.y, x.z);
this[0] += parseFloat(x)||0;
this[1] += parseFloat(y)||0;
this[2] += parseFloat(z)||0;
return this;
}
Array.prototype.V3_subtract = function(x, y, z) {
if (x instanceof Array) return this.V3_subtract(...x);
if (x instanceof THREE.Vector3) return this.V3_subtract(x.x, x.y, x.z);
this[0] -= parseFloat(x)||0;
this[1] -= parseFloat(y)||0;
this[2] -= parseFloat(z)||0;
return this;
}
Array.prototype.V3_multiply = function(x, y, z) {
if (x instanceof Array) return this.V3_multiply(...x);
if (x instanceof THREE.Vector3) return this.V3_multiply(x.x, x.y, x.z);
if (y === undefined && z === undefined) z = y = x;
this[0] *= parseFloat(x)||0;
this[1] *= parseFloat(y)||0;
this[2] *= parseFloat(z)||0;
return this;
}
Array.prototype.V3_divide = function(x, y, z) {
if (x instanceof Array) return this.V3_divide(...x);
if (x instanceof THREE.Vector3) return this.V3_divide(x.x, x.y, x.z);
if (y === undefined && z === undefined) z = y = x;
this[0] /= parseFloat(x)||1;
this[1] /= parseFloat(y)||1;
this[2] /= parseFloat(z)||1;
return this;
}
Array.prototype.V3_toThree = function() {
return new THREE.Vector3(this[0], this[1], this[2]);
}
//Object
Object.defineProperty(Array.prototype, "equals", {enumerable: false});
@ -469,6 +520,11 @@ var Merge = {
if (typeof source[index] === 'function') {
obj[index] = source[index]
}
},
arrayVector: function(obj, source, index) {
if (source[index] instanceof Array) {
obj[index].V3_set(source[index]);
}
}
}

View File

@ -18,6 +18,21 @@ function initializeWebApp() {
EditSession.dialog()
$('#edit_session_token').val(location.hash.substr(9))
}
if (location.hash.substr(1, 5) == 'load=') {
$.getJSON('https://blockbench.net/api/rawtext.php?url='+location.hash.substr(6), (model) => {
if (showSaveDialog()) {
resetProject();
Codecs.project.load(model, {path: ''});
}
})
} else if (location.hash.substr(1, 5) == 'pbin=') {
$.getJSON('https://blockbench.net/api/rawtext.php?url='+'https://pastebin.com/raw/'+location.hash.substr(6), (model) => {
if (showSaveDialog()) {
resetProject();
Codecs.project.load(model, {path: ''});
}
})
}
}
setInterval(function() {

View File

@ -157,7 +157,6 @@
"dialog.update.connecting": "Mit Server verbinden",
"dialog.settings.settings": "Einstellungen",
"dialog.settings.keybinds": "Tastenbelegungen",
"dialog.settings.layout": "Layout",
"dialog.settings.about": "Über",
"layout.color.back": "Dunkler",
"layout.color.back.desc": "Hintergründe und Eingabefelder",
@ -364,8 +363,6 @@
"action.delete.desc": "Löscht ausgewählter Elemente oder Gruppen",
"action.sort_outliner": "Outliner sortieren",
"action.sort_outliner.desc": "Den Outliner alphabetisch sortieren",
"action.local_move": "Relativ Verschieben",
"action.local_move.desc": "Elemente wenn möglich auf ihrer eigenen Achse verschieben",
"action.select_window": "Auswahl...",
"action.select_window.desc": "Elemente basierend auf ihren Eigenschaften suchen und auswählen",
"action.invert_selection": "Auswahl umkehren",
@ -464,19 +461,16 @@
"menu.preview.background.load": "Laden",
"menu.preview.background.position": "Positionieren",
"menu.preview.background.lock": "An Kamera anheften",
"menu.preview.background.remove": "Entfernen",
"menu.preview.screenshot": "Bildschirmfoto",
"menu.preview.perspective": "Blickwinkel",
"menu.preview.perspective.normal": "Normal",
"menu.preview.quadview": "Vierfachansicht",
"menu.preview.fullview": "Vollansicht",
"menu.preview.stop_drag": "Hintergrundpositionierung beenden",
"menu.uv.mapping": "UV Mapping",
"menu.uv.mapping.export": "Exportieren",
"menu.uv.mapping.rotation": "Drehung",
"menu.uv.mapping.mirror_x": "Spiegeln X",
"menu.uv.mapping.mirror_y": "Spiegeln Y",
"menu.uv.tint": "Einfärben",
"menu.uv.texture": "Textur",
"cube.color.light_blue": "Hellblau",
"cube.color.yellow": "Gelb",
@ -671,13 +665,11 @@
"message.bone_material": "Bone-Material verändern",
"action.slider_animation_length": "Animationslänge",
"action.slider_animation_length.desc": "Verändert die Länge der ausgewählten Animation",
"action.camera_reset": "Kamera zurücksetzen",
"action.camera_reset.desc": "Setzt die Kamera der aktuellen Ansicht auf die Standardperspektive zurück",
"panel.variable_placeholders": "Variablen-Platzhalter",
"panel.variable_placeholders.info": "Gebe die Variablen der Animation an, für die du eine Vorschau brauchst, als Name=Wert",
"status_bar.vertex_distance": "Entfernung: %0",
"dialog.create_gif.title": "GIF aufzeichnen",
"dialog.create_gif.length": "Länge (Sekunden)",
"dialog.create_gif.length": "Länge",
"dialog.create_gif.fps": "FPS",
"dialog.create_gif.compression": "Kompression",
"dialog.create_gif.play": "Animation starten",
@ -934,8 +926,6 @@
"status_bar.recording": "Zeitraffer wird aufgezeichnet",
"message.add_to_palette": "Zur Palette hinzugefügt",
"message.size_modifiers": "Halte Steuerung oder Umschalt, um Objekte in kleineren Abständen zu bewegen",
"message.checkerboard.enabled": "Schachbrettmuster aktiviert",
"message.checkerboard.disabled": "Schachbrettmuster deaktiviert",
"message.timelapse_start": "Zeitrafferaufnahme angefangen",
"message.timelapse_stop": "Zeitrafferaufnahme beendet",
"message.import_palette.replace_palette": "Alte Palette ersetzen",
@ -981,8 +971,6 @@
"action.sort_palette.desc": "Sortiert alle Farben der Palette nach Farbton und Helligkeit",
"action.clear_palette": "Palette leeren",
"action.clear_palette.desc": "Alle Farben aus der Palette entfernen",
"action.toggle_checkerboard": "Schachbrettmuster",
"action.toggle_checkerboard.desc": "Schaltet das Schachbrettmuster hinter der Vorschau und dem UV Fenster an/aus",
"action.timelapse": "Zeitraffer...",
"action.timelapse.desc": "Zeichnet eine Zeitrafferaufnahme von der Benutzung von Blockbench auf",
"action.add_keyframe": "Keyframe hinzufügen",
@ -1023,5 +1011,81 @@
"menu.help.search_action": "Befehl suchen und ausführen",
"menu.help.donate": "Spenden",
"menu.help.about": "Über...",
"menu.preview.background.clipboard": "Aus Zwischenablage laden"
"menu.preview.background.clipboard": "Aus Zwischenablage laden",
"dialog.ignore": "Ignorieren",
"generic.unset": "Unset",
"message.invalid_builtin_parent.title": "Invalid Built-in Parent",
"message.invalid_builtin_parent.message": "The link to the invalid parent model '%0' was removed in order to export a valid model.",
"dialog.resize_texture.fill": "Fill with",
"dialog.resize_texture.fill.transparent": "Transparent",
"dialog.resize_texture.fill.color": "Color",
"dialog.resize_texture.fill.repeat": "Repeat",
"dialog.resize_texture.fill.stretch": "Stretch",
"dialog.scale.element_pivot": "Element Pivot",
"dialog.scale.selection_center": "Selection Center",
"dialog.create_gif.length_mode": "Length Mode",
"dialog.create_gif.length_mode.seconds": "Seconds",
"dialog.create_gif.length_mode.frames": "Frames",
"dialog.create_gif.length_mode.animation": "Animation Length",
"dialog.create_gif.length_mode.turntable": "Turntable Rotation",
"dialog.save_angle.projection": "Projection",
"dialog.save_angle.projection.perspective": "Perspective",
"dialog.save_angle.projection.orthographic": "Orthographic",
"dialog.sketchfab_uploader.animations": "Animations",
"dialog.settings.theme": "Theme",
"settings.category.interface": "Interface",
"settings.preview_checkerboard": "Preview Checkerboard",
"settings.preview_checkerboard.desc": "Toggle the checkerboard background behind the preview",
"settings.uv_checkerboard": "UV Editor Checkerboard",
"settings.uv_checkerboard.desc": "Toggle the checkerboard background behind the UV editor",
"category.paint": "Paint",
"action.fill_mode.color_connected": "Connected Colors",
"action.draw_shape_type": "Shape Type",
"action.draw_shape_type.rectangle": "Rectangle",
"action.draw_shape_type.rectangle_h": "Rectangle (Hollow)",
"action.draw_shape_type.ellipse": "Ellipse",
"action.draw_shape_type.ellipse_h": "Ellipse (Hollow)",
"action.draw_shape_type.line": "Line",
"action.mirror_painting": "Mirror Painting",
"action.mirror_painting.description": "Mirror your paint strokes to the other side of the model",
"action.lock_alpha": "Lock Alpha Channel",
"action.lock_alpha.description": "Lock the transparency of all pixels",
"action.draw_shape_tool": "Draw Shape",
"action.draw_shape_tool.desc": "Tool to draw simple shapes on textures",
"action.copy_paste_tool": "Copy Paste Tool",
"action.copy_paste_tool.desc": "Tool to copy and paste selections of textures",
"action.export_gltf": "Export As glTF",
"action.export_gltf.desc": "Export model and animations as glTF file to use in other 3D applications",
"action.transform_space": "Transform Space",
"action.transform_space.desc": "Default transform space for elements and bones",
"action.transform_space.global": "Global",
"action.transform_space.bone": "Bone",
"action.transform_space.local": "Local",
"action.toggle_camera_projection": "Toggle Camera Projection",
"action.toggle_camera_projection.desc": "Toggle the camera projection between perspective and orthographic",
"action.load_camera_angle": "Camera Angle: %0",
"action.load_camera_angle.desc": "Load the camera angle '%0'",
"action.slider_face_tint": "Tint Index",
"action.slider_face_tint.desc": "Set the tint index of the current face. -1 means unset.",
"menu.help.quickstart": "Quickstart Wizard",
"menu.help.developer": "Developer",
"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.cache_reload": "Cache Reload",
"menu.texture.resize": "Resize...",
"menu.preview.orthographic": "Orthographic",
"menu.preview.save_angle": "Save Angle...",
"menu.preview.angle": "Angles",
"menu.preview.angle.initial": "Initial Angle",
"menu.preview.angle.load": "Load",
"menu.preview.maximize": "Maximize",
"panel.color.both": "Both",
"uv_editor.copy_selection": "Copy Selection",
"uv_editor.paste_selection": "Paste Selection",
"uv_editor.copy_paste_tool.place": "Place",
"uv_editor.copy_paste_tool.cut": "Cut",
"uv_editor.copy_paste_tool.mirror_x": "Mirror X",
"uv_editor.copy_paste_tool.mirror_y": "Mirror Y",
"uv_editor.copy_paste_tool.rotate": "Rotate 90 Degrees"
}

View File

@ -11,6 +11,7 @@
"dialog.save": "Save",
"dialog.discard": "Discard",
"dialog.continue": "Continue",
"dialog.ignore": "Ignore",
"dialog.dontshowagain": "Don't Show Again",
"data.cube": "Cube",
@ -37,6 +38,7 @@
"generic.help": "Help",
"generic.name": "Name",
"generic.none": "None",
"generic.unset": "Unset",
"dates.today": "Today",
"dates.yesterday": "Yesterday",
@ -140,6 +142,8 @@
"message.unsaved_textures.message": "Your model has unsaved textures. Make sure to save them and paste them into your resource pack in the correct folder.",
"message.model_clipping.title": "Model Too Large",
"message.model_clipping.message": "Your model contains %0 cubes that are larger than the 3x3x3 limit allowed by Minecraft. This model will not work in Minecraft.",
"message.invalid_builtin_parent.title": "Invalid Built-in Parent",
"message.invalid_builtin_parent.message": "The link to the invalid parent model '%0' was removed in order to export a valid model.",
"message.cleared_blank_faces.title": "Blank Faces",
"message.cleared_blank_faces.message": "Blockbench has found %0 cubes without any texture. Do you want to remove those elements?",
@ -205,8 +209,6 @@
"message.wireframe.enabled": "Wireframe view enabled",
"message.wireframe.disabled": "Wireframe view disabled",
"message.checkerboard.enabled": "Checkerboard enabled",
"message.checkerboard.disabled": "Checkerboard disabled",
"message.timelapse_start": "Timelapse started",
"message.timelapse_stop": "Timelapse stopped",
@ -241,6 +243,12 @@
"dialog.texture.namespace": "Namespace",
"dialog.texture.folder": "Folder",
"dialog.resize_texture.fill": "Fill with",
"dialog.resize_texture.fill.transparent": "Transparent",
"dialog.resize_texture.fill.color": "Color",
"dialog.resize_texture.fill.repeat": "Repeat",
"dialog.resize_texture.fill.stretch": "Stretch",
"dialog.extrude.title": "Extrude Image",
"dialog.extrude.mode": "Scan Mode",
"dialog.extrude.mode.areas": "Areas",
@ -264,6 +272,8 @@
"dialog.scale.title": "Scale Model",
"dialog.scale.axis": "Axis",
"dialog.scale.scale": "Scale",
"dialog.scale.element_pivot": "Element Pivot",
"dialog.scale.selection_center": "Selection Center",
"dialog.scale.clipping": "Model clipping: Your model is too large for the canvas",
"dialog.scale.confirm": "Scale",
"dialog.scale.select_overflow": "Select Overflow",
@ -298,7 +308,12 @@
"dialog.create_texture.resolution": "Resolution",
"dialog.create_gif.title": "Record GIF",
"dialog.create_gif.length": "Length (Seconds)",
"dialog.create_gif.length_mode": "Length Mode",
"dialog.create_gif.length_mode.seconds": "Seconds",
"dialog.create_gif.length_mode.frames": "Frames",
"dialog.create_gif.length_mode.animation": "Animation Length",
"dialog.create_gif.length_mode.turntable": "Turntable Rotation",
"dialog.create_gif.length": "Length",
"dialog.create_gif.fps": "FPS",
"dialog.create_gif.compression": "Compression Amount",
"dialog.create_gif.turn": "Turntable Speed",
@ -310,6 +325,10 @@
"dialog.timelapse.source.locked": "Locked Angle",
"dialog.timelapse.destination": "Destination Folder",
"dialog.save_angle.projection": "Projection",
"dialog.save_angle.projection.perspective": "Perspective",
"dialog.save_angle.projection.orthographic": "Orthographic",
"dialog.input.title": "Input",
"dialog.update.title": "Updates",
@ -346,7 +365,7 @@
"dialog.settings.settings": "Settings",
"dialog.settings.keybinds": "Keybindings",
"dialog.settings.layout": "Layout",
"dialog.settings.theme": "Theme",
"dialog.settings.about": "About",
"dialog.settings.search_results": "Search Results",
@ -398,6 +417,7 @@
"about.libraries": "Libraries:",
"settings.category.general": "General",
"settings.category.interface": "Interface",
"settings.category.preview": "Preview",
"settings.category.grid": "Grid",
"settings.category.edit": "Edit",
@ -438,6 +458,10 @@
"settings.volume.desc": "Volume control for sound effects in animations",
"settings.outliner_colors": "Outliner Colors",
"settings.outliner_colors.desc": "Display cube colors in the outliner",
"settings.preview_checkerboard": "Preview Checkerboard",
"settings.preview_checkerboard.desc": "Toggle the checkerboard background behind the preview",
"settings.uv_checkerboard": "UV Editor Checkerboard",
"settings.uv_checkerboard.desc": "Toggle the checkerboard background behind the UV editor",
"settings.base_grid": "Small Grid",
"settings.base_grid.desc": "Show small grid and axes",
@ -519,6 +543,7 @@
"category.edit": "Edit",
"category.transform": "Transform",
"category.color": "Color",
"category.paint": "Paint",
"category.filter": "Filter",
"category.view": "View",
"category.display": "Display Settings",
@ -544,13 +569,21 @@
"action.slider_origin": "Pivot %0",
"action.slider_origin.desc": "Move pivot on the %0 axis",
"action.brush_mode": "Brush Mode",
"action.brush_mode.brush": "Round",
"action.brush_mode.noise": "Noise",
"action.fill_mode": "Fill Mode",
"action.fill_mode.face": "Face",
"action.fill_mode.color": "Color",
"action.fill_mode.color_connected": "Connected Colors",
"action.fill_mode.color": "Colors",
"action.fill_mode.cube": "Cube",
"action.draw_shape_type": "Shape Type",
"action.draw_shape_type.rectangle": "Rectangle",
"action.draw_shape_type.rectangle_h": "Rectangle (Hollow)",
"action.draw_shape_type.ellipse": "Ellipse",
"action.draw_shape_type.ellipse_h": "Ellipse (Hollow)",
"action.draw_shape_type.line": "Line",
"action.mirror_painting": "Mirror Painting",
"action.mirror_painting.description": "Mirror your paint strokes to the other side of the model",
"action.lock_alpha": "Lock Alpha Channel",
"action.lock_alpha.description": "Lock the transparency of all pixels",
"action.slider_brush_size": "Size",
"action.slider_brush_size.desc": "Radius of the brush in pixels",
"action.slider_brush_opacity": "Opacity",
@ -590,6 +623,10 @@
"action.eraser.desc": "Eraser tool to replace colors on a texture with transparency",
"action.color_picker": "Color Picker",
"action.color_picker.desc": "Tool to pick the color of pixels on your texture",
"action.draw_shape_tool": "Draw Shape",
"action.draw_shape_tool.desc": "Tool to draw simple shapes on textures",
"action.copy_paste_tool": "Copy Paste Tool",
"action.copy_paste_tool.desc": "Tool to copy and paste selections of textures",
"action.toggle_skin_layer": "Toggle Skin Layer",
"action.toggle_skin_layer.desc": "Toggle the hat and clothing layer of the skin model",
@ -641,7 +678,7 @@
"action.save_project.desc": "Saves the current model as a project file",
"action.save_project_as": "Save Project As",
"action.save_project_as.desc": "Saves the current model as a project file at a new location",
"action.export_over": "Overwrite Model",
"action.export_over": "Save Model",
"action.export_over.desc": "Saves the model, textures and animations by overwriting the files",
"action.settings_window": "Settings...",
@ -695,6 +732,7 @@
"action.outliner_toggle": "Toggle More Options",
"action.outliner_toggle.desc": "Toggles switches for more options in the outliner",
"action.cube_counter": "Cube Counter",
"action.cube_counter": "Displays the current number of cubes and other statistics",
"action.duplicate": "Duplicate",
"action.duplicate.desc": "Duplicates the selected cubes or group",
@ -702,8 +740,6 @@
"action.delete.desc": "Deletes the selected cubes or group",
"action.sort_outliner": "Sort Outliner",
"action.sort_outliner.desc": "Sort the outliner alphabetically",
"action.local_move": "Move Relative",
"action.local_move.desc": "Move rotated elements on their own axes if possible",
"action.element_colors": "Cube Colors",
"action.element_colors.desc": "Show cube colors in the outliner",
"action.select_window": "Select...",
@ -731,6 +767,11 @@
"action.clear_palette": "Clear Palette",
"action.clear_palette.desc": "Remove all colors from the palette",
"action.transform_space": "Transform Space",
"action.transform_space.desc": "Default transform space for elements and bones",
"action.transform_space.global": "Global",
"action.transform_space.bone": "Bone",
"action.transform_space.local": "Local",
"action.scale": "Scale...",
"action.scale.desc": "Scale the selected cubes",
"action.rotate_cw": "Rotate %0 +90",
@ -742,24 +783,24 @@
"action.center": "Center %0",
"action.center.desc": "Center the selected cubes on the %0 axis",
"action.center_all": "Center All",
"action.center_all.desc": "Center the selected cubes.",
"action.center_all.desc": "Center the selected cubes",
"action.toggle_visibility": "Toggle Visibility",
"action.toggle_visibility.desc": "Toggle the visibility of the selected cubes.",
"action.toggle_visibility.desc": "Toggle the visibility of the selected cubes",
"action.toggle_export": "Toggle Export",
"action.toggle_export.desc": "Toggle the export setting of the selected cubes.",
"action.toggle_export.desc": "Toggle the export setting of the selected cubes",
"action.toggle_autouv": "Toggle Auto UV",
"action.toggle_autouv.desc": "Toggle the auto UV setting of the selected cubes.",
"action.toggle_autouv.desc": "Toggle the auto UV setting of the selected cubes",
"action.toggle_shade": "Toggle Shading",
"action.toggle_shade.desc": "Toggle the shading of the selected cubes.",
"action.toggle_shade.desc": "Toggle the shading of the selected cubes",
"action.toggle_mirror_uv": "Mirror UV",
"action.toggle_mirror_uv.desc": "Toggle the UV mirroring on the X axis of the selected cubes.",
"action.toggle_mirror_uv.desc": "Toggle the UV mirroring on the X axis of the selected cubes",
"action.rename": "Rename",
"action.rename.desc": "Change the name of the selected cubes.",
"action.rename.desc": "Change the name of the selected cubes",
"action.update_autouv": "Update Auto UV",
"action.update_autouv.desc": "Update the auto UV mapping of the selected cubes",
"action.add_display_preset": "New Preset",
"action.add_display_preset.desc": "Add a new display setting preset.",
"action.add_display_preset.desc": "Add a new display setting preset",
"action.gui_light": "GUI Light",
"action.gui_light.desc": "Select the way the item is lit in the inventory",
"action.gui_light.side": "Side Light",
@ -790,8 +831,6 @@
"action.reset_interface.desc": "Reset size and positions of the GUI",
"action.toggle_wireframe": "Toggle Wireframe",
"action.toggle_wireframe.desc": "Toggle the wireframe display mode",
"action.toggle_checkerboard": "Toggle Checkerboard",
"action.toggle_checkerboard.desc": "Toggle the checkerboard background behind the preview or UV editor",
"action.screenshot_model": "Screenshot Model",
"action.screenshot_model.desc": "Take a cropped screenshot of the model from the current angle",
"action.record_model_gif": "Record GIF",
@ -802,12 +841,14 @@
"action.screenshot_app.desc": "Take a screenshot of the whole application",
"action.toggle_quad_view": "Toggle Quad View",
"action.toggle_quad_view.desc": "Toggle the 4 viewport mode",
"action.camera_reset": "Reset Camera",
"action.camera_reset.desc": "Reset the current preview to the default camera angle",
"action.toggle_camera_projection": "Toggle Camera Projection",
"action.toggle_camera_projection.desc": "Toggle the camera projection between perspective and orthographic",
"action.sidebar_left": "Textures and UV",
"action.sidebar_left.desc": "Open the interface for UV and textures",
"action.sidebar_right": "Elements",
"action.sidebar_right.desc": "Open the interface to edit elements",
"action.load_camera_angle": "Camera Angle: %0",
"action.load_camera_angle.desc": "Load the camera angle '%0'",
"action.import_texture": "Import Texture",
"action.import_texture.desc": "Import one or more textures from your file system",
@ -860,6 +901,8 @@
"action.auto_cullface.desc": "Sets the cullface for this face to itself",
"action.face_tint": "Tint",
"action.face_tint.desc": "Enables the tint option for the current face",
"action.slider_face_tint": "Tint Index",
"action.slider_face_tint.desc": "Set the tint index of the current face. -1 means unset.",
"action.toggle_uv_overlay": "Toggle UV Overlay",
"action.toggle_uv_overlay.desc": "When enabled, displays all UV mapping overlays above the texture.",
"action.remove_blank_faces": "Remove Blank Faces",
@ -944,11 +987,17 @@
"menu.view.screenshot": "Screenshot",
"menu.help.discord": "Discord Server",
"menu.help.quickstart": "Quickstart Wizard",
"menu.help.report_issue": "Report an Issue",
"menu.help.plugin_documentation": "Plugin API Documentation",
"menu.help.search_action": "Search and Run Action",
"menu.help.donate": "Donate",
"menu.help.about": "About...",
"menu.help.developer": "Developer",
"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.cache_reload": "Cache Reload",
"menu.cube.color": "Marker Color",
"menu.cube.texture": "Texture",
@ -968,6 +1017,8 @@
"menu.texture.refresh": "Refresh",
"menu.texture.change": "Change File",
"menu.texture.folder": "Open in Folder",
"menu.texture.resize": "Resize...",
"menu.texture.edit": "Edit",
"menu.texture.particle": "Use for Particles",
"menu.texture.export": "Save As",
@ -980,13 +1031,19 @@
"menu.preview.background.position": "Position",
"menu.preview.background.set_position": "Set Position",
"menu.preview.background.lock": "Lock To Camera",
"menu.preview.background.remove": "Remove",
"menu.preview.screenshot": "Screenshot",
"menu.preview.orthographic": "Orthographic",
"menu.preview.save_angle": "Save Angle...",
"menu.preview.angle": "Angles",
"menu.preview.angle.initial": "Initial Angle",
"menu.preview.angle.load": "Load",
"menu.preview.perspective": "Perspective",
"menu.preview.perspective.normal": "Normal",
"menu.preview.perspective.reset": "Reset Camera",
"menu.preview.quadview": "Quad View",
"menu.preview.fullview": "Full View",
"menu.preview.maximize": "Maximize",
"menu.preview.stop_drag": "Stop Background Positioning",
"menu.uv.select": "Select Cubes",
@ -995,7 +1052,6 @@
"menu.uv.mapping.rotation": "Rotation",
"menu.uv.mapping.mirror_x": "Mirror X",
"menu.uv.mapping.mirror_y": "Mirror Y",
"menu.uv.tint": "Tint",
"menu.uv.texture": "Texture",
"menu.toolbar.edit": "Customize",
@ -1037,6 +1093,7 @@
"panel.color": "Color",
"panel.color.picker": "Picker",
"panel.color.palette": "Palette",
"panel.color.both": "Both",
"panel.outliner": "Outliner",
"panel.chat": "Chat",
"panel.animations": "Animations",
@ -1072,6 +1129,14 @@
"uv_editor.cullface_off": "Cullface Off",
"uv_editor.tint_on": "Tint On",
"uv_editor.tint_off": "Tint Off",
"uv_editor.copy_selection": "Copy Selection",
"uv_editor.paste_selection": "Paste Selection",
"uv_editor.copy_paste_tool.place": "Place",
"uv_editor.copy_paste_tool.cut": "Cut",
"uv_editor.copy_paste_tool.mirror_x": "Mirror X",
"uv_editor.copy_paste_tool.mirror_y": "Mirror Y",
"uv_editor.copy_paste_tool.rotate": "Rotate 90 Degrees",
"face.north": "North",
"face.south": "South",

View File

@ -47,7 +47,7 @@
"keys.printscreen": "Impr. Pantalla",
"keys.pause": "Pausa",
"message.rotation_limit.title": "Límites de Rotación",
"message.rotation_limit.message": "Las rotaciones están limitadas por Minecraft en un sólo eje y en incrementos de 22.5 grados. Rotar en un eje diferente quitará la rotación en otros ejes. Desactiva la opción \"Rotación Restringida\" si están modelando para otros propósitos y necesitas rotación libre.",
"message.rotation_limit.message": "Las rotaciones están limitadas por Minecraft en un sólo eje y en incrementos de 22.5 grados. Rotar en un eje diferente quitará la rotación en otros ejes. Convierte el modelo a \"Modelo Libre\" si quieres modelar para otros propósitos y necesitas rotaciones libres.",
"message.file_not_found.title": "Archivo no encontrado",
"message.file_not_found.message": "Blockbench no pudo encontrar el archivo pedido. Asegúrate de que está guardado localmente y no en una nube.",
"message.screenshot.title": "Captura de pantalla",
@ -65,7 +65,7 @@
"message.unsaved_textures.title": "Texturas sin guardadas",
"message.unsaved_textures.message": "Tu modelo tiene texturas sin guardar. Asegúrate de guardarlas y pegarlas en el Resource Pack en la carpeta correcta",
"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 3x3x3 establecido por Minecraft. Este modelo no funcionará en Minecraft. Activa la opción \"Bordes Restringidos\" para prevenir esto.",
"message.model_clipping.message": "Tu modelo contiene %0 cubos que son más grandes que el límite 3x3x3 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",
@ -102,8 +102,8 @@
"dialog.project.geoname": "Nombre de la Geometría del Mob",
"dialog.project.openparent": "Abrir Padre",
"dialog.project.ao": "Oclusión Ambiental",
"dialog.project.width": "Anchura",
"dialog.project.height": "Altura",
"dialog.project.width": "Anchura de Textura",
"dialog.project.height": "Altura de Textura",
"dialog.texture.title": "Textura",
"dialog.texture.variable": "Variable",
"dialog.texture.namespace": "Espacio del Nombre",
@ -157,7 +157,6 @@
"dialog.update.connecting": "Conectando con el servidor",
"dialog.settings.settings": "Ajustes",
"dialog.settings.keybinds": "Atajos de Teclado",
"dialog.settings.layout": "Apariencia",
"dialog.settings.about": "Acerca de",
"layout.color.back": "Fondo",
"layout.color.back.desc": "Fondos y cajas de entrada",
@ -180,9 +179,9 @@
"layout.color.text": "Texto",
"layout.color.text.desc": "Texto normal",
"layout.color.light": "Claro",
"layout.color.light.desc": "Texto seleccionado",
"layout.color.light.desc": "Texto destacado",
"layout.color.accent_text": "Acento del texto",
"layout.color.accent_text.desc": "Texto en elementos acentuados",
"layout.color.accent_text.desc": "Texto en elementos claros o acentuados",
"layout.font.main": "Fuente principal",
"layout.font.headline": "Fuente para títulos",
"about.version": "Versión:",
@ -207,8 +206,8 @@
"settings.show_actions.desc": "Mostrar todas las acciones en la barra de estado",
"settings.backup_interval": "Intervalo de Backup",
"settings.backup_interval.desc": "Intervalo de los backups automáticos en minutos",
"settings.origin_size": "Origen de rotación",
"settings.origin_size.desc": "Tamaño del origen de rotación",
"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",
@ -236,7 +235,7 @@
"settings.paint_side_restrict": "Restringir el pincel a los lados",
"settings.paint_side_restrict.desc": "Restringir los pinceles para sólo pintar en el lado actual",
"settings.autouv": "Auto UV",
"settings.autouv.desc": "Activar AutoUV por defecto",
"settings.autouv.desc": "Activar Auto UV por defecto",
"settings.create_rename": "Renombrar Nuevo Cubo",
"settings.create_rename.desc": "Campo de nombre de enfoque al crear nuevo elemento o grupo",
"settings.edit_size": "Resolución de la Cuadrícula",
@ -305,25 +304,25 @@
"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.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.vertex_snap_tool.desc": "Mover un cubo a otro cubo al conectar 2 vértices",
"action.swap_tools": "Cambiar Herramientas",
"action.swap_tools.desc": "Cambiar entre la herramienta para mover y para reescalar",
"action.project_window": "Proyecto...",
"action.project_window.desc": "Abre la ventana del proyecto, donde puedes cambiar la metadata de tu modelo",
"action.open_model": "Abrir Modelo",
"action.open_model.desc": "Abre un archivo de modelo de tu ordenador.",
"action.open_model.desc": "Abre un archivo de modelo de tu ordenador",
"action.add_model": "Añadir Modelo",
"action.add_model.desc": "Añade un modelo desde un archivo al modelo actual",
"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_optifine_part": "Exportar a OptiFine JPM",
"action.export_optifine_part.desc": "Exportar un modelo de parte de entidad para OptiFine",
"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": "Crear un modelo WaveFront OBJ para usar en otros programas",
"action.export_obj.desc": "Exportar a un modelo Wavefront OBJ para renderizar o motores de juego",
"action.settings_window": "Ajustes...",
"action.settings_window.desc": "Abre la ventana de ajustes de Blockbench",
"action.plugins_window": "Plugins...",
@ -364,8 +363,6 @@
"action.delete.desc": "Borra los grupos o cubos seleccionados",
"action.sort_outliner": "Ordenar Esquema",
"action.sort_outliner.desc": "Ordena el esquema alfabéticamente",
"action.local_move": "Mover relativamente",
"action.local_move.desc": "Mueve los elementos en su propio eje si es posible",
"action.select_window": "Seleccionar...",
"action.select_window.desc": "Busca y selecciona cubos basados en sus propiedades",
"action.invert_selection": "Invertir Selección",
@ -401,7 +398,7 @@
"action.reset_interface": "Resetar Interfaz",
"action.reset_interface.desc": "Resetea el tamaño y las posiciones de la Interfaz.",
"action.toggle_wireframe": "Activar estructura",
"action.toggle_wireframe.desc": "Activa el modo de visualización de la estructura",
"action.toggle_wireframe.desc": "Cambiar el modo de visualización de la estructura",
"action.screenshot_model": "Captura de Pantalla del Modelo",
"action.screenshot_model.desc": "Toma una captura de pantalla recortada del modelo desde el ángulo actual",
"action.screenshot_app": "Captura de Pantalla de la Aplicación",
@ -416,14 +413,14 @@
"action.save_textures.desc": "Guarda todas las texturas que no han sido guardadas",
"action.animated_textures": "Activar Texturas Animadas",
"action.animated_textures.desc": "Activa y pone en pausa la previsualización de las texturas animadas",
"action.origin_to_geometry": "Origen a Geometría",
"action.origin_to_geometry.desc": "Pone el origen al centro de la geometría",
"action.origin_to_geometry": "Centrar Pivote",
"action.origin_to_geometry.desc": "Pone el punto de pivote al centro de la selección",
"action.rescale_toggle": "Cambiar Reescalado",
"action.rescale_toggle.desc": "Reescalar cubos basándonse en su rotación actual",
"action.bone_reset_toggle": "Resetear Hueso",
"action.bone_reset_toggle.desc": "Impide que el hueso muestre cubos del modelo padre",
"action.reload": "Recargar Blockbench",
"action.reload.desc": "Reinicia Blockbench. Esto borrará todo el progreso no guardado.",
"action.reload.desc": "Reinicia Blockbench. Esto borrará todo el progreso no guardado",
"menu.file": "Archivo",
"menu.edit": "Editar",
"menu.transform": "Transformar",
@ -464,19 +461,16 @@
"menu.preview.background.load": "Cargar",
"menu.preview.background.position": "Posición",
"menu.preview.background.lock": "Fijar a la Cámara",
"menu.preview.background.remove": "Borrar",
"menu.preview.screenshot": "Captura de Pantalla",
"menu.preview.perspective": "Perspectiva",
"menu.preview.perspective.normal": "Normal",
"menu.preview.quadview": "Vista Cuádruple",
"menu.preview.fullview": "Vista Completa",
"menu.preview.stop_drag": "Parar la Colocación del Fondo",
"menu.uv.mapping": "Mapeado del UV",
"menu.uv.mapping.export": "Exportar",
"menu.uv.mapping.rotation": "Rotación",
"menu.uv.mapping.mirror_x": "Invertir X",
"menu.uv.mapping.mirror_y": "Invertir Y",
"menu.uv.tint": "Tintar",
"menu.uv.texture": "Textura",
"cube.color.light_blue": "Azul claro",
"cube.color.yellow": "Amarillo",
@ -547,7 +541,7 @@
"dialog.update.latest": "Última version",
"dialog.update.installed": "Versión instalada",
"dialog.update.update": "Actualizar",
"action.brush_mode.brush": "Pincel",
"action.brush_mode.brush": "Redondo",
"action.brush_mode.noise": "Ruido",
"action.vertex_snap_mode.move": "Mover",
"action.vertex_snap_mode.scale": "Reescalar",
@ -574,7 +568,7 @@
"action.uv_maximize.desc": "Configura el UV para esta cara a la textura completa",
"action.uv_auto": "Auto UV",
"action.uv_auto.desc": "Configura el tamaño del UV de esta cara al tamaño real de la propia cara",
"action.uv_rel_auto": "Rel. Auto UV",
"action.uv_rel_auto": "Auto UV Relativo",
"action.uv_rel_auto.desc": "Configura el UV de esta cara a la posición y tamaño de la propia cara",
"action.uv_mirror_x": "Invertir UV en X",
"action.uv_mirror_x.desc": "Invierte el UV de esta cara en el eje X",
@ -671,13 +665,11 @@
"message.bone_material": "Cambiar el material del hueso",
"action.slider_animation_length": "Duración de la Animación",
"action.slider_animation_length.desc": "Cambia la duración de la animación seleccionada",
"action.camera_reset": "Resetear Cámara",
"action.camera_reset.desc": "Resetea la previsualización actual al ángulo de cámara por defecto",
"panel.variable_placeholders": "Variables Temporales",
"panel.variable_placeholders.info": "Muestra las variables que quieres visualizar mediante nombre=valor",
"status_bar.vertex_distance": "Distancia: %0",
"dialog.create_gif.title": "Grabar GIF",
"dialog.create_gif.length": "Duración (Segundos)",
"dialog.create_gif.length": "Duración",
"dialog.create_gif.fps": "FPS",
"dialog.create_gif.compression": "Cantidad de Compresión",
"dialog.create_gif.play": "Empezar Animación",
@ -755,7 +747,7 @@
"settings.sketchfab_token": "Token de Sketchfab",
"settings.sketchfab_token.desc": "Token para autorizar a Blockbench a subir a tu cuenta de Sketchfab",
"panel.color": "Color",
"data.origin": "Origen",
"data.origin": "Pivote",
"message.sketchfab.success": "Modelo subido con éxito",
"message.sketchfab.error": "La subida del modelo a Sketchfab ha fallado",
"settings.outliner_colors": "Colores del Borde",
@ -785,8 +777,8 @@
"edit_session.join": "Entrar a Sesión",
"edit_session.create": "Crear Sesión",
"edit_session.quit": "Salir de Sesión",
"edit_session.joined": "Usuario %0 ha entrado la sesión",
"edit_session.left": "Usuario %0 ha salido de la sesión",
"edit_session.joined": "%0 ha entrado a la sesión",
"edit_session.left": "%0 ha salido de la sesión",
"edit_session.quit_session": "Salir de la sesión actual",
"edit_session.status": "Estado",
"edit_session.hosting": "Anfitrión",
@ -926,7 +918,7 @@
"action.flip.desc": "Voltea los cubos seleccionados en el eje %0",
"action.center": "Centrar %0",
"action.center.desc": "Centra los cubos seleccionados en el eje %0",
"action.bring_up_all_animations": "Trae todos los animadores modificados a la timeline",
"action.bring_up_all_animations": "Subir Todas las Animaciones",
"panel.bone": "Hueso",
"data.color": "Color",
"generic.export": "Exportar",
@ -934,8 +926,6 @@
"status_bar.recording": "Grabando Timelapse",
"message.add_to_palette": "Añadido a la paleta",
"message.size_modifiers": "Mantén pulsado Ctrl o Shift para transformar en incrementos más pequeños",
"message.checkerboard.enabled": "Cuadrícula habilitada",
"message.checkerboard.disabled": "Cuadrícula deshabilitada",
"message.timelapse_start": "Timelapse iniciado",
"message.timelapse_stop": "Timelapse parado",
"message.import_palette.replace_palette": "Reemplazar paleta vieja",
@ -981,12 +971,10 @@
"action.sort_palette.desc": "Organiza todos los colores de la paleta por color y brillo",
"action.clear_palette": "Limpiar Paleta",
"action.clear_palette.desc": "Elimina todos los colores de la Paleta",
"action.toggle_checkerboard": "Cambiar Cuadrícula",
"action.toggle_checkerboard.desc": "Cambia el fondo de la cuadrícula detrás de la previsualización o el editor de UV",
"action.timelapse": "Timelapse...",
"action.timelapse.desc": "Graba un timelapse de tu proceso de modelaje",
"action.add_keyframe": "Añadir Frame Clave",
"action.add_keyframe.desc": "Añade un frame clave automáticamente. Pulsa Alt para forzar los valores por defecto",
"action.add_keyframe.desc": "Añade un frame clave automáticamente. Pulsa shift para forzar los valores por defecto",
"action.bring_up_all_animations.desc": "Trae todos los animadores modificados a la timeline",
"timeline.timeline": "Instrucciones",
"menu.palette.load": "Cargar Paleta",
@ -1023,5 +1011,81 @@
"menu.help.search_action": "Buscar y Ejecutar Acción",
"menu.help.donate": "Donar",
"menu.help.about": "Acerca de...",
"menu.preview.background.clipboard": "Cargar desde Portapapeles"
"menu.preview.background.clipboard": "Cargar desde Portapapeles",
"dialog.ignore": "Ignore",
"generic.unset": "Unset",
"message.invalid_builtin_parent.title": "Invalid Built-in Parent",
"message.invalid_builtin_parent.message": "The link to the invalid parent model '%0' was removed in order to export a valid model.",
"dialog.resize_texture.fill": "Fill with",
"dialog.resize_texture.fill.transparent": "Transparent",
"dialog.resize_texture.fill.color": "Color",
"dialog.resize_texture.fill.repeat": "Repeat",
"dialog.resize_texture.fill.stretch": "Stretch",
"dialog.scale.element_pivot": "Element Pivot",
"dialog.scale.selection_center": "Selection Center",
"dialog.create_gif.length_mode": "Length Mode",
"dialog.create_gif.length_mode.seconds": "Seconds",
"dialog.create_gif.length_mode.frames": "Frames",
"dialog.create_gif.length_mode.animation": "Animation Length",
"dialog.create_gif.length_mode.turntable": "Turntable Rotation",
"dialog.save_angle.projection": "Projection",
"dialog.save_angle.projection.perspective": "Perspective",
"dialog.save_angle.projection.orthographic": "Orthographic",
"dialog.sketchfab_uploader.animations": "Animations",
"dialog.settings.theme": "Theme",
"settings.category.interface": "Interface",
"settings.preview_checkerboard": "Preview Checkerboard",
"settings.preview_checkerboard.desc": "Toggle the checkerboard background behind the preview",
"settings.uv_checkerboard": "UV Editor Checkerboard",
"settings.uv_checkerboard.desc": "Toggle the checkerboard background behind the UV editor",
"category.paint": "Paint",
"action.fill_mode.color_connected": "Connected Colors",
"action.draw_shape_type": "Shape Type",
"action.draw_shape_type.rectangle": "Rectangle",
"action.draw_shape_type.rectangle_h": "Rectangle (Hollow)",
"action.draw_shape_type.ellipse": "Ellipse",
"action.draw_shape_type.ellipse_h": "Ellipse (Hollow)",
"action.draw_shape_type.line": "Line",
"action.mirror_painting": "Mirror Painting",
"action.mirror_painting.description": "Mirror your paint strokes to the other side of the model",
"action.lock_alpha": "Lock Alpha Channel",
"action.lock_alpha.description": "Lock the transparency of all pixels",
"action.draw_shape_tool": "Draw Shape",
"action.draw_shape_tool.desc": "Tool to draw simple shapes on textures",
"action.copy_paste_tool": "Copy Paste Tool",
"action.copy_paste_tool.desc": "Tool to copy and paste selections of textures",
"action.export_gltf": "Export As glTF",
"action.export_gltf.desc": "Export model and animations as glTF file to use in other 3D applications",
"action.transform_space": "Transform Space",
"action.transform_space.desc": "Default transform space for elements and bones",
"action.transform_space.global": "Global",
"action.transform_space.bone": "Bone",
"action.transform_space.local": "Local",
"action.toggle_camera_projection": "Toggle Camera Projection",
"action.toggle_camera_projection.desc": "Toggle the camera projection between perspective and orthographic",
"action.load_camera_angle": "Camera Angle: %0",
"action.load_camera_angle.desc": "Load the camera angle '%0'",
"action.slider_face_tint": "Tint Index",
"action.slider_face_tint.desc": "Set the tint index of the current face. -1 means unset.",
"menu.help.quickstart": "Quickstart Wizard",
"menu.help.developer": "Developer",
"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.cache_reload": "Cache Reload",
"menu.texture.resize": "Resize...",
"menu.preview.orthographic": "Orthographic",
"menu.preview.save_angle": "Save Angle...",
"menu.preview.angle": "Angles",
"menu.preview.angle.initial": "Initial Angle",
"menu.preview.angle.load": "Load",
"menu.preview.maximize": "Maximize",
"panel.color.both": "Both",
"uv_editor.copy_selection": "Copy Selection",
"uv_editor.paste_selection": "Paste Selection",
"uv_editor.copy_paste_tool.place": "Place",
"uv_editor.copy_paste_tool.cut": "Cut",
"uv_editor.copy_paste_tool.mirror_x": "Mirror X",
"uv_editor.copy_paste_tool.mirror_y": "Mirror Y",
"uv_editor.copy_paste_tool.rotate": "Rotate 90 Degrees"
}

View File

@ -157,7 +157,6 @@
"dialog.update.connecting": "Connexion au serveur en cours",
"dialog.settings.settings": "Réglages",
"dialog.settings.keybinds": "Raccourcis clavier",
"dialog.settings.layout": "Disposition",
"dialog.settings.about": "À propos",
"layout.color.back": "Arrière",
"layout.color.back.desc": "Arrières-plans et champs de saisie",
@ -364,8 +363,6 @@
"action.delete.desc": "Supprime les cubes ou groupes sélectionnés",
"action.sort_outliner": "Trier la liste",
"action.sort_outliner.desc": "Trie la liste par ordre alphabétique",
"action.local_move": "Mouvement relatif",
"action.local_move.desc": "Déplacer les éléments pivotés selon leurs propres axes si possible",
"action.select_window": "Sélectionner…",
"action.select_window.desc": "Rechercher et sélectionner des cubes en fonction de leurs propriétés",
"action.invert_selection": "Inverser la sélection",
@ -464,19 +461,16 @@
"menu.preview.background.load": "Charger",
"menu.preview.background.position": "Position",
"menu.preview.background.lock": "Verrouiller à la caméra",
"menu.preview.background.remove": "Retirer",
"menu.preview.screenshot": "Capture décran",
"menu.preview.perspective": "Perspective",
"menu.preview.perspective.normal": "Normal",
"menu.preview.quadview": "Vue quadruple",
"menu.preview.fullview": "Vue complète",
"menu.preview.stop_drag": "Arrêter le positionnement en arrière-plan",
"menu.uv.mapping": "Mapping UV",
"menu.uv.mapping.export": "Exporter",
"menu.uv.mapping.rotation": "Rotation",
"menu.uv.mapping.mirror_x": "Miroir X",
"menu.uv.mapping.mirror_y": "Miroir Y",
"menu.uv.tint": "Teinte",
"menu.uv.texture": "Texture",
"cube.color.light_blue": "Bleu clair",
"cube.color.yellow": "Jaune",
@ -671,13 +665,11 @@
"message.bone_material": "Changer le matériau d'un os",
"action.slider_animation_length": "Longueur de l'animation",
"action.slider_animation_length.desc": "Changer la longueur de l'animation selectionnée",
"action.camera_reset": "Réinitialiser la caméra",
"action.camera_reset.desc": "Réinitialiser la prévisualisation actuelle à l'angle par défaut",
"panel.variable_placeholders": "Espaces de variables",
"panel.variable_placeholders.info": "Lister les variables à prévisualiser par nom=valeur",
"status_bar.vertex_distance": "Distance : %0",
"dialog.create_gif.title": "Enregistrer un GIF",
"dialog.create_gif.length": "Durée (secondes)",
"dialog.create_gif.length": "Durée",
"dialog.create_gif.fps": "FPS",
"dialog.create_gif.compression": "Taux de compression",
"dialog.create_gif.play": "Démarrer l'animation",
@ -772,7 +764,7 @@
"message.install_plugin": "Plugin %0 en cours d'installation",
"message.invalid_session.title": "Jeton de session invalide",
"message.invalid_session.message": "La session que vous essayez de rejoindre a expiré ou le jeton fourni n'est pas valide.",
"dialog.create_texture.power": "Taille puissance-de-2",
"dialog.create_texture.power": "Taille au carré",
"dialog.create_gif.turn": "Vitesse de rotation",
"action.edit_session": "Éditer la session…",
"action.edit_session.desc": "Connectez-vous à une session de travail pour collaborer avec d'autres utilisateurs",
@ -934,8 +926,6 @@
"status_bar.recording": "Enregistrement en cours",
"message.add_to_palette": "Ajouté à la palette",
"message.size_modifiers": "Maintenez Ctrl ou Shift pour de plus petits incréments",
"message.checkerboard.enabled": "Damier activé",
"message.checkerboard.disabled": "Damier désactivé",
"message.timelapse_start": "Timelapse démarré",
"message.timelapse_stop": "Timelapse arrêté",
"message.import_palette.replace_palette": "Remplacer l'ancienne palette",
@ -981,8 +971,6 @@
"action.sort_palette.desc": "Trier toutes les couleurs par teinte et luminosité",
"action.clear_palette": "Vider la palette",
"action.clear_palette.desc": "Retire toutes les couleurs de la palette",
"action.toggle_checkerboard": "Basculer damier",
"action.toggle_checkerboard.desc": "Activer/désactiver le damier d'arrière-plan derrière la preview ou l'éditeur UV",
"action.timelapse": "Timelapse…",
"action.timelapse.desc": "Enregistrer un timelapse de la modélisation",
"action.add_keyframe": "Ajouter une keyframe",
@ -1003,25 +991,101 @@
"action.add_marker.desc": "Définir un repère chronologique",
"timeline.pre_effect_script": "Scripte",
"format.skin": "Skin",
"format.skin.desc": "Edit player and entity skins",
"message.sketchfab.setup_guide": "Want to learn how to set up models in Sketchfab? Read %0",
"dialog.skin.title": "Create Skin",
"format.skin.desc": "Modifier les skins des joueurs et des entités",
"message.sketchfab.setup_guide": "Vous voulez apprendre comment mettre en place des modèles à Sketchfab ? Lire %0",
"dialog.skin.title": "Créer un skin",
"dialog.skin.model": "Skin",
"dialog.skin.texture": "Texture (Optional)",
"action.toggle_skin_layer": "Toggle Skin Layer",
"action.toggle_skin_layer.desc": "Toggle the hat and clothing layer of the skin model",
"action.gui_light": "GUI Light",
"action.gui_light.desc": "Select the way the item is lit in the inventory",
"action.gui_light.side": "Side Light",
"action.gui_light.front": "Front Light",
"action.move_keyframe_back": "Move Keyframes Back",
"action.move_keyframe_forth": "Move Keyframes Forth",
"menu.help": "Help",
"menu.help.discord": "Discord Server",
"menu.help.report_issue": "Report an Issue",
"menu.help.plugin_documentation": "Plugin API Documentation",
"menu.help.search_action": "Search and Run Action",
"menu.help.donate": "Donate",
"menu.help.about": "About...",
"menu.preview.background.clipboard": "Load from Clipboard"
"dialog.skin.texture": "Texture (optionnel)",
"action.toggle_skin_layer": "Alterner la couche du skin",
"action.toggle_skin_layer.desc": "Basculer la couche du chapeau et des vêtement du modèle du skin",
"action.gui_light": "Lumière dans la GUI",
"action.gui_light.desc": "Sélectionnez la façon dont l'item est éclairé dans l'inventaire",
"action.gui_light.side": "Lumière latérale",
"action.gui_light.front": "Lumière frontale",
"action.move_keyframe_back": "Déplacer les Keyframes vers l'arrière",
"action.move_keyframe_forth": "Déplacer les images clés",
"menu.help": "Aide",
"menu.help.discord": "Serveur Discord",
"menu.help.report_issue": "Rapporter un bug",
"menu.help.plugin_documentation": "Documentation de l'API du plugin",
"menu.help.search_action": "Chercher et exécuter une action",
"menu.help.donate": "Faire un dons",
"menu.help.about": "A propos",
"menu.preview.background.clipboard": "Charger depuis le presse-papier",
"dialog.ignore": "Ignore",
"generic.unset": "Unset",
"message.invalid_builtin_parent.title": "Invalid Built-in Parent",
"message.invalid_builtin_parent.message": "The link to the invalid parent model '%0' was removed in order to export a valid model.",
"dialog.resize_texture.fill": "Fill with",
"dialog.resize_texture.fill.transparent": "Transparent",
"dialog.resize_texture.fill.color": "Color",
"dialog.resize_texture.fill.repeat": "Repeat",
"dialog.resize_texture.fill.stretch": "Stretch",
"dialog.scale.element_pivot": "Element Pivot",
"dialog.scale.selection_center": "Selection Center",
"dialog.create_gif.length_mode": "Length Mode",
"dialog.create_gif.length_mode.seconds": "Seconds",
"dialog.create_gif.length_mode.frames": "Frames",
"dialog.create_gif.length_mode.animation": "Animation Length",
"dialog.create_gif.length_mode.turntable": "Turntable Rotation",
"dialog.save_angle.projection": "Projection",
"dialog.save_angle.projection.perspective": "Perspective",
"dialog.save_angle.projection.orthographic": "Orthographic",
"dialog.sketchfab_uploader.animations": "Animations",
"dialog.settings.theme": "Theme",
"settings.category.interface": "Interface",
"settings.preview_checkerboard": "Preview Checkerboard",
"settings.preview_checkerboard.desc": "Toggle the checkerboard background behind the preview",
"settings.uv_checkerboard": "UV Editor Checkerboard",
"settings.uv_checkerboard.desc": "Toggle the checkerboard background behind the UV editor",
"category.paint": "Paint",
"action.fill_mode.color_connected": "Connected Colors",
"action.draw_shape_type": "Shape Type",
"action.draw_shape_type.rectangle": "Rectangle",
"action.draw_shape_type.rectangle_h": "Rectangle (Hollow)",
"action.draw_shape_type.ellipse": "Ellipse",
"action.draw_shape_type.ellipse_h": "Ellipse (Hollow)",
"action.draw_shape_type.line": "Line",
"action.mirror_painting": "Mirror Painting",
"action.mirror_painting.description": "Mirror your paint strokes to the other side of the model",
"action.lock_alpha": "Lock Alpha Channel",
"action.lock_alpha.description": "Lock the transparency of all pixels",
"action.draw_shape_tool": "Draw Shape",
"action.draw_shape_tool.desc": "Tool to draw simple shapes on textures",
"action.copy_paste_tool": "Copy Paste Tool",
"action.copy_paste_tool.desc": "Tool to copy and paste selections of textures",
"action.export_gltf": "Export As glTF",
"action.export_gltf.desc": "Export model and animations as glTF file to use in other 3D applications",
"action.transform_space": "Transform Space",
"action.transform_space.desc": "Default transform space for elements and bones",
"action.transform_space.global": "Global",
"action.transform_space.bone": "Bone",
"action.transform_space.local": "Local",
"action.toggle_camera_projection": "Toggle Camera Projection",
"action.toggle_camera_projection.desc": "Toggle the camera projection between perspective and orthographic",
"action.load_camera_angle": "Camera Angle: %0",
"action.load_camera_angle.desc": "Load the camera angle '%0'",
"action.slider_face_tint": "Tint Index",
"action.slider_face_tint.desc": "Set the tint index of the current face. -1 means unset.",
"menu.help.quickstart": "Quickstart Wizard",
"menu.help.developer": "Developer",
"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.cache_reload": "Cache Reload",
"menu.texture.resize": "Resize...",
"menu.preview.orthographic": "Orthographic",
"menu.preview.save_angle": "Save Angle...",
"menu.preview.angle": "Angles",
"menu.preview.angle.initial": "Initial Angle",
"menu.preview.angle.load": "Load",
"menu.preview.maximize": "Maximize",
"panel.color.both": "Both",
"uv_editor.copy_selection": "Copy Selection",
"uv_editor.paste_selection": "Paste Selection",
"uv_editor.copy_paste_tool.place": "Place",
"uv_editor.copy_paste_tool.cut": "Cut",
"uv_editor.copy_paste_tool.mirror_x": "Mirror X",
"uv_editor.copy_paste_tool.mirror_y": "Mirror Y",
"uv_editor.copy_paste_tool.rotate": "Rotate 90 Degrees"
}

View File

@ -157,7 +157,6 @@
"dialog.update.connecting": "Connesione al server",
"dialog.settings.settings": "Impostazioni",
"dialog.settings.keybinds": "Tasti",
"dialog.settings.layout": "Layout",
"dialog.settings.about": "Sul Programma",
"layout.color.back": "Retro",
"layout.color.back.desc": "Sfondi e campi di input",
@ -364,8 +363,6 @@
"action.delete.desc": "Elimina i cubi o gruppi selezionati",
"action.sort_outliner": "Ordina Lista Elementi",
"action.sort_outliner.desc": "Ordina la lista degli elementi in ordine alfabetico",
"action.local_move": "Muovi Relativamente",
"action.local_move.desc": "Muovi elementi ruotati sul loro asse, se possibile",
"action.select_window": "Seleziona...",
"action.select_window.desc": "Cerca e seleziona cubi basandosi sulle loro proprietà",
"action.invert_selection": "Inverti Selezione",
@ -464,19 +461,16 @@
"menu.preview.background.load": "Caricare",
"menu.preview.background.position": "Posizione",
"menu.preview.background.lock": "Blocca Alla Videocamera",
"menu.preview.background.remove": "Rimuovi",
"menu.preview.screenshot": "Screenshot",
"menu.preview.perspective": "Prospettiva",
"menu.preview.perspective.normal": "Normale",
"menu.preview.quadview": "Vista Quadrupla",
"menu.preview.fullview": "Vista Completa",
"menu.preview.stop_drag": "Ferma Posizionamento Sfondo",
"menu.uv.mapping": "Mappatura UV",
"menu.uv.mapping.export": "Esporta",
"menu.uv.mapping.rotation": "Rotazione",
"menu.uv.mapping.mirror_x": "Specchia Asse X",
"menu.uv.mapping.mirror_y": "Specchia Asse Y",
"menu.uv.tint": "Tinta",
"menu.uv.texture": "Texture",
"cube.color.light_blue": "Azzurro",
"cube.color.yellow": "Giallo",
@ -494,7 +488,7 @@
"panel.display": "Display",
"panel.textures": "Texture",
"panel.outliner": "Outliner",
"uv_editor.title": "Editor UV",
"uv_editor.title": "Editore UV",
"uv_editor.all_faces": "Tutte",
"uv_editor.no_faces": "Nulla",
"face.north": "Nord",
@ -671,13 +665,11 @@
"message.bone_material": "Modifica il materiale dell'osso",
"action.slider_animation_length": "Lunghezza Dell'Animazione",
"action.slider_animation_length.desc": "Modifica la lunghezza dell'animazione selezionata",
"action.camera_reset": "Ripristina Videocamera",
"action.camera_reset.desc": "Ripristina l'anteprima corrente all'angolo della videocamera predefinito",
"panel.variable_placeholders": "Variabili Segnaposto",
"panel.variable_placeholders.info": "Elenca le variabili che vuoi vedere in anteprima facendo nome=valore",
"status_bar.vertex_distance": "Distanza: %0",
"dialog.create_gif.title": "Registra GIF",
"dialog.create_gif.length": "Lunghezza (secondi)",
"dialog.create_gif.length": "Lunghezza",
"dialog.create_gif.fps": "FPS",
"dialog.create_gif.compression": "Quantità di Compressione",
"dialog.create_gif.play": "Inizia Animazione",
@ -882,146 +874,218 @@
"panel.element.size": "Dimensione",
"panel.element.origin": "Origine",
"panel.element.rotation": "Rotazione",
"message.canvas_limit_error.title": "Canvas Limit Error",
"message.canvas_limit_error.title": "Errore di Limite della Tela",
"message.canvas_limit_error.message": "The action could not be performed correctly because the format limits the canvas to 48 units. Shift the pivot point to prevent this.",
"data.effect": "Effect",
"generic.name": "Name",
"settings.recent_projects": "Recent Model Cap",
"settings.recent_projects.desc": "Maximum number of recent models to remember",
"data.effect": "Effetto",
"generic.name": "Nome",
"settings.recent_projects": "Limite Modelli Recenti",
"settings.recent_projects.desc": "Numero massimo di modelli recenti da ricordare",
"settings.volume": "Volume",
"settings.volume.desc": "Volume control for sound effects in animations",
"action.change_keyframe_file": "Select File",
"action.change_keyframe_file.desc": "Select an audio file to preview a sound effect.",
"action.clear_timeline": "Clear Timeline",
"action.clear_timeline.desc": "Clear all unselected bones from the timeline",
"action.select_effect_animator": "Animate Effects",
"action.select_effect_animator.desc": "Opens timeline to add sound and particle effects",
"action.timeline_focus": "Channel",
"action.timeline_focus.desc": "Select the animation channels to display in the timeline",
"action.timeline_focus.all": "All",
"timeline.particle": "Particle",
"timeline.sound": "Sound",
"timeline.effects": "Effects",
"data.format": "Format",
"format.optifine_part": "OptiFine Part",
"format.optifine_part.desc": "JPM part for OptiFine entity models",
"action.reverse_keyframes": "Reverse Keyframes",
"action.reverse_keyframes.desc": "Reverse the order of the selected keyframes",
"generic.help": "Help",
"message.removed_faces": "Removed %0 faces",
"dialog.sketchfab_uploader.draft": "Draft",
"action.slider_pos": "Move %0",
"action.slider_pos.desc": "Move cubes on the %0 axis",
"action.slider_size": "Size %0",
"action.slider_size.desc": "Resize cubes on the %0 axis",
"action.slider_rotation": "Rotate %0",
"action.slider_rotation.desc": "Rotate cubes on the %0 axis",
"action.slider_origin": "Pivot %0",
"action.slider_origin.desc": "Move pivot on the %0 axis",
"action.rotate_cw": "Rotate %0 +90",
"action.rotate_cw.desc": "Rotate the selected cubes 90° on the %0 axis",
"action.rotate_ccw": "Rotate %0 -90",
"action.rotate_ccw.desc": "Rotate the selected cubes -90° on the %0 axis",
"action.flip": "Flip %0",
"action.flip.desc": "Flip the selected cubes on the %0 axis",
"action.center": "Center %0",
"action.center.desc": "Center the selected cubes on the %0 axis",
"action.bring_up_all_animations": "Bring Up All Animations",
"panel.bone": "Bone",
"data.color": "Color",
"generic.export": "Export",
"generic.none": "None",
"status_bar.recording": "Recording Timelapse",
"message.add_to_palette": "Added to palette",
"message.size_modifiers": "Hold down Ctrl or Shift to transform in smaller increments.",
"message.checkerboard.enabled": "Checkerboard enabled",
"message.checkerboard.disabled": "Checkerboard disabled",
"message.timelapse_start": "Timelapse started",
"message.timelapse_stop": "Timelapse stopped",
"message.import_palette.replace_palette": "Replace old palette",
"settings.volume.desc": "Volume degli effetti sonori nelle animazioni",
"action.change_keyframe_file": "Seleziona File",
"action.change_keyframe_file.desc": "Seleziona un file audio per l'anteprima di un effetto sonoro",
"action.clear_timeline": "Cancella Sequenza",
"action.clear_timeline.desc": "Cancella tutte le ossa non selezionate dalla sequenza",
"action.select_effect_animator": "Anima Effetti",
"action.select_effect_animator.desc": "Apri la sequenza per aggiungere effetti sonori e particelle",
"action.timeline_focus": "Canale",
"action.timeline_focus.desc": "Seleziona i canali animazione da mostrare sulla sequenza",
"action.timeline_focus.all": "Tutti",
"timeline.particle": "Particella",
"timeline.sound": "Suono",
"timeline.effects": "Effetti",
"data.format": "Formato",
"format.optifine_part": "Parte OptiFine",
"format.optifine_part.desc": "Parte JPM per modelli entity OptiFine",
"action.reverse_keyframes": "Inverti Fotogrammi",
"action.reverse_keyframes.desc": "Inverti l'ordine dei fotogrammi selezionati",
"generic.help": "Aiuto",
"message.removed_faces": "%0 facce rimosse",
"dialog.sketchfab_uploader.draft": "Bozza",
"action.slider_pos": "Spostamento %0",
"action.slider_pos.desc": "Sposta cubi sull'asse %0",
"action.slider_size": "Dimensione %0",
"action.slider_size.desc": "Ridimensiona i cubi sull'asse %0",
"action.slider_rotation": "Rotazione %0",
"action.slider_rotation.desc": "Ruota i cubi sull'asse %0",
"action.slider_origin": "Centro %0",
"action.slider_origin.desc": "Sposta centro sull'asse %0",
"action.rotate_cw": "Ruota %0 +90",
"action.rotate_cw.desc": "Ruota i cubi selezionati di 90° sull'asse %0",
"action.rotate_ccw": "Ruota %0 -90",
"action.rotate_ccw.desc": "Ruota i cubi selezionati di -90° sull'asse %0",
"action.flip": "Capovolgi %0",
"action.flip.desc": "Capovolgi i cubi selezionati sull'asse %0",
"action.center": "Centra %0",
"action.center.desc": "Centra i cubi selezionati sull'asse %0",
"action.bring_up_all_animations": "Minimizza Tutte le Animazioni",
"panel.bone": "Osso",
"data.color": "Colore",
"generic.export": "Esporta",
"generic.none": "Nessuno",
"status_bar.recording": "Registrazione Timelapse",
"message.add_to_palette": "Aggiunto a tavolozza",
"message.size_modifiers": "Tieni premuto Ctrl o Shift per trasformare in incrementi piu' piccoli.",
"message.timelapse_start": "Timelapse avviato",
"message.timelapse_stop": "Timelapse interrotto",
"message.import_palette.replace_palette": "Sostituisci vecchia tavolozza",
"message.import_palette.threshold": "Merge Threshold",
"dialog.timelapse.interval": "Interval (Seconds)",
"dialog.timelapse.source": "Source",
"dialog.timelapse.source.interface": "Interface",
"dialog.timelapse.source.locked": "Locked Angle",
"dialog.timelapse.destination": "Destination Folder",
"layout.color.checkerboard": "Checkerboard",
"layout.color.checkerboard.desc": "Background of canvas and UV editor",
"layout.font.code": "Code Font",
"layout.css": "Custom CSS",
"settings.category.paint": "Paint",
"settings.deactivate_size_limit": "Deactivate Size Limit",
"dialog.timelapse.interval": "Intervallo (Secondi)",
"dialog.timelapse.source": "Sorgente",
"dialog.timelapse.source.interface": "Interfaccia",
"dialog.timelapse.source.locked": "Angolo Bloccato",
"dialog.timelapse.destination": "Cartella Destinataria",
"layout.color.checkerboard": "Scacchiera",
"layout.color.checkerboard.desc": "Sfondo tela ed editore UV",
"layout.font.code": "Carattere Codici",
"layout.css": "CSS Personalizzato",
"settings.category.paint": "Dipingere",
"settings.deactivate_size_limit": "Disattiva Limite Dimensioni",
"settings.deactivate_size_limit.desc": "Deactivate the size limit for specific model formats. WARNING: This can cause invalid models.",
"settings.brush_opacity_modifier": "Brush Opacity Modifier",
"settings.brush_opacity_modifier.desc": "Modify the brush opacity when using a stylus",
"settings.brush_size_modifier": "Brush Size Modifier",
"settings.brush_opacity_modifier": "Modificatore Opacità Pennello",
"settings.brush_opacity_modifier.desc": "Modifica l'opacità del pennello quando viene utilizzato uno stilo",
"settings.brush_size_modifier": "Modificatore Dimensioni Pennello",
"settings.brush_size_modifier.desc": "Modify the brush size when using a stylus",
"settings.brush_modifier.pressure": "Pressure",
"settings.brush_modifier.tilt": "Tilt",
"settings.class_export_version": "Modded Entity Export Version",
"settings.class_export_version.desc": "The format version for modded entity models",
"category.color": "Color",
"action.import_theme": "Import Theme",
"action.export_theme": "Export Theme",
"action.export_theme.desc": "Create a theme file based on the current settings",
"action.reset_theme": "Reset Theme",
"action.reset_theme.desc": "Reset to the default Blockbench theme",
"action.slider_color_h": "Hue",
"action.slider_color_s": "Saturation",
"action.slider_color_v": "Value",
"action.add_to_palette": "Add To Palette",
"action.add_to_palette.desc": "Add the selected color to the color palette",
"action.import_palette": "Import Palette",
"action.import_palette.desc": "Import a .bbpalette file",
"action.export_palette": "Export Palette",
"action.export_palette.desc": "Export palette as a .bbpalette file",
"action.generate_palette": "Generate Palette",
"action.generate_palette.desc": "Generate palette from a texture",
"action.sort_palette": "Sort Palette",
"action.sort_palette.desc": "Sort all colors on the palette by color and brightness",
"action.clear_palette": "Clear Palette",
"action.clear_palette.desc": "Remove all colors from the palette",
"action.toggle_checkerboard": "Toggle Checkerboard",
"action.toggle_checkerboard.desc": "Toggle the checkerboard background behind the preview or UV editor",
"settings.brush_modifier.pressure": "Pressione",
"settings.brush_modifier.tilt": "Inclinazione",
"settings.class_export_version": "Versione Entity Export per Mod",
"settings.class_export_version.desc": "La versione del formato per modelli entity per i mod",
"category.color": "Colore",
"action.import_theme": "Importa Tema",
"action.export_theme": "Esporta Tema",
"action.export_theme.desc": "Crea un file tema basato sulle impostazioni correnti",
"action.reset_theme": "Ripristina Tema",
"action.reset_theme.desc": "Ripristina il tema al predefinito di Blockbench",
"action.slider_color_h": "Tonalità",
"action.slider_color_s": "Saturazione",
"action.slider_color_v": "Valore",
"action.add_to_palette": "Aggiungi a Tavolozza",
"action.add_to_palette.desc": "Aggiungi il colore selezionato alla tavolozza",
"action.import_palette": "Importa Tavolozza",
"action.import_palette.desc": "Importa un file .bbpalette",
"action.export_palette": "Esporta Tavolozza",
"action.export_palette.desc": "Esporta la tavolozza come un file .bbpalette",
"action.generate_palette": "Genera Tavolozza",
"action.generate_palette.desc": "Genera una tavolozza da una texture",
"action.sort_palette": "Ordina Tavolozza",
"action.sort_palette.desc": "Ordina tutti i colori della tavolozza per colore e luminosità",
"action.clear_palette": "Pulisci Tavolozza",
"action.clear_palette.desc": "Rimuovi tutti i colori dalla tavolozza",
"action.timelapse": "Timelapse...",
"action.timelapse.desc": "Record a timelapse of your modeling process",
"action.add_keyframe": "Add Keyframe",
"action.add_keyframe.desc": "Automatically add a keyframe. Press shift to force default values",
"action.timelapse.desc": "Registra un timelapse del tuo processo di modellazione",
"action.add_keyframe": "Aggiungi Fotogramma",
"action.add_keyframe.desc": "Aggiungi un fotogramma automaticamente. Premi shift per forzare valori predefinti",
"action.bring_up_all_animations.desc": "Brings all modified animators into the timeline",
"timeline.timeline": "Instructions",
"menu.palette.load": "Load Palette",
"menu.palette.load.default": "Default",
"timeline.timeline": "Istruzioni",
"menu.palette.load": "Carica Tavolozza",
"menu.palette.load.default": "Predefinita",
"panel.color.picker": "Picker",
"panel.color.palette": "Palette",
"generic.import": "Import",
"settings.brush_modifier.none": "None",
"action.export_entity": "Export Bedrock Entity",
"action.export_entity.desc": "Add the current model as an entity to a mobs.json file",
"settings.highlight_cubes": "Highlight Cubes",
"settings.highlight_cubes.desc": "Highlight cubes when you hover over them or select them",
"action.add_marker": "Set Marker",
"action.add_marker.desc": "Set a timeline marker",
"panel.color.palette": "Tavolozza",
"generic.import": "Importa",
"settings.brush_modifier.none": "Nessuno",
"action.export_entity": "Esporta Entity Bedrock",
"action.export_entity.desc": "Aggiungi il modello corrente come un entity ad un file mobs.json",
"settings.highlight_cubes": "Evidenzia Cubi",
"settings.highlight_cubes.desc": "Evidenzia i cubi quando il mouse passa sopra o quando li selezioni",
"action.add_marker": "Imposta Marcatore",
"action.add_marker.desc": "Imposta un marcatore sulla sequenza",
"timeline.pre_effect_script": "Script",
"format.skin": "Skin",
"format.skin.desc": "Edit player and entity skins",
"message.sketchfab.setup_guide": "Want to learn how to set up models in Sketchfab? Read %0",
"dialog.skin.title": "Create Skin",
"format.skin.desc": "Modifica skin giocatori ed entity",
"message.sketchfab.setup_guide": "Vuoi sapere come impostare i modelli su Sketchfab? Visita %0",
"dialog.skin.title": "Crea Skin",
"dialog.skin.model": "Skin",
"dialog.skin.texture": "Texture (Optional)",
"action.toggle_skin_layer": "Toggle Skin Layer",
"action.toggle_skin_layer.desc": "Toggle the hat and clothing layer of the skin model",
"action.gui_light": "GUI Light",
"action.gui_light.desc": "Select the way the item is lit in the inventory",
"action.gui_light.side": "Side Light",
"action.gui_light.front": "Front Light",
"action.move_keyframe_back": "Move Keyframes Back",
"action.move_keyframe_forth": "Move Keyframes Forth",
"menu.help": "Help",
"menu.help.discord": "Discord Server",
"menu.help.report_issue": "Report an Issue",
"menu.help.plugin_documentation": "Plugin API Documentation",
"menu.help.search_action": "Search and Run Action",
"menu.help.donate": "Donate",
"menu.help.about": "About...",
"menu.preview.background.clipboard": "Load from Clipboard"
"dialog.skin.texture": "Texture (Opzionale)",
"action.toggle_skin_layer": "Alterna Strati Skin",
"action.toggle_skin_layer.desc": "Alterna lo strato del capello e dei vestiti del modello della skin",
"action.gui_light": "Illuminazione GUI",
"action.gui_light.desc": "Scegli il modo in quale l'item è illuminato nell'inventario",
"action.gui_light.side": "Luce Laterale",
"action.gui_light.front": "Luce Frontale",
"action.move_keyframe_back": "Sposta Fotogrammi Indietro",
"action.move_keyframe_forth": "Sposta Fotogrammi Avanti",
"menu.help": "Aiuto",
"menu.help.discord": "Server Discord",
"menu.help.report_issue": "Segnala un Problema",
"menu.help.plugin_documentation": "Documentazione Plugin API",
"menu.help.search_action": "Cerca ed Esegui un'Azione",
"menu.help.donate": "Dona",
"menu.help.about": "Informazioni",
"menu.preview.background.clipboard": "Carica dagli Appunti",
"dialog.ignore": "Ignore",
"generic.unset": "Unset",
"message.invalid_builtin_parent.title": "Invalid Built-in Parent",
"message.invalid_builtin_parent.message": "The link to the invalid parent model '%0' was removed in order to export a valid model.",
"dialog.resize_texture.fill": "Fill with",
"dialog.resize_texture.fill.transparent": "Transparent",
"dialog.resize_texture.fill.color": "Color",
"dialog.resize_texture.fill.repeat": "Repeat",
"dialog.resize_texture.fill.stretch": "Stretch",
"dialog.scale.element_pivot": "Element Pivot",
"dialog.scale.selection_center": "Selection Center",
"dialog.create_gif.length_mode": "Length Mode",
"dialog.create_gif.length_mode.seconds": "Seconds",
"dialog.create_gif.length_mode.frames": "Frames",
"dialog.create_gif.length_mode.animation": "Animation Length",
"dialog.create_gif.length_mode.turntable": "Turntable Rotation",
"dialog.save_angle.projection": "Projection",
"dialog.save_angle.projection.perspective": "Perspective",
"dialog.save_angle.projection.orthographic": "Orthographic",
"dialog.sketchfab_uploader.animations": "Animations",
"dialog.settings.theme": "Theme",
"settings.category.interface": "Interface",
"settings.preview_checkerboard": "Preview Checkerboard",
"settings.preview_checkerboard.desc": "Toggle the checkerboard background behind the preview",
"settings.uv_checkerboard": "UV Editor Checkerboard",
"settings.uv_checkerboard.desc": "Toggle the checkerboard background behind the UV editor",
"category.paint": "Paint",
"action.fill_mode.color_connected": "Connected Colors",
"action.draw_shape_type": "Shape Type",
"action.draw_shape_type.rectangle": "Rectangle",
"action.draw_shape_type.rectangle_h": "Rectangle (Hollow)",
"action.draw_shape_type.ellipse": "Ellipse",
"action.draw_shape_type.ellipse_h": "Ellipse (Hollow)",
"action.draw_shape_type.line": "Line",
"action.mirror_painting": "Mirror Painting",
"action.mirror_painting.description": "Mirror your paint strokes to the other side of the model",
"action.lock_alpha": "Lock Alpha Channel",
"action.lock_alpha.description": "Lock the transparency of all pixels",
"action.draw_shape_tool": "Draw Shape",
"action.draw_shape_tool.desc": "Tool to draw simple shapes on textures",
"action.copy_paste_tool": "Copy Paste Tool",
"action.copy_paste_tool.desc": "Tool to copy and paste selections of textures",
"action.export_gltf": "Export As glTF",
"action.export_gltf.desc": "Export model and animations as glTF file to use in other 3D applications",
"action.transform_space": "Transform Space",
"action.transform_space.desc": "Default transform space for elements and bones",
"action.transform_space.global": "Global",
"action.transform_space.bone": "Bone",
"action.transform_space.local": "Local",
"action.toggle_camera_projection": "Toggle Camera Projection",
"action.toggle_camera_projection.desc": "Toggle the camera projection between perspective and orthographic",
"action.load_camera_angle": "Camera Angle: %0",
"action.load_camera_angle.desc": "Load the camera angle '%0'",
"action.slider_face_tint": "Tint Index",
"action.slider_face_tint.desc": "Set the tint index of the current face. -1 means unset.",
"menu.help.quickstart": "Quickstart Wizard",
"menu.help.developer": "Developer",
"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.cache_reload": "Cache Reload",
"menu.texture.resize": "Resize...",
"menu.preview.orthographic": "Orthographic",
"menu.preview.save_angle": "Save Angle...",
"menu.preview.angle": "Angles",
"menu.preview.angle.initial": "Initial Angle",
"menu.preview.angle.load": "Load",
"menu.preview.maximize": "Maximize",
"panel.color.both": "Both",
"uv_editor.copy_selection": "Copy Selection",
"uv_editor.paste_selection": "Paste Selection",
"uv_editor.copy_paste_tool.place": "Place",
"uv_editor.copy_paste_tool.cut": "Cut",
"uv_editor.copy_paste_tool.mirror_x": "Mirror X",
"uv_editor.copy_paste_tool.mirror_y": "Mirror Y",
"uv_editor.copy_paste_tool.rotate": "Rotate 90 Degrees"
}

View File

@ -157,7 +157,6 @@
"dialog.update.connecting": "サーバーにつなげる",
"dialog.settings.settings": "設定",
"dialog.settings.keybinds": "キー設定",
"dialog.settings.layout": "レイアウト",
"dialog.settings.about": "About",
"layout.color.back": "戻る",
"layout.color.back.desc": "背景と入力フィールド",
@ -364,8 +363,6 @@
"action.delete.desc": "選択したキューブ、またはグループを削除します",
"action.sort_outliner": "Sort Outliner",
"action.sort_outliner.desc": "アウトライナーをアルファベット順に並べ替える",
"action.local_move": "相対移動",
"action.local_move.desc": "回転した要素を独自の軸上で移動する",
"action.select_window": "選択…",
"action.select_window.desc": "そのプロパティに基づいてキューブを検索して選択する",
"action.invert_selection": "選択範囲を反転",
@ -464,19 +461,16 @@
"menu.preview.background.load": "Load",
"menu.preview.background.position": "Position",
"menu.preview.background.lock": "Lock to Camera",
"menu.preview.background.remove": "Remove",
"menu.preview.screenshot": "スクリーンショット",
"menu.preview.perspective": "Rerspective",
"menu.preview.perspective.normal": "Normal",
"menu.preview.quadview": "Quad View",
"menu.preview.fullview": "Full View",
"menu.preview.stop_drag": "Stop Background Positioing",
"menu.uv.mapping": "UVマッピング",
"menu.uv.mapping.export": "エクスポート",
"menu.uv.mapping.rotation": "Rotation",
"menu.uv.mapping.mirror_x": "Mirror X",
"menu.uv.mapping.mirror_y": "Mirror Y",
"menu.uv.tint": "色合い",
"menu.uv.texture": "Texture",
"cube.color.light_blue": "Light Blue",
"cube.color.yellow": "Yellow",
@ -671,13 +665,11 @@
"message.bone_material": "Change bone material",
"action.slider_animation_length": "アニメーションの長さ",
"action.slider_animation_length.desc": "選択したアニメーションの長さを変更する",
"action.camera_reset": "Reset Camera",
"action.camera_reset.desc": "現在のプレビューをデフォルトのカメラアングルにリセットする",
"panel.variable_placeholders": "可変プレースホルダ",
"panel.variable_placeholders.info": "プレビューする変数を 名前 = 値で表示する",
"status_bar.vertex_distance": "間隔:%0",
"dialog.create_gif.title": "GIF",
"dialog.create_gif.length": "長さ-秒-",
"dialog.create_gif.length": "Length",
"dialog.create_gif.fps": "FPS",
"dialog.create_gif.compression": "圧縮率",
"dialog.create_gif.play": "アニメーションを再生",
@ -934,8 +926,6 @@
"status_bar.recording": "タイムラプスを記録中…",
"message.add_to_palette": "パレットを追加",
"message.size_modifiers": "Shiftを押したままにすると、少しずつ変化します。",
"message.checkerboard.enabled": "チェッカーボードを有効",
"message.checkerboard.disabled": "チェッカーボードを無効",
"message.timelapse_start": "スタート",
"message.timelapse_stop": "ストップ",
"message.import_palette.replace_palette": "古いパレットを置き換えます",
@ -981,8 +971,6 @@
"action.sort_palette.desc": "パレット上のすべてのカラーを色と明るさで並べ替えます",
"action.clear_palette": "クリアー",
"action.clear_palette.desc": "パレット上のすべてのカラーを削除します",
"action.toggle_checkerboard": "チェッカーボードを固定",
"action.toggle_checkerboard.desc": "プレビューまたはUVエディターのチェッカーボードの背景を切り替えます",
"action.timelapse": "タイムラプス…",
"action.timelapse.desc": "モデリングプロセスのタイムラプスを記録します",
"action.add_keyframe": "キーフレームを追加",
@ -1023,5 +1011,81 @@
"menu.help.search_action": "Search and Run Action",
"menu.help.donate": "Donate",
"menu.help.about": "About...",
"menu.preview.background.clipboard": "Load from Clipboard"
"menu.preview.background.clipboard": "Load from Clipboard",
"dialog.ignore": "Ignore",
"generic.unset": "Unset",
"message.invalid_builtin_parent.title": "Invalid Built-in Parent",
"message.invalid_builtin_parent.message": "The link to the invalid parent model '%0' was removed in order to export a valid model.",
"dialog.resize_texture.fill": "Fill with",
"dialog.resize_texture.fill.transparent": "Transparent",
"dialog.resize_texture.fill.color": "Color",
"dialog.resize_texture.fill.repeat": "Repeat",
"dialog.resize_texture.fill.stretch": "Stretch",
"dialog.scale.element_pivot": "Element Pivot",
"dialog.scale.selection_center": "Selection Center",
"dialog.create_gif.length_mode": "Length Mode",
"dialog.create_gif.length_mode.seconds": "Seconds",
"dialog.create_gif.length_mode.frames": "Frames",
"dialog.create_gif.length_mode.animation": "Animation Length",
"dialog.create_gif.length_mode.turntable": "Turntable Rotation",
"dialog.save_angle.projection": "Projection",
"dialog.save_angle.projection.perspective": "Perspective",
"dialog.save_angle.projection.orthographic": "Orthographic",
"dialog.sketchfab_uploader.animations": "Animations",
"dialog.settings.theme": "Theme",
"settings.category.interface": "Interface",
"settings.preview_checkerboard": "Preview Checkerboard",
"settings.preview_checkerboard.desc": "Toggle the checkerboard background behind the preview",
"settings.uv_checkerboard": "UV Editor Checkerboard",
"settings.uv_checkerboard.desc": "Toggle the checkerboard background behind the UV editor",
"category.paint": "Paint",
"action.fill_mode.color_connected": "Connected Colors",
"action.draw_shape_type": "Shape Type",
"action.draw_shape_type.rectangle": "Rectangle",
"action.draw_shape_type.rectangle_h": "Rectangle (Hollow)",
"action.draw_shape_type.ellipse": "Ellipse",
"action.draw_shape_type.ellipse_h": "Ellipse (Hollow)",
"action.draw_shape_type.line": "Line",
"action.mirror_painting": "Mirror Painting",
"action.mirror_painting.description": "Mirror your paint strokes to the other side of the model",
"action.lock_alpha": "Lock Alpha Channel",
"action.lock_alpha.description": "Lock the transparency of all pixels",
"action.draw_shape_tool": "Draw Shape",
"action.draw_shape_tool.desc": "Tool to draw simple shapes on textures",
"action.copy_paste_tool": "Copy Paste Tool",
"action.copy_paste_tool.desc": "Tool to copy and paste selections of textures",
"action.export_gltf": "Export As glTF",
"action.export_gltf.desc": "Export model and animations as glTF file to use in other 3D applications",
"action.transform_space": "Transform Space",
"action.transform_space.desc": "Default transform space for elements and bones",
"action.transform_space.global": "Global",
"action.transform_space.bone": "Bone",
"action.transform_space.local": "Local",
"action.toggle_camera_projection": "Toggle Camera Projection",
"action.toggle_camera_projection.desc": "Toggle the camera projection between perspective and orthographic",
"action.load_camera_angle": "Camera Angle: %0",
"action.load_camera_angle.desc": "Load the camera angle '%0'",
"action.slider_face_tint": "Tint Index",
"action.slider_face_tint.desc": "Set the tint index of the current face. -1 means unset.",
"menu.help.quickstart": "Quickstart Wizard",
"menu.help.developer": "Developer",
"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.cache_reload": "Cache Reload",
"menu.texture.resize": "Resize...",
"menu.preview.orthographic": "Orthographic",
"menu.preview.save_angle": "Save Angle...",
"menu.preview.angle": "Angles",
"menu.preview.angle.initial": "Initial Angle",
"menu.preview.angle.load": "Load",
"menu.preview.maximize": "Maximize",
"panel.color.both": "Both",
"uv_editor.copy_selection": "Copy Selection",
"uv_editor.paste_selection": "Paste Selection",
"uv_editor.copy_paste_tool.place": "Place",
"uv_editor.copy_paste_tool.cut": "Cut",
"uv_editor.copy_paste_tool.mirror_x": "Mirror X",
"uv_editor.copy_paste_tool.mirror_y": "Mirror Y",
"uv_editor.copy_paste_tool.rotate": "Rotate 90 Degrees"
}

View File

@ -18,7 +18,7 @@
"keys.shift": "Shift",
"keys.alt": "Alt",
"keys.meta": "Cmd",
"keys.delete": "Verwijder",
"keys.delete": "Delete",
"keys.space": "Space",
"keys.leftclick": "Linker muisknop",
"keys.middleclick": "Midden muisknop",
@ -35,8 +35,8 @@
"keys.up": "Omhoog",
"keys.right": "Rechts",
"keys.down": "Omlaag",
"keys.pageup": "Pagina Terug",
"keys.pagedown": "Pagina Verder",
"keys.pageup": "Page Up",
"keys.pagedown": "Page Down",
"keys.plus": "Plus",
"keys.comma": "Komma",
"keys.point": "Punt",
@ -47,7 +47,7 @@
"keys.printscreen": "Schermafbeelding",
"keys.pause": "Pauzeer",
"message.rotation_limit.title": "Rotatie Limiet",
"message.rotation_limit.message": "Rotaties zijn gelimiteerd door Minecraft over één as en 22,5 graden veranderingen. Roteren op een andere as zal de rotaties op overige assen verwijderen. Deze optie kan uitgezet worden in het instellingen menu.",
"message.rotation_limit.message": "Rotaties zijn door Minecraft over één as tegelijkertijd en stappen van 22,5 graad gelimiteerd. Roteren op een andere as zal de rotaties op overige assen verwijderen. Je kan je model converteren naar een \"vrije model\" als je voor een andere reden aan het moddelen bent en vrije rotatie nodig hebt.",
"message.file_not_found.title": "Bestand Niet Gevonden",
"message.file_not_found.message": "Blockbench kon het gekozen bestand niet vinden. Zorg ervoor dat het lokaal opgeslagen is en niet in de cloud.",
"message.screenshot.title": "Schermafbeelding",
@ -157,7 +157,6 @@
"dialog.update.connecting": "Verbinden met de server",
"dialog.settings.settings": "Instellingen",
"dialog.settings.keybinds": "Sneltoetsen",
"dialog.settings.layout": "Lay-out",
"dialog.settings.about": "Over",
"layout.color.back": "Terug",
"layout.color.back.desc": "Achtergronden en invoervelden",
@ -207,7 +206,7 @@
"settings.show_actions.desc": "Toon alle acties in de status balk",
"settings.backup_interval": "Backup Frequentie",
"settings.backup_interval.desc": "Frequentie van de automatische backups in minuten",
"settings.origin_size": "Rotatie Oorsprong",
"settings.origin_size": "Oorsprong Markeerder",
"settings.origin_size.desc": "Grootte van de rotatie oorsprong",
"settings.control_size": "As Controle Grootte",
"settings.control_size.desc": "Grootte van de 3 assen controle gereedschap",
@ -364,8 +363,6 @@
"action.delete.desc": "Verwijdert de geselecteerde kubus of groep",
"action.sort_outliner": "Omlijning Sorteren",
"action.sort_outliner.desc": "Sorteert de omlijning alfabetisch",
"action.local_move": "Relatief Verplaatsen",
"action.local_move.desc": "Verplaatst gedraaide elementen volgens hun eigen assen indien mogenlijk",
"action.select_window": "Selecteer...",
"action.select_window.desc": "Zoek en selecteer kubussen op basis van hun eigenschappen",
"action.invert_selection": "Selectie Omkeren",
@ -464,19 +461,16 @@
"menu.preview.background.load": "Laden",
"menu.preview.background.position": "Positie",
"menu.preview.background.lock": "Vastzetten Op De Camera",
"menu.preview.background.remove": "Verwijderen",
"menu.preview.screenshot": "Schermafbeelding",
"menu.preview.perspective": "Perspectief",
"menu.preview.perspective.normal": "Normaal",
"menu.preview.quadview": "Vierdelige Weergave",
"menu.preview.fullview": "Volledige Weergave",
"menu.preview.stop_drag": "Stop Achtergrong Positionering",
"menu.uv.mapping": "UV Mapping",
"menu.uv.mapping.export": "Exporteren",
"menu.uv.mapping.rotation": "Rotatie",
"menu.uv.mapping.mirror_x": "Spiegel X",
"menu.uv.mapping.mirror_y": "Spiegel Y",
"menu.uv.tint": "Tint",
"menu.uv.texture": "Afbeelding",
"cube.color.light_blue": "Lichtblauw",
"cube.color.yellow": "Geel",
@ -671,13 +665,11 @@
"message.bone_material": "Verander materiaal",
"action.slider_animation_length": "Animatie Lengte",
"action.slider_animation_length.desc": "Verander de lengte van de geselecteerde animatie",
"action.camera_reset": "Reset Camera Positie",
"action.camera_reset.desc": "Reset het perspectief naar de standaard camera positie",
"panel.variable_placeholders": "Variabele Plaatshouder",
"panel.variable_placeholders.info": "Maak een lijst van de variabele s die je vooraf wil zien via naam=waarde",
"status_bar.vertex_distance": "Afstand:%0",
"dialog.create_gif.title": "Neem GIF Op",
"dialog.create_gif.length": "Tijdsduur (Seconden)",
"dialog.create_gif.length": "Tijdsduur",
"dialog.create_gif.fps": "FPS",
"dialog.create_gif.compression": "Compressie Gehalte",
"dialog.create_gif.play": "Start Animatie",
@ -693,7 +685,7 @@
"action.export_class_entity.desc": "Exporteer het entity model als een Java klasse",
"settings.seethrough_outline": "X-Ray Buitenlijnen",
"settings.seethrough_outline.desc": "Laat buitenlijnen door voorwerpen heen zien",
"mode.edit": "Verander",
"mode.edit": "Bewerk",
"mode.paint": "Verf",
"mode.display": "Positie",
"mode.animate": "Animeer",
@ -934,8 +926,6 @@
"status_bar.recording": "Timelapse Aan Het Opnemen",
"message.add_to_palette": "Toegevoegd aan palet",
"message.size_modifiers": "Houd Ctrl of Shift vast om met ",
"message.checkerboard.enabled": "Schaakbord ingeschakeld",
"message.checkerboard.disabled": "Schaakbord uitgeschakeld ",
"message.timelapse_start": "Timelapse gestart ",
"message.timelapse_stop": "Timelapse gestopt",
"message.import_palette.replace_palette": "Vervang oud palet",
@ -981,8 +971,6 @@
"action.sort_palette.desc": "Sorteer alle kleuren op het palet op basis van kleur en helderheid",
"action.clear_palette": "Maak Palet Schoon",
"action.clear_palette.desc": "Verwijder alle kleuren van het palet",
"action.toggle_checkerboard": "Zet Schaakbord Aan/Uit",
"action.toggle_checkerboard.desc": "Zet de schaakbord achtergrond achter de voorvertoning of de UV editor aan/uit",
"action.timelapse": "Timelapse...",
"action.timelapse.desc": "Neem een timelapse van u modeleer proces op",
"action.add_keyframe": "Voeg Keyframe toe",
@ -999,29 +987,105 @@
"action.export_entity.desc": "Voeg het huidige model als een enitity toe aan een mobs.json bestand",
"settings.highlight_cubes": "Markeer Kubussen",
"settings.highlight_cubes.desc": "Markeer kubussen waneer je over ze heen beweegt of ze selecteert",
"action.add_marker": "Set Marker",
"action.add_marker.desc": "Set a timeline marker",
"action.add_marker": "Stel Markeerder In",
"action.add_marker.desc": "Stel een tijdlijn markeerder in",
"timeline.pre_effect_script": "Script",
"format.skin": "Skin",
"format.skin.desc": "Edit player and entity skins",
"message.sketchfab.setup_guide": "Want to learn how to set up models in Sketchfab? Read %0",
"dialog.skin.title": "Create Skin",
"format.skin.desc": "Wijzig speler en entiteit skins",
"message.sketchfab.setup_guide": "Wil je leren hoe je modellen moet instellen op Sketchfab? Lees %0",
"dialog.skin.title": "Creëer Skin",
"dialog.skin.model": "Skin",
"dialog.skin.texture": "Texture (Optional)",
"action.toggle_skin_layer": "Toggle Skin Layer",
"action.toggle_skin_layer.desc": "Toggle the hat and clothing layer of the skin model",
"action.gui_light": "GUI Light",
"action.gui_light.desc": "Select the way the item is lit in the inventory",
"action.gui_light.side": "Side Light",
"action.gui_light.front": "Front Light",
"action.move_keyframe_back": "Move Keyframes Back",
"action.move_keyframe_forth": "Move Keyframes Forth",
"dialog.skin.texture": "Textuur (Optioneel)",
"action.toggle_skin_layer": "Zet Skin Laag Aan/Uit",
"action.toggle_skin_layer.desc": "Zet de hoed- en klerenlaag van het skin model",
"action.gui_light": "GUI Licht",
"action.gui_light.desc": "Selecteer de manier waarop het item is belicht in de inventaris",
"action.gui_light.side": "Zijkant Licht",
"action.gui_light.front": "Voorkant Licht",
"action.move_keyframe_back": "Beweeg Keyframes Naar Achteren",
"action.move_keyframe_forth": "Beweeg Keyframes Naar Voren",
"menu.help": "Help",
"menu.help.discord": "Discord Server",
"menu.help.report_issue": "Report an Issue",
"menu.help.plugin_documentation": "Plugin API Documentation",
"menu.help.search_action": "Search and Run Action",
"menu.help.donate": "Donate",
"menu.help.about": "About...",
"menu.preview.background.clipboard": "Load from Clipboard"
"menu.help.report_issue": "Rapporteer een probleem",
"menu.help.plugin_documentation": "Plugin API Documentatie",
"menu.help.search_action": "Zoek en Voer Actie uit",
"menu.help.donate": "Doneer",
"menu.help.about": "Over...",
"menu.preview.background.clipboard": "Laad van Klembord",
"dialog.ignore": "Ignore",
"generic.unset": "Unset",
"message.invalid_builtin_parent.title": "Invalid Built-in Parent",
"message.invalid_builtin_parent.message": "The link to the invalid parent model '%0' was removed in order to export a valid model.",
"dialog.resize_texture.fill": "Fill with",
"dialog.resize_texture.fill.transparent": "Transparent",
"dialog.resize_texture.fill.color": "Color",
"dialog.resize_texture.fill.repeat": "Repeat",
"dialog.resize_texture.fill.stretch": "Stretch",
"dialog.scale.element_pivot": "Element Pivot",
"dialog.scale.selection_center": "Selection Center",
"dialog.create_gif.length_mode": "Length Mode",
"dialog.create_gif.length_mode.seconds": "Seconds",
"dialog.create_gif.length_mode.frames": "Frames",
"dialog.create_gif.length_mode.animation": "Animation Length",
"dialog.create_gif.length_mode.turntable": "Turntable Rotation",
"dialog.save_angle.projection": "Projection",
"dialog.save_angle.projection.perspective": "Perspective",
"dialog.save_angle.projection.orthographic": "Orthographic",
"dialog.sketchfab_uploader.animations": "Animations",
"dialog.settings.theme": "Theme",
"settings.category.interface": "Interface",
"settings.preview_checkerboard": "Preview Checkerboard",
"settings.preview_checkerboard.desc": "Toggle the checkerboard background behind the preview",
"settings.uv_checkerboard": "UV Editor Checkerboard",
"settings.uv_checkerboard.desc": "Toggle the checkerboard background behind the UV editor",
"category.paint": "Paint",
"action.fill_mode.color_connected": "Connected Colors",
"action.draw_shape_type": "Shape Type",
"action.draw_shape_type.rectangle": "Rectangle",
"action.draw_shape_type.rectangle_h": "Rectangle (Hollow)",
"action.draw_shape_type.ellipse": "Ellipse",
"action.draw_shape_type.ellipse_h": "Ellipse (Hollow)",
"action.draw_shape_type.line": "Line",
"action.mirror_painting": "Mirror Painting",
"action.mirror_painting.description": "Mirror your paint strokes to the other side of the model",
"action.lock_alpha": "Lock Alpha Channel",
"action.lock_alpha.description": "Lock the transparency of all pixels",
"action.draw_shape_tool": "Draw Shape",
"action.draw_shape_tool.desc": "Tool to draw simple shapes on textures",
"action.copy_paste_tool": "Copy Paste Tool",
"action.copy_paste_tool.desc": "Tool to copy and paste selections of textures",
"action.export_gltf": "Export As glTF",
"action.export_gltf.desc": "Export model and animations as glTF file to use in other 3D applications",
"action.transform_space": "Transform Space",
"action.transform_space.desc": "Default transform space for elements and bones",
"action.transform_space.global": "Global",
"action.transform_space.bone": "Bone",
"action.transform_space.local": "Local",
"action.toggle_camera_projection": "Toggle Camera Projection",
"action.toggle_camera_projection.desc": "Toggle the camera projection between perspective and orthographic",
"action.load_camera_angle": "Camera Angle: %0",
"action.load_camera_angle.desc": "Load the camera angle '%0'",
"action.slider_face_tint": "Tint Index",
"action.slider_face_tint.desc": "Set the tint index of the current face. -1 means unset.",
"menu.help.quickstart": "Quickstart Wizard",
"menu.help.developer": "Developer",
"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.cache_reload": "Cache Reload",
"menu.texture.resize": "Resize...",
"menu.preview.orthographic": "Orthographic",
"menu.preview.save_angle": "Save Angle...",
"menu.preview.angle": "Angles",
"menu.preview.angle.initial": "Initial Angle",
"menu.preview.angle.load": "Load",
"menu.preview.maximize": "Maximize",
"panel.color.both": "Both",
"uv_editor.copy_selection": "Copy Selection",
"uv_editor.paste_selection": "Paste Selection",
"uv_editor.copy_paste_tool.place": "Place",
"uv_editor.copy_paste_tool.cut": "Cut",
"uv_editor.copy_paste_tool.mirror_x": "Mirror X",
"uv_editor.copy_paste_tool.mirror_y": "Mirror Y",
"uv_editor.copy_paste_tool.rotate": "Rotate 90 Degrees"
}

View File

@ -157,7 +157,6 @@
"dialog.update.connecting": "Łączenie z serwerem",
"dialog.settings.settings": "Ustawienia",
"dialog.settings.keybinds": "Klawisze",
"dialog.settings.layout": "Układ",
"dialog.settings.about": "O programie",
"layout.color.back": "Wstecz",
"layout.color.back.desc": "Tła i pola wpisywania",
@ -364,8 +363,6 @@
"action.delete.desc": "Usuwa zaznaczone kostki lub grupę",
"action.sort_outliner": "Sortuj outliner",
"action.sort_outliner.desc": "Sortuje outliner alfabetycznie",
"action.local_move": "Przesuń względnie",
"action.local_move.desc": "Przesuń obrócone elementy na ich własnych osiach, jeżeli to możliwe",
"action.select_window": "Wybierz...",
"action.select_window.desc": "Wyszukaj i wybierz kostki ze względu na ich własności",
"action.invert_selection": "Odwróć zaznaczenie",
@ -464,19 +461,16 @@
"menu.preview.background.load": "Załaduj",
"menu.preview.background.position": "Pozycja",
"menu.preview.background.lock": "Zablokuj do kamery",
"menu.preview.background.remove": "Usuń",
"menu.preview.screenshot": "Zrzut ekranu",
"menu.preview.perspective": "Perspektywa",
"menu.preview.perspective.normal": "Normalna",
"menu.preview.quadview": "Widok Quad",
"menu.preview.fullview": "Pełny widok",
"menu.preview.stop_drag": "Skończ pozycjonowanie tła",
"menu.uv.mapping": "Mapowanie UV",
"menu.uv.mapping.export": "Eksport",
"menu.uv.mapping.rotation": "Rotacja",
"menu.uv.mapping.mirror_x": "Odbicie X",
"menu.uv.mapping.mirror_y": "Odbicie Y",
"menu.uv.tint": "Odcień",
"menu.uv.texture": "Tekstura",
"cube.color.light_blue": "Jasnoniebieski",
"cube.color.yellow": "Żółty",
@ -671,13 +665,11 @@
"message.bone_material": "Zmień materiał kości",
"action.slider_animation_length": "Długość animacji",
"action.slider_animation_length.desc": "Zmień długość zaznaczonej animacji",
"action.camera_reset": "Zresetój Kamerę",
"action.camera_reset.desc": "\n Zresetuj bieżący podgląd do domyślnego kąta kamery",
"panel.variable_placeholders": "\n Zmienne symbole zastępcze",
"panel.variable_placeholders.info": " Wymień zmienne, które chcesz podglądnąć za pomocą nazwy = wartość",
"status_bar.vertex_distance": "Odległość: 0%",
"dialog.create_gif.title": "Zapisz GIF",
"dialog.create_gif.length": "Długość (sekundy)",
"dialog.create_gif.length": "Długość",
"dialog.create_gif.fps": "FPS",
"dialog.create_gif.compression": "Ilość kompresji",
"dialog.create_gif.play": "Rozpocznij animację",
@ -719,10 +711,10 @@
"menu.preview.perspective.reset": "Reset Camera",
"action.fill_mode": "Fill Mode",
"action.fill_mode.face": "Face",
"action.fill_mode.color": "Color",
"action.fill_mode.color": "Colors",
"action.fill_mode.cube": "Cube",
"action.toggle_mirror_uv": "Mirror UV",
"action.toggle_mirror_uv.desc": "Toggle the UV mirroring on the X axis of the selected cubes.",
"action.toggle_mirror_uv.desc": "Toggle the UV mirroring on the X axis of the selected cubes",
"action.toggle_uv_overlay": "Toggle UV Overlay",
"action.toggle_uv_overlay.desc": "When enabled, displays all UV mapping overlays above the texture.",
"menu.texture.blank": "Apply to Untextured Faces",
@ -854,7 +846,7 @@
"action.save_project.desc": "Saves the current model as a project file",
"action.save_project_as": "Save Project As",
"action.save_project_as.desc": "Saves the current model as a project file at a new location",
"action.export_over": "Overwrite Model",
"action.export_over": "Save Model",
"action.export_over.desc": "Saves the model, textures and animations by overwriting the files",
"action.add_locator": "Add Locator",
"action.add_locator.desc": "Adds a new locator to control positions of particles, leashes etc",
@ -934,8 +926,6 @@
"status_bar.recording": "Recording Timelapse",
"message.add_to_palette": "Added to palette",
"message.size_modifiers": "Hold down Ctrl or Shift to transform in smaller increments.",
"message.checkerboard.enabled": "Checkerboard enabled",
"message.checkerboard.disabled": "Checkerboard disabled",
"message.timelapse_start": "Timelapse started",
"message.timelapse_stop": "Timelapse stopped",
"message.import_palette.replace_palette": "Replace old palette",
@ -960,68 +950,142 @@
"settings.brush_modifier.tilt": "Tilt",
"settings.class_export_version": "Modded Entity Export Version",
"settings.class_export_version.desc": "The format version for modded entity models",
"category.color": "Color",
"action.import_theme": "Import Theme",
"action.export_theme": "Export Theme",
"action.export_theme.desc": "Create a theme file based on the current settings",
"action.reset_theme": "Reset Theme",
"action.reset_theme.desc": "Reset to the default Blockbench theme",
"action.slider_color_h": "Hue",
"action.slider_color_s": "Saturation",
"action.slider_color_v": "Value",
"action.add_to_palette": "Add To Palette",
"action.add_to_palette.desc": "Add the selected color to the color palette",
"action.import_palette": "Import Palette",
"action.import_palette.desc": "Import a .bbpalette file",
"action.export_palette": "Export Palette",
"category.color": "Kolor",
"action.import_theme": "Importuj styl",
"action.export_theme": "Eksportuj styl",
"action.export_theme.desc": "Stwórz plik stylu bazowany na aktualnych ustawieniach",
"action.reset_theme": "Zresetuj styl",
"action.reset_theme.desc": "Zresetuj do podstawowego stylu",
"action.slider_color_h": "Barwa",
"action.slider_color_s": "Nasycenie",
"action.slider_color_v": "Wartość",
"action.add_to_palette": "Dodaj do palety",
"action.add_to_palette.desc": "Dodaj zaznaczony kolor do palety kolorów",
"action.import_palette": "Importuj paletę",
"action.import_palette.desc": "Importuj plik .bbpalette",
"action.export_palette": "Eksportuj paletę",
"action.export_palette.desc": "Export palette as a .bbpalette file",
"action.generate_palette": "Generate Palette",
"action.generate_palette.desc": "Generate palette from a texture",
"action.sort_palette": "Sort Palette",
"action.sort_palette.desc": "Sort all colors on the palette by color and brightness",
"action.clear_palette": "Clear Palette",
"action.clear_palette.desc": "Remove all colors from the palette",
"action.toggle_checkerboard": "Toggle Checkerboard",
"action.toggle_checkerboard.desc": "Toggle the checkerboard background behind the preview or UV editor",
"action.timelapse": "Timelapse...",
"action.timelapse.desc": "Record a timelapse of your modeling process",
"action.add_keyframe": "Add Keyframe",
"action.add_keyframe.desc": "Automatically add a keyframe. Press shift to force default values",
"action.clear_palette": "Wyczyść paletę",
"action.clear_palette.desc": "Usuń wszystkie kolory z palety",
"action.timelapse": "Timelapse",
"action.timelapse.desc": "Nagraj timelaps procesu modelowania",
"action.add_keyframe": "Dodaj klatkę kluczową",
"action.add_keyframe.desc": "Automatycznie dodawaj klatki kluczowe. Naciśnij Shift, aby wymusić podstawowe wartości",
"action.bring_up_all_animations.desc": "Brings all modified animators into the timeline",
"timeline.timeline": "Instructions",
"menu.palette.load": "Load Palette",
"menu.palette.load.default": "Default",
"panel.color.picker": "Picker",
"panel.color.palette": "Palette",
"generic.import": "Import",
"settings.brush_modifier.none": "None",
"timeline.timeline": "Instrukcje",
"menu.palette.load": "Wczytaj paletę",
"menu.palette.load.default": "Podstawowa",
"panel.color.picker": "Wybierz kolor",
"panel.color.palette": "Paleta",
"generic.import": "Importuj",
"settings.brush_modifier.none": "Żaden",
"action.export_entity": "Export Bedrock Entity",
"action.export_entity.desc": "Add the current model as an entity to a mobs.json file",
"settings.highlight_cubes": "Highlight Cubes",
"settings.highlight_cubes": "Podświetl kostki",
"settings.highlight_cubes.desc": "Highlight cubes when you hover over them or select them",
"action.add_marker": "Set Marker",
"action.add_marker.desc": "Set a timeline marker",
"timeline.pre_effect_script": "Script",
"format.skin": "Skin",
"format.skin.desc": "Edit player and entity skins",
"action.add_marker": "Ustaw znacznik",
"action.add_marker.desc": "Ustaw znacznik osi czasu",
"timeline.pre_effect_script": "Skrypt",
"format.skin": "Skórka",
"format.skin.desc": "Edytuj skórki graczy i stworzeń",
"message.sketchfab.setup_guide": "Want to learn how to set up models in Sketchfab? Read %0",
"dialog.skin.title": "Create Skin",
"dialog.skin.model": "Skin",
"dialog.skin.texture": "Texture (Optional)",
"action.toggle_skin_layer": "Toggle Skin Layer",
"action.toggle_skin_layer.desc": "Toggle the hat and clothing layer of the skin model",
"action.gui_light": "GUI Light",
"action.gui_light.desc": "Select the way the item is lit in the inventory",
"action.gui_light.side": "Side Light",
"action.gui_light.front": "Front Light",
"action.move_keyframe_back": "Move Keyframes Back",
"action.move_keyframe_forth": "Move Keyframes Forth",
"menu.help": "Help",
"menu.help.discord": "Discord Server",
"menu.help.report_issue": "Report an Issue",
"dialog.skin.title": "Stwórz skórkę",
"dialog.skin.model": "Skórka",
"dialog.skin.texture": "Tekstura (Opcjonalna)",
"action.toggle_skin_layer": "Włącz warstwę skórki",
"action.toggle_skin_layer.desc": "Włącz warstwę nakrycia głowy i ubrań",
"action.gui_light": "Światło GUI",
"action.gui_light.desc": "Wybierz sposób w jaki przedmiot jest podświetlony w ekwipunku",
"action.gui_light.side": "Boczne światło",
"action.gui_light.front": "Frontowe światło",
"action.move_keyframe_back": "Przemieść klatki kluczowe do tyłu",
"action.move_keyframe_forth": "Przemieść klatki kluczowe do przodu",
"menu.help": "Pomoc",
"menu.help.discord": "Serwer Discord",
"menu.help.report_issue": "Zgłoś błąd",
"menu.help.plugin_documentation": "Plugin API Documentation",
"menu.help.search_action": "Search and Run Action",
"menu.help.donate": "Donate",
"menu.help.donate": "Wesprzyj",
"menu.help.about": "About...",
"menu.preview.background.clipboard": "Load from Clipboard"
"menu.preview.background.clipboard": "Wczytaj ze schowka",
"dialog.ignore": "Ignore",
"generic.unset": "Unset",
"message.invalid_builtin_parent.title": "Invalid Built-in Parent",
"message.invalid_builtin_parent.message": "The link to the invalid parent model '%0' was removed in order to export a valid model.",
"dialog.resize_texture.fill": "Fill with",
"dialog.resize_texture.fill.transparent": "Transparent",
"dialog.resize_texture.fill.color": "Color",
"dialog.resize_texture.fill.repeat": "Repeat",
"dialog.resize_texture.fill.stretch": "Stretch",
"dialog.scale.element_pivot": "Element Pivot",
"dialog.scale.selection_center": "Selection Center",
"dialog.create_gif.length_mode": "Length Mode",
"dialog.create_gif.length_mode.seconds": "Seconds",
"dialog.create_gif.length_mode.frames": "Frames",
"dialog.create_gif.length_mode.animation": "Animation Length",
"dialog.create_gif.length_mode.turntable": "Turntable Rotation",
"dialog.save_angle.projection": "Projection",
"dialog.save_angle.projection.perspective": "Perspective",
"dialog.save_angle.projection.orthographic": "Orthographic",
"dialog.sketchfab_uploader.animations": "Animations",
"dialog.settings.theme": "Theme",
"settings.category.interface": "Interface",
"settings.preview_checkerboard": "Preview Checkerboard",
"settings.preview_checkerboard.desc": "Toggle the checkerboard background behind the preview",
"settings.uv_checkerboard": "UV Editor Checkerboard",
"settings.uv_checkerboard.desc": "Toggle the checkerboard background behind the UV editor",
"category.paint": "Paint",
"action.fill_mode.color_connected": "Connected Colors",
"action.draw_shape_type": "Shape Type",
"action.draw_shape_type.rectangle": "Rectangle",
"action.draw_shape_type.rectangle_h": "Rectangle (Hollow)",
"action.draw_shape_type.ellipse": "Ellipse",
"action.draw_shape_type.ellipse_h": "Ellipse (Hollow)",
"action.draw_shape_type.line": "Line",
"action.mirror_painting": "Mirror Painting",
"action.mirror_painting.description": "Mirror your paint strokes to the other side of the model",
"action.lock_alpha": "Lock Alpha Channel",
"action.lock_alpha.description": "Lock the transparency of all pixels",
"action.draw_shape_tool": "Draw Shape",
"action.draw_shape_tool.desc": "Tool to draw simple shapes on textures",
"action.copy_paste_tool": "Copy Paste Tool",
"action.copy_paste_tool.desc": "Tool to copy and paste selections of textures",
"action.export_gltf": "Export As glTF",
"action.export_gltf.desc": "Export model and animations as glTF file to use in other 3D applications",
"action.transform_space": "Transform Space",
"action.transform_space.desc": "Default transform space for elements and bones",
"action.transform_space.global": "Global",
"action.transform_space.bone": "Bone",
"action.transform_space.local": "Local",
"action.toggle_camera_projection": "Toggle Camera Projection",
"action.toggle_camera_projection.desc": "Toggle the camera projection between perspective and orthographic",
"action.load_camera_angle": "Camera Angle: %0",
"action.load_camera_angle.desc": "Load the camera angle '%0'",
"action.slider_face_tint": "Tint Index",
"action.slider_face_tint.desc": "Set the tint index of the current face. -1 means unset.",
"menu.help.quickstart": "Quickstart Wizard",
"menu.help.developer": "Developer",
"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.cache_reload": "Cache Reload",
"menu.texture.resize": "Resize...",
"menu.preview.orthographic": "Orthographic",
"menu.preview.save_angle": "Save Angle...",
"menu.preview.angle": "Angles",
"menu.preview.angle.initial": "Initial Angle",
"menu.preview.angle.load": "Load",
"menu.preview.maximize": "Maximize",
"panel.color.both": "Both",
"uv_editor.copy_selection": "Copy Selection",
"uv_editor.paste_selection": "Paste Selection",
"uv_editor.copy_paste_tool.place": "Place",
"uv_editor.copy_paste_tool.cut": "Cut",
"uv_editor.copy_paste_tool.mirror_x": "Mirror X",
"uv_editor.copy_paste_tool.mirror_y": "Mirror Y",
"uv_editor.copy_paste_tool.rotate": "Rotate 90 Degrees"
}

View File

@ -157,7 +157,6 @@
"dialog.update.connecting": "Conectando-se ao servidor",
"dialog.settings.settings": "Configurações",
"dialog.settings.keybinds": "Atalhos",
"dialog.settings.layout": "Aparência",
"dialog.settings.about": "Sobre",
"layout.color.back": "Cor de fundo",
"layout.color.back.desc": "Planos de fundo e campos de texto",
@ -364,8 +363,6 @@
"action.delete.desc": "Exclui os cubos ou grupos selecionados",
"action.sort_outliner": "Ordenar",
"action.sort_outliner.desc": "Ordenar os elementos em ordem alfabética",
"action.local_move": "Mover relativamente",
"action.local_move.desc": "Mover elementos rotacionados em seus próprios eixos, se possível",
"action.select_window": "Selecionar...",
"action.select_window.desc": "Procurar e selecionar cubos com base em suas propriedades",
"action.invert_selection": "Inverter seleção",
@ -464,19 +461,16 @@
"menu.preview.background.load": "Carregar",
"menu.preview.background.position": "Posição",
"menu.preview.background.lock": "Travar À Câmera",
"menu.preview.background.remove": "Remover",
"menu.preview.screenshot": "Captura de Tela",
"menu.preview.perspective": "Perspectiva",
"menu.preview.perspective.normal": "Normal",
"menu.preview.quadview": "Visão Quad",
"menu.preview.fullview": "Visão Completa",
"menu.preview.stop_drag": "Pare o Posicionamento do Plano de Fundo",
"menu.uv.mapping": "Mapeamento UV",
"menu.uv.mapping.export": "Exportar",
"menu.uv.mapping.rotation": "Rotação",
"menu.uv.mapping.mirror_x": "Espelhar X",
"menu.uv.mapping.mirror_y": "Espelhar Y",
"menu.uv.tint": "Tom",
"menu.uv.texture": "Textura",
"cube.color.light_blue": "Azul claro",
"cube.color.yellow": "Amarelo",
@ -671,13 +665,11 @@
"message.bone_material": "Mudar o material do osso",
"action.slider_animation_length": "Duração da animação",
"action.slider_animation_length.desc": "Muda a duração da animação selecionada",
"action.camera_reset": "Redefinir Câmera",
"action.camera_reset.desc": "Redefinir a visualização atual para o ângulo de câmera padrão",
"panel.variable_placeholders": "Preenchedores de Espaço de Variáveis",
"panel.variable_placeholders.info": "Lista as variáveis que você deseja visualizar via nome=valor",
"status_bar.vertex_distance": "Distância: %0",
"dialog.create_gif.title": "Gravar GIF",
"dialog.create_gif.length": "Duração (Segundos)",
"dialog.create_gif.length": "Duração",
"dialog.create_gif.fps": "FPS",
"dialog.create_gif.compression": "Quantidade de Compressão",
"dialog.create_gif.play": "Iniciar Animação",
@ -934,8 +926,6 @@
"status_bar.recording": "Linha do Tempo de gravação",
"message.add_to_palette": "Adicionado à paleta",
"message.size_modifiers": "Mantenha pressionada a tecla Ctrl ou Shift para transformar em incrementos menores.",
"message.checkerboard.enabled": "Checkerboard ativado",
"message.checkerboard.disabled": "Checkerboard desativado",
"message.timelapse_start": "Timelapse iniciado",
"message.timelapse_stop": "Timelapse parado",
"message.import_palette.replace_palette": "Substituir paleta antiga",
@ -981,8 +971,6 @@
"action.sort_palette.desc": "Classifique todas as cores da paleta por cor e brilho",
"action.clear_palette": "Limpar Paleta",
"action.clear_palette.desc": "Remove todas as cores da paleta",
"action.toggle_checkerboard": "Alternar Checkerboard",
"action.toggle_checkerboard.desc": "Alterne o fundo do checkerboard atrás da visualização ou do editor UV",
"action.timelapse": "Timelapse...",
"action.timelapse.desc": "Grave um timelapse do seu progresso de modelagem",
"action.add_keyframe": "Adicionar quadro-chave",
@ -1023,5 +1011,81 @@
"menu.help.search_action": "Search and Run Action",
"menu.help.donate": "Donate",
"menu.help.about": "About...",
"menu.preview.background.clipboard": "Load from Clipboard"
"menu.preview.background.clipboard": "Load from Clipboard",
"dialog.ignore": "Ignore",
"generic.unset": "Unset",
"message.invalid_builtin_parent.title": "Invalid Built-in Parent",
"message.invalid_builtin_parent.message": "The link to the invalid parent model '%0' was removed in order to export a valid model.",
"dialog.resize_texture.fill": "Fill with",
"dialog.resize_texture.fill.transparent": "Transparent",
"dialog.resize_texture.fill.color": "Color",
"dialog.resize_texture.fill.repeat": "Repeat",
"dialog.resize_texture.fill.stretch": "Stretch",
"dialog.scale.element_pivot": "Element Pivot",
"dialog.scale.selection_center": "Selection Center",
"dialog.create_gif.length_mode": "Length Mode",
"dialog.create_gif.length_mode.seconds": "Seconds",
"dialog.create_gif.length_mode.frames": "Frames",
"dialog.create_gif.length_mode.animation": "Animation Length",
"dialog.create_gif.length_mode.turntable": "Turntable Rotation",
"dialog.save_angle.projection": "Projection",
"dialog.save_angle.projection.perspective": "Perspective",
"dialog.save_angle.projection.orthographic": "Orthographic",
"dialog.sketchfab_uploader.animations": "Animations",
"dialog.settings.theme": "Theme",
"settings.category.interface": "Interface",
"settings.preview_checkerboard": "Preview Checkerboard",
"settings.preview_checkerboard.desc": "Toggle the checkerboard background behind the preview",
"settings.uv_checkerboard": "UV Editor Checkerboard",
"settings.uv_checkerboard.desc": "Toggle the checkerboard background behind the UV editor",
"category.paint": "Paint",
"action.fill_mode.color_connected": "Connected Colors",
"action.draw_shape_type": "Shape Type",
"action.draw_shape_type.rectangle": "Rectangle",
"action.draw_shape_type.rectangle_h": "Rectangle (Hollow)",
"action.draw_shape_type.ellipse": "Ellipse",
"action.draw_shape_type.ellipse_h": "Ellipse (Hollow)",
"action.draw_shape_type.line": "Line",
"action.mirror_painting": "Mirror Painting",
"action.mirror_painting.description": "Mirror your paint strokes to the other side of the model",
"action.lock_alpha": "Lock Alpha Channel",
"action.lock_alpha.description": "Lock the transparency of all pixels",
"action.draw_shape_tool": "Draw Shape",
"action.draw_shape_tool.desc": "Tool to draw simple shapes on textures",
"action.copy_paste_tool": "Copy Paste Tool",
"action.copy_paste_tool.desc": "Tool to copy and paste selections of textures",
"action.export_gltf": "Export As glTF",
"action.export_gltf.desc": "Export model and animations as glTF file to use in other 3D applications",
"action.transform_space": "Transform Space",
"action.transform_space.desc": "Default transform space for elements and bones",
"action.transform_space.global": "Global",
"action.transform_space.bone": "Bone",
"action.transform_space.local": "Local",
"action.toggle_camera_projection": "Toggle Camera Projection",
"action.toggle_camera_projection.desc": "Toggle the camera projection between perspective and orthographic",
"action.load_camera_angle": "Camera Angle: %0",
"action.load_camera_angle.desc": "Load the camera angle '%0'",
"action.slider_face_tint": "Tint Index",
"action.slider_face_tint.desc": "Set the tint index of the current face. -1 means unset.",
"menu.help.quickstart": "Quickstart Wizard",
"menu.help.developer": "Developer",
"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.cache_reload": "Cache Reload",
"menu.texture.resize": "Resize...",
"menu.preview.orthographic": "Orthographic",
"menu.preview.save_angle": "Save Angle...",
"menu.preview.angle": "Angles",
"menu.preview.angle.initial": "Initial Angle",
"menu.preview.angle.load": "Load",
"menu.preview.maximize": "Maximize",
"panel.color.both": "Both",
"uv_editor.copy_selection": "Copy Selection",
"uv_editor.paste_selection": "Paste Selection",
"uv_editor.copy_paste_tool.place": "Place",
"uv_editor.copy_paste_tool.cut": "Cut",
"uv_editor.copy_paste_tool.mirror_x": "Mirror X",
"uv_editor.copy_paste_tool.mirror_y": "Mirror Y",
"uv_editor.copy_paste_tool.rotate": "Rotate 90 Degrees"
}

View File

@ -157,7 +157,6 @@
"dialog.update.connecting": "Подключение к серверу",
"dialog.settings.settings": "Настройки",
"dialog.settings.keybinds": "Управление",
"dialog.settings.layout": "Внешний вид",
"dialog.settings.about": "О программе",
"layout.color.back": "Задний план",
"layout.color.back.desc": "Фон и поля ввода",
@ -364,8 +363,6 @@
"action.delete.desc": "Удаляет выделенные кубы или группы",
"action.sort_outliner": "Сортировать элементы",
"action.sort_outliner.desc": "Сортировать элементы в алфавитном порядке",
"action.local_move": "Относительное перемещение",
"action.local_move.desc": "По возможности сделать перемещение повёрнутых элементов по своим осям",
"action.select_window": "Выделить...",
"action.select_window.desc": "Выделить кубы на основе их свойств",
"action.invert_selection": "Инвертировать выделение",
@ -464,19 +461,16 @@
"menu.preview.background.load": "Загрузить",
"menu.preview.background.position": "Позиция",
"menu.preview.background.lock": "Привязать к камере",
"menu.preview.background.remove": "Удалить",
"menu.preview.screenshot": "Скриншот",
"menu.preview.perspective": "Перспектива",
"menu.preview.perspective.normal": "Обычная",
"menu.preview.quadview": "Четыре вида",
"menu.preview.fullview": "Полный вид",
"menu.preview.stop_drag": "Закончить изменение позиции",
"menu.uv.mapping": "UV-преобразование",
"menu.uv.mapping.export": "Экспортировать",
"menu.uv.mapping.rotation": "Поворот",
"menu.uv.mapping.mirror_x": "Отразить ось X",
"menu.uv.mapping.mirror_y": "Отразить ось Y",
"menu.uv.tint": "Тон",
"menu.uv.texture": "Текстура",
"cube.color.light_blue": "Голубой",
"cube.color.yellow": "Жёлтый",
@ -671,13 +665,11 @@
"message.bone_material": "Изменить материал кости",
"action.slider_animation_length": "Длительность анимации",
"action.slider_animation_length.desc": "Изменить длительность выбранной анимации",
"action.camera_reset": "Сбросить камеру",
"action.camera_reset.desc": "Сбросить угол камеры",
"panel.variable_placeholders": "Заполнители переменных",
"panel.variable_placeholders.info": "Перечислите переменные, которые вы хотите просмотреть используя имя=значение",
"status_bar.vertex_distance": "Дистанция: %0",
"dialog.create_gif.title": "Запись GIF",
"dialog.create_gif.length": "Длительность (В секундах)",
"dialog.create_gif.length": "Длительность",
"dialog.create_gif.fps": "FPS",
"dialog.create_gif.compression": "Сжатие",
"dialog.create_gif.play": "Воспроизвести анимацию",
@ -886,142 +878,214 @@
"message.canvas_limit_error.message": "Действие не может быть выполнено правильно, потому что формат ограничивает размеры рабочей области до 48 единиц. Сместите модель, чтобы предотвратить это.",
"data.effect": "Эффект",
"generic.name": "Имя",
"settings.recent_projects": "Recent Model Cap",
"settings.recent_projects.desc": "Maximum number of recent models to remember",
"settings.volume": "Volume",
"settings.volume.desc": "Volume control for sound effects in animations",
"settings.recent_projects": "Недавние модели",
"settings.recent_projects.desc": "Громкость",
"settings.volume": "Громкость",
"settings.volume.desc": "Регулятор громкости звуковых эффектов в анимации",
"action.change_keyframe_file": "Выбрать",
"action.change_keyframe_file.desc": "Select an audio file to preview a sound effect.",
"action.clear_timeline": "Clear Timeline",
"action.clear_timeline.desc": "Clear all unselected bones from the timeline",
"action.select_effect_animator": "Animate Effects",
"action.select_effect_animator.desc": "Opens timeline to add sound and particle effects",
"action.change_keyframe_file.desc": "Выбрать аудиофайл для предварительного просмотра звукового эффекта",
"action.clear_timeline": "Очистить шкалу времени",
"action.clear_timeline.desc": "Удалить все невыбранные <...> из временной шкалы",
"action.select_effect_animator": "Эффекты анимации",
"action.select_effect_animator.desc": "Открыть временную шкалу для добавления звуковых эффектов и частиц",
"action.timeline_focus": "Канал",
"action.timeline_focus.desc": "Select the animation channels to display in the timeline",
"action.timeline_focus.desc": "Выбрать каналы анимации для отображения на временной шкале",
"action.timeline_focus.all": "Все",
"timeline.particle": "Частица",
"timeline.sound": "Звук",
"timeline.effects": "Эффекты",
"data.format": "Формат",
"format.optifine_part": "OptiFine Part",
"format.optifine_part.desc": "JPM part for OptiFine entity models",
"action.reverse_keyframes": "Reverse Keyframes",
"action.reverse_keyframes.desc": "Reverse the order of the selected keyframes",
"generic.help": "Help",
"message.removed_faces": "Removed %0 faces",
"dialog.sketchfab_uploader.draft": "Draft",
"action.slider_pos": "Move %0",
"action.slider_pos.desc": "Move cubes on the %0 axis",
"action.slider_size": "Size %0",
"action.slider_size.desc": "Resize cubes on the %0 axis",
"action.slider_rotation": "Rotate %0",
"action.slider_rotation.desc": "Rotate cubes on the %0 axis",
"action.slider_origin": "Pivot %0",
"action.slider_origin.desc": "Move pivot on the %0 axis",
"action.rotate_cw": "Rotate %0 +90",
"action.rotate_cw.desc": "Rotate the selected cubes 90° on the %0 axis",
"action.rotate_ccw": "Rotate %0 -90",
"action.rotate_ccw.desc": "Rotate the selected cubes -90° on the %0 axis",
"action.flip": "Flip %0",
"action.flip.desc": "Flip the selected cubes on the %0 axis",
"action.center": "Center %0",
"action.center.desc": "Center the selected cubes on the %0 axis",
"action.bring_up_all_animations": "Bring Up All Animations",
"panel.bone": "Bone",
"data.color": "Color",
"generic.export": "Export",
"generic.none": "None",
"status_bar.recording": "Recording Timelapse",
"message.add_to_palette": "Added to palette",
"message.size_modifiers": "Hold down Ctrl or Shift to transform in smaller increments.",
"message.checkerboard.enabled": "Checkerboard enabled",
"message.checkerboard.disabled": "Checkerboard disabled",
"message.timelapse_start": "Timelapse started",
"message.timelapse_stop": "Timelapse stopped",
"message.import_palette.replace_palette": "Replace old palette",
"message.import_palette.threshold": "Merge Threshold",
"dialog.timelapse.interval": "Interval (Seconds)",
"dialog.timelapse.source": "Source",
"dialog.timelapse.source.interface": "Interface",
"dialog.timelapse.source.locked": "Locked Angle",
"dialog.timelapse.destination": "Destination Folder",
"layout.color.checkerboard": "Checkerboard",
"layout.color.checkerboard.desc": "Background of canvas and UV editor",
"layout.font.code": "Code Font",
"layout.css": "Custom CSS",
"settings.category.paint": "Paint",
"settings.deactivate_size_limit": "Deactivate Size Limit",
"settings.deactivate_size_limit.desc": "Deactivate the size limit for specific model formats. WARNING: This can cause invalid models.",
"settings.brush_opacity_modifier": "Brush Opacity Modifier",
"settings.brush_opacity_modifier.desc": "Modify the brush opacity when using a stylus",
"settings.brush_size_modifier": "Brush Size Modifier",
"settings.brush_size_modifier.desc": "Modify the brush size when using a stylus",
"settings.brush_modifier.pressure": "Pressure",
"settings.brush_modifier.tilt": "Tilt",
"settings.class_export_version": "Modded Entity Export Version",
"settings.class_export_version.desc": "The format version for modded entity models",
"category.color": "Color",
"action.import_theme": "Import Theme",
"action.export_theme": "Export Theme",
"action.export_theme.desc": "Create a theme file based on the current settings",
"action.reset_theme": "Reset Theme",
"action.reset_theme.desc": "Reset to the default Blockbench theme",
"action.slider_color_h": "Hue",
"action.slider_color_s": "Saturation",
"action.slider_color_v": "Value",
"action.add_to_palette": "Add To Palette",
"action.add_to_palette.desc": "Add the selected color to the color palette",
"action.import_palette": "Import Palette",
"action.import_palette.desc": "Import a .bbpalette file",
"action.export_palette": "Export Palette",
"action.export_palette.desc": "Export palette as a .bbpalette file",
"action.generate_palette": "Generate Palette",
"action.generate_palette.desc": "Generate palette from a texture",
"action.sort_palette": "Sort Palette",
"action.sort_palette.desc": "Sort all colors on the palette by color and brightness",
"action.clear_palette": "Clear Palette",
"action.clear_palette.desc": "Remove all colors from the palette",
"action.toggle_checkerboard": "Toggle Checkerboard",
"action.toggle_checkerboard.desc": "Toggle the checkerboard background behind the preview or UV editor",
"action.timelapse": "Timelapse...",
"action.timelapse.desc": "Record a timelapse of your modeling process",
"action.add_keyframe": "Add Keyframe",
"action.add_keyframe.desc": "Automatically add a keyframe. Press shift to force default values",
"action.bring_up_all_animations.desc": "Brings all modified animators into the timeline",
"timeline.timeline": "Instructions",
"menu.palette.load": "Load Palette",
"menu.palette.load.default": "Default",
"panel.color.picker": "Picker",
"panel.color.palette": "Palette",
"generic.import": "Import",
"settings.brush_modifier.none": "None",
"action.export_entity": "Export Bedrock Entity",
"action.export_entity.desc": "Add the current model as an entity to a mobs.json file",
"settings.highlight_cubes": "Highlight Cubes",
"settings.highlight_cubes.desc": "Highlight cubes when you hover over them or select them",
"action.add_marker": "Set Marker",
"action.add_marker.desc": "Set a timeline marker",
"timeline.pre_effect_script": "Script",
"format.skin": "Skin",
"format.skin.desc": "Edit player and entity skins",
"message.sketchfab.setup_guide": "Want to learn how to set up models in Sketchfab? Read %0",
"dialog.skin.title": "Create Skin",
"dialog.skin.model": "Skin",
"dialog.skin.texture": "Texture (Optional)",
"action.toggle_skin_layer": "Toggle Skin Layer",
"action.toggle_skin_layer.desc": "Toggle the hat and clothing layer of the skin model",
"action.gui_light": "GUI Light",
"action.gui_light.desc": "Select the way the item is lit in the inventory",
"action.gui_light.side": "Side Light",
"action.gui_light.front": "Front Light",
"action.move_keyframe_back": "Move Keyframes Back",
"action.move_keyframe_forth": "Move Keyframes Forth",
"menu.help": "Help",
"menu.help.discord": "Discord Server",
"menu.help.report_issue": "Report an Issue",
"menu.help.plugin_documentation": "Plugin API Documentation",
"menu.help.search_action": "Search and Run Action",
"menu.help.donate": "Donate",
"menu.help.about": "About...",
"menu.preview.background.clipboard": "Load from Clipboard"
"format.optifine_part": "Раздел Optifine",
"format.optifine_part.desc": "JPM для моделей сущности OptiFine",
"action.reverse_keyframes": "Реверс ключевых кадров",
"action.reverse_keyframes.desc": "Реверс ключевых кадров в обратном порядке",
"generic.help": "Помощь",
"message.removed_faces": "Удалено %0 лиц",
"dialog.sketchfab_uploader.draft": "Черновик",
"action.slider_pos": "Перемещено %0",
"action.slider_pos.desc": "Перемещение кубов по оси %0",
"action.slider_size": "Размер %0",
"action.slider_size.desc": "Изменить размер кубов на оси %0",
"action.slider_rotation": "Поворот %0",
"action.slider_rotation.desc": "Повернуть кубы на оси %0",
"action.slider_origin": "Ось вращения %0",
"action.slider_origin.desc": "Переместить ось вращения на оси %0",
"action.rotate_cw": "Поворот %0 +90",
"action.rotate_cw.desc": "Повернуть выбранные кубы на 90° на оси %0",
"action.rotate_ccw": "Поворот %0 -90",
"action.rotate_ccw.desc": "Повернуть выбранные кубы на -90° на оси %0",
"action.flip": "Переворот %0",
"action.flip.desc": "Переворот выбранных кубов по оси %0",
"action.center": "Центр %0",
"action.center.desc": "Центр выбранных кубов по оси %0",
"action.bring_up_all_animations": "Свернуть все анимации",
"panel.bone": "Кость",
"data.color": "Цвет",
"generic.export": "Экспорт",
"generic.none": "Ничего",
"status_bar.recording": "Шкала записи",
"message.add_to_palette": "Добавлено в палитру",
"message.size_modifiers": "Удерживайте Ctrl или Shift для уменьшения длины преобразования",
"message.timelapse_start": "Ускоренная съемка началась",
"message.timelapse_stop": "Ускоренная съемка закончилась",
"message.import_palette.replace_palette": "Заменить старую палитру",
"message.import_palette.threshold": "Граница соединения",
"dialog.timelapse.interval": "Интервал (с)",
"dialog.timelapse.source": "Источник",
"dialog.timelapse.source.interface": "Интерфейс",
"dialog.timelapse.source.locked": "Заблокированный угол",
"dialog.timelapse.destination": "Папка назначения",
"layout.color.checkerboard": "Клетка",
"layout.color.checkerboard.desc": "Фон рабочей области и редактора UV",
"layout.font.code": "Шрифт кода",
"layout.css": "Пользовательский CSS",
"settings.category.paint": "Красить",
"settings.deactivate_size_limit": "Выключить лимит размера",
"settings.deactivate_size_limit.desc": "Выключить лимит размера для определенных форматов. ПРЕДУПРЕЖДЕНИЕ: Это может вызвать ошибки с моделями.",
"settings.brush_opacity_modifier": "Модификатор непрозрачности кисти",
"settings.brush_opacity_modifier.desc": "Модифицировать непрозрачность кисти при использовании стилуса",
"settings.brush_size_modifier": "Модификатор размера кисти",
"settings.brush_size_modifier.desc": "Модифицировать размер кисти при использовании стилуса",
"settings.brush_modifier.pressure": "Давление",
"settings.brush_modifier.tilt": "Наклон",
"settings.class_export_version": "Модифицированная версия экспорта сущностей",
"settings.class_export_version.desc": "Версия формата для модифицированных моделей сущностей",
"category.color": "Цвет",
"action.import_theme": "Импорт темы",
"action.export_theme": "Экспорт темы",
"action.export_theme.desc": "Создать файл темы на основе текущих настроек",
"action.reset_theme": "Сбросить тему",
"action.reset_theme.desc": "Возврат к стандартной теме Blockbench",
"action.slider_color_h": "Оттенок",
"action.slider_color_s": "Насыщение",
"action.slider_color_v": "Значение",
"action.add_to_palette": "Добавить в палитру",
"action.add_to_palette.desc": "Добавить выбранные цвета в палитру",
"action.import_palette": "Импорт палитры",
"action.import_palette.desc": "Импорт палитры в файл .bbpalette",
"action.export_palette": "Экспорт палитры",
"action.export_palette.desc": "Экспорт палитры в файл .bbpalette",
"action.generate_palette": "Сгенерировать палитру",
"action.generate_palette.desc": "Сгенерировать палитру из текстуры",
"action.sort_palette": "Сортировка палитры",
"action.sort_palette.desc": "Сортировать цвета на палитре по цвету и яркости",
"action.clear_palette": "Очистка палитры",
"action.clear_palette.desc": "Удалить все цвета из палитры",
"action.timelapse": "Временная шкала",
"action.timelapse.desc": "Записать процесс создания модели",
"action.add_keyframe": "Добавить ключевой кадр",
"action.add_keyframe.desc": "Автоматическое добавление ключевого кадра. Нажмите Shift для ввода стандартных значений ",
"action.bring_up_all_animations.desc": "Перенос всех модифицированных анимаций на временную шкалу",
"timeline.timeline": "Инструкции",
"menu.palette.load": "Загрузка палитры",
"menu.palette.load.default": "Стандарт",
"panel.color.picker": "Подборщик",
"panel.color.palette": "Палитра",
"generic.import": "Импорт",
"settings.brush_modifier.none": "Ничего",
"action.export_entity": "Экспорт Bedrock-сущности",
"action.export_entity.desc": "Добавить выбранную модель как сущность в файл mobs.json",
"settings.highlight_cubes": "Выделить кубы",
"settings.highlight_cubes.desc": "Выделение кубов в момент наведения на них курсора мыши",
"action.add_marker": "Установить пометку",
"action.add_marker.desc": "Установить пометку на шкале времени",
"timeline.pre_effect_script": "Скрипт",
"format.skin": "Скин",
"format.skin.desc": "Редактировать скины игроков и сущностей",
"message.sketchfab.setup_guide": "Узнать, как настроить модели в Sketchfab: %0",
"dialog.skin.title": "Создать скин",
"dialog.skin.model": "Скин",
"dialog.skin.texture": "Текстура",
"action.toggle_skin_layer": "Переключить слой скина",
"action.toggle_skin_layer.desc": "Переключить слои шляпы и одежды",
"action.gui_light": "Светлый интерфейс",
"action.gui_light.desc": "Выбрать способ освещения предмета в инвентаре",
"action.gui_light.side": "Боковой свет",
"action.gui_light.front": "Передний свет",
"action.move_keyframe_back": "Сдвинуть кадры назад",
"action.move_keyframe_forth": "Сдвинуть кадры вперед",
"menu.help": "Помощь",
"menu.help.discord": "Сервер Дискорд",
"menu.help.report_issue": "Сообщить о проблеме",
"menu.help.plugin_documentation": "Документация API плагинов",
"menu.help.search_action": "Найти и выполнить действие",
"menu.help.donate": "Пожертвовать",
"menu.help.about": "Инфо",
"menu.preview.background.clipboard": "Загрузить из буфера обмена",
"dialog.ignore": "Ignore",
"generic.unset": "Unset",
"message.invalid_builtin_parent.title": "Invalid Built-in Parent",
"message.invalid_builtin_parent.message": "The link to the invalid parent model '%0' was removed in order to export a valid model.",
"dialog.resize_texture.fill": "Fill with",
"dialog.resize_texture.fill.transparent": "Transparent",
"dialog.resize_texture.fill.color": "Color",
"dialog.resize_texture.fill.repeat": "Repeat",
"dialog.resize_texture.fill.stretch": "Stretch",
"dialog.scale.element_pivot": "Element Pivot",
"dialog.scale.selection_center": "Selection Center",
"dialog.create_gif.length_mode": "Length Mode",
"dialog.create_gif.length_mode.seconds": "Seconds",
"dialog.create_gif.length_mode.frames": "Frames",
"dialog.create_gif.length_mode.animation": "Animation Length",
"dialog.create_gif.length_mode.turntable": "Turntable Rotation",
"dialog.save_angle.projection": "Projection",
"dialog.save_angle.projection.perspective": "Perspective",
"dialog.save_angle.projection.orthographic": "Orthographic",
"dialog.sketchfab_uploader.animations": "Animations",
"dialog.settings.theme": "Theme",
"settings.category.interface": "Interface",
"settings.preview_checkerboard": "Preview Checkerboard",
"settings.preview_checkerboard.desc": "Toggle the checkerboard background behind the preview",
"settings.uv_checkerboard": "UV Editor Checkerboard",
"settings.uv_checkerboard.desc": "Toggle the checkerboard background behind the UV editor",
"category.paint": "Paint",
"action.fill_mode.color_connected": "Connected Colors",
"action.draw_shape_type": "Shape Type",
"action.draw_shape_type.rectangle": "Rectangle",
"action.draw_shape_type.rectangle_h": "Rectangle (Hollow)",
"action.draw_shape_type.ellipse": "Ellipse",
"action.draw_shape_type.ellipse_h": "Ellipse (Hollow)",
"action.draw_shape_type.line": "Line",
"action.mirror_painting": "Mirror Painting",
"action.mirror_painting.description": "Mirror your paint strokes to the other side of the model",
"action.lock_alpha": "Lock Alpha Channel",
"action.lock_alpha.description": "Lock the transparency of all pixels",
"action.draw_shape_tool": "Draw Shape",
"action.draw_shape_tool.desc": "Tool to draw simple shapes on textures",
"action.copy_paste_tool": "Copy Paste Tool",
"action.copy_paste_tool.desc": "Tool to copy and paste selections of textures",
"action.export_gltf": "Export As glTF",
"action.export_gltf.desc": "Export model and animations as glTF file to use in other 3D applications",
"action.transform_space": "Transform Space",
"action.transform_space.desc": "Default transform space for elements and bones",
"action.transform_space.global": "Global",
"action.transform_space.bone": "Bone",
"action.transform_space.local": "Local",
"action.toggle_camera_projection": "Toggle Camera Projection",
"action.toggle_camera_projection.desc": "Toggle the camera projection between perspective and orthographic",
"action.load_camera_angle": "Camera Angle: %0",
"action.load_camera_angle.desc": "Load the camera angle '%0'",
"action.slider_face_tint": "Tint Index",
"action.slider_face_tint.desc": "Set the tint index of the current face. -1 means unset.",
"menu.help.quickstart": "Quickstart Wizard",
"menu.help.developer": "Developer",
"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.cache_reload": "Cache Reload",
"menu.texture.resize": "Resize...",
"menu.preview.orthographic": "Orthographic",
"menu.preview.save_angle": "Save Angle...",
"menu.preview.angle": "Angles",
"menu.preview.angle.initial": "Initial Angle",
"menu.preview.angle.load": "Load",
"menu.preview.maximize": "Maximize",
"panel.color.both": "Both",
"uv_editor.copy_selection": "Copy Selection",
"uv_editor.paste_selection": "Paste Selection",
"uv_editor.copy_paste_tool.place": "Place",
"uv_editor.copy_paste_tool.cut": "Cut",
"uv_editor.copy_paste_tool.mirror_x": "Mirror X",
"uv_editor.copy_paste_tool.mirror_y": "Mirror Y",
"uv_editor.copy_paste_tool.rotate": "Rotate 90 Degrees"
}

View File

@ -157,7 +157,6 @@
"dialog.update.connecting": "Ansluter till servern",
"dialog.settings.settings": "Inställningar",
"dialog.settings.keybinds": "Tangentbindningar",
"dialog.settings.layout": "Layout",
"dialog.settings.about": "Om",
"layout.color.back": "Tillbaka",
"layout.color.back.desc": "Bakgrund och inmatningsfält",
@ -364,8 +363,6 @@
"action.delete.desc": "Raderar de valda kuberna eller en grupp",
"action.sort_outliner": "Sortera konturer",
"action.sort_outliner.desc": "Sortera konturen alfabetiskt",
"action.local_move": "Flytta relativt",
"action.local_move.desc": "Flytta roterade element på deras egna axlar om möjligt",
"action.select_window": "Välj...",
"action.select_window.desc": "Sök och välj kuber baserat på deras egenskaper",
"action.invert_selection": "Invertera valet",
@ -464,19 +461,16 @@
"menu.preview.background.load": "Ladda",
"menu.preview.background.position": "Position",
"menu.preview.background.lock": "Lås till kamera",
"menu.preview.background.remove": "Ta bort",
"menu.preview.screenshot": "Skärmbild",
"menu.preview.perspective": "Perspektiv",
"menu.preview.perspective.normal": "Normal",
"menu.preview.quadview": "Fyrvy",
"menu.preview.fullview": "Fullvy",
"menu.preview.stop_drag": "Stoppa bakgrundspositionering",
"menu.uv.mapping": "UV kartläggning",
"menu.uv.mapping.export": "Exportera",
"menu.uv.mapping.rotation": "Rotation",
"menu.uv.mapping.mirror_x": "Spegla X",
"menu.uv.mapping.mirror_y": "Spegla Y",
"menu.uv.tint": "Nyans",
"menu.uv.texture": "Textur",
"cube.color.light_blue": "Ljus blå",
"cube.color.yellow": "Gul",
@ -671,13 +665,11 @@
"message.bone_material": "Ändra ben material",
"action.slider_animation_length": "Animationslängd",
"action.slider_animation_length.desc": "Ändra längden av den valda animationen",
"action.camera_reset": "Återställ kamera",
"action.camera_reset.desc": "Återställ den aktuella förhandsvisningen till standard kameravinkeln",
"panel.variable_placeholders": "Platshållare variabel",
"panel.variable_placeholders.info": "Ange de variabler du vill förhandsgranska via namn=värde",
"status_bar.vertex_distance": "Distans: %0",
"dialog.create_gif.title": "Spela in GIF",
"dialog.create_gif.length": "Längd (Sekunder)",
"dialog.create_gif.length": "Längd",
"dialog.create_gif.fps": "FPS",
"dialog.create_gif.compression": "Kompressionsstorlek",
"dialog.create_gif.play": "Starta animationen",
@ -854,7 +846,7 @@
"action.save_project.desc": "Saves the current model as a project file",
"action.save_project_as": "Save Project As",
"action.save_project_as.desc": "Saves the current model as a project file at a new location",
"action.export_over": "Overwrite Model",
"action.export_over": "Save Model",
"action.export_over.desc": "Saves the model, textures and animations by overwriting the files",
"action.add_locator": "Add Locator",
"action.add_locator.desc": "Adds a new locator to control positions of particles, leashes etc",
@ -934,8 +926,6 @@
"status_bar.recording": "Recording Timelapse",
"message.add_to_palette": "Added to palette",
"message.size_modifiers": "Hold down Ctrl or Shift to transform in smaller increments.",
"message.checkerboard.enabled": "Checkerboard enabled",
"message.checkerboard.disabled": "Checkerboard disabled",
"message.timelapse_start": "Timelapse started",
"message.timelapse_stop": "Timelapse stopped",
"message.import_palette.replace_palette": "Replace old palette",
@ -981,8 +971,6 @@
"action.sort_palette.desc": "Sort all colors on the palette by color and brightness",
"action.clear_palette": "Clear Palette",
"action.clear_palette.desc": "Remove all colors from the palette",
"action.toggle_checkerboard": "Toggle Checkerboard",
"action.toggle_checkerboard.desc": "Toggle the checkerboard background behind the preview or UV editor",
"action.timelapse": "Timelapse...",
"action.timelapse.desc": "Record a timelapse of your modeling process",
"action.add_keyframe": "Add Keyframe",
@ -1023,5 +1011,81 @@
"menu.help.search_action": "Search and Run Action",
"menu.help.donate": "Donate",
"menu.help.about": "About...",
"menu.preview.background.clipboard": "Load from Clipboard"
"menu.preview.background.clipboard": "Load from Clipboard",
"dialog.ignore": "Ignore",
"generic.unset": "Unset",
"message.invalid_builtin_parent.title": "Invalid Built-in Parent",
"message.invalid_builtin_parent.message": "The link to the invalid parent model '%0' was removed in order to export a valid model.",
"dialog.resize_texture.fill": "Fill with",
"dialog.resize_texture.fill.transparent": "Transparent",
"dialog.resize_texture.fill.color": "Color",
"dialog.resize_texture.fill.repeat": "Repeat",
"dialog.resize_texture.fill.stretch": "Stretch",
"dialog.scale.element_pivot": "Element Pivot",
"dialog.scale.selection_center": "Selection Center",
"dialog.create_gif.length_mode": "Length Mode",
"dialog.create_gif.length_mode.seconds": "Seconds",
"dialog.create_gif.length_mode.frames": "Frames",
"dialog.create_gif.length_mode.animation": "Animation Length",
"dialog.create_gif.length_mode.turntable": "Turntable Rotation",
"dialog.save_angle.projection": "Projection",
"dialog.save_angle.projection.perspective": "Perspective",
"dialog.save_angle.projection.orthographic": "Orthographic",
"dialog.sketchfab_uploader.animations": "Animations",
"dialog.settings.theme": "Theme",
"settings.category.interface": "Interface",
"settings.preview_checkerboard": "Preview Checkerboard",
"settings.preview_checkerboard.desc": "Toggle the checkerboard background behind the preview",
"settings.uv_checkerboard": "UV Editor Checkerboard",
"settings.uv_checkerboard.desc": "Toggle the checkerboard background behind the UV editor",
"category.paint": "Paint",
"action.fill_mode.color_connected": "Connected Colors",
"action.draw_shape_type": "Shape Type",
"action.draw_shape_type.rectangle": "Rectangle",
"action.draw_shape_type.rectangle_h": "Rectangle (Hollow)",
"action.draw_shape_type.ellipse": "Ellipse",
"action.draw_shape_type.ellipse_h": "Ellipse (Hollow)",
"action.draw_shape_type.line": "Line",
"action.mirror_painting": "Mirror Painting",
"action.mirror_painting.description": "Mirror your paint strokes to the other side of the model",
"action.lock_alpha": "Lock Alpha Channel",
"action.lock_alpha.description": "Lock the transparency of all pixels",
"action.draw_shape_tool": "Draw Shape",
"action.draw_shape_tool.desc": "Tool to draw simple shapes on textures",
"action.copy_paste_tool": "Copy Paste Tool",
"action.copy_paste_tool.desc": "Tool to copy and paste selections of textures",
"action.export_gltf": "Export As glTF",
"action.export_gltf.desc": "Export model and animations as glTF file to use in other 3D applications",
"action.transform_space": "Transform Space",
"action.transform_space.desc": "Default transform space for elements and bones",
"action.transform_space.global": "Global",
"action.transform_space.bone": "Bone",
"action.transform_space.local": "Local",
"action.toggle_camera_projection": "Toggle Camera Projection",
"action.toggle_camera_projection.desc": "Toggle the camera projection between perspective and orthographic",
"action.load_camera_angle": "Camera Angle: %0",
"action.load_camera_angle.desc": "Load the camera angle '%0'",
"action.slider_face_tint": "Tint Index",
"action.slider_face_tint.desc": "Set the tint index of the current face. -1 means unset.",
"menu.help.quickstart": "Quickstart Wizard",
"menu.help.developer": "Developer",
"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.cache_reload": "Cache Reload",
"menu.texture.resize": "Resize...",
"menu.preview.orthographic": "Orthographic",
"menu.preview.save_angle": "Save Angle...",
"menu.preview.angle": "Angles",
"menu.preview.angle.initial": "Initial Angle",
"menu.preview.angle.load": "Load",
"menu.preview.maximize": "Maximize",
"panel.color.both": "Both",
"uv_editor.copy_selection": "Copy Selection",
"uv_editor.paste_selection": "Paste Selection",
"uv_editor.copy_paste_tool.place": "Place",
"uv_editor.copy_paste_tool.cut": "Cut",
"uv_editor.copy_paste_tool.mirror_x": "Mirror X",
"uv_editor.copy_paste_tool.mirror_y": "Mirror Y",
"uv_editor.copy_paste_tool.rotate": "Rotate 90 Degrees"
}

File diff suppressed because it is too large Load Diff

View File

@ -56,6 +56,22 @@ var WEBGL_CONSTANTS = {
REPEAT: 10497
};
var img = this.img = new Image()
img.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVQYV2NgAAIAAAUAAarVyFEAAAAASUVORK5CYII='
var tex = new THREE.Texture(img)
img.tex = tex;
img.tex.magFilter = THREE.NearestFilter
img.tex.minFilter = THREE.NearestFilter
var invisibleMaterial = new THREE.MeshLambertMaterial({
color: 0xffffff,
map: tex,
transparent: true,
alphaTest: 0.2
});
var THREE_TO_WEBGL = {};
THREE_TO_WEBGL[ NearestFilter ] = WEBGL_CONSTANTS.NEAREST;
@ -910,6 +926,11 @@ GLTFExporter.prototype = {
*/
function processMaterial( material ) {
// blockbench custom material
if ( material == Canvas.transparentMaterial ) {
material = invisibleMaterial;
}
if ( cachedData.materials.has( material ) ) {
return cachedData.materials.get( material );
@ -1265,18 +1286,20 @@ GLTFExporter.prototype = {
modifiedAttribute = new BufferAttribute( new Float32Array( array ), attribute.itemSize, attribute.normalized );
let isCube = mesh.type == 'cube';
if (!isCube) {
var img = mesh.material.map.image;
var map = mesh.material.map;
}
modifiedAttribute.array.forEach((v, i) => {
if (isCube) {
var img = mesh.material[Math.floor(i / 12)].map.image;
var map = mesh.material[Math.floor(i / 12)].map;
}
if (i%2 == 0) {
modifiedAttribute.array[i] = v * (img.width / THREE.Math.ceilPowerOfTwo(img.width));
} else {
modifiedAttribute.array[i] = 1-(1-v) * (img.height / THREE.Math.ceilPowerOfTwo(img.height));
if (map && map.image) {
if (i%2 == 0) {
modifiedAttribute.array[i] = v * (map.image.width / THREE.Math.ceilPowerOfTwo(map.image.width));
} else {
modifiedAttribute.array[i] = 1-(1-v) * (map.image.height / THREE.Math.ceilPowerOfTwo(map.image.height));
}
}
})
}

File diff suppressed because one or more lines are too long

8
lib/gifshot.min.js vendored

File diff suppressed because one or more lines are too long

49160
lib/three.js

File diff suppressed because one or more lines are too long

1036
lib/three.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -53,7 +53,7 @@ Object.assign( THREE.Euler.prototype, {
this._y = Math.degToRad(arr[1]) * (invert ? -1 : 1);
this._z = Math.degToRad(arr[2]) * (invert ? -1 : 1);
this.onChangeCallback();
this._onChangeCallback();
return this;
@ -166,11 +166,99 @@ THREE.Object3D.prototype.toScreenPosition = function(camera, canvas)
};
THREE.AxesHelper = function( size ) {
size = size || 1;
var vertices = [
0, 0, 0, size, 0, 0,
0, 0, 0, 0, size, 0,
0, 0, 0, 0, 0, size
];
var c = gizmo_colors
var colors = [
c.r.r, c.r.g, c.r.b, c.r.r, c.r.g, c.r.b,
c.g.r, c.g.g, c.g.b, c.g.r, c.g.g, c.g.b,
c.b.r, c.b.g, c.b.b, c.b.r, c.b.g, c.b.b,
]
var geometry = new THREE.BufferGeometry();
geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) );
geometry.setAttribute( 'color', new THREE.Float32BufferAttribute( colors, 3 ) );
var material = new THREE.LineBasicMaterial( { vertexColors: THREE.VertexColors } );
THREE.LineSegments.call( this, geometry, material );
}
THREE.AxesHelper.prototype = Object.create( THREE.LineSegments.prototype );
THREE.AxesHelper.prototype.constructor = THREE.AxesHelper;
THREE.GridHelper = function( size, divisions, color1, color2 ) {
size = size || 10;
divisions = divisions || 10;
color1 = new THREE.Color( color1 !== undefined ? color1 : 0x444444 );
color2 = new THREE.Color( color2 !== undefined ? color2 : 0x888888 );
var center = divisions / 2;
var step = size / divisions;
var halfSize = size / 2;
var vertices = [], colors = [];
for ( var i = 0, j = 0, k = - halfSize; i <= divisions; i ++, k += step ) {
vertices.push( - halfSize, 0, k, halfSize, 0, k );
vertices.push( k, 0, - halfSize, k, 0, halfSize );
var color = i === center ? color1 : color2;
color.toArray( colors, j ); j += 3;
color.toArray( colors, j ); j += 3;
color.toArray( colors, j ); j += 3;
color.toArray( colors, j ); j += 3;
}
var geometry = new THREE.BufferGeometry();
geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) );
geometry.setAttribute( 'color', new THREE.Float32BufferAttribute( colors, 3 ) );
var material = new THREE.LineBasicMaterial( { color: color1 } );
THREE.LineSegments.call( this, geometry, material );
}
THREE.GridHelper.prototype = Object.assign( Object.create( THREE.LineSegments.prototype ), {
constructor: THREE.GridHelper,
copy: function ( source ) {
THREE.LineSegments.prototype.copy.call( this, source );
this.geometry.copy( source.geometry );
this.material.copy( source.material );
return this;
},
clone: function () {
return new this.constructor().copy( this );
}
} );
THREE.NormalX = new THREE.Vector3(1, 0, 0);
THREE.NormalY = new THREE.Vector3(0, 1, 0);
THREE.NormalZ = new THREE.Vector3(0, 0, 1);
//22725 Init Log
//17544 ProgramLog message
// x 22725 Init Log
// x 17544 ProgramLog message
//22919 WebGL Error
//AxesHelper
//45899 Grid Color { color: color1 }

View File

@ -1,7 +1,7 @@
{
"name": "Blockbench",
"description": "Model editing and animation software",
"version": "3.3.1",
"version": "3.4.0",
"license": "MIT",
"author": {
"name": "JannisX11",
@ -80,7 +80,7 @@
},
"devDependencies": {
"async": "^2.4.1",
"electron": "6.1.4",
"electron-builder": "^21.2.0"
"electron": "8.0.2",
"electron-builder": "^22.3.2"
}
}