mirror of
https://github.com/JannisX11/blockbench.git
synced 2025-03-19 17:01:55 +08:00
v2.5.0
This commit is contained in:
parent
293238948a
commit
6ffc628ccc
@ -11,7 +11,7 @@ matrix:
|
||||
|
||||
- name: "Windows"
|
||||
os: osx
|
||||
script: build -w --x64 --publish=always && build -w --ia32 --publish=always
|
||||
script: build -w --x64 --publish=always
|
||||
|
||||
- name: "Linux"
|
||||
os: linux
|
||||
|
206
css/style.css
206
css/style.css
@ -79,78 +79,81 @@
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.icon-mirror_x:before {
|
||||
content: "\e915";
|
||||
}
|
||||
.icon-mirror_y:before {
|
||||
content: "\e916";
|
||||
}
|
||||
.icon-mirror_z:before {
|
||||
content: "\e917";
|
||||
}
|
||||
.icon-saved:before {
|
||||
content: "\e913";
|
||||
}
|
||||
.icon-player:before {
|
||||
content: "\e914";
|
||||
}
|
||||
.icon-vertexsnap:before {
|
||||
.icon-blockbench_file:before {
|
||||
content: "\e900";
|
||||
}
|
||||
.icon-optifine_file:before {
|
||||
content: "\e912";
|
||||
}
|
||||
.icon-objects:before {
|
||||
content: "\e902";
|
||||
}
|
||||
.icon-create_bitmap:before {
|
||||
.icon-vertexsnap:before {
|
||||
content: "\e901";
|
||||
}
|
||||
.icon-bow:before {
|
||||
.icon-create_bitmap:before {
|
||||
content: "\e902";
|
||||
}
|
||||
.icon-objects:before {
|
||||
content: "\e903";
|
||||
}
|
||||
.icon-bb_interface:before {
|
||||
.icon-bow:before {
|
||||
content: "\e904";
|
||||
}
|
||||
.icon-blockbench_inverted:before {
|
||||
content: "\e911";
|
||||
}
|
||||
.icon-blockbench:before {
|
||||
.icon-bb_interface:before {
|
||||
content: "\e905";
|
||||
}
|
||||
.icon-x11:before {
|
||||
.icon-blockbench:before {
|
||||
content: "\e906";
|
||||
}
|
||||
.icon-baby_zombie:before {
|
||||
.icon-x11:before {
|
||||
content: "\e907";
|
||||
}
|
||||
.icon-armor_stand:before {
|
||||
.icon-baby_zombie:before {
|
||||
content: "\e908";
|
||||
}
|
||||
.icon-armor_stand_small:before {
|
||||
.icon-armor_stand:before {
|
||||
content: "\e909";
|
||||
}
|
||||
.icon-ground:before {
|
||||
.icon-armor_stand_small:before {
|
||||
content: "\e90a";
|
||||
}
|
||||
.icon-hud:before {
|
||||
.icon-ground:before {
|
||||
content: "\e90b";
|
||||
}
|
||||
.icon-inventory_full:before {
|
||||
.icon-hud:before {
|
||||
content: "\e90c";
|
||||
}
|
||||
.icon-inventory_nine:before {
|
||||
.icon-inventory_full:before {
|
||||
content: "\e90d";
|
||||
}
|
||||
.icon-inventory_single:before {
|
||||
.icon-inventory_nine:before {
|
||||
content: "\e90e";
|
||||
}
|
||||
.icon-player_head:before {
|
||||
.icon-inventory_single:before {
|
||||
content: "\e90f";
|
||||
}
|
||||
.icon-zombie:before {
|
||||
.icon-player_head:before {
|
||||
content: "\e910";
|
||||
}
|
||||
.icon-zombie:before {
|
||||
content: "\e911";
|
||||
}
|
||||
.icon-blockbench_inverted:before {
|
||||
content: "\e912";
|
||||
}
|
||||
.icon-optifine_file:before {
|
||||
content: "\e913";
|
||||
}
|
||||
.icon-saved:before {
|
||||
content: "\e914";
|
||||
}
|
||||
.icon-player:before {
|
||||
content: "\e915";
|
||||
}
|
||||
.icon-mirror_x:before {
|
||||
content: "\e916";
|
||||
}
|
||||
.icon-mirror_y:before {
|
||||
content: "\e917";
|
||||
}
|
||||
.icon-mirror_z:before {
|
||||
content: "\e918";
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -177,6 +180,7 @@
|
||||
height: 30px;
|
||||
width: 24px;
|
||||
text-align: center;
|
||||
vertical-align: text-top;
|
||||
}
|
||||
.dialog .message_box_icon {
|
||||
font-size: 40pt;
|
||||
@ -787,7 +791,7 @@
|
||||
}
|
||||
|
||||
.half {
|
||||
width: calc(50% - 2px);
|
||||
width: calc(50% - 4px);
|
||||
}
|
||||
|
||||
.tooltip {
|
||||
@ -928,14 +932,46 @@
|
||||
.outliner_object:hover {
|
||||
color: var(--color-light);
|
||||
}
|
||||
.drag_hover {
|
||||
border: 2px solid var(--color-accent);
|
||||
#cubes_list.drag_hover > .vue-tree {
|
||||
position: relative;
|
||||
}
|
||||
.drag_hover.drag_hover_insert_before {
|
||||
border-top: 2px solid var(--color-accent);
|
||||
border-bottom: none;
|
||||
border-right: none;
|
||||
border-left: none;
|
||||
#cubes_list.drag_hover > .vue-tree > ul::before {
|
||||
content: '';
|
||||
width: calc(100% - 12px);
|
||||
height: 2px;
|
||||
margin-left: 6px;
|
||||
background: var(--color-accent);
|
||||
z-index: 3;
|
||||
display: block;
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
}
|
||||
.drag_hover[order]::before {
|
||||
content: '';
|
||||
width: calc(100% - 12px);
|
||||
height: 2px;
|
||||
margin-left: 6px;
|
||||
background: var(--color-accent);
|
||||
z-index: 3;
|
||||
display: block;
|
||||
position: absolute;
|
||||
}
|
||||
.drag_hover[order] {
|
||||
position: relative;
|
||||
}
|
||||
.drag_hover[order="-1"]::before {
|
||||
margin-top: -1px;
|
||||
}
|
||||
.drag_hover[order="1"]::before {
|
||||
bottom: 0px;
|
||||
}
|
||||
.drag_hover[order="0"]::before {
|
||||
width: 5px;
|
||||
height: 30px;
|
||||
margin-left: 0;
|
||||
border-top-right-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
|
||||
}
|
||||
/*Cancel Dragover for main list*/
|
||||
#cubes_list > div > ul > li.outliner_node.parent_li {
|
||||
@ -957,7 +993,8 @@
|
||||
float: right;
|
||||
}
|
||||
body > .outliner_object {
|
||||
width: 260px;
|
||||
width: 180px;
|
||||
padding-left: 0 !important;
|
||||
box-shadow: 0 0 4px black;
|
||||
}
|
||||
body > .outliner_object a {
|
||||
@ -992,7 +1029,7 @@
|
||||
font-weight: normal;
|
||||
position: absolute;
|
||||
top: -20px;
|
||||
left: 40px;
|
||||
left: 20px;
|
||||
border: 1px solid var(--color-border);
|
||||
}
|
||||
|
||||
@ -1143,7 +1180,8 @@
|
||||
white-space: nowrap;
|
||||
position: relative;
|
||||
vertical-align: middle;
|
||||
padding: 8px;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
border: 1px solid transparent;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
@ -1155,7 +1193,8 @@
|
||||
border: 1px solid var(--color-border);
|
||||
}
|
||||
.texture > i {
|
||||
margin-top: 4px;
|
||||
margin-top: 12px;
|
||||
float: right;
|
||||
}
|
||||
.texture > i.clickable:hover {
|
||||
color: var(--color-light);
|
||||
@ -1169,7 +1208,6 @@
|
||||
div.texture_icon_wrapper {
|
||||
height: 48px;
|
||||
width: 48px;
|
||||
margin-top: -8px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
@ -1185,16 +1223,8 @@
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
}
|
||||
.texture_id {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.texture_remove {
|
||||
width: 24px;
|
||||
}
|
||||
|
||||
.texture_name {
|
||||
margin-top: 3px;
|
||||
margin-top: 2px;
|
||||
margin-left: 6px;
|
||||
margin-right: 4px;
|
||||
width: calc(100% - 82px);
|
||||
@ -1202,7 +1232,18 @@
|
||||
font-size: 0.94em;
|
||||
cursor: default;
|
||||
}
|
||||
.texture.particle .texture_name {
|
||||
.texture_res {
|
||||
margin-top: -3px;
|
||||
margin-left: 6px;
|
||||
margin-right: 4px;
|
||||
width: calc(100% - 82px);
|
||||
height: 20px;
|
||||
overflow: hidden;
|
||||
font-size: 0.86em;
|
||||
opacity: 0.6;
|
||||
cursor: default;
|
||||
}
|
||||
.texture.particle .texture_name, .texture.particle .texture_res {
|
||||
width: calc(100% - 106px);
|
||||
}
|
||||
.texture_error {
|
||||
@ -1260,12 +1301,12 @@
|
||||
}
|
||||
body.animation_mode #timeline {
|
||||
display: block;
|
||||
height: 130px;
|
||||
background-color: var(--color-dark);
|
||||
height: 162px;
|
||||
background-color: var(--color-back);
|
||||
border-top: 1px solid var(--color-border);
|
||||
}
|
||||
body.animation_mode #preview .single_canvas_wrapper {
|
||||
height: calc(100% - 130px);
|
||||
height: calc(100% - 162px);
|
||||
}
|
||||
#timeline_inner {
|
||||
overflow-y: hidden;
|
||||
@ -1482,6 +1523,7 @@
|
||||
bottom: -3px;
|
||||
font-size: 0.8em;
|
||||
cursor: default;
|
||||
pointer-events: none;
|
||||
}
|
||||
#uv .bar.next_to_title {
|
||||
margin-top: -32px;
|
||||
@ -1782,6 +1824,30 @@
|
||||
border: none;
|
||||
}
|
||||
|
||||
/*Keybind recording*/
|
||||
#overlay_message_box {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
z-index: 130;
|
||||
text-align: center;
|
||||
background-color: rgba(0, 0, 0, 0.8);
|
||||
}
|
||||
#overlay_message_box > div {
|
||||
margin-top: 64px;
|
||||
width: 400px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
#overlay_message_box > div > p {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
#overlay_message_box h3 i {
|
||||
vertical-align: sub;
|
||||
padding: 8px;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
/*Display*/
|
||||
.mode_tab {
|
||||
display: block;
|
||||
@ -1992,14 +2058,6 @@
|
||||
cursor: default;
|
||||
pointer-events: none;
|
||||
}
|
||||
#overlay_message_box {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
z-index: 130;
|
||||
text-align: center;
|
||||
background-color: rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
.uv_message_box {
|
||||
position: absolute;
|
||||
margin-left: auto;
|
||||
|
BIN
font/icomoon.eot
BIN
font/icomoon.eot
Binary file not shown.
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 24 KiB |
BIN
font/icomoon.ttf
BIN
font/icomoon.ttf
Binary file not shown.
Binary file not shown.
28
index.html
28
index.html
@ -19,7 +19,7 @@
|
||||
<script>
|
||||
if (typeof module === 'object') {window.module = module; module = undefined;}//jQuery Fix
|
||||
const isApp = typeof require !== 'undefined';
|
||||
const appVersion = '2.4.0';
|
||||
const appVersion = '2.5.0';
|
||||
</script>
|
||||
<script src="lib/vue.min.js"></script>
|
||||
<script src="lib/vue_sortable.js"></script>
|
||||
@ -28,12 +28,12 @@
|
||||
<script src="lib/jquery-ui.min.js"></script>
|
||||
<script src="lib/targa.js"></script>
|
||||
<script src="lib/jimp.min.js"></script>
|
||||
<script src="lib/jszip.min.js"></script>
|
||||
<script src="lib/gif.js"></script>
|
||||
<script src="lib/spectrum.js"></script>
|
||||
<script src="lib/three.js"></script>
|
||||
<script src="lib/three_custom.js"></script>
|
||||
<script src="js/OrbitControls.js"></script>
|
||||
<script src="js/TransformControls.js"></script>
|
||||
<script src="js/OBJExporter.js"></script>
|
||||
|
||||
<script src="js/language.js"></script>
|
||||
@ -54,8 +54,9 @@
|
||||
|
||||
<script src="js/api.js"></script>
|
||||
<script src="js/io.js"></script>
|
||||
<script src="js/elements.js"></script>
|
||||
<script src="js/element.js"></script>
|
||||
<script src="js/preview.js"></script>
|
||||
<script src="js/TransformControls.js"></script>
|
||||
<script src="js/transform.js"></script>
|
||||
<script src="js/textures.js"></script>
|
||||
<script src="js/uv.js"></script>
|
||||
@ -72,6 +73,16 @@
|
||||
|
||||
<div id="blackout" onclick="$('.dialog#'+open_dialog).find('.cancel_btn:not([disabled])').click()"></div>
|
||||
|
||||
<div id="overlay_message_box" style="display: none;">
|
||||
<div>
|
||||
<h3><i class="material-icons">keyboard</i><span class="tl">keybindings.recording</span></h3>
|
||||
<p class="tl">keybindings.press</p>
|
||||
<button class="large tl" onclick="Keybinds.recording.stopRecording()">dialog.cancel</button>
|
||||
<button class="large tl" onclick="Keybinds.recording.clear().stopRecording()">keybindings.clear</button>
|
||||
<div id="keybind_input_box" contenteditable="true" style="font-size: 0"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dialog draggable" id="welcome_screen">
|
||||
<div id="welcome_content"></div>
|
||||
<button type="button" class="large cancel_btn hidden tl" onclick="hideDialog()">dialog.cancel</button>
|
||||
@ -180,7 +191,7 @@
|
||||
<i class="material-icons" id="plugin_search_bar_icon">search</i>
|
||||
</div>
|
||||
<ul id="pe_list" class="list">
|
||||
<li v-for="item in searched" v-bind:class="{ selected: item.selected }" v-on:click="selectE(item, $event)" ondblclick="loadPEModel()">
|
||||
<li v-for="item in searched" v-bind:class="{ selected: item.selected }" v-on:click="selectE(item, $event)" ondblclick="loadEntityModel()">
|
||||
<img class="pe_icon" v-if="item.icon" v-bind:src="item.icon">
|
||||
<div class="pe_icon" v-else></div>
|
||||
<h4>{{ item.title }} <span>({{ item.name }})</span></h4>
|
||||
@ -189,7 +200,7 @@
|
||||
</ul>
|
||||
|
||||
<div class="dialog_bar">
|
||||
<button type="button" class="large tl confirm_btn" onclick="loadPEModel()">dialog.import</button>
|
||||
<button type="button" class="large tl confirm_btn" onclick="loadEntityModel()">dialog.import</button>
|
||||
<button type="button" class="large tl cancel_btn" onclick="hideDialog()">dialog.cancel</button>
|
||||
</div>
|
||||
<div id="dialog_close_button" onclick="$('.dialog#'+open_dialog).find('.cancel_btn:not([disabled])').click()"><i class="material-icons">clear</i></div>
|
||||
@ -381,7 +392,7 @@
|
||||
<label for="project_name" class="tl">dialog.project.name</label>
|
||||
</div>
|
||||
<div class="dialog_bar">
|
||||
<input v-model="Project.name" type="text" id="project_name" class="dark_bordered input_wide">
|
||||
<input v-model="Project.name" type="text" id="project_name" v-on:focusout="syncGeometry()" class="dark_bordered input_wide">
|
||||
</div>
|
||||
|
||||
|
||||
@ -631,6 +642,7 @@
|
||||
<a class="open-in-browser" href="https://github.com/oliver-moran/jimp">Jimp</a>,
|
||||
<a class="open-in-browser" href="https://bgrins.github.io/spectrum">Spectrum</a>,
|
||||
<a class="open-in-browser" href="https://github.com/jnordberg/gif.js">gif.js</a>
|
||||
<a class="open-in-browser" href="https://stuk.github.io/jszip/">JSZip</a>
|
||||
</p>
|
||||
</div>
|
||||
<div class="dialog_bar">
|
||||
@ -855,12 +867,13 @@
|
||||
<i class="material-icons texture_error" title="Image Error" v-if="texture.error">error_outline</i>
|
||||
<i class="texture_movie fa fa_big fa-film" title="Animated Texture" v-if="texture.frameCount > 1"></i>
|
||||
</div>
|
||||
<div class="texture_name">{{ texture.name }}</div>
|
||||
<i class="material-icons texture_particle_icon" v-if="texture.particle">bubble_chart</i>
|
||||
<i class="material-icons texture_save_icon" v-bind:class="{clickable: !texture.saved}" v-on:click="texture.save()">
|
||||
<template v-if="texture.saved">check_circle</template>
|
||||
<template v-else>save</template>
|
||||
</i>
|
||||
<div class="texture_name">{{ texture.name }}</div>
|
||||
<div class="texture_res">{{!Blockbench.entity_mode ? (texture.ratio == 1 ? texture.res + 'px' : (texture.res + 'px, ' + texture.frameCount+'f')) : (texture.res + ' x ' + texture.res*texture.ratio + 'px')}}</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@ -882,6 +895,7 @@
|
||||
<div id="preview">
|
||||
</div>
|
||||
<div id="timeline">
|
||||
<div class="toolbar_wrapper timeline"></div>
|
||||
<div id="timeline_head">
|
||||
<div id="timeline_corner"></div>
|
||||
<div class="channel_head">
|
||||
|
29
index.php
29
index.php
@ -19,7 +19,7 @@
|
||||
<script>
|
||||
if (typeof module === 'object') {window.module = module; module = undefined;}//jQuery Fix
|
||||
const isApp = typeof require !== 'undefined';
|
||||
const appVersion = '2.4.0';
|
||||
const appVersion = '2.5.0';
|
||||
</script>
|
||||
<script src="lib/vue.min.js"></script>
|
||||
<script src="lib/vue_sortable.js"></script>
|
||||
@ -28,12 +28,12 @@
|
||||
<script src="lib/jquery-ui.min.js"></script>
|
||||
<script src="lib/targa.js"></script>
|
||||
<script src="lib/jimp.min.js"></script>
|
||||
<script src="lib/jszip.min.js"></script>
|
||||
<script src="lib/gif.js"></script>
|
||||
<script src="lib/spectrum.js"></script>
|
||||
<script src="lib/three.js"></script>
|
||||
<script src="lib/three_custom.js"></script>
|
||||
<script src="js/OrbitControls.js"></script>
|
||||
<script src="js/TransformControls.js"></script>
|
||||
<script src="js/OBJExporter.js"></script>
|
||||
|
||||
<script src="js/language.js"></script>
|
||||
@ -54,8 +54,9 @@
|
||||
|
||||
<script src="js/api.js"></script>
|
||||
<script src="js/io.js"></script>
|
||||
<script src="js/elements.js"></script>
|
||||
<script src="js/element.js"></script>
|
||||
<script src="js/preview.js"></script>
|
||||
<script src="js/TransformControls.js"></script>
|
||||
<script src="js/transform.js"></script>
|
||||
<script src="js/textures.js"></script>
|
||||
<script src="js/uv.js"></script>
|
||||
@ -85,9 +86,18 @@
|
||||
?></div>
|
||||
<div style="display: none;"></div>
|
||||
|
||||
|
||||
<div id="blackout" onclick="$('.dialog#'+open_dialog).find('.cancel_btn:not([disabled])').click()"></div>
|
||||
|
||||
<div id="overlay_message_box" style="display: none;">
|
||||
<div>
|
||||
<h3><i class="material-icons">keyboard</i><span class="tl">keybindings.recording</span></h3>
|
||||
<p class="tl">keybindings.press</p>
|
||||
<button class="large tl" onclick="Keybinds.recording.stopRecording()">dialog.cancel</button>
|
||||
<button class="large tl" onclick="Keybinds.recording.clear().stopRecording()">keybindings.clear</button>
|
||||
<div id="keybind_input_box" contenteditable="true" style="font-size: 0"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dialog draggable" id="welcome_screen">
|
||||
<div id="welcome_content"></div>
|
||||
<button type="button" class="large cancel_btn hidden tl" onclick="hideDialog()">dialog.cancel</button>
|
||||
@ -196,7 +206,7 @@
|
||||
<i class="material-icons" id="plugin_search_bar_icon">search</i>
|
||||
</div>
|
||||
<ul id="pe_list" class="list">
|
||||
<li v-for="item in searched" v-bind:class="{ selected: item.selected }" v-on:click="selectE(item, $event)" ondblclick="loadPEModel()">
|
||||
<li v-for="item in searched" v-bind:class="{ selected: item.selected }" v-on:click="selectE(item, $event)" ondblclick="loadEntityModel()">
|
||||
<img class="pe_icon" v-if="item.icon" v-bind:src="item.icon">
|
||||
<div class="pe_icon" v-else></div>
|
||||
<h4>{{ item.title }} <span>({{ item.name }})</span></h4>
|
||||
@ -205,7 +215,7 @@
|
||||
</ul>
|
||||
|
||||
<div class="dialog_bar">
|
||||
<button type="button" class="large tl confirm_btn" onclick="loadPEModel()">dialog.import</button>
|
||||
<button type="button" class="large tl confirm_btn" onclick="loadEntityModel()">dialog.import</button>
|
||||
<button type="button" class="large tl cancel_btn" onclick="hideDialog()">dialog.cancel</button>
|
||||
</div>
|
||||
<div id="dialog_close_button" onclick="$('.dialog#'+open_dialog).find('.cancel_btn:not([disabled])').click()"><i class="material-icons">clear</i></div>
|
||||
@ -397,7 +407,7 @@
|
||||
<label for="project_name" class="tl">dialog.project.name</label>
|
||||
</div>
|
||||
<div class="dialog_bar">
|
||||
<input v-model="Project.name" type="text" id="project_name" class="dark_bordered input_wide">
|
||||
<input v-model="Project.name" type="text" id="project_name" v-on:focusout="syncGeometry()" class="dark_bordered input_wide">
|
||||
</div>
|
||||
|
||||
|
||||
@ -647,6 +657,7 @@
|
||||
<a class="open-in-browser" href="https://github.com/oliver-moran/jimp">Jimp</a>,
|
||||
<a class="open-in-browser" href="https://bgrins.github.io/spectrum">Spectrum</a>,
|
||||
<a class="open-in-browser" href="https://github.com/jnordberg/gif.js">gif.js</a>
|
||||
<a class="open-in-browser" href="https://stuk.github.io/jszip/">JSZip</a>
|
||||
</p>
|
||||
</div>
|
||||
<div class="dialog_bar">
|
||||
@ -871,12 +882,13 @@
|
||||
<i class="material-icons texture_error" title="Image Error" v-if="texture.error">error_outline</i>
|
||||
<i class="texture_movie fa fa_big fa-film" title="Animated Texture" v-if="texture.frameCount > 1"></i>
|
||||
</div>
|
||||
<div class="texture_name">{{ texture.name }}</div>
|
||||
<i class="material-icons texture_particle_icon" v-if="texture.particle">bubble_chart</i>
|
||||
<i class="material-icons texture_save_icon" v-bind:class="{clickable: !texture.saved}" v-on:click="texture.save()">
|
||||
<template v-if="texture.saved">check_circle</template>
|
||||
<template v-else>save</template>
|
||||
</i>
|
||||
<div class="texture_name">{{ texture.name }}</div>
|
||||
<div class="texture_res">{{!Blockbench.entity_mode ? (texture.ratio == 1 ? texture.res + 'px' : (texture.res + 'px, ' + texture.frameCount+'f')) : (texture.res + ' x ' + texture.res*texture.ratio + 'px')}}</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@ -898,6 +910,7 @@
|
||||
<div id="preview">
|
||||
</div>
|
||||
<div id="timeline">
|
||||
<div class="toolbar_wrapper timeline"></div>
|
||||
<div id="timeline_head">
|
||||
<div id="timeline_corner"></div>
|
||||
<div class="channel_head">
|
||||
|
@ -175,7 +175,7 @@ function getMtlFace(obj, index) {
|
||||
|
||||
if (tex === null) {
|
||||
return false
|
||||
} else if (typeof tex === 'string') {
|
||||
} else if (!tex || typeof tex === 'string') {
|
||||
return 'usemtl none\n'
|
||||
} else {
|
||||
return 'usemtl ' + tex.id + '\n';
|
||||
|
@ -923,7 +923,7 @@
|
||||
point.sub( offset );
|
||||
}
|
||||
|
||||
if (Toolbox.selected.id === 'rotate_tool') {
|
||||
if (Toolbox.selected.transformerMode === 'rotate') {
|
||||
|
||||
point.sub( worldPosition );
|
||||
var rotations = [
|
||||
@ -941,35 +941,7 @@
|
||||
|
||||
if (Modes.id === 'edit') {
|
||||
|
||||
if (Toolbox.selected.id === 'resize_tool') {
|
||||
//Scale
|
||||
var snap_factor = canvasGridSize(event.shiftKey, event.ctrlKey)
|
||||
point[axis] = Math.round( point[axis] / snap_factor ) * snap_factor// * (useBedrockFlipFix(axis) ? -1 : 1)
|
||||
|
||||
|
||||
if (previousValue !== point[axis]) {
|
||||
beforeFirstChange(event)
|
||||
|
||||
selected.forEach(function(obj, i) {
|
||||
var mesh = scope.objects[i]
|
||||
var allow_negative = settings.negative_size.value
|
||||
|
||||
if (scope.direction) { //Positive
|
||||
scaleCube(obj, limitNumber(obj.oldScale + point[axis], (allow_negative ? -32000 : 0), 32000), axisNumber)
|
||||
} else {
|
||||
scaleCubeNegative(obj, limitNumber(obj.oldScale - point[axis], (allow_negative ? -32000 : 0), 32000), axisNumber)
|
||||
}
|
||||
if (Blockbench.entity_mode === true) {
|
||||
Canvas.updateUV(obj)
|
||||
}
|
||||
})
|
||||
Canvas.updatePositions(true)
|
||||
centerTransformer()
|
||||
previousValue = point[axis]
|
||||
scope.hasChanged = true
|
||||
}
|
||||
|
||||
} else if (Toolbox.selected.id === 'move_tool') {
|
||||
if (Toolbox.selected.id === 'move_tool') {
|
||||
|
||||
var snap_factor = canvasGridSize(event.shiftKey, event.ctrlKey)
|
||||
point[axis] = Math.round( point[axis] / snap_factor ) * snap_factor// * (useBedrockFlipFix(axis) ? -1 : 1)
|
||||
@ -1001,7 +973,6 @@
|
||||
|
||||
}
|
||||
selected.forEach(function(obj, i) {
|
||||
var mesh = scope.objects[i]
|
||||
var valx = obj.from[axisNumber]
|
||||
valx += difference
|
||||
moveCube(obj, valx, axisNumber, _has_groups)
|
||||
@ -1012,6 +983,34 @@
|
||||
previousValue = point[axis]
|
||||
scope.hasChanged = true
|
||||
}
|
||||
} else if (Toolbox.selected.id === 'resize_tool') {
|
||||
//Scale
|
||||
var snap_factor = canvasGridSize(event.shiftKey, event.ctrlKey)
|
||||
point[axis] = Math.round( point[axis] / snap_factor ) * snap_factor// * (useBedrockFlipFix(axis) ? -1 : 1)
|
||||
|
||||
|
||||
if (previousValue !== point[axis]) {
|
||||
beforeFirstChange(event)
|
||||
|
||||
selected.forEach(function(obj, i) {
|
||||
var mesh = scope.objects[i]
|
||||
var allow_negative = settings.negative_size.value
|
||||
|
||||
if (scope.direction) { //Positive
|
||||
scaleCube(obj, limitNumber(obj.oldScale + point[axis], (allow_negative ? -32000 : 0), 32000), axisNumber)
|
||||
} else {
|
||||
scaleCubeNegative(obj, limitNumber(obj.oldScale - point[axis], (allow_negative ? -32000 : 0), 32000), axisNumber)
|
||||
}
|
||||
if (Blockbench.entity_mode === true) {
|
||||
Canvas.updateUV(obj)
|
||||
}
|
||||
})
|
||||
Canvas.updatePositions(true)
|
||||
centerTransformer()
|
||||
previousValue = point[axis]
|
||||
scope.hasChanged = true
|
||||
}
|
||||
|
||||
} else if (Toolbox.selected.id === 'rotate_tool') {
|
||||
|
||||
var snap = getRotationInterval(event)
|
||||
@ -1029,6 +1028,35 @@
|
||||
previousValue = angle
|
||||
scope.hasChanged = true
|
||||
}
|
||||
} else if (Toolbox.selected.id === 'pivot_tool') {
|
||||
|
||||
var snap_factor = canvasGridSize(event.shiftKey, event.ctrlKey)
|
||||
point[axis] = Math.round( point[axis] / snap_factor ) * snap_factor// * (useBedrockFlipFix(axis) ? -1 : 1)
|
||||
|
||||
if (previousValue === undefined) {
|
||||
previousValue = point[axis]
|
||||
|
||||
} else if (previousValue !== point[axis]) {
|
||||
beforeFirstChange(event)
|
||||
|
||||
var difference = point[axis] - previousValue
|
||||
|
||||
if (Blockbench.entity_mode && selected_group) {
|
||||
selected_group.origin[axisNumber] += difference;
|
||||
} else {
|
||||
var origin = Transformer.position.toArray()
|
||||
origin[axisNumber] += difference;
|
||||
selected.forEach(cube => {
|
||||
cube.transferOrigin(origin)
|
||||
})
|
||||
}
|
||||
Canvas.updatePositions(true)
|
||||
centerTransformer()
|
||||
|
||||
previousValue = point[axis]
|
||||
scope.hasChanged = true
|
||||
}
|
||||
|
||||
}
|
||||
} else if (Animator.open) {
|
||||
|
||||
|
@ -272,7 +272,7 @@ class Widget extends BarItem {
|
||||
constructor(data) {
|
||||
super(data);
|
||||
this.type = 'widget';
|
||||
this.uniqueNode = true;
|
||||
//this.uniqueNode = true;
|
||||
}
|
||||
}
|
||||
class NumSlider extends Widget {
|
||||
@ -283,6 +283,7 @@ class NumSlider extends Widget {
|
||||
this.icon = 'code'
|
||||
this.value = 0;
|
||||
this.width = 79;
|
||||
this.uniqueNode = true;
|
||||
if (typeof data.get === 'function') this.get = data.get;
|
||||
this.onBefore = data.onBefore;
|
||||
this.onAfter = data.onAfter;
|
||||
@ -879,10 +880,20 @@ const BARS = {
|
||||
selectFace: true,
|
||||
transformerMode: 'rotate',
|
||||
toolbar: 'transform',
|
||||
alt_tool: 'move_tool',
|
||||
alt_tool: 'pivot_tool',
|
||||
modes: ['edit', 'display', 'animate'],
|
||||
keybind: new Keybind({key: 82}),
|
||||
})
|
||||
new Tool({
|
||||
id: 'pivot_tool',
|
||||
icon: 'gps_fixed',
|
||||
category: 'tools',
|
||||
transformerMode: 'translate',
|
||||
toolbar: 'transform',
|
||||
alt_tool: 'rotate_tool',
|
||||
modes: ['edit'],
|
||||
keybind: new Keybind({key: 80}),
|
||||
})
|
||||
new Tool({
|
||||
id: 'vertex_snap_tool',
|
||||
icon: 'icon-vertexsnap',
|
||||
@ -1227,10 +1238,9 @@ const BARS = {
|
||||
|
||||
//Find Action
|
||||
new Action({
|
||||
id: 'select_action',
|
||||
id: 'action_control',
|
||||
icon: 'fullscreen',
|
||||
category: 'blockbench',
|
||||
condition: isApp,
|
||||
keybind: new Keybind({key: 70}),
|
||||
click: function () {
|
||||
ActionControl.select()
|
||||
@ -1279,6 +1289,7 @@ const BARS = {
|
||||
'move_tool',
|
||||
'resize_tool',
|
||||
'rotate_tool',
|
||||
'pivot_tool',
|
||||
'vertex_snap_tool',
|
||||
'brush_tool',
|
||||
'fill_tool',
|
||||
@ -1370,7 +1381,6 @@ const BARS = {
|
||||
children: [
|
||||
'add_animation',
|
||||
'slider_animation_length',
|
||||
'play_animation'
|
||||
],
|
||||
default_place: true
|
||||
})
|
||||
@ -1381,6 +1391,16 @@ const BARS = {
|
||||
],
|
||||
default_place: true
|
||||
})
|
||||
Toolbars.timeline = new Toolbar({
|
||||
id: 'timeline',
|
||||
children: [
|
||||
'slider_animation_speed',
|
||||
'previous_keyframe',
|
||||
'next_keyframe',
|
||||
'play_animation',
|
||||
],
|
||||
default_place: true
|
||||
})
|
||||
//Tools
|
||||
Toolbars.transform = new Toolbar({
|
||||
id: 'transform',
|
||||
@ -1965,11 +1985,15 @@ const MenuBar = {
|
||||
{name: 'menu.file.recent', id: 'recent', icon: 'history', condition: function() {return isApp && recent_projects.length}, children: function() {
|
||||
var arr = []
|
||||
recent_projects.forEach(function(p) {
|
||||
var entity = p.name.substr(0,4) === 'mobs'
|
||||
switch (p.icon_id) {
|
||||
default: var icon = 'fa-file-o'; break;
|
||||
case 1: var icon = 'icon-blockbench_file'; break;
|
||||
case 2: var icon = 'fa-file-text-o'; break;
|
||||
}
|
||||
arr.splice(0, 0, {
|
||||
name: p.name,
|
||||
path: p.path,
|
||||
icon: entity ? 'view_list' : 'insert_drive_file',
|
||||
icon: icon,
|
||||
click: function(c, event) {
|
||||
readFile(p.path, !event.shiftKey)
|
||||
}
|
||||
|
141
js/animations.js
141
js/animations.js
@ -20,9 +20,24 @@ class Animation {
|
||||
Merge.boolean(this, data, 'override')
|
||||
Merge.string(this, data, 'anim_time_update')
|
||||
Merge.number(this, data, 'length')
|
||||
if (data.bones) {
|
||||
for (var key in data.bones) {
|
||||
var group = TreeElements.findRecursive( isUUID(key) ? 'uuid' : 'name', key )
|
||||
if (group) {
|
||||
var ba = this.getBoneAnimator(group)
|
||||
var kfs = data.bones[key]
|
||||
if (kfs && ba) {
|
||||
kfs.forEach(kf_data => {
|
||||
var kf = new Keyframe(kf_data)
|
||||
ba.pushKeyframe(kf)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
undoCopy() {
|
||||
undoCopy(options) {
|
||||
var scope = this;
|
||||
var copy = {
|
||||
uuid: this.uuid,
|
||||
@ -33,11 +48,14 @@ class Animation {
|
||||
length: this.length,
|
||||
selected: this.selected,
|
||||
}
|
||||
if (this.bones.length) {
|
||||
if (Object.keys(this.bones).length) {
|
||||
copy.bones = {}
|
||||
for (var uuid in this.bones) {
|
||||
var kfs = this.bones[uuid].keyframes
|
||||
if (kfs && kfs.length) {
|
||||
if (options && options.bone_names) {
|
||||
uuid = this.bones[uuid].getGroup().name
|
||||
}
|
||||
var kfs_copy = copy.bones[uuid] = []
|
||||
kfs.forEach(kf => {
|
||||
kfs_copy.push(kf.undoCopy())
|
||||
@ -768,6 +786,8 @@ const Animator = {
|
||||
}
|
||||
if (Animator.selected) {
|
||||
Animator.selected.select()
|
||||
} else if (Animator.animations.length) {
|
||||
Animator.animations[0].select()
|
||||
}
|
||||
if (isApp && !Prop.animation_path && !Animator.animations.length && Prop.file_path) {
|
||||
//Load
|
||||
@ -894,6 +914,7 @@ const Animator = {
|
||||
const Timeline = {
|
||||
keyframes: [],//frames
|
||||
selected: [],//frames
|
||||
playback_speed: 100,
|
||||
second: 0,
|
||||
playing: false,
|
||||
setTime: function(seconds, editing) {
|
||||
@ -1024,6 +1045,7 @@ const Timeline = {
|
||||
}
|
||||
})
|
||||
|
||||
BarItems.slider_animation_speed.update()
|
||||
Timeline.is_setup = true
|
||||
Timeline.setTime(0)
|
||||
},
|
||||
@ -1144,8 +1166,9 @@ const Timeline = {
|
||||
loop: function() {
|
||||
Animator.preview()
|
||||
if (Animator.selected && Timeline.second < (Animator.selected.length||1e3)) {
|
||||
Animator.interval = setTimeout(Timeline.loop, 16.66)
|
||||
Timeline.setTime(Timeline.second + 1/60)
|
||||
|
||||
Animator.interval = setTimeout(Timeline.loop, 100/6)
|
||||
Timeline.setTime(Timeline.second + (1/60) * (Timeline.playback_speed/100))
|
||||
} else {
|
||||
Timeline.setTime(0)
|
||||
if (Animator.selected && Animator.selected.loop) {
|
||||
@ -1321,6 +1344,50 @@ BARS.defineActions(function() {
|
||||
Animator.selected.length = limitNumber(value, 0, 1e4)
|
||||
}
|
||||
})
|
||||
new NumSlider({
|
||||
id: 'slider_animation_speed',
|
||||
category: 'animation',
|
||||
condition: () => Animator.open,
|
||||
get: function() {
|
||||
return Timeline.playback_speed;
|
||||
},
|
||||
change: function(value, fixed) {
|
||||
if (!fixed) {
|
||||
value += Timeline.playback_speed
|
||||
}
|
||||
Timeline.playback_speed = limitNumber(value, 0, 10000)
|
||||
},
|
||||
getInterval: (e) => {
|
||||
var val = BarItems.slider_animation_speed.get()
|
||||
if (e.shiftKey) {
|
||||
if (val < 50) {
|
||||
return 10;
|
||||
} else {
|
||||
return 50;
|
||||
}
|
||||
}
|
||||
if (e.ctrlKey) {
|
||||
if (val < 500) {
|
||||
return 1;
|
||||
} else {
|
||||
return 10;
|
||||
}
|
||||
}
|
||||
if (val < 10) {
|
||||
return 1;
|
||||
} else if (val < 50) {
|
||||
return 5;
|
||||
} else if (val < 160) {
|
||||
return 10;
|
||||
} else if (val < 300) {
|
||||
return 20;
|
||||
} else if (val < 1000) {
|
||||
return 50;
|
||||
} else {
|
||||
return 500;
|
||||
}
|
||||
}
|
||||
})
|
||||
new NumSlider({
|
||||
id: 'slider_keyframe_time',
|
||||
category: 'animation',
|
||||
@ -1344,6 +1411,72 @@ BARS.defineActions(function() {
|
||||
Undo.finishEdit('edit keyframe')
|
||||
}
|
||||
})
|
||||
|
||||
new Action({
|
||||
id: 'previous_keyframe',
|
||||
icon: 'fa-arrow-circle-left',
|
||||
category: 'animation',
|
||||
condition: () => Animator.open,
|
||||
click: function () {
|
||||
|
||||
var time = Timeline.second;
|
||||
function getDelta(kf, abs) {
|
||||
return kf.time - time
|
||||
}
|
||||
var matches = []
|
||||
for (var i = 0; i < Timeline.keyframes.length; i++) {
|
||||
var kf = Timeline.keyframes[i]
|
||||
let delta = getDelta(kf)
|
||||
if (delta < 0) {
|
||||
matches.push(kf)
|
||||
}
|
||||
}
|
||||
matches.sort((a, b) => {
|
||||
return Math.abs(getDelta(a)) - Math.abs(getDelta(b))
|
||||
})
|
||||
var kf = matches[0]
|
||||
if (kf) {
|
||||
kf.select().callMarker()
|
||||
} else {
|
||||
if (Timeline.selected.length) {
|
||||
selectAllKeyframes()
|
||||
selectAllKeyframes()
|
||||
}
|
||||
Timeline.setTime(0)
|
||||
Animator.preview()
|
||||
}
|
||||
}
|
||||
})
|
||||
new Action({
|
||||
id: 'next_keyframe',
|
||||
icon: 'fa-arrow-circle-right',
|
||||
category: 'animation',
|
||||
condition: () => Animator.open,
|
||||
click: function () {
|
||||
|
||||
var time = Timeline.second;
|
||||
function getDelta(kf, abs) {
|
||||
return kf.time - time
|
||||
}
|
||||
var matches = []
|
||||
for (var i = 0; i < Timeline.keyframes.length; i++) {
|
||||
var kf = Timeline.keyframes[i]
|
||||
let delta = getDelta(kf)
|
||||
if (delta > 0) {
|
||||
matches.push(kf)
|
||||
}
|
||||
}
|
||||
matches.sort((a, b) => {
|
||||
return Math.abs(getDelta(a)) - Math.abs(getDelta(b))
|
||||
})
|
||||
var kf = matches[0]
|
||||
if (kf) {
|
||||
kf.select().callMarker()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
new Action({
|
||||
id: 'select_all_keyframes',
|
||||
icon: 'select_all',
|
||||
|
@ -380,6 +380,7 @@ class API {
|
||||
*/
|
||||
if (Blockbench.isWeb) {
|
||||
var file_name = options.name + (options.extensions ? '.'+options.extensions[0] : '')
|
||||
var callback_used;
|
||||
if (options.custom_writer) {
|
||||
options.custom_writer(options.content, file_name)
|
||||
|
||||
@ -391,6 +392,10 @@ class API {
|
||||
if (Blockbench.browser === 'firefox') document.body.appendChild(download);
|
||||
download.click();
|
||||
if (Blockbench.browser === 'firefox') document.body.removeChild(download);
|
||||
|
||||
} else if (options.savetype === 'zip') {
|
||||
saveAs(options.content, file_name)
|
||||
|
||||
} else {
|
||||
var blob = new Blob([options.content], {type: "text/plain;charset=utf-8"});
|
||||
saveAs(blob, file_name, {autoBOM: true})
|
||||
@ -399,7 +404,7 @@ class API {
|
||||
Prop.project_saved = true;
|
||||
setProjectTitle(options.name)
|
||||
}
|
||||
if (typeof cb === 'function') {
|
||||
if (!callback_used && typeof cb === 'function') {
|
||||
cb()
|
||||
}
|
||||
} else {
|
||||
@ -446,7 +451,7 @@ class API {
|
||||
Prop.project_saved = true;
|
||||
Project.name = pathToName(file_path, true)
|
||||
setProjectTitle(pathToName(file_path, false))
|
||||
addRecentProject({name: pathToName(file_path, Blockbench.entity_mode ? 'mobs_id' : false), path: Prop.file_path})
|
||||
addRecentProject({name: pathToName(file_path, Blockbench.entity_mode ? 'mobs_id' : true), path: Prop.file_path})
|
||||
Blockbench.showQuickMessage(tl('message.save_file', [Project.name]))
|
||||
if (Blockbench.hasFlag('close_after_saving')) {
|
||||
closeBlockbenchWindow()
|
||||
|
21
js/app.js
21
js/app.js
@ -88,7 +88,11 @@ function addRecentProject(data) {
|
||||
}
|
||||
i--;
|
||||
}
|
||||
recent_projects.push({name: data.name, path: data.path})
|
||||
var icon_id = pathToExtension(data.path) === 'bbmodel' ? 1 : 0;
|
||||
if (data.name.substr(0,4) === 'mobs') {
|
||||
icon_id = 2;
|
||||
}
|
||||
recent_projects.push({name: data.name, path: data.path, icon_id})
|
||||
if (recent_projects.length > 8) {
|
||||
recent_projects.shift()
|
||||
}
|
||||
@ -519,6 +523,7 @@ function createBackup(init) {
|
||||
var days = d.getDate() + (d.getMonth()+1)*30.44 + (d.getYear()-100)*365.25
|
||||
|
||||
if (init) {
|
||||
//Clear old backups
|
||||
fs.readdir(folder_path, (err, files) => {
|
||||
if (!err) {
|
||||
files.forEach((name, i) => {
|
||||
@ -541,23 +546,15 @@ function createBackup(init) {
|
||||
}
|
||||
if (init || elements.length === 0) return;
|
||||
|
||||
var model = buildBlockModel({
|
||||
backup: true,
|
||||
raw: true,
|
||||
cube_name: true,
|
||||
prevent_dialog: true,
|
||||
comment: false,
|
||||
groups: true
|
||||
})
|
||||
var model = buildBBModel()
|
||||
var file_name = 'backup_'+d.getDate()+'.'+(d.getMonth()+1)+'.'+(d.getYear()-100)+'_'+d.getHours()+'.'+d.getMinutes()
|
||||
var file_path = folder_path+osfs+file_name+'.json'
|
||||
var file_path = folder_path+osfs+file_name+'.bbmodel'
|
||||
|
||||
fs.writeFile(file_path, JSON.stringify(model), function (err) {
|
||||
fs.writeFile(file_path, model, function (err) {
|
||||
if (err) {
|
||||
console.log('Error creating backup: '+err)
|
||||
}
|
||||
})
|
||||
//trimBackups
|
||||
}
|
||||
//Zoom
|
||||
function setZoomLevel(mode) {
|
||||
|
167
js/blockbench.js
167
js/blockbench.js
@ -33,6 +33,12 @@ const Project = {
|
||||
texture_width : 16,
|
||||
texture_height : 16,
|
||||
ambientocclusion: true,
|
||||
get geometry_name() {
|
||||
return this.parent;
|
||||
},
|
||||
set geometry_name(n) {
|
||||
this.parent = n;
|
||||
},
|
||||
}
|
||||
const mouse_pos = {x:0,y:0}
|
||||
const sort_collator = new Intl.Collator(undefined, {numeric: true, sensitivity: 'base'});
|
||||
@ -163,9 +169,7 @@ function updateNslideValues() {
|
||||
BarItems.slider_size_y.update()
|
||||
BarItems.slider_size_z.update()
|
||||
|
||||
if (Blockbench.entity_mode) {
|
||||
BarItems.slider_inflate.update()
|
||||
}
|
||||
BarItems.slider_inflate.update()
|
||||
}
|
||||
if (selected.length || (Blockbench.entity_mode && selected_group)) {
|
||||
BarItems.slider_origin_x.update()
|
||||
@ -437,7 +441,19 @@ BARS.defineActions(function() {
|
||||
})
|
||||
})
|
||||
//Misc
|
||||
var Screencam = {
|
||||
const TickUpdates = {
|
||||
Run: function() {
|
||||
if (TickUpdates.outliner) {
|
||||
delete TickUpdates.outliner;
|
||||
loadOutlinerDraggable()
|
||||
}
|
||||
if (TickUpdates.selection) {
|
||||
delete TickUpdates.selection;
|
||||
updateSelection()
|
||||
}
|
||||
}
|
||||
}
|
||||
const Screencam = {
|
||||
fullScreen: function(options, cb) {
|
||||
setTimeout(function() {
|
||||
currentwindow.capturePage(function(screenshot) {
|
||||
@ -516,34 +532,6 @@ var Screencam = {
|
||||
})
|
||||
var frame_count = (options.length/interval)
|
||||
|
||||
/*
|
||||
gif.on('finished', blob => {
|
||||
var reader = new FileReader()
|
||||
reader.onload = () => {
|
||||
Screencam.returnScreenshot(reader.result, cb)
|
||||
}
|
||||
if (Animator.open && Timeline.playing) {
|
||||
Timeline.pause()
|
||||
}
|
||||
reader.readAsDataURL(blob)
|
||||
if (!options.silent) {
|
||||
Blockbench.setProgress(0)
|
||||
Blockbench.setStatusBarText()
|
||||
}
|
||||
})
|
||||
if (!options.silent) {
|
||||
Blockbench.setStatusBarText(tl('status_bar.recording_gif'))
|
||||
gif.on('progress', Blockbench.setProgress)
|
||||
}
|
||||
|
||||
|
||||
for (var frame = 0; frame < frame_count; frame++) {
|
||||
gif.addFrame(quad_previews.current.canvas, {delay: interval})
|
||||
}
|
||||
gif.render()*/
|
||||
|
||||
//Problem with this ^^ When recording, frames get generated as fast as possible
|
||||
|
||||
gif.on('finished', blob => {
|
||||
var reader = new FileReader()
|
||||
reader.onload = () => {
|
||||
@ -582,7 +570,7 @@ var Screencam = {
|
||||
}, options.length)
|
||||
}
|
||||
}
|
||||
var Clipbench = {
|
||||
const Clipbench = {
|
||||
cubes: [],
|
||||
copy: function(event, cut) {
|
||||
var p = Prop.active_panel
|
||||
@ -632,7 +620,6 @@ var Clipbench = {
|
||||
}
|
||||
if (Clipbench.keyframes && Clipbench.keyframes.length) {
|
||||
|
||||
|
||||
if (!Animator.selected) return;
|
||||
var bone = Animator.selected.getBoneAnimator()
|
||||
if (bone) {
|
||||
@ -659,12 +646,12 @@ var Clipbench = {
|
||||
|
||||
Undo.initEdit({outliner: true, cubes: [], selection: true});
|
||||
//Group
|
||||
var group = 'root'
|
||||
var target = 'root'
|
||||
if (selected_group) {
|
||||
group = selected_group
|
||||
target = selected_group
|
||||
selected_group.isOpen = true
|
||||
} else if (selected[0]) {
|
||||
group = selected[0]
|
||||
target = selected[0]
|
||||
}
|
||||
selected.length = 0
|
||||
if (isApp) {
|
||||
@ -681,18 +668,30 @@ var Clipbench = {
|
||||
} catch (err) {}
|
||||
}
|
||||
if (Clipbench.group) {
|
||||
if (typeof Clipbench.group.duplicate !== 'function') {
|
||||
Clipbench.group = new Group(Clipbench.group)
|
||||
function iterate(obj, parent) {
|
||||
if (obj.children) {
|
||||
var copy = new Group(obj)
|
||||
if (obj.children && obj.children.length) {
|
||||
obj.children.forEach((child) => {
|
||||
iterate(child, copy)
|
||||
})
|
||||
}
|
||||
copy.addTo(parent)
|
||||
} else {
|
||||
var copy = new Cube(obj)
|
||||
copy.addTo(parent).init()
|
||||
selected.push(elements[elements.length-1])
|
||||
}
|
||||
}
|
||||
Clipbench.group.duplicate(group)
|
||||
} else {
|
||||
Clipbench.cubes.forEach(function(obj) {
|
||||
var base_cube = new Cube(obj)
|
||||
iterate(Clipbench.group, target)
|
||||
updateSelection()
|
||||
|
||||
base_cube.addTo(group, false).init()
|
||||
} else if (Clipbench.cubes && Clipbench.cubes.length) {
|
||||
Clipbench.cubes.forEach(function(obj) {
|
||||
var copy = new Cube(obj)
|
||||
copy.addTo(target).init()
|
||||
selected.push(elements[elements.length-1])
|
||||
})
|
||||
loadOutlinerDraggable()
|
||||
updateSelection()
|
||||
}
|
||||
Undo.finishEdit('paste', {outliner: true, cubes: selected, selection: true});
|
||||
@ -759,82 +758,8 @@ var Clipbench = {
|
||||
}
|
||||
}
|
||||
}
|
||||
TextureAnimator = {
|
||||
isPlaying: false,
|
||||
interval: false,
|
||||
start: function() {
|
||||
clearInterval(TextureAnimator.interval)
|
||||
TextureAnimator.isPlaying = true
|
||||
TextureAnimator.updateButton()
|
||||
TextureAnimator.interval = setInterval(TextureAnimator.nextFrame, 1000/settings.texture_fps.value)
|
||||
},
|
||||
stop: function() {
|
||||
TextureAnimator.isPlaying = false
|
||||
clearInterval(TextureAnimator.interval)
|
||||
TextureAnimator.updateButton()
|
||||
},
|
||||
toggle: function() {
|
||||
if (TextureAnimator.isPlaying) {
|
||||
TextureAnimator.stop()
|
||||
} else {
|
||||
TextureAnimator.start()
|
||||
}
|
||||
},
|
||||
updateSpeed: function() {
|
||||
if (TextureAnimator.isPlaying) {
|
||||
TextureAnimator.stop()
|
||||
TextureAnimator.start()
|
||||
}
|
||||
},
|
||||
nextFrame: function() {
|
||||
var animated_tex = []
|
||||
textures.forEach(function(tex, i) {
|
||||
if (tex.frameCount > 1) {
|
||||
if (tex.currentFrame === undefined) {
|
||||
tex.currentFrame = 0
|
||||
} else if (tex.currentFrame >= tex.frameCount-1) {
|
||||
tex.currentFrame = 0
|
||||
} else {
|
||||
tex.currentFrame++;
|
||||
}
|
||||
$($('.texture').get(i)).find('img').css('margin-top', (tex.currentFrame*-48)+'px')
|
||||
animated_tex.push(''+tex.id)
|
||||
}
|
||||
})
|
||||
elements.forEach(function(obj) {
|
||||
var update = false
|
||||
for (var face in obj.faces) {
|
||||
if (update === false) {
|
||||
update = (
|
||||
obj.faces.hasOwnProperty(face) &&
|
||||
typeof obj.faces[face].texture === 'string' &&
|
||||
animated_tex.includes(obj.faces[face].texture.replace(/^#/, ''))
|
||||
)
|
||||
}
|
||||
}
|
||||
if (update) {
|
||||
Canvas.updateUV(obj, true)
|
||||
}
|
||||
})
|
||||
},
|
||||
reset: function() {
|
||||
TextureAnimator.stop()
|
||||
textures.forEach(function(tex, i) {
|
||||
if (tex.frameCount) {
|
||||
tex.currentFrame = 0
|
||||
$($('.texture').get(i)).find('img').css('margin-top', '0')
|
||||
}
|
||||
})
|
||||
while (i < elements.length) {
|
||||
Canvas.updateUV(elements[i], true)
|
||||
i++;
|
||||
}
|
||||
},
|
||||
updateButton: function() {
|
||||
BarItems.animated_textures.setIcon( TextureAnimator.isPlaying ? 'pause' : 'play_arrow' )
|
||||
}
|
||||
}
|
||||
var Vertexsnap = {
|
||||
|
||||
const Vertexsnap = {
|
||||
step1: true,
|
||||
vertexes: new THREE.Object3D(),
|
||||
vertexed_cubes: [],
|
||||
|
@ -228,7 +228,8 @@ class refModel {
|
||||
this.onload()
|
||||
}
|
||||
}
|
||||
load() {
|
||||
load(index) {
|
||||
displayReferenceObjects.ref_indexes[display_slot] = index || 0;
|
||||
displayReferenceObjects.clear()
|
||||
if (typeof this.onload === 'function') {
|
||||
this.onload()
|
||||
@ -1232,15 +1233,15 @@ window.displayReferenceObjects = {
|
||||
var button = $(
|
||||
`<div>
|
||||
<input class="hidden" type="radio" name="refmodel" id="${ref.id}"${ i === 0 ? ' selected' : '' }>
|
||||
<label class="tool" onclick="displayReferenceObjects.refmodels.${ref.id}.load()" for="${ref.id}">
|
||||
<label class="tool" onclick="displayReferenceObjects.refmodels.${ref.id}.load(${i})" for="${ref.id}">
|
||||
<div class="tooltip">${ref.name}</div>
|
||||
<i class="${icon}"></i>
|
||||
</label>
|
||||
</div>`
|
||||
)
|
||||
$('#display_ref_bar').append(button)
|
||||
if (i === 0) {
|
||||
ref.load()
|
||||
if (i === displayReferenceObjects.ref_indexes[display_slot]) {
|
||||
ref.load(i)
|
||||
button.find('input').prop("checked", true)
|
||||
}
|
||||
i++;
|
||||
@ -1251,6 +1252,16 @@ window.displayReferenceObjects = {
|
||||
displayReferenceObjects.active = false
|
||||
$('#donation_hint').hide()
|
||||
},
|
||||
ref_indexes: {
|
||||
thirdperson_righthand: 0,
|
||||
thirdperson_lefthand: 0,
|
||||
firstperson_righthand: 0,
|
||||
firstperson_lefthand: 0,
|
||||
ground: 0,
|
||||
gui: 0,
|
||||
head: 0,
|
||||
fixed: 0,
|
||||
},
|
||||
slots: [
|
||||
'thirdperson_righthand',
|
||||
'thirdperson_lefthand',
|
||||
@ -1280,6 +1291,7 @@ enterDisplaySettings = function() { //Enterung Display Setting Mode, changes th
|
||||
display_preview.setNormalCamera()
|
||||
display_preview.camPers.position.set(-80, 40, -30)
|
||||
display_preview.camPers.setFocalLength(45)
|
||||
lights.rotation.y = (Math.PI/4)*3
|
||||
|
||||
$('body').addClass('display_mode')
|
||||
$('.m_edit').hide()
|
||||
@ -1305,6 +1317,7 @@ exitDisplaySettings = function() { //Enterung Display Setting Mode, changes the
|
||||
setDisplayArea(0,0,0, 0,0,0, 1,1,1)
|
||||
display_area.updateMatrixWorld()
|
||||
display_base.updateMatrixWorld()
|
||||
lights.rotation.y = 0
|
||||
|
||||
display_mode = false;
|
||||
main_preview.fullscreen()
|
||||
|
File diff suppressed because it is too large
Load Diff
454
js/io.js
454
js/io.js
@ -43,7 +43,7 @@ function newProject(entity_mode) {
|
||||
function setupDragHandlers() {
|
||||
Blockbench.addDragHandler(
|
||||
'model',
|
||||
{extensions: ['json', 'jem', 'jpm']},
|
||||
{extensions: ['json', 'jem', 'jpm', 'bbmodel']},
|
||||
function(files) {
|
||||
loadModel(files[0].content, files[0].path || files[0].path)
|
||||
if (isApp) {
|
||||
@ -94,14 +94,16 @@ function loadModel(data, filepath, add) {
|
||||
var model = autoParseJSON(data)
|
||||
var extension = pathToExtension(filepath)
|
||||
|
||||
if (extension === 'jpm') {
|
||||
if (extension === 'bbmodel') {
|
||||
loadBBModel(model)
|
||||
} else if (extension === 'jpm') {
|
||||
loadJPMModel(model)
|
||||
} else if (extension === 'jem') {
|
||||
loadJEMModel(model)
|
||||
} else { //JSON
|
||||
for (var key in model) {
|
||||
if (key.includes('geometry.')) {
|
||||
loadPEModelFile(model)
|
||||
loadEntityModelFile(model)
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -116,6 +118,80 @@ function loadModel(data, filepath, add) {
|
||||
Prop.project_saved = true;
|
||||
}
|
||||
}
|
||||
function loadBBModel(model) {
|
||||
if (!model.meta || !model.meta.format) {
|
||||
Blockbench.showMessageBox({
|
||||
translateKey: 'invalid_model',
|
||||
icon: 'error',
|
||||
})
|
||||
return;
|
||||
}
|
||||
if (compareVersions(model.meta.format, '1.0')) {
|
||||
Blockbench.showMessageBox({
|
||||
translateKey: 'outdated_client',
|
||||
icon: 'error',
|
||||
})
|
||||
return;
|
||||
}
|
||||
if (model.meta.box_uv && model.meta.bone_rig) {
|
||||
entityMode.join()
|
||||
} else {
|
||||
Blockbench.entity_mode = false;
|
||||
}
|
||||
saveSettings()
|
||||
Project.name = model.name;
|
||||
if (model.geo_name) {
|
||||
Project.geometry_name = model.geo_name;
|
||||
} else if (model.parent) {
|
||||
Project.parent = model.parent;
|
||||
}
|
||||
if (model.ambientocclusion !== undefined) {
|
||||
Project.ambientocclusion = !!model.ambientocclusion;
|
||||
}
|
||||
if (model.resolution !== undefined) {
|
||||
Project.texture_width = model.resolution.width;
|
||||
Project.texture_height = model.resolution.height;
|
||||
}
|
||||
|
||||
if (model.textures) {
|
||||
model.textures.forEach(tex => {
|
||||
var tex_copy = new Texture(tex).add(false);
|
||||
tex_copy.uuid = tex.uuid;
|
||||
if (tex_copy.mode === 'link') {
|
||||
tex_copy.fromPath(tex.path)
|
||||
} else {
|
||||
tex_copy.fromDataURL(tex.source)
|
||||
}
|
||||
})
|
||||
}
|
||||
if (model.cubes) {
|
||||
model.cubes.forEach(function(cube) {
|
||||
base_cube = new Cube(cube).init(false)
|
||||
for (var face in base_cube.faces) {
|
||||
if (!model.meta.box_uv) {
|
||||
var texture = textures[cube.faces[face].texture]
|
||||
if (texture) {
|
||||
base_cube.faces[face].texture = texture.uuid
|
||||
}
|
||||
} else if (textures[0]) {
|
||||
base_cube.faces[face].texture = textures[0].uuid
|
||||
}
|
||||
}
|
||||
})
|
||||
loadOutlinerDraggable()
|
||||
}
|
||||
if (model.outliner) {
|
||||
parseGroups(model.outliner)
|
||||
}
|
||||
if (model.animations) {
|
||||
model.animations.forEach(ani => {
|
||||
var base_ani = new Animation(ani).add();
|
||||
})
|
||||
}
|
||||
if (model.display !== undefined) {
|
||||
DisplayMode.loadJSON(model.display)
|
||||
}
|
||||
}
|
||||
function loadBlockModel(model, filepath, add) {
|
||||
if (!model.elements && !model.parent && !model.display && !model.textures) {
|
||||
Blockbench.showMessageBox({
|
||||
@ -329,6 +405,8 @@ function loadJEMModel(model) {
|
||||
if (model.models) {
|
||||
model.models.forEach(function(b) {
|
||||
if (typeof b !== 'object') return;
|
||||
var subcount = 0;
|
||||
|
||||
//Bone
|
||||
var group = new Group({
|
||||
name: b.part,
|
||||
@ -339,40 +417,60 @@ function loadJEMModel(model) {
|
||||
group.origin[1] *= -1
|
||||
group.origin[2] *= -1
|
||||
|
||||
//Cubes
|
||||
if ((b.boxes && b.boxes.length) || (b.submodel && b.submodel.boxes && b.submodel.boxes.length)) {
|
||||
function addBox(box, i, mirrored) {
|
||||
var base_cube = new Cube({
|
||||
name: box.name || group.name,
|
||||
autouv: 0,
|
||||
uv_offset: box.textureOffset,
|
||||
inflate: box.sizeAdd
|
||||
})
|
||||
if (box.coordinates) {
|
||||
base_cube.extend({
|
||||
from: [
|
||||
box.coordinates[0],
|
||||
box.coordinates[1],
|
||||
box.coordinates[2]
|
||||
],
|
||||
to: [
|
||||
box.coordinates[0]+box.coordinates[3],
|
||||
box.coordinates[1]+box.coordinates[4],
|
||||
box.coordinates[2]+box.coordinates[5]
|
||||
]
|
||||
function readContent(submodel, p_group) {
|
||||
|
||||
if (submodel.boxes && submodel.boxes.length) {
|
||||
submodel.boxes.forEach(box => {
|
||||
|
||||
var base_cube = new Cube({
|
||||
name: box.name || p_group.name,
|
||||
autouv: 0,
|
||||
uv_offset: box.textureOffset,
|
||||
inflate: box.sizeAdd,
|
||||
mirror_uv: p_group.mirror_uv
|
||||
})
|
||||
}
|
||||
elements.push(base_cube)
|
||||
base_cube.addTo(group, false)
|
||||
if (box.coordinates) {
|
||||
base_cube.extend({
|
||||
from: [
|
||||
box.coordinates[0],
|
||||
box.coordinates[1],
|
||||
box.coordinates[2]
|
||||
],
|
||||
to: [
|
||||
box.coordinates[0]+box.coordinates[3],
|
||||
box.coordinates[1]+box.coordinates[4],
|
||||
box.coordinates[2]+box.coordinates[5]
|
||||
]
|
||||
})
|
||||
}
|
||||
if (p_group.parent !== 'root') {
|
||||
for (var i = 0; i < 3; i++) {
|
||||
base_cube.from[i] += p_group.origin[i];
|
||||
base_cube.to[i] += p_group.origin[i];
|
||||
}
|
||||
}
|
||||
elements.push(base_cube)
|
||||
base_cube.addTo(p_group)
|
||||
})
|
||||
}
|
||||
if (b.boxes && b.boxes.length) {
|
||||
b.boxes.forEach(addBox)
|
||||
}
|
||||
if (b.submodel && b.submodel.boxes && b.submodel.boxes.length) {
|
||||
b.submodel.boxes.forEach(function(box, i) {addBox(box, i, true)})
|
||||
if (submodel.submodels && submodel.submodels.length) {
|
||||
submodel.submodels.forEach(subsub => {
|
||||
var group = new Group({
|
||||
name: `${b.part}_sub_${subcount}`,
|
||||
origin: subsub.translate || submodel.translate,
|
||||
rotation: subsub.rotate,
|
||||
mirror_uv: (subsub.mirrorTexture && subsub.mirrorTexture.includes('u'))
|
||||
})
|
||||
subcount++;
|
||||
group.rotation[2] *= -1
|
||||
group.addTo(p_group)
|
||||
readContent(subsub, group)
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
group.addTo(undefined, false)
|
||||
group.addTo(undefined)
|
||||
readContent(b, group)
|
||||
})
|
||||
}
|
||||
loadOutlinerDraggable()
|
||||
@ -382,7 +480,7 @@ function loadJEMModel(model) {
|
||||
new Texture().fromPath(path).add(false)
|
||||
}
|
||||
}
|
||||
function loadPEModelFile(data) {
|
||||
function loadEntityModelFile(data) {
|
||||
pe_list_data.length = 0
|
||||
entityMode.join()
|
||||
|
||||
@ -393,7 +491,7 @@ function loadPEModelFile(data) {
|
||||
}
|
||||
}
|
||||
if (geometries.length === 1) {
|
||||
loadPEModel({object: data[geometries[0]], name: geometries[0]})
|
||||
loadEntityModel({object: data[geometries[0]], name: geometries[0]})
|
||||
return;
|
||||
}
|
||||
|
||||
@ -536,7 +634,7 @@ function loadPEModelFile(data) {
|
||||
$('input#pe_search_bar').select()
|
||||
//texturelist._data.elements = textures
|
||||
}
|
||||
function loadPEModel(data) {
|
||||
function loadEntityModel(data) {
|
||||
if (data === undefined) {
|
||||
pe_list_data.forEach(function(s) {
|
||||
if (s.selected === true) {
|
||||
@ -621,12 +719,12 @@ function loadPEModel(data) {
|
||||
base_cube.mirror_uv = s.mirror === true
|
||||
}
|
||||
elements.push(base_cube)
|
||||
base_cube.addTo(group, false)
|
||||
base_cube.addTo(group)
|
||||
})
|
||||
}
|
||||
if (b.children) {
|
||||
b.children.forEach(function(cg) {
|
||||
cg.addTo(group, false)
|
||||
cg.addTo(group)
|
||||
})
|
||||
}
|
||||
var parent_group = 'root';
|
||||
@ -641,7 +739,7 @@ function loadPEModel(data) {
|
||||
})
|
||||
}
|
||||
}
|
||||
group.addTo(parent_group, false)
|
||||
group.addTo(parent_group)
|
||||
})
|
||||
}
|
||||
pe_list_data.length = 0;
|
||||
@ -700,7 +798,7 @@ var Extruder = {
|
||||
},
|
||||
startConversion: function() {
|
||||
var scan_mode = $('select#scan_mode option:selected').attr('id') /*areas, lines, columns, pixels*/
|
||||
var texture_index = '#'+textures[textures.length-1].id
|
||||
var texture = textures[textures.length-1].uuid
|
||||
var isNewProject = elements.length === 0;
|
||||
|
||||
var jimage = Jimp.read(Extruder.ext_img.src).then(function(image) {
|
||||
@ -809,12 +907,12 @@ var Extruder = {
|
||||
from: [rect.x*scale_i, 0, rect.y*scale_i],
|
||||
to: [(rect.x2+1)*scale_i, scale_i, (rect.y2+1)*scale_i],
|
||||
faces: {
|
||||
up: {uv:[rect.x*scale_i, rect.y*scale_i, (rect.x2+1)*scale_i, (rect.y2+1)*scale_i], texture: texture_index},
|
||||
down: {uv:[rect.x*scale_i, (rect.y2+1)*scale_i, (rect.x2+1)*scale_i, rect.y*scale_i], texture: texture_index},
|
||||
north: {uv:[(rect.x2+1)*scale_i, rect.y*scale_i, rect.x*scale_i, (rect.y+1)*scale_i], texture: texture_index},
|
||||
south: {uv:[rect.x*scale_i, rect.y2*scale_i, (rect.x2+1)*scale_i, (rect.y2+1)*scale_i], texture: texture_index},
|
||||
east: {uv:[rect.x2*scale_i, rect.y*scale_i, (rect.x2+1)*scale_i, (rect.y2+1)*scale_i], texture: texture_index, rotation: 90},
|
||||
west: {uv:[rect.x*scale_i, rect.y*scale_i, (rect.x+1)*scale_i, (rect.y2+1)*scale_i], texture: texture_index, rotation: 270}
|
||||
up: {uv:[rect.x*scale_i, rect.y*scale_i, (rect.x2+1)*scale_i, (rect.y2+1)*scale_i], texture: texture},
|
||||
down: {uv:[rect.x*scale_i, (rect.y2+1)*scale_i, (rect.x2+1)*scale_i, rect.y*scale_i], texture: texture},
|
||||
north: {uv:[(rect.x2+1)*scale_i, rect.y*scale_i, rect.x*scale_i, (rect.y+1)*scale_i], texture: texture},
|
||||
south: {uv:[rect.x*scale_i, rect.y2*scale_i, (rect.x2+1)*scale_i, (rect.y2+1)*scale_i], texture: texture},
|
||||
east: {uv:[rect.x2*scale_i, rect.y*scale_i, (rect.x2+1)*scale_i, (rect.y2+1)*scale_i], texture: texture, rotation: 90},
|
||||
west: {uv:[rect.x*scale_i, rect.y*scale_i, (rect.x+1)*scale_i, (rect.y2+1)*scale_i], texture: texture, rotation: 270}
|
||||
}
|
||||
})
|
||||
|
||||
@ -831,7 +929,7 @@ var Extruder = {
|
||||
|
||||
var group = new Group(cube_name).addTo()
|
||||
selected.forEach(function(s) {
|
||||
s.addTo(group, false)
|
||||
s.addTo(group)
|
||||
})
|
||||
if (Blockbench.hasFlag('new_project') || isNewProject) {
|
||||
setProjectTitle(cube_name)
|
||||
@ -845,6 +943,89 @@ var Extruder = {
|
||||
}
|
||||
}
|
||||
//Export
|
||||
function buildBBModel(options) {
|
||||
if (!options) options = 0;
|
||||
var model = {
|
||||
meta: {
|
||||
format: '1.0',
|
||||
box_uv: Blockbench.entity_mode,
|
||||
bone_rig: Blockbench.entity_mode,
|
||||
},
|
||||
name: Project.name,
|
||||
}
|
||||
model[Blockbench.entity_mode ? 'geo_name' : 'parent'] = Project.parent
|
||||
if (!Blockbench.entity_mode) {
|
||||
model.ambientocclusion = Project.ambientocclusion
|
||||
}
|
||||
if (model.meta.box_uv) {
|
||||
model.resolution = {
|
||||
width: Project.texture_width || 16,
|
||||
height: Project.texture_height || 16,
|
||||
}
|
||||
}
|
||||
model.cubes = []
|
||||
elements.forEach(cube => {
|
||||
var el = {
|
||||
name: cube.name,
|
||||
from: cube.from,
|
||||
to: cube.to,
|
||||
autouv: cube.autouv,
|
||||
color: cube.color
|
||||
}
|
||||
if (!cube.visibility) el.visibility = false;
|
||||
if (!cube.export) el.export = false;
|
||||
if (!cube.shade) el.shade = false;
|
||||
if (cube.inflate) el.inflate = cube.inflate;
|
||||
if (!cube.rotation.allEqual(0)) el.rotation = cube.rotation;
|
||||
if (!cube.origin.allEqual(0)) el.origin = cube.origin;
|
||||
if (!cube.uv_offset.allEqual(0)) el.uv_offset = cube.uv_offset;
|
||||
|
||||
if (!model.meta.box_uv) {
|
||||
el.faces = {}
|
||||
for (var face in cube.faces) {
|
||||
el.faces[face] = cube.faces[face].getSaveCopy()
|
||||
}
|
||||
}
|
||||
|
||||
model.cubes.push(el)
|
||||
})
|
||||
model.outliner = compileGroups()
|
||||
|
||||
model.textures = [];
|
||||
textures.forEach(tex => {
|
||||
var t = tex.getUndoCopy();
|
||||
delete t.selected;
|
||||
model.textures.push(t);
|
||||
})
|
||||
|
||||
if (Animator.animations.length) {
|
||||
model.animations = [];
|
||||
Animator.animations.forEach(a => {
|
||||
model.animations.push(a.undoCopy({bone_names: true}))
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
if (!Blockbench.entity_mode && Object.keys(display).length >= 1) {
|
||||
var new_display = {}
|
||||
var entries = 0;
|
||||
for (var i in DisplayMode.slots) {
|
||||
var key = DisplayMode.slots[i]
|
||||
if (DisplayMode.slots.hasOwnProperty(i) && display[key] && display[key].export) {
|
||||
new_display[key] = display[key].export()
|
||||
entries++;
|
||||
}
|
||||
}
|
||||
if (entries) {
|
||||
model.display = new_display
|
||||
}
|
||||
}
|
||||
if (options.raw) {
|
||||
return model
|
||||
} else {
|
||||
return JSON.stringify(model)
|
||||
}
|
||||
}
|
||||
function buildBlockModel(options) {
|
||||
if (options === undefined) options = {}
|
||||
var clear_elements = []
|
||||
@ -865,6 +1046,12 @@ function buildBlockModel(options) {
|
||||
}
|
||||
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;
|
||||
element.to[i] += s.inflate;
|
||||
}
|
||||
}
|
||||
if (s.shade === false) {
|
||||
element.shade = false
|
||||
}
|
||||
@ -1233,77 +1420,92 @@ function buildJEMModel(options) {
|
||||
entitymodel.texture = textures[0].name
|
||||
}
|
||||
entitymodel.textureSize = [parseInt(Project.texture_width), parseInt(Project.texture_height)];
|
||||
var models = []
|
||||
entitymodel.models = []
|
||||
|
||||
TreeElements.forEach(function(g) {
|
||||
if (g.type !== 'group') return;
|
||||
//Bone
|
||||
var bone = {}
|
||||
bone.part = g.name
|
||||
bone.invertAxis = 'xy'
|
||||
bone.translate = g.origin.slice()
|
||||
var bone = {
|
||||
part: g.name,
|
||||
invertAxis: 'xy',
|
||||
translate: g.origin.slice()
|
||||
}
|
||||
bone.translate[1] *= -1
|
||||
bone.translate[2] *= -1
|
||||
|
||||
if (g.rotation.join('_') !== '0_0_0') {
|
||||
if (!g.rotation.allEqual(0)) {
|
||||
bone.rotate = g.rotation.slice()
|
||||
}
|
||||
if (g.mirror_uv) {
|
||||
bone.mirrorTexture = 'u'
|
||||
}
|
||||
//Cubes
|
||||
if (g.children && g.children.length) {
|
||||
bone.boxes = []
|
||||
var mirrored_boxes = []
|
||||
function iterate(arr) {
|
||||
var i = 0;
|
||||
while (i < arr.length) {
|
||||
if (arr[i].type === 'group') {
|
||||
iterate(arr[i].children)
|
||||
} else if (arr[i].type === 'cube') {
|
||||
var s = arr[i]
|
||||
if (s !== undefined && s.export !== false) {
|
||||
var cube = new oneLiner()
|
||||
|
||||
var c_pos = s.from.slice()
|
||||
var c_size = s.size()
|
||||
cube.coordinates = [
|
||||
c_pos[0],//b_translate[0] - c_pos[0] - c_size[0],
|
||||
c_pos[1],//b_translate[1] - c_pos[1] - c_size[1],
|
||||
c_pos[2],
|
||||
c_size[0],
|
||||
c_size[1],
|
||||
c_size[2]
|
||||
]
|
||||
function populate(p_model, group) {
|
||||
|
||||
cube.textureOffset = s.uv_offset
|
||||
if (s.inflate && typeof s.inflate === 'number') {
|
||||
cube.sizeAdd = s.inflate
|
||||
}
|
||||
if (s.mirror_uv === g.mirror_uv) {
|
||||
bone.boxes.push(cube)
|
||||
} else {
|
||||
mirrored_boxes.push(cube)
|
||||
}
|
||||
}
|
||||
if (group.children.length === 0) return;
|
||||
var mirror_sub;
|
||||
|
||||
group.children.forEach(obj => {
|
||||
if (!obj.export) return;
|
||||
if (obj.type === 'cube') {
|
||||
|
||||
var box = new oneLiner()
|
||||
var c_size = obj.size()
|
||||
box.coordinates = [
|
||||
obj.from[0],
|
||||
obj.from[1],
|
||||
obj.from[2],
|
||||
c_size[0],
|
||||
c_size[1],
|
||||
c_size[2]
|
||||
]
|
||||
if (p_model && p_model.part === undefined) {
|
||||
box.coordinates[0] -= p_model.translate[0];
|
||||
box.coordinates[1] -= p_model.translate[1];
|
||||
box.coordinates[2] -= p_model.translate[2];
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
iterate(g.children)
|
||||
if (mirrored_boxes.length) {
|
||||
bone.submodel = {
|
||||
invertAxis: 'xy',
|
||||
boxes: mirrored_boxes
|
||||
}
|
||||
if (g.shade !== false) {
|
||||
bone.submodel.mirrorTexture = 'u'
|
||||
}
|
||||
}
|
||||
box.textureOffset = obj.uv_offset
|
||||
if (obj.inflate && typeof obj.inflate === 'number') {
|
||||
box.sizeAdd = obj.inflate
|
||||
}
|
||||
|
||||
if (obj.mirror_uv !== group.mirror_uv) {
|
||||
if (!mirror_sub) {
|
||||
mirror_sub = {
|
||||
invertAxis: 'xy',
|
||||
mirrorTexture: 'u',//xxx
|
||||
boxes: []
|
||||
}
|
||||
if (!p_model.submodels) p_model.submodels = [];
|
||||
p_model.submodels.splice(0, 0, mirror_sub)
|
||||
}
|
||||
mirror_sub.boxes.push(box)
|
||||
} else {
|
||||
if (!p_model.boxes) p_model.boxes = []
|
||||
p_model.boxes.push(box)
|
||||
}
|
||||
} else if (obj.type === 'group') {
|
||||
|
||||
var bone = {
|
||||
invertAxis: 'xy',
|
||||
translate: obj.origin.slice()
|
||||
}
|
||||
if (obj.mirror_uv) {
|
||||
bone.mirrorTexture = 'u'
|
||||
}
|
||||
if (!obj.rotation.allEqual(0)) {
|
||||
bone.rotate = obj.rotation.slice()
|
||||
bone.rotate[2] *= -1
|
||||
}
|
||||
populate(bone, obj)
|
||||
|
||||
if (!p_model.submodels) p_model.submodels = [];
|
||||
p_model.submodels.push(bone)
|
||||
}
|
||||
})
|
||||
}
|
||||
models.push(bone)
|
||||
populate(bone, g)
|
||||
entitymodel.models.push(bone)
|
||||
})
|
||||
entitymodel.models = models
|
||||
|
||||
if (options.raw) {
|
||||
return entitymodel
|
||||
@ -1597,7 +1799,7 @@ BARS.defineActions(function() {
|
||||
keybind: new Keybind({key: 79, ctrl: true}),
|
||||
click: function () {
|
||||
Blockbench.import({
|
||||
extensions: ['json', 'jem', 'jpm'],
|
||||
extensions: ['json', 'jem', 'jpm', 'bbmodel'],
|
||||
type: 'JSON Model'
|
||||
}, function(files) {
|
||||
if (isApp) {
|
||||
@ -1663,6 +1865,21 @@ BARS.defineActions(function() {
|
||||
})
|
||||
}
|
||||
})
|
||||
new Action({
|
||||
id: 'export_bbmodel',
|
||||
icon: 'insert_drive_file',
|
||||
category: 'file',
|
||||
click: function () {
|
||||
Blockbench.export({
|
||||
type: 'Blockbench Save',
|
||||
extensions: ['bbmodel'],
|
||||
name: Project.name||'model',
|
||||
startpath: Prop.file_path,
|
||||
project_file: true,
|
||||
content: buildBBModel()
|
||||
})
|
||||
}
|
||||
})
|
||||
new Action({
|
||||
id: 'export_entity',
|
||||
icon: 'pets',
|
||||
@ -1748,4 +1965,35 @@ BARS.defineActions(function() {
|
||||
keybind: new Keybind({key: 83, ctrl: true}),
|
||||
click: function () {saveFile();saveTextures();}
|
||||
})
|
||||
new Action({
|
||||
id: 'export_asset_archive',
|
||||
icon: 'archive',
|
||||
category: 'file',
|
||||
click: function() {
|
||||
var archive = new JSZip();
|
||||
if (Blockbench.entity_mode === false) {
|
||||
var content = buildBlockModel()
|
||||
} else {
|
||||
var content = buildEntityModel()
|
||||
}
|
||||
archive.file((Project.name||'model')+'.json', content)
|
||||
var texfolder = archive.folder('textures');
|
||||
textures.forEach(tex => {
|
||||
if (tex.mode === 'bitmap') {
|
||||
texfolder.file(pathToName(tex.name) + '.png', tex.source.replace('data:image/png;base64,', ''), {base64: true});
|
||||
}
|
||||
})
|
||||
archive.generateAsync({type: 'blob'}).then(content => {
|
||||
Blockbench.export({
|
||||
type: 'Zip Archive',
|
||||
extensions: ['zip'],
|
||||
name: 'assets',
|
||||
startpath: Prop.file_path,
|
||||
content: content,
|
||||
savetype: 'zip',
|
||||
project_file: true
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
|
@ -143,12 +143,16 @@ class Keybind {
|
||||
}
|
||||
record() {
|
||||
var scope = this;
|
||||
Keybinds.recording = true;
|
||||
var overlay = $('<div id="overlay_message_box" contenteditable="true"></div>')
|
||||
$('body').append(overlay)
|
||||
overlay.focus()
|
||||
overlay.on('keyup mousedown', function(event) {
|
||||
overlay.off('keyup mousedown')
|
||||
Keybinds.recording = this;
|
||||
var overlay = $('#overlay_message_box').show()
|
||||
var input = overlay.find('#keybind_input_box')
|
||||
var top = limitNumber($(window).height()/2 - 200, 30, 800)
|
||||
overlay.find('> div').css('margin-top', top+'px')
|
||||
|
||||
function onActivate(event) {
|
||||
|
||||
if (event.target && event.target.tagName === 'BUTTON') return;
|
||||
|
||||
scope.key = event.which
|
||||
if (scope.ctrl !== null) scope.ctrl = event.ctrlKey
|
||||
if (scope.shift !== null) scope.shift = event.shiftKey
|
||||
@ -156,13 +160,26 @@ class Keybind {
|
||||
if (scope.meta !== null) scope.meta = event.metaKey
|
||||
scope.label = scope.getText()
|
||||
scope.save(true)
|
||||
Keybinds.recording = false
|
||||
overlay.detach().hide()
|
||||
}).on('keydown keypress keyup click click dblclick mouseup', function(event) {
|
||||
Blockbench.showQuickMessage(scope.label)
|
||||
|
||||
scope.stopRecording()
|
||||
}
|
||||
|
||||
input.focus().on('keyup', onActivate)
|
||||
overlay.on('mousedown', onActivate)
|
||||
|
||||
overlay.on('keydown keypress keyup click click dblclick mouseup', function(event) {
|
||||
event.preventDefault()
|
||||
})
|
||||
return this;
|
||||
}
|
||||
stopRecording() {
|
||||
var scope = this;
|
||||
Keybinds.recording = false
|
||||
$('#overlay_message_box').hide().off('mousedown')
|
||||
$('#keybind_input_box').off('keyup')
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
onVueSetup(function() {
|
||||
|
@ -71,6 +71,8 @@ class BBPainter {
|
||||
}
|
||||
startBrushCanvas(data, event) {
|
||||
Painter.current.x = Painter.current.y = 0
|
||||
Painter.current.face = data.face;
|
||||
Painter.current.cube = data.cube;
|
||||
var texture = data.cube.faces[data.face].getTexture()
|
||||
if (!texture) {
|
||||
Blockbench.showQuickMessage('message.untextured')
|
||||
@ -205,8 +207,7 @@ class BBPainter {
|
||||
ctx.fillStyle = BarItems.brush_color.get().toRgbString()
|
||||
|
||||
var fill_mode = BarItems.fill_mode.get()
|
||||
var cube = selected[0]
|
||||
|
||||
var cube = Painter.current.cube;
|
||||
if (cube && fill_mode === 'cube') {
|
||||
for (var face in cube.faces) {
|
||||
var tag = cube.faces[face]
|
||||
@ -265,10 +266,7 @@ class BBPainter {
|
||||
px[3] = result_color.a*255
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
ctx.clip()
|
||||
|
||||
@ -282,7 +280,6 @@ class BBPainter {
|
||||
return {r: pxcolor.r, g: pxcolor.g, b: pxcolor.b, a: pxcolor.a*(1-b_opacity*opacity*(noise?Math.random():1))};
|
||||
})
|
||||
}
|
||||
|
||||
ctx.restore();
|
||||
}
|
||||
Painter.editing_area = undefined;
|
||||
@ -561,7 +558,12 @@ class BBPainter {
|
||||
return texture.add(false);
|
||||
}
|
||||
if (options.entity_template === true) {
|
||||
Undo.initEdit({textures: Blockbench.entity_mode ? textures : [], cubes: Blockbench.entity_mode ? elements : selected, uv_only: true})
|
||||
Undo.initEdit({
|
||||
textures: Blockbench.entity_mode ? textures : [],
|
||||
cubes: Blockbench.entity_mode ? elements : selected,
|
||||
uv_only: true,
|
||||
resolution: true
|
||||
})
|
||||
Painter.generateTemplate(options, makeTexture)
|
||||
} else {
|
||||
Undo.initEdit({textures: []})
|
||||
|
@ -110,6 +110,7 @@ class Preview {
|
||||
this.camOrtho.updateProjectionMatrix();
|
||||
}
|
||||
this.renderer.setSize(this.width, this.height);
|
||||
this.renderer.setPixelRatio(window.devicePixelRatio);
|
||||
this.updateBackground()
|
||||
return this;
|
||||
}
|
||||
@ -297,6 +298,7 @@ class Preview {
|
||||
//Controls
|
||||
click(event) {
|
||||
$(':focus').blur()
|
||||
display_mode
|
||||
this.static_rclick = event.button === 2
|
||||
quad_previews.current = this;
|
||||
if (Transformer.hoverAxis !== null || !Keybinds.extra.preview_select.keybind.isTriggered(event)) return;
|
||||
@ -310,7 +312,7 @@ class Preview {
|
||||
main_uv.setFace(data.face, false)
|
||||
}
|
||||
Blockbench.dispatchEvent( 'canvas_select', data )
|
||||
if (Animator.open || (Toolbox.selected.id === 'rotate_tool' && Blockbench.entity_mode)) {
|
||||
if (Animator.open || (Blockbench.entity_mode && ['rotate_tool', 'pivot_tool'].includes(Toolbox.selected.id))) {
|
||||
if (data.cube.parent.type === 'group') {
|
||||
data.cube.parent.select()
|
||||
}
|
||||
@ -357,7 +359,7 @@ class Preview {
|
||||
showContextMenu(event) {
|
||||
if (this.static_rclick && event.which === 3) {
|
||||
var data = this.raycast()
|
||||
if (data && data.cube) {
|
||||
if (Toolbox.selected.selectCubes && Modes.selected.selectCubes && data && data.cube) {
|
||||
data.cube.showContextMenu(event)
|
||||
} else {
|
||||
this.menu.open(event, this)
|
||||
@ -560,7 +562,7 @@ class Preview {
|
||||
var scope = this;
|
||||
var dialog = new Dialog({
|
||||
id: 'background_position',
|
||||
title: 'message.set_background_position.title',
|
||||
title: tl('message.set_background_position.title'),
|
||||
lines: [
|
||||
`<div class="dialog_bar">
|
||||
<input type="number" class="dark_bordered" value="${scope.background.x}" id="background_pos_x">
|
||||
@ -611,33 +613,40 @@ class Preview {
|
||||
if (display_mode && ground_animation) {
|
||||
ground_animation = false
|
||||
}
|
||||
this.render()
|
||||
|
||||
setTimeout(function() {
|
||||
var dataUrl = scope.canvas.toDataURL()
|
||||
|
||||
var dataUrl = scope.canvas.toDataURL()
|
||||
dataUrl = dataUrl.replace('data:image/png;base64,','')
|
||||
Jimp.read(Buffer.from(dataUrl, 'base64')).then(function(image) {
|
||||
|
||||
if (display_mode && display_slot === 'gui') {
|
||||
var zoom = display_preview.camOrtho.zoom * devicePixelRatio
|
||||
var resolution = 256 * zoom;
|
||||
|
||||
dataUrl = dataUrl.replace('data:image/png;base64,','')
|
||||
Jimp.read(Buffer.from(dataUrl, 'base64')).then(function(image) {
|
||||
var start_x = display_preview.width *devicePixelRatio/2 - display_preview.controls.target.x*zoom*40 - resolution/2;
|
||||
var start_y = display_preview.height*devicePixelRatio/2 + display_preview.controls.target.y*zoom*40 - resolution/2;
|
||||
|
||||
image.crop(start_x, start_y, resolution, resolution)
|
||||
} else {
|
||||
image.autocrop([0, false])
|
||||
if (options && options.width && options.height) {
|
||||
image.contain(options.width, options.height)
|
||||
}
|
||||
|
||||
image.getBase64(Jimp.MIME_PNG, function(a, dataUrl){
|
||||
Screencam.returnScreenshot(dataUrl, cb)
|
||||
})
|
||||
});
|
||||
|
||||
editVis(obj => {
|
||||
obj.visible = obj.was_visible
|
||||
delete obj.was_visible
|
||||
})
|
||||
if (display_mode && ground_anim_before) {
|
||||
ground_animation = ground_anim_before
|
||||
}
|
||||
|
||||
}, 40)
|
||||
image.getBase64(Jimp.MIME_PNG, function(a, dataUrl){
|
||||
Screencam.returnScreenshot(dataUrl, cb)
|
||||
})
|
||||
});
|
||||
|
||||
editVis(obj => {
|
||||
obj.visible = obj.was_visible
|
||||
delete obj.was_visible
|
||||
})
|
||||
if (display_mode && ground_anim_before) {
|
||||
ground_animation = ground_anim_before
|
||||
}
|
||||
}
|
||||
fullscreen() {
|
||||
quad_previews.current = this;
|
||||
@ -735,7 +744,6 @@ class Preview {
|
||||
}}
|
||||
])
|
||||
|
||||
|
||||
function openQuadView() {
|
||||
quad_previews.enabled = true;
|
||||
|
||||
@ -760,7 +768,6 @@ function openQuadView() {
|
||||
updateInterface()
|
||||
}
|
||||
|
||||
|
||||
//Init/Update
|
||||
function initCanvas() {
|
||||
|
||||
@ -955,6 +962,7 @@ function initCanvas() {
|
||||
resizeWindow()
|
||||
}
|
||||
function animate() {
|
||||
TickUpdates.Run()
|
||||
requestAnimationFrame( animate );
|
||||
previews.forEach(function(prev) {
|
||||
prev.render()
|
||||
@ -1092,7 +1100,7 @@ function buildGrid() {
|
||||
function centerTransformer(offset) {
|
||||
if (selected.length === 0) return;
|
||||
|
||||
var rotate_tool = Toolbox.selected.transformerMode === 'rotate'
|
||||
var pivot_center = Toolbox.selected.id === 'rotate_tool' || Toolbox.selected.id === 'pivot_tool'
|
||||
|
||||
if (Animator.open && selected_group) {
|
||||
var g_mesh = selected_group.mesh
|
||||
@ -1110,7 +1118,7 @@ function centerTransformer(offset) {
|
||||
if (Blockbench.entity_mode) {
|
||||
Canvas.updateAllBones()
|
||||
}
|
||||
if (!rotate_tool) {
|
||||
if (!pivot_center) {
|
||||
var first_obj;
|
||||
var center = getSelectionCenter()
|
||||
for (var i = 0; i < selected.length && !first_obj; i++) {
|
||||
@ -1133,13 +1141,13 @@ function centerTransformer(offset) {
|
||||
Transformer.position.copy(vec)
|
||||
|
||||
var mesh = first_obj.mesh
|
||||
if (mesh && Blockbench.globalMovement === false && !rotate_tool) {
|
||||
if (mesh && Blockbench.globalMovement === false && !pivot_center) {
|
||||
Transformer.rotation.copy(mesh.rotation)
|
||||
}
|
||||
} else {
|
||||
//Entity Mode
|
||||
|
||||
if (selected_group && rotate_tool) {
|
||||
if (selected_group && pivot_center) {
|
||||
var mesh = selected_group.mesh
|
||||
if (mesh) {
|
||||
mesh.getWorldPosition(Transformer.position)
|
||||
@ -1177,7 +1185,7 @@ function centerTransformer(offset) {
|
||||
vec.z += group.origin[2]
|
||||
}
|
||||
Transformer.position.copy(vec)
|
||||
if (Blockbench.globalMovement === false && !rotate_tool) {
|
||||
if (Blockbench.globalMovement === false && !pivot_center) {
|
||||
var rotation = new THREE.Quaternion()
|
||||
first_obj.mesh.getWorldQuaternion(rotation)
|
||||
Transformer.rotation.setFromQuaternion( rotation )
|
||||
@ -1482,18 +1490,19 @@ class CanvasController {
|
||||
|
||||
if (!mesh || mesh > 0) mesh = obj.mesh
|
||||
|
||||
function setSize(geo) {
|
||||
if (Blockbench.entity_mode && obj.inflate !== undefined) {
|
||||
var inflate = obj.inflate
|
||||
geo.from([ obj.from[0]-inflate, obj.from[1]-inflate, obj.from[2]-inflate ])
|
||||
geo.to( [ obj.to[0] +inflate, obj.to[1] +inflate, obj.to[2] +inflate ])
|
||||
} else {
|
||||
geo.from(obj.from)
|
||||
geo.to(obj.to)
|
||||
var from = obj.from.slice()
|
||||
from.forEach((v, i) => {
|
||||
from[i] -= obj.inflate
|
||||
})
|
||||
var to = obj.to.slice()
|
||||
to.forEach((v, i) => {
|
||||
to[i] += obj.inflate
|
||||
if (from[i] === to[i]) {
|
||||
to[i] += 0.001
|
||||
}
|
||||
}
|
||||
|
||||
setSize(mesh.geometry)
|
||||
})
|
||||
mesh.geometry.from(from)
|
||||
mesh.geometry.to(to)
|
||||
mesh.geometry.computeBoundingSphere()
|
||||
|
||||
mesh.scale.set(1, 1, 1)
|
||||
@ -1684,7 +1693,7 @@ class CanvasController {
|
||||
frame = 0
|
||||
if (obj[face].texture && obj[face].texture !== null) {
|
||||
var tex = obj[face].getTexture()
|
||||
if (typeof tex === 'object' && tex.constructor.name === 'Texture' && tex.frameCount) {
|
||||
if (tex instanceof Texture && tex.frameCount !== 1) {
|
||||
stretch = tex.frameCount
|
||||
if (animation === true && tex.currentFrame) {
|
||||
frame = tex.currentFrame
|
||||
|
@ -318,6 +318,13 @@ onVueSetup(function() {
|
||||
})
|
||||
var project_vue = new Vue({
|
||||
el: '#project_settings',
|
||||
data: {Project}
|
||||
data: {Project},
|
||||
methods: {
|
||||
syncGeometry: function() {
|
||||
if (Blockbench.entity_mode && Project.name.length > 0 && !Project.geometry_name) {
|
||||
Project.geometry_name = Project.name.toLowerCase().replace(/\s/g, '')
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
125
js/textures.js
125
js/textures.js
@ -9,7 +9,7 @@ class Texture {
|
||||
this.particle = false
|
||||
this.selected = false
|
||||
this.error = false;
|
||||
this.frameCount = 1
|
||||
this.ratio = 1
|
||||
this.show_icon = true
|
||||
this.average_color = {r:0, g:0, b:0}
|
||||
this.dark_box = false
|
||||
@ -43,6 +43,11 @@ class Texture {
|
||||
}
|
||||
}
|
||||
}
|
||||
get frameCount() {
|
||||
if (this.ratio !== 1) {
|
||||
return 1/this.ratio
|
||||
}
|
||||
}
|
||||
getUndoCopy(bitmap) {
|
||||
var copy = {
|
||||
path: this.path,
|
||||
@ -57,17 +62,28 @@ class Texture {
|
||||
old_width: this.old_width,
|
||||
old_height: this.old_height
|
||||
}
|
||||
if (bitmap || this.mode === 'link') {
|
||||
if (bitmap || this.mode === 'bitmap') {
|
||||
copy.source = this.source
|
||||
}
|
||||
return copy
|
||||
}
|
||||
extend(properties) {
|
||||
extend(data) {
|
||||
Merge.string(this, data, 'path')
|
||||
Merge.string(this, data, 'name')
|
||||
Merge.string(this, data, 'folder')
|
||||
Merge.string(this, data, 'namespace')
|
||||
Merge.boolean(this, data, 'particle')
|
||||
Merge.string(this, data, 'mode')
|
||||
Merge.boolean(this, data, 'saved')
|
||||
if (this.mode === 'bitmap') {
|
||||
Merge.string(this, data, 'source')
|
||||
}
|
||||
/*
|
||||
for (var key in properties) {
|
||||
if (properties.hasOwnProperty(key)) {
|
||||
this[key] = properties[key]
|
||||
}
|
||||
}
|
||||
}*/
|
||||
return this;
|
||||
}
|
||||
//Loading
|
||||
@ -79,7 +95,6 @@ class Texture {
|
||||
}
|
||||
this.error = false;
|
||||
this.show_icon = true
|
||||
this.frameCount = 1
|
||||
var img = this.img = new Image()
|
||||
|
||||
if (Canvas.materials[scope.uuid] !== undefined) {
|
||||
@ -117,6 +132,7 @@ class Texture {
|
||||
|
||||
this.tex.needsUpdate = true;
|
||||
scope.res = img.naturalWidth;
|
||||
scope.ratio = img.naturalWidth / img.naturalHeight;
|
||||
|
||||
if (isDefault) {
|
||||
console.log('Successfully loaded '+scope.name+' from default pack')
|
||||
@ -128,7 +144,6 @@ class Texture {
|
||||
//Width / Animation
|
||||
if (img.naturalWidth !== img.naturalHeight && Blockbench.entity_mode === false) {
|
||||
if (img.naturalHeight % img.naturalWidth === 0) {
|
||||
scope.frameCount = img.naturalHeight / img.naturalWidth
|
||||
Canvas.updateAllUVs()
|
||||
BARS.updateConditions()
|
||||
} else {
|
||||
@ -838,21 +853,10 @@ function saveTextures() {
|
||||
}
|
||||
})
|
||||
}
|
||||
function getSelectedTextureIndex() {
|
||||
var index = false
|
||||
textures.forEach(function(s, i) {
|
||||
if (s.selected === true) {
|
||||
index = i
|
||||
}
|
||||
})
|
||||
return index;
|
||||
}
|
||||
function saveTextureMenu() {
|
||||
hideDialog()
|
||||
Undo.initEdit({textures})
|
||||
index = getSelectedTextureIndex()
|
||||
if (index === false) return;
|
||||
var tex = textures[index]
|
||||
var tex = textures.selected
|
||||
tex.name = $('#texture_edit input#te_name').val()
|
||||
tex.id = $('#texture_edit input#te_variable').val()
|
||||
tex.folder = $('#texture_edit input#te_folder').val()
|
||||
@ -873,20 +877,31 @@ function loadTextureDraggable() {
|
||||
if (!t.hasClass('texture')) t = t.parent()
|
||||
return t.find('.texture_icon_wrapper').clone().addClass('texture_drag_helper').attr('texid', t.attr('texid'))
|
||||
},
|
||||
cursorAt: { left: 24, top: 24 },
|
||||
cursorAt: { left: 2, top: -5 },
|
||||
revert: 'invalid',
|
||||
appendTo: 'body',
|
||||
zIndex: 19,
|
||||
distance: 4,
|
||||
drag: function(event, ui) {
|
||||
$('.outliner_node[order]').attr('order', null)
|
||||
var tar = $('#cubes_list li .drag_hover.outliner_node').deepest()
|
||||
var element = TreeElements.findRecursive('uuid', tar.attr('id'))
|
||||
if (element) {
|
||||
tar.attr('order', '0')
|
||||
}
|
||||
},
|
||||
stop: function(event, ui) {
|
||||
setTimeout(function() {
|
||||
if ($('canvas.preview:hover').length > 0) {
|
||||
var data = Canvas.getCurrentPreview().raycast()
|
||||
if (data.cube && data.face) {
|
||||
var tex = textures.findInArray('uuid', ui.helper.attr('texid'));
|
||||
var cubes_list = data.cube.selected ? selected : [data.cube];
|
||||
Undo.initEdit({})
|
||||
if (tex) {
|
||||
data.cube.applyTexture(tex, [data.face])
|
||||
}
|
||||
Undo.finishEdit('apply texture')
|
||||
}
|
||||
}
|
||||
}, 10)
|
||||
@ -948,6 +963,76 @@ function getTexturesById(id) {
|
||||
return $.grep(textures, function(e) {return e.id == id});
|
||||
}
|
||||
|
||||
TextureAnimator = {
|
||||
isPlaying: false,
|
||||
interval: false,
|
||||
start: function() {
|
||||
clearInterval(TextureAnimator.interval)
|
||||
TextureAnimator.isPlaying = true
|
||||
TextureAnimator.updateButton()
|
||||
TextureAnimator.interval = setInterval(TextureAnimator.nextFrame, 1000/settings.texture_fps.value)
|
||||
},
|
||||
stop: function() {
|
||||
TextureAnimator.isPlaying = false
|
||||
clearInterval(TextureAnimator.interval)
|
||||
TextureAnimator.updateButton()
|
||||
},
|
||||
toggle: function() {
|
||||
if (TextureAnimator.isPlaying) {
|
||||
TextureAnimator.stop()
|
||||
} else {
|
||||
TextureAnimator.start()
|
||||
}
|
||||
},
|
||||
updateSpeed: function() {
|
||||
if (TextureAnimator.isPlaying) {
|
||||
TextureAnimator.stop()
|
||||
TextureAnimator.start()
|
||||
}
|
||||
},
|
||||
nextFrame: function() {
|
||||
var animated_tex = []
|
||||
textures.forEach(function(tex, i) {
|
||||
if (tex.frameCount > 1) {
|
||||
if (tex.currentFrame === undefined) {
|
||||
tex.currentFrame = 0
|
||||
} else if (tex.currentFrame >= tex.frameCount-1) {
|
||||
tex.currentFrame = 0
|
||||
} else {
|
||||
tex.currentFrame++;
|
||||
}
|
||||
$($('.texture').get(i)).find('img').css('margin-top', (tex.currentFrame*-48)+'px')
|
||||
animated_tex.push(tex)
|
||||
}
|
||||
})
|
||||
elements.forEach(function(obj) {
|
||||
var update = false
|
||||
for (var face in obj.faces) {
|
||||
update = update || animated_tex.includes(obj.faces[face].getTexture());
|
||||
}
|
||||
if (update) {
|
||||
Canvas.updateUV(obj, true)
|
||||
}
|
||||
})
|
||||
},
|
||||
reset: function() {
|
||||
TextureAnimator.stop()
|
||||
textures.forEach(function(tex, i) {
|
||||
if (tex.frameCount) {
|
||||
tex.currentFrame = 0
|
||||
$($('.texture').get(i)).find('img').css('margin-top', '0')
|
||||
}
|
||||
})
|
||||
while (i < elements.length) {
|
||||
Canvas.updateUV(elements[i], true)
|
||||
i++;
|
||||
}
|
||||
},
|
||||
updateButton: function() {
|
||||
BarItems.animated_textures.setIcon( TextureAnimator.isPlaying ? 'pause' : 'play_arrow' )
|
||||
}
|
||||
}
|
||||
|
||||
onVueSetup(function() {
|
||||
texturelist = new Vue({
|
||||
el: '#texture_list',
|
||||
@ -1018,4 +1103,4 @@ BARS.defineActions(function() {
|
||||
TextureAnimator.toggle()
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -646,7 +646,7 @@ BARS.defineActions(function() {
|
||||
//Inflage
|
||||
new NumSlider({
|
||||
id: 'slider_inflate',
|
||||
condition: function() {return Blockbench.entity_mode && selected.length && Modes.id === 'edit'},
|
||||
condition: function() {return selected.length && Modes.id === 'edit'},
|
||||
get: function() {
|
||||
return selected[0].inflate
|
||||
},
|
||||
|
19
js/undo.js
19
js/undo.js
@ -177,7 +177,7 @@ var Undo = {
|
||||
Canvas.adaptObjectFaces(obj)
|
||||
Canvas.updateUV(obj)
|
||||
} else {
|
||||
obj = new Cube(data, uuid).init(false)
|
||||
obj = new Cube(data, uuid).init()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -269,10 +269,8 @@ var Undo = {
|
||||
|
||||
var animation = Animator.animations.findInArray('uuid', save.animation)
|
||||
if (!animation) {
|
||||
//new
|
||||
animation = new Animation()
|
||||
}
|
||||
//populate
|
||||
Animation.extend(save.animation)
|
||||
|
||||
} else if (reference.animation) {
|
||||
@ -356,6 +354,13 @@ var Undo = {
|
||||
display[slot].extend(data).update()
|
||||
}
|
||||
}
|
||||
if (open_dialog == 'uv_dialog') {
|
||||
for (var key in uv_dialog.editors) {
|
||||
if (uv_dialog.editors[key]) {
|
||||
uv_dialog.editors[key].loadData()
|
||||
}
|
||||
}
|
||||
}
|
||||
updateSelection()
|
||||
}
|
||||
}
|
||||
@ -371,14 +376,18 @@ BARS.defineActions(function() {
|
||||
id: 'undo',
|
||||
icon: 'undo',
|
||||
category: 'edit',
|
||||
condition: () => (!open_dialog || open_dialog === 'uv_dialog'),
|
||||
work_in_dialog: true,
|
||||
keybind: new Keybind({key: 90, ctrl: true}),
|
||||
click: function () {Undo.undo()}
|
||||
click: Undo.undo
|
||||
})
|
||||
new Action({
|
||||
id: 'redo',
|
||||
icon: 'redo',
|
||||
category: 'edit',
|
||||
condition: () => (!open_dialog || open_dialog === 'uv_dialog'),
|
||||
work_in_dialog: true,
|
||||
keybind: new Keybind({key: 89, ctrl: true}),
|
||||
click: function () {Undo.redo()}
|
||||
click: Undo.redo
|
||||
})
|
||||
})
|
20
js/util.js
20
js/util.js
@ -81,6 +81,23 @@ var asyncLoop = function(o){
|
||||
}
|
||||
async_loop();//init
|
||||
}
|
||||
// 1234567890qwertzuiopuasdfghjklyxcvbn
|
||||
//Jquery
|
||||
$.fn.deepest = function() {
|
||||
if (!this.length) return this;
|
||||
var opts = []
|
||||
this.each((i, node) => {
|
||||
var i = 0;
|
||||
var obj = $(node)
|
||||
while (obj.parent().get(0) instanceof HTMLBodyElement === false) {
|
||||
obj = obj.parent()
|
||||
i++;
|
||||
}
|
||||
opts.push({depth: i, o: node})
|
||||
})
|
||||
opts.sort((a, b) => (a.depth < b.depth));
|
||||
return $(opts[0].o)
|
||||
}
|
||||
|
||||
//Math
|
||||
function guid() {
|
||||
@ -92,6 +109,9 @@ function guid() {
|
||||
return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
|
||||
s4() + '-' + s4() + s4() + s4();
|
||||
}
|
||||
function isUUID(s) {
|
||||
return (s.length === 36 && s.match(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/))
|
||||
}
|
||||
function bbuid(l) {
|
||||
l = l || 1
|
||||
let chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
||||
|
25
js/uv.js
25
js/uv.js
@ -226,6 +226,7 @@ class UVEditor {
|
||||
scope.displayMappingOverlay()
|
||||
})
|
||||
this.jquery.size.mouseleave(function() {
|
||||
console.trace('RM')
|
||||
$(this).find('.uv_mapping_overlay').remove()
|
||||
})
|
||||
|
||||
@ -284,6 +285,9 @@ class UVEditor {
|
||||
scope.updateDragHandle(ui.position)
|
||||
if (Blockbench.entity_mode) {
|
||||
scope.displayAllMappingOverlays()
|
||||
if (scope.jquery.size.is(':hover')) {
|
||||
scope.displayMappingOverlay()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -1137,7 +1141,7 @@ class UVEditor {
|
||||
return;
|
||||
}
|
||||
var tag = selected[0].faces[face]
|
||||
var new_tag = new Face().extend(tag)
|
||||
var new_tag = new Face(face, tag)
|
||||
uv_dialog.clipboard.push(new_tag)
|
||||
}
|
||||
if (event.shiftKey) {
|
||||
@ -1180,7 +1184,7 @@ class UVEditor {
|
||||
applyFace(uv_dialog.clipboard[0], main_uv.face)
|
||||
} else {
|
||||
uv_dialog.clipboard.forEach(function(s) {
|
||||
applyFace(s)
|
||||
applyFace(s, s.direction)
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -1556,19 +1560,25 @@ const uv_dialog = {
|
||||
|
||||
function addToClipboard(face) {
|
||||
var tag = selected[0].faces[face]
|
||||
uv_dialog.clipboard.push(new Face(tag))
|
||||
uv_dialog.clipboard.push(new Face(null, tag))
|
||||
}
|
||||
if (uv_dialog.hoveredSide) {
|
||||
addToClipboard(uv_dialog.hoveredSide)
|
||||
uv_dialog.editors[uv_dialog.hoveredSide].message('uv_editor.copied')
|
||||
|
||||
} else if (uv_dialog.single) {
|
||||
addToClipboard(uv_dialog.editors.single.face)
|
||||
uv_dialog.editors.single.message('uv_editor.copied')
|
||||
|
||||
} else if (uv_dialog.selection.length > 0) {
|
||||
uv_dialog.selection.forEach(function(s) {
|
||||
addToClipboard(s)
|
||||
uv_dialog.editors[s].message('uv_editor.copied')
|
||||
})
|
||||
} else {
|
||||
uv_dialog.allFaces.forEach(function(s) {
|
||||
addToClipboard(s)
|
||||
uv_dialog.editors[s].message('uv_editor.copied')
|
||||
})
|
||||
}
|
||||
},
|
||||
@ -1588,15 +1598,22 @@ const uv_dialog = {
|
||||
|
||||
} else if (uv_dialog.selection.length === 1) {
|
||||
applyFace(uv_dialog.clipboard[0], uv_dialog.selection[0])
|
||||
if (uv_dialog.single) {
|
||||
uv_dialog.editors.single.message('uv_editor.pasted')
|
||||
} else {
|
||||
uv_dialog.editors[uv_dialog.selection[0]].message('uv_editor.pasted')
|
||||
}
|
||||
} else {
|
||||
if (uv_dialog.clipboard.length === 1) {
|
||||
uv_dialog.selection.forEach(function(s) {
|
||||
applyFace(uv_dialog.clipboard[0], s)
|
||||
uv_dialog.editors[s].message('uv_editor.pasted')
|
||||
})
|
||||
} else {
|
||||
uv_dialog.clipboard.forEach(function(s) {
|
||||
if (uv_dialog.selection.includes(s.face)) {
|
||||
applyFace(s)
|
||||
uv_dialog.editors[s].message('uv_editor.pasted')
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -1717,9 +1734,7 @@ BARS.defineActions(function() {
|
||||
category: 'uv',
|
||||
condition: () => !Blockbench.entity_mode && selected.length,
|
||||
click: function (event) {
|
||||
Undo.initEdit({cubes: selected, uv_only: true})
|
||||
uv_dialog.forSelection('clear', event)
|
||||
Undo.finishEdit('remove face')
|
||||
}
|
||||
})
|
||||
new Action({
|
||||
|
20
lang/de.json
20
lang/de.json
@ -836,5 +836,23 @@
|
||||
"action.toggle_uv_overlay.desc": "Blendet UV Masken für alle Elemente über der Textur ein",
|
||||
"menu.texture.blank": "Auf leere Flächen anwenden",
|
||||
"dialog.scale.select_overflow": "Überstehendes auswählen",
|
||||
"dialog.create_texture.compress": "Template verdichten"
|
||||
"dialog.create_texture.compress": "Template verdichten",
|
||||
"action.action_control": "Kommandozentrale",
|
||||
"action.action_control.desc": "Suche und benutze jede verfügbare Aktion",
|
||||
"keybindings.recording": "Tastenkombination wird aufgezeichnet",
|
||||
"keybindings.press": "Drücke eine Taste bzw. Tastenkombination oder klicke auf den Bildschirm, um eine Tastenkombination aufzuzeichnen.",
|
||||
"action.pivot_tool": "Drehpunktwerkzeug",
|
||||
"action.pivot_tool.desc": "Werkzeug zum Bearbeiten des Drehpunktes",
|
||||
"action.slider_animation_speed": "Wiedergabegeschwindigkeit",
|
||||
"action.slider_animation_speed.desc": "Wiedergabegeschwindigkeit der Timeline in Prozent",
|
||||
"action.previous_keyframe": "Vorheriger Keyframe",
|
||||
"action.previous_keyframe.desc": "Springe zum vorherigen Keyframe",
|
||||
"action.next_keyframe": "Nächster Keyframe",
|
||||
"action.next_keyframe.desc": "Springe zum nächsten Keyframe",
|
||||
"message.outdated_client.title": "Version veraltet",
|
||||
"message.outdated_client.message": "Bitte update auf die neuste Version von Blockbench",
|
||||
"action.export_bbmodel": "Blockbench-Projekt exportieren",
|
||||
"action.export_bbmodel.desc": "Exportiere ein Blockbench Projekt mit allen Elementen, Texturen und Animationen",
|
||||
"action.export_asset_archive": "ZIP-Ordner herunterladen",
|
||||
"action.export_asset_archive.desc": "Lädt ein Archiv mit dem Modell und allen benötigten Texturen herunter"
|
||||
}
|
21
lang/en.json
21
lang/en.json
@ -80,6 +80,8 @@
|
||||
"message.invalid_file.message": "Could not open json file: %0",
|
||||
"message.invalid_model.title": "Invalid Model File",
|
||||
"message.invalid_model.message": "This file does not contain valid model data.",
|
||||
"message.outdated_client.title": "Outdated client",
|
||||
"message.outdated_client.message": "Please update to the latest version of Blockbench to do this.",
|
||||
"message.child_model_only.title": "Empty Child Model",
|
||||
"message.child_model_only.message": "This file is a child of %0 and does not contain a model.",
|
||||
"message.drag_background.title": "Position Background",
|
||||
@ -263,6 +265,8 @@
|
||||
|
||||
"keybindings.reset": "Reset",
|
||||
"keybindings.clear": "Empty",
|
||||
"keybindings.recording": "Recording Keybinding",
|
||||
"keybindings.press": "Press a key or key combination or click anywhere on the screen to record your keybinding.",
|
||||
|
||||
"layout.color.back": "Back",
|
||||
"layout.color.back.desc": "Backgrounds and input fields",
|
||||
@ -482,6 +486,8 @@
|
||||
"action.resize_tool.desc": "Tool to select and resize elements",
|
||||
"action.rotate_tool": "Rotate",
|
||||
"action.rotate_tool.desc": "Tool to select and rotate elements",
|
||||
"action.pivot_tool": "Pivot Tool",
|
||||
"action.pivot_tool.desc": "Tool to change the pivot point of cubes and bones",
|
||||
"action.brush_tool": "Paint Brush",
|
||||
"action.brush_tool.desc": "Tool to paint on bitmap textures on surfaces or the UV editor",
|
||||
"action.fill_tool": "Paint Bucket",
|
||||
@ -514,6 +520,10 @@
|
||||
"action.extrude_texture.desc": "Generate a model by stretching out a texture",
|
||||
"action.export_blockmodel": "Export Blockmodel",
|
||||
"action.export_blockmodel.desc": "Export a Minecraft block or item model",
|
||||
"action.export_bbmodel": "Export Blockbench Project",
|
||||
"action.export_bbmodel.desc": "Export a Blockbench project with all cubes, textures and animations",
|
||||
"action.export_asset_archive": "Download Archive",
|
||||
"action.export_asset_archive.desc": "Download an archive with the model and all textures in it",
|
||||
"action.export_entity": "Export Bedrock Entity",
|
||||
"action.export_entity.desc": "Add the current model as an entity to a mobs.json file",
|
||||
"action.export_class_entity": "Export Java Entity",
|
||||
@ -534,6 +544,8 @@
|
||||
"action.update_window.desc": "Search for Blockbench updates.",
|
||||
"action.donate": "Donate",
|
||||
"action.donate.desc": "Donate to Blockbench",
|
||||
"action.action_control": "Action Control",
|
||||
"action.action_control.desc": "Search and execute any available action",
|
||||
|
||||
"action.reset_keybindings": "Reset Keybindings",
|
||||
"action.reset_keybindings.desc": "Reset all keybindings to Blockbench's defaults",
|
||||
@ -729,7 +741,7 @@
|
||||
"action.add_animation.desc": "Create a blank animation",
|
||||
"action.load_animation_file": "Import Animations",
|
||||
"action.load_animation_file.desc": "Import an animation file",
|
||||
"action.play_animation": "Play Animations",
|
||||
"action.play_animation": "Play Animation",
|
||||
"action.play_animation.desc": "Preview the selected animation",
|
||||
"action.export_animation_file": "Export Animations",
|
||||
"action.export_animation_file.desc": "Export a json file with the current animations",
|
||||
@ -741,7 +753,12 @@
|
||||
"action.select_all_keyframes.desc": "Select all keyframes of the current bone",
|
||||
"action.delete_keyframes": "Delete Keyframes",
|
||||
"action.delete_keyframes.desc": "Delete all selected keyframes",
|
||||
|
||||
"action.slider_animation_speed": "Playback Speed",
|
||||
"action.slider_animation_speed.desc": "Playback speed of the timeline in percent",
|
||||
"action.previous_keyframe": "Previous Keyframe",
|
||||
"action.previous_keyframe.desc": "Jump to the previous keyframe",
|
||||
"action.next_keyframe": "Next Keyframe",
|
||||
"action.next_keyframe.desc": "Jump to the next keyframe",
|
||||
|
||||
"timeline.rotation": "Rotation",
|
||||
"timeline.position": "Position",
|
||||
|
48
lang/es.json
48
lang/es.json
@ -821,20 +821,38 @@
|
||||
"action.open_backup_folder.desc": "Abre la carpeta de backups de Blockbench",
|
||||
"switches.mirror": "Invertir UV",
|
||||
"language_name": "Inglés",
|
||||
"message.plugin_reload": "Reloaded %0 local plugins",
|
||||
"settings.brightness": "Brightness",
|
||||
"settings.brightness.desc": "Brightness of the preview. Default is 50",
|
||||
"menu.preview.perspective.reset": "Reset Camera",
|
||||
"action.fill_mode": "Fill Mode",
|
||||
"action.fill_mode.desc": "Mode of the fill tool",
|
||||
"action.fill_mode.face": "Face",
|
||||
"message.plugin_reload": "Recargados %0 plugins locales",
|
||||
"settings.brightness": "Brillo",
|
||||
"settings.brightness.desc": "Brillo de la previsualización. Por defecto es 50",
|
||||
"menu.preview.perspective.reset": "Resetear Cámara",
|
||||
"action.fill_mode": "Modo de Llenado",
|
||||
"action.fill_mode.desc": "Modo de la herramienta de llenado",
|
||||
"action.fill_mode.face": "Cara",
|
||||
"action.fill_mode.color": "Color",
|
||||
"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_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",
|
||||
"dialog.scale.select_overflow": "Select Overflow",
|
||||
"dialog.create_texture.compress": "Compress Template"
|
||||
"action.fill_mode.cube": "Cubo",
|
||||
"action.toggle_mirror_uv": "Invertir UV",
|
||||
"action.toggle_mirror_uv.desc": "Activa el invertido de UV en el eje X de los cubos seleccionados",
|
||||
"action.toggle_uv_overlay": "Cambiar Superposición de UV",
|
||||
"action.toggle_uv_overlay.desc": "Cuando está activado, muestra las superposiciones de UV sobre la textura",
|
||||
"menu.texture.blank": "Aplicar a Caras sin Textura",
|
||||
"dialog.scale.select_overflow": "Seleccionar Overflow",
|
||||
"dialog.create_texture.compress": "Comprimir Plantilla",
|
||||
"action.action_control": "Control de Acción",
|
||||
"action.action_control.desc": "Busca y ejecuta cualquier acción disponible",
|
||||
"keybindings.recording": "Anotando Atajo de Teclado",
|
||||
"keybindings.press": "Pulsa una tecla o una combinación de teclas o haz click en cualquier lugar de tu pantalla para anotar el atajo de teclado",
|
||||
"action.pivot_tool": "Herramienta de Pivote",
|
||||
"action.pivot_tool.desc": "Herramienta para cambiar el punto de pivote de cubos y huesos",
|
||||
"action.slider_animation_speed": "Velocidad de Playback",
|
||||
"action.slider_animation_speed.desc": "Velocidad de playback del línea de tiempo en porcentaje",
|
||||
"action.previous_keyframe": "Frame Anterior",
|
||||
"action.previous_keyframe.desc": "Salta al frame anterior",
|
||||
"action.next_keyframe": "Frame Siguiente",
|
||||
"action.next_keyframe.desc": "Salta al frame siguiente",
|
||||
"message.outdated_client.title": "Outdated client",
|
||||
"message.outdated_client.message": "Please update to the latest version of Blockbench to do this.",
|
||||
"action.export_bbmodel": "Export Blockbench Project",
|
||||
"action.export_bbmodel.desc": "Export a Blockbench project with all cubes, textures and animations",
|
||||
"action.export_asset_archive": "Download Archive",
|
||||
"action.export_asset_archive.desc": "Download an archive with the model and all textures in it"
|
||||
}
|
20
lang/fr.json
20
lang/fr.json
@ -836,5 +836,23 @@
|
||||
"action.toggle_uv_overlay.desc": "When enabled, displays all UV mapping overlays above the texture.",
|
||||
"menu.texture.blank": "Apply to Untextured Faces",
|
||||
"dialog.scale.select_overflow": "Select Overflow",
|
||||
"dialog.create_texture.compress": "Compress Template"
|
||||
"dialog.create_texture.compress": "Compress Template",
|
||||
"action.action_control": "Action Control",
|
||||
"action.action_control.desc": "Search and execute any available action",
|
||||
"keybindings.recording": "Recording Keybinding",
|
||||
"keybindings.press": "Press a key or key combination or click anywhere on the screen to record your keybinding.",
|
||||
"action.pivot_tool": "Pivot Tool",
|
||||
"action.pivot_tool.desc": "Tool to change the pivot point of cubes and bones",
|
||||
"action.slider_animation_speed": "Playback Speed",
|
||||
"action.slider_animation_speed.desc": "Playback speed of the timeline in percent",
|
||||
"action.previous_keyframe": "Previous Keyframe",
|
||||
"action.previous_keyframe.desc": "Jump to the previous keyframe",
|
||||
"action.next_keyframe": "Next Keyframe",
|
||||
"action.next_keyframe.desc": "Jump to the next keyframe",
|
||||
"message.outdated_client.title": "Outdated client",
|
||||
"message.outdated_client.message": "Please update to the latest version of Blockbench to do this.",
|
||||
"action.export_bbmodel": "Export Blockbench Project",
|
||||
"action.export_bbmodel.desc": "Export a Blockbench project with all cubes, textures and animations",
|
||||
"action.export_asset_archive": "Download Archive",
|
||||
"action.export_asset_archive.desc": "Download an archive with the model and all textures in it"
|
||||
}
|
38
lang/ja.json
38
lang/ja.json
@ -822,19 +822,37 @@
|
||||
"switches.mirror": "ミラーUV",
|
||||
"language_name": "English",
|
||||
"message.plugin_reload": "Reloaded %0 local plugins",
|
||||
"settings.brightness": "Brightness",
|
||||
"settings.brightness": "輝度",
|
||||
"settings.brightness.desc": "Brightness of the preview. Default is 50",
|
||||
"menu.preview.perspective.reset": "Reset Camera",
|
||||
"action.fill_mode": "Fill Mode",
|
||||
"action.fill_mode.desc": "Mode of the fill tool",
|
||||
"action.fill_mode.face": "Face",
|
||||
"action.fill_mode.color": "Color",
|
||||
"action.fill_mode.cube": "Cube",
|
||||
"action.toggle_mirror_uv": "Mirror UV",
|
||||
"menu.preview.perspective.reset": "カメラをリセット",
|
||||
"action.fill_mode": "塗りつぶし",
|
||||
"action.fill_mode.desc": "塗りつぶしモード",
|
||||
"action.fill_mode.face": "面",
|
||||
"action.fill_mode.color": "カラー",
|
||||
"action.fill_mode.cube": "キューブ",
|
||||
"action.toggle_mirror_uv": "ミラーUV",
|
||||
"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",
|
||||
"menu.texture.blank": "テクスチャのない面に適用",
|
||||
"dialog.scale.select_overflow": "Select Overflow",
|
||||
"dialog.create_texture.compress": "Compress Template"
|
||||
"dialog.create_texture.compress": "Compress Template",
|
||||
"action.action_control": "Action Control",
|
||||
"action.action_control.desc": "Search and execute any available action",
|
||||
"keybindings.recording": "Recording Keybinding",
|
||||
"keybindings.press": "Press a key or key combination or click anywhere on the screen to record your keybinding.",
|
||||
"action.pivot_tool": "Pivot Tool",
|
||||
"action.pivot_tool.desc": "Tool to change the pivot point of cubes and bones",
|
||||
"action.slider_animation_speed": "Playback Speed",
|
||||
"action.slider_animation_speed.desc": "Playback speed of the timeline in percent",
|
||||
"action.previous_keyframe": "Previous Keyframe",
|
||||
"action.previous_keyframe.desc": "Jump to the previous keyframe",
|
||||
"action.next_keyframe": "Next Keyframe",
|
||||
"action.next_keyframe.desc": "Jump to the next keyframe",
|
||||
"message.outdated_client.title": "Outdated client",
|
||||
"message.outdated_client.message": "Please update to the latest version of Blockbench to do this.",
|
||||
"action.export_bbmodel": "Export Blockbench Project",
|
||||
"action.export_bbmodel.desc": "Export a Blockbench project with all cubes, textures and animations",
|
||||
"action.export_asset_archive": "Download Archive",
|
||||
"action.export_asset_archive.desc": "Download an archive with the model and all textures in it"
|
||||
}
|
20
lang/nl.json
20
lang/nl.json
@ -836,5 +836,23 @@
|
||||
"action.toggle_uv_overlay.desc": "When enabled, displays all UV mapping overlays above the texture.",
|
||||
"menu.texture.blank": "Apply to Untextured Faces",
|
||||
"dialog.scale.select_overflow": "Select Overflow",
|
||||
"dialog.create_texture.compress": "Compress Template"
|
||||
"dialog.create_texture.compress": "Compress Template",
|
||||
"action.action_control": "Action Control",
|
||||
"action.action_control.desc": "Search and execute any available action",
|
||||
"keybindings.recording": "Recording Keybinding",
|
||||
"keybindings.press": "Press a key or key combination or click anywhere on the screen to record your keybinding.",
|
||||
"action.pivot_tool": "Pivot Tool",
|
||||
"action.pivot_tool.desc": "Tool to change the pivot point of cubes and bones",
|
||||
"action.slider_animation_speed": "Playback Speed",
|
||||
"action.slider_animation_speed.desc": "Playback speed of the timeline in percent",
|
||||
"action.previous_keyframe": "Previous Keyframe",
|
||||
"action.previous_keyframe.desc": "Jump to the previous keyframe",
|
||||
"action.next_keyframe": "Next Keyframe",
|
||||
"action.next_keyframe.desc": "Jump to the next keyframe",
|
||||
"message.outdated_client.title": "Outdated client",
|
||||
"message.outdated_client.message": "Please update to the latest version of Blockbench to do this.",
|
||||
"action.export_bbmodel": "Export Blockbench Project",
|
||||
"action.export_bbmodel.desc": "Export a Blockbench project with all cubes, textures and animations",
|
||||
"action.export_asset_archive": "Download Archive",
|
||||
"action.export_asset_archive.desc": "Download an archive with the model and all textures in it"
|
||||
}
|
20
lang/pl.json
20
lang/pl.json
@ -836,5 +836,23 @@
|
||||
"action.toggle_uv_overlay.desc": "When enabled, displays all UV mapping overlays above the texture.",
|
||||
"menu.texture.blank": "Apply to Untextured Faces",
|
||||
"dialog.scale.select_overflow": "Select Overflow",
|
||||
"dialog.create_texture.compress": "Compress Template"
|
||||
"dialog.create_texture.compress": "Compress Template",
|
||||
"action.action_control": "Action Control",
|
||||
"action.action_control.desc": "Search and execute any available action",
|
||||
"keybindings.recording": "Recording Keybinding",
|
||||
"keybindings.press": "Press a key or key combination or click anywhere on the screen to record your keybinding.",
|
||||
"action.pivot_tool": "Pivot Tool",
|
||||
"action.pivot_tool.desc": "Tool to change the pivot point of cubes and bones",
|
||||
"action.slider_animation_speed": "Playback Speed",
|
||||
"action.slider_animation_speed.desc": "Playback speed of the timeline in percent",
|
||||
"action.previous_keyframe": "Previous Keyframe",
|
||||
"action.previous_keyframe.desc": "Jump to the previous keyframe",
|
||||
"action.next_keyframe": "Next Keyframe",
|
||||
"action.next_keyframe.desc": "Jump to the next keyframe",
|
||||
"message.outdated_client.title": "Outdated client",
|
||||
"message.outdated_client.message": "Please update to the latest version of Blockbench to do this.",
|
||||
"action.export_bbmodel": "Export Blockbench Project",
|
||||
"action.export_bbmodel.desc": "Export a Blockbench project with all cubes, textures and animations",
|
||||
"action.export_asset_archive": "Download Archive",
|
||||
"action.export_asset_archive.desc": "Download an archive with the model and all textures in it"
|
||||
}
|
36
lang/ru.json
36
lang/ru.json
@ -815,26 +815,44 @@
|
||||
"action.fill_tool.desc": "Paint bucket to fill entire faces with one color",
|
||||
"action.eraser": "Ластик",
|
||||
"action.eraser.desc": "Eraser tool to replace colors on a texture with transparency",
|
||||
"action.color_picker": "Color Picker",
|
||||
"action.color_picker": "Выбор цвета",
|
||||
"action.color_picker.desc": "Tool to pick the color of pixels on your texture",
|
||||
"action.open_backup_folder": "Открыть папку автосохранений",
|
||||
"action.open_backup_folder.desc": "Opens the Blockbench backup folder",
|
||||
"switches.mirror": "Mirror UV",
|
||||
"language_name": "English",
|
||||
"message.plugin_reload": "Reloaded %0 local plugins",
|
||||
"settings.brightness": "Brightness",
|
||||
"language_name": "Английский",
|
||||
"message.plugin_reload": "Перезагружено %0 локальных плагинов",
|
||||
"settings.brightness": "Яркость",
|
||||
"settings.brightness.desc": "Brightness of the preview. Default is 50",
|
||||
"menu.preview.perspective.reset": "Reset Camera",
|
||||
"action.fill_mode": "Fill Mode",
|
||||
"action.fill_mode": "Режим заполнения",
|
||||
"action.fill_mode.desc": "Mode of the fill tool",
|
||||
"action.fill_mode.face": "Face",
|
||||
"action.fill_mode.color": "Color",
|
||||
"action.fill_mode.cube": "Cube",
|
||||
"action.fill_mode.face": "Грань",
|
||||
"action.fill_mode.color": "Цвет",
|
||||
"action.fill_mode.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_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",
|
||||
"dialog.scale.select_overflow": "Select Overflow",
|
||||
"dialog.create_texture.compress": "Compress Template"
|
||||
"dialog.create_texture.compress": "Сжать шаблон",
|
||||
"action.action_control": "Контроль действий",
|
||||
"action.action_control.desc": "Search and execute any available action",
|
||||
"keybindings.recording": "Recording Keybinding",
|
||||
"keybindings.press": "Press a key or key combination or click anywhere on the screen to record your keybinding.",
|
||||
"action.pivot_tool": "Pivot Tool",
|
||||
"action.pivot_tool.desc": "Tool to change the pivot point of cubes and bones",
|
||||
"action.slider_animation_speed": "Скорость воспроизведения",
|
||||
"action.slider_animation_speed.desc": "Playback speed of the timeline in percent",
|
||||
"action.previous_keyframe": "Предыдущий кадр",
|
||||
"action.previous_keyframe.desc": "Jump to the previous keyframe",
|
||||
"action.next_keyframe": "Следующий кадр",
|
||||
"action.next_keyframe.desc": "Jump to the next keyframe",
|
||||
"message.outdated_client.title": "Outdated client",
|
||||
"message.outdated_client.message": "Please update to the latest version of Blockbench to do this.",
|
||||
"action.export_bbmodel": "Export Blockbench Project",
|
||||
"action.export_bbmodel.desc": "Export a Blockbench project with all cubes, textures and animations",
|
||||
"action.export_asset_archive": "Download Archive",
|
||||
"action.export_asset_archive.desc": "Download an archive with the model and all textures in it"
|
||||
}
|
20
lang/sv.json
20
lang/sv.json
@ -836,5 +836,23 @@
|
||||
"action.toggle_uv_overlay.desc": "When enabled, displays all UV mapping overlays above the texture.",
|
||||
"menu.texture.blank": "Apply to Untextured Faces",
|
||||
"dialog.scale.select_overflow": "Select Overflow",
|
||||
"dialog.create_texture.compress": "Compress Template"
|
||||
"dialog.create_texture.compress": "Compress Template",
|
||||
"action.action_control": "Action Control",
|
||||
"action.action_control.desc": "Search and execute any available action",
|
||||
"keybindings.recording": "Recording Keybinding",
|
||||
"keybindings.press": "Press a key or key combination or click anywhere on the screen to record your keybinding.",
|
||||
"action.pivot_tool": "Pivot Tool",
|
||||
"action.pivot_tool.desc": "Tool to change the pivot point of cubes and bones",
|
||||
"action.slider_animation_speed": "Playback Speed",
|
||||
"action.slider_animation_speed.desc": "Playback speed of the timeline in percent",
|
||||
"action.previous_keyframe": "Previous Keyframe",
|
||||
"action.previous_keyframe.desc": "Jump to the previous keyframe",
|
||||
"action.next_keyframe": "Next Keyframe",
|
||||
"action.next_keyframe.desc": "Jump to the next keyframe",
|
||||
"message.outdated_client.title": "Outdated client",
|
||||
"message.outdated_client.message": "Please update to the latest version of Blockbench to do this.",
|
||||
"action.export_bbmodel": "Export Blockbench Project",
|
||||
"action.export_bbmodel.desc": "Export a Blockbench project with all cubes, textures and animations",
|
||||
"action.export_asset_archive": "Download Archive",
|
||||
"action.export_asset_archive.desc": "Download an archive with the model and all textures in it"
|
||||
}
|
92
lang/zh.json
92
lang/zh.json
@ -1,5 +1,5 @@
|
||||
{
|
||||
"dialog.ok": "确认",
|
||||
"dialog.ok": "确定",
|
||||
"dialog.cancel": "取消",
|
||||
"dialog.confirm": "确认",
|
||||
"dialog.close": "关闭",
|
||||
@ -228,8 +228,8 @@
|
||||
"settings.shading.desc": "启用阴影",
|
||||
"settings.transparency": "透明度",
|
||||
"settings.transparency.desc": "渲染贴图的透明部分",
|
||||
"settings.texture_fps": "动态贴图 FPS",
|
||||
"settings.texture_fps.desc": "动态贴图的帧数",
|
||||
"settings.texture_fps": "动画贴图 FPS",
|
||||
"settings.texture_fps.desc": "动画贴图的帧数",
|
||||
"settings.base_grid": "小网格",
|
||||
"settings.base_grid.desc": "显示小网格和轴",
|
||||
"settings.large_grid": "大网格",
|
||||
@ -516,7 +516,7 @@
|
||||
"menu.edit": "编辑",
|
||||
"menu.transform": "模型控制",
|
||||
"menu.filter": "插件目录",
|
||||
"menu.display": "物品显示",
|
||||
"menu.display": "显示",
|
||||
"menu.view": "视图",
|
||||
"menu.file.new": "新建",
|
||||
"menu.file.recent": "最近",
|
||||
@ -590,12 +590,12 @@
|
||||
"uv_editor.title": "UV 编辑器",
|
||||
"uv_editor.all_faces": "全部",
|
||||
"uv_editor.no_faces": "无",
|
||||
"face.north": "北/-X面",
|
||||
"face.south": "南/X面",
|
||||
"face.west": "西/-Y面",
|
||||
"face.east": "东/Y面",
|
||||
"face.up": "上/Z面",
|
||||
"face.down": "下/-Z面",
|
||||
"face.north": "北面/-x",
|
||||
"face.south": "南面/+x",
|
||||
"face.west": "西面/-y",
|
||||
"face.east": "东面/+y",
|
||||
"face.up": "顶面/+z",
|
||||
"face.down": "底面/-z",
|
||||
"direction.north": "北",
|
||||
"direction.south": "南",
|
||||
"direction.west": "西",
|
||||
@ -606,7 +606,7 @@
|
||||
"display.slot.third_left": "第三人称左手",
|
||||
"display.slot.first_right": "第一人称右手",
|
||||
"display.slot.first_left": "第一人称左手",
|
||||
"display.slot.head": "头",
|
||||
"display.slot.head": "头上",
|
||||
"display.slot.ground": "地面",
|
||||
"display.slot.frame": "展示框",
|
||||
"display.slot.gui": "GUI",
|
||||
@ -642,7 +642,7 @@
|
||||
"dialog.update.installed": "已安装的版本",
|
||||
"dialog.update.update": "更新",
|
||||
"action.brush_mode.brush": "笔刷",
|
||||
"action.brush_mode.noise": "像素点",
|
||||
"action.brush_mode.noise": "噪点",
|
||||
"action.vertex_snap_mode.move": "移动",
|
||||
"action.vertex_snap_mode.scale": "规模",
|
||||
"action.open_model_folder": "打开模型文件夹",
|
||||
@ -702,13 +702,13 @@
|
||||
"uv_editor.maximized": "最大化",
|
||||
"uv_editor.autouv": "尺寸自动",
|
||||
"uv_editor.mirrored": "镜像",
|
||||
"uv_editor.to_all": "适用于所有的面",
|
||||
"uv_editor.to_all": "已适用于所有面",
|
||||
"uv_editor.transparent": "设置透明度",
|
||||
"uv_editor.cullface_on": "开启面剔除",
|
||||
"uv_editor.cullface_off": "关闭面剔除",
|
||||
"uv_editor.tint_on": "开启着色",
|
||||
"uv_editor.tint_off": "关闭着色",
|
||||
"action.uv_apply_all": "适用于所有的面",
|
||||
"action.uv_apply_all": "适用于所有面",
|
||||
"action.uv_apply_all.desc": "将当前面的设置应用于所有面",
|
||||
"message.convert_mode.title": "模型转换",
|
||||
"message.convert_mode.message": "您确定要将此类型转换为 %0 吗?您无法撤消此步骤",
|
||||
@ -737,13 +737,13 @@
|
||||
"action.move_back.desc": "相对于当前摄像机角度向后移动选定的立方体",
|
||||
"layout.color.wireframe": "线框",
|
||||
"layout.color.wireframe.desc": "线框模式中的线",
|
||||
"action.add_animation": "添加动态",
|
||||
"action.add_animation": "添加动画",
|
||||
"action.add_animation.desc": "创建一个空白动画",
|
||||
"action.load_animation_file": "导入动态文件",
|
||||
"action.load_animation_file": "导入动画文件",
|
||||
"action.load_animation_file.desc": "导入动画文件",
|
||||
"action.play_animation": "播放动态",
|
||||
"action.play_animation": "播放动画",
|
||||
"action.play_animation.desc": "预览所选的动画",
|
||||
"action.export_animation_file": "导出动态文件",
|
||||
"action.export_animation_file": "导出动画文件",
|
||||
"action.export_animation_file.desc": "导出当前动画的JSON文件",
|
||||
"action.slider_keyframe_time": "时间码",
|
||||
"action.slider_keyframe_time.desc": "修改选定关键帧的时间码",
|
||||
@ -752,7 +752,7 @@
|
||||
"timeline.scale": "放大",
|
||||
"menu.timeline.add": "添加关键帧",
|
||||
"menu.keyframe.quaternion": "四元数",
|
||||
"panel.animations": "动态",
|
||||
"panel.animations": "动画",
|
||||
"panel.keyframe": "关键帧",
|
||||
"panel.keyframe.type": "关键帧(%0)",
|
||||
"generic.delete": "删除",
|
||||
@ -772,7 +772,7 @@
|
||||
"menu.animation.override": "覆盖",
|
||||
"menu.animation.anim_time_update": "更新变量",
|
||||
"message.display_skin_model.title": "皮肤模型",
|
||||
"message.display_skin_model.message": "选择你的皮肤的模型类型",
|
||||
"message.display_skin_model.message": "选择皮肤模型的类型",
|
||||
"message.display_skin_model.classic": "经典\nSteve",
|
||||
"message.display_skin_model.slim": "瘦小\nAlex",
|
||||
"message.bone_material": "改变骨骼材料",
|
||||
@ -820,21 +820,39 @@
|
||||
"action.open_backup_folder": "打开备份文件夹",
|
||||
"action.open_backup_folder.desc": "打开Blockbench备份文件夹",
|
||||
"switches.mirror": "镜像 UV",
|
||||
"language_name": "中文",
|
||||
"message.plugin_reload": "Reloaded %0 local plugins",
|
||||
"settings.brightness": "Brightness",
|
||||
"settings.brightness.desc": "Brightness of the preview. Default is 50",
|
||||
"menu.preview.perspective.reset": "Reset Camera",
|
||||
"action.fill_mode": "Fill Mode",
|
||||
"action.fill_mode.desc": "Mode of the fill tool",
|
||||
"action.fill_mode.face": "Face",
|
||||
"action.fill_mode.color": "Color",
|
||||
"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_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",
|
||||
"dialog.scale.select_overflow": "Select Overflow",
|
||||
"dialog.create_texture.compress": "Compress Template"
|
||||
"language_name": "简体中文",
|
||||
"message.plugin_reload": "重新加载 %0 个本地插件",
|
||||
"settings.brightness": "亮度",
|
||||
"settings.brightness.desc": "预览的亮度,默认值为50",
|
||||
"menu.preview.perspective.reset": "重置相机位置",
|
||||
"action.fill_mode": "填充模式",
|
||||
"action.fill_mode.desc": "填充工具的模式",
|
||||
"action.fill_mode.face": "面",
|
||||
"action.fill_mode.color": "颜色",
|
||||
"action.fill_mode.cube": "立方体",
|
||||
"action.toggle_mirror_uv": "镜面 UV",
|
||||
"action.toggle_mirror_uv.desc": "在所选立方体的X轴上切换UV镜像",
|
||||
"action.toggle_uv_overlay": "切换UV覆盖",
|
||||
"action.toggle_uv_overlay.desc": "启用后,将在纹理上方显示所有UV贴图叠加层",
|
||||
"menu.texture.blank": "适用于无纹理面",
|
||||
"dialog.scale.select_overflow": "选择溢出",
|
||||
"dialog.create_texture.compress": "压缩模板",
|
||||
"action.action_control": "动作控制",
|
||||
"action.action_control.desc": "搜索并且执行任何可用的操作",
|
||||
"keybindings.recording": "Recording Keybinding",
|
||||
"keybindings.press": "Press a key or key combination or click anywhere on the screen to record your keybinding.",
|
||||
"action.pivot_tool": "Pivot Tool",
|
||||
"action.pivot_tool.desc": "Tool to change the pivot point of cubes and bones",
|
||||
"action.slider_animation_speed": "Playback Speed",
|
||||
"action.slider_animation_speed.desc": "Playback speed of the timeline in percent",
|
||||
"action.previous_keyframe": "Previous Keyframe",
|
||||
"action.previous_keyframe.desc": "Jump to the previous keyframe",
|
||||
"action.next_keyframe": "Next Keyframe",
|
||||
"action.next_keyframe.desc": "Jump to the next keyframe",
|
||||
"message.outdated_client.title": "Outdated client",
|
||||
"message.outdated_client.message": "Please update to the latest version of Blockbench to do this.",
|
||||
"action.export_bbmodel": "Export Blockbench Project",
|
||||
"action.export_bbmodel.desc": "Export a Blockbench project with all cubes, textures and animations",
|
||||
"action.export_asset_archive": "Download Archive",
|
||||
"action.export_asset_archive.desc": "Download an archive with the model and all textures in it"
|
||||
}
|
15
lib/jszip.min.js
vendored
Normal file
15
lib/jszip.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
6
main.js
6
main.js
@ -5,7 +5,7 @@ const url = require('url')
|
||||
let orig_win;
|
||||
|
||||
function createWindow() {
|
||||
if (!app.requestSingleInstanceLock()) {
|
||||
if (app.requestSingleInstanceLock && !app.requestSingleInstanceLock()) {
|
||||
return;
|
||||
}
|
||||
let win = new BrowserWindow({
|
||||
@ -83,7 +83,7 @@ app.on('window-all-closed', () => {
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
if (win === null) {
|
||||
/*if (win === null) {
|
||||
createWindow()
|
||||
}
|
||||
}*/
|
||||
})
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "Blockbench",
|
||||
"description": "Minecraft Block Model Editor",
|
||||
"version": "2.4.0",
|
||||
"version": "2.5.0",
|
||||
"license": "MIT",
|
||||
"author": {
|
||||
"name": "JannisX11",
|
||||
@ -77,7 +77,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"async": "^2.4.1",
|
||||
"electron": "4.0.1",
|
||||
"electron": "4.0.3",
|
||||
"electron-builder": "^20.38.4"
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user