mirror of
https://github.com/JannisX11/blockbench.git
synced 2025-03-19 17:01:55 +08:00
v2.3.0
This commit is contained in:
parent
a72d09e872
commit
5e2b5a9e1e
@ -490,7 +490,7 @@
|
||||
}
|
||||
li.menu_bar_point {
|
||||
font-size: 1.1em;
|
||||
padding: 16px;
|
||||
padding: 12px;
|
||||
padding-top: 2px;
|
||||
padding-bottom: 0;
|
||||
float: left;
|
||||
@ -532,6 +532,25 @@
|
||||
}
|
||||
}
|
||||
|
||||
#mode_selector {
|
||||
float: right;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
#mode_selector li {
|
||||
display: inline-block;
|
||||
height: 32px;
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
overflow: hidden;
|
||||
padding-top: 2px;
|
||||
}
|
||||
#mode_selector li:hover {
|
||||
color: var(--color-light);
|
||||
}
|
||||
#mode_selector li.selected {
|
||||
border-bottom: 4px solid var(--color-accent);
|
||||
}
|
||||
|
||||
/*Actions*/
|
||||
.toolbar {
|
||||
width: 100%;
|
||||
@ -599,9 +618,6 @@
|
||||
grid-area: right_bar;
|
||||
}
|
||||
|
||||
|
||||
.panel {
|
||||
}
|
||||
.panel.grow {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
@ -613,7 +629,6 @@
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
|
||||
h3.panel_handle {
|
||||
width: calc(100% - 6px);
|
||||
height: auto;
|
||||
@ -621,7 +636,7 @@
|
||||
padding: 6px;
|
||||
background: var(--color-ui);
|
||||
}
|
||||
.panel > p {
|
||||
.panel p {
|
||||
margin-left: 12px;
|
||||
}
|
||||
body > h3.panel_handle {
|
||||
@ -629,7 +644,6 @@
|
||||
width: auto;
|
||||
}
|
||||
|
||||
|
||||
div#preview {
|
||||
grid-area: preview;
|
||||
background: var(--color-dark);
|
||||
@ -886,6 +900,7 @@
|
||||
#cubes_list > div.vue-tree > ul > li > *:not(ul) {
|
||||
display: none;
|
||||
}
|
||||
/*
|
||||
#cubes_list > div > ul > li > ul > li > ul > li > div {
|
||||
padding-left: 20px;
|
||||
}
|
||||
@ -904,6 +919,7 @@
|
||||
#cubes_list > div > ul > li > ul > li > ul > li > ul > li > ul > li > ul > li > ul > li > ul li > div {
|
||||
padding-left: 120px;
|
||||
}
|
||||
*/
|
||||
.outliner_object i.fa {
|
||||
text-align: center;
|
||||
width: 18px;
|
||||
@ -1254,6 +1270,7 @@
|
||||
background-color: var(--color-back);
|
||||
padding: 3px;
|
||||
padding-left: 8px;
|
||||
overflow: hidden;
|
||||
}
|
||||
#timeline_head > .channel_head {
|
||||
height: 31px;
|
||||
@ -2178,12 +2195,13 @@
|
||||
/*Status Bar*/
|
||||
|
||||
#status_bar {
|
||||
background: var(--color-back);
|
||||
position: relative;
|
||||
padding: 2px;
|
||||
padding-top: 0;
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
font-size: 0.92em;
|
||||
background: var(--color-back);
|
||||
border: 1px solid var(--color-border);
|
||||
}
|
||||
#status_bar > div {
|
||||
@ -2194,6 +2212,13 @@
|
||||
#status_bar > div#status_fps {
|
||||
float: right;
|
||||
}
|
||||
#status_bar #status_progress {
|
||||
position: absolute;
|
||||
height: 4px;
|
||||
background: var(--color-accent);
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
/*Entity Mode*/
|
||||
|
||||
|
112
index.html
112
index.html
@ -13,7 +13,9 @@
|
||||
<style type="text/css" id="bbstyle"></style>
|
||||
</head>
|
||||
<body spellcheck="false">
|
||||
<div id="loading_error_message" style="display: none;">An error occurred while loading Blockbench</div>
|
||||
<div id="loading_error_message" style="display: none;">An error occurred while loading Blockbench
|
||||
<button onclick="Blockbench.reload()" class="large" style="display: block; margin-right: auto; margin-left: auto;">Reload</button>
|
||||
</div>
|
||||
<script>
|
||||
if (typeof module === 'object') {window.module = module; module = undefined;}//jQuery Fix
|
||||
var isApp = typeof require !== 'undefined'
|
||||
@ -28,6 +30,7 @@
|
||||
<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>
|
||||
@ -36,6 +39,7 @@
|
||||
<script src="js/util.js"></script>
|
||||
<script src="js/keyboard.js"></script>
|
||||
<script src="js/settings.js"></script>
|
||||
<script src="js/actions.js"></script>
|
||||
<script src="js/blockbench.js"></script>
|
||||
<script src="js/undo.js"></script>
|
||||
|
||||
@ -48,7 +52,6 @@
|
||||
</script>
|
||||
|
||||
<script src="js/api.js"></script>
|
||||
<script src="js/actions.js"></script>
|
||||
<script src="js/io.js"></script>
|
||||
<script src="js/elements.js"></script>
|
||||
<script src="js/preview.js"></script>
|
||||
@ -63,8 +66,6 @@
|
||||
<script src="js/plugin_loader.js"></script>
|
||||
<script>if (window.module) module = window.module;</script>
|
||||
|
||||
<div id="post_model" class="web_only post_data" hidden></div>
|
||||
<div id="post_textures" class="web_only post_data" hidden></div>
|
||||
<div style="display: none;"></div>
|
||||
|
||||
|
||||
@ -297,55 +298,44 @@
|
||||
<div class="dialog draggable paddinged" id="create_preset">
|
||||
<h2 class="dialog_handle tl">dialog.display_preset.title</h2>
|
||||
<div class="dialog_bar tl">dialog.display_preset.message</div>
|
||||
|
||||
<div class="dialog_bar">
|
||||
<input type="checkbox" id="thirdperson_righthand_save" checked>
|
||||
<label for="thirdperson_righthand_save" class="tl">display.slot.third_right</label>
|
||||
</div>
|
||||
|
||||
<div class="dialog_bar">
|
||||
<input type="checkbox" id="thirdperson_lefthand_save" checked>
|
||||
<label for="thirdperson_lefthand_save" class="tl">display.slot.third_left</label>
|
||||
</div>
|
||||
|
||||
<div class="dialog_bar">
|
||||
<input type="checkbox" id="firstperson_righthand_save" checked>
|
||||
<label for="firstperson_righthand_save" class="tl">display.slot.first_right</label>
|
||||
</div>
|
||||
|
||||
<div class="dialog_bar">
|
||||
<input type="checkbox" id="firstperson_lefthand_save" checked>
|
||||
<label for="firstperson_lefthand_save" class="tl">display.slot.first_left</label>
|
||||
</div>
|
||||
|
||||
<div class="dialog_bar">
|
||||
<input type="checkbox" id="head_save" checked>
|
||||
<label for="head_save" class="tl">display.slot.head</label>
|
||||
</div>
|
||||
|
||||
<div class="dialog_bar">
|
||||
<input type="checkbox" id="ground_save" checked>
|
||||
<label for="ground_save" class="tl">display.slot.ground</label>
|
||||
</div>
|
||||
|
||||
<div class="dialog_bar">
|
||||
<input type="checkbox" id="fixed_save" checked>
|
||||
<label for="fixed_save" class="tl">display.slot.frame</label>
|
||||
</div>
|
||||
|
||||
<div class="dialog_bar">
|
||||
<input type="checkbox" id="gui_save" checked>
|
||||
<label for="gui_save" class="tl">display.slot.gui</label>
|
||||
</div>
|
||||
|
||||
<div class="dialog_bar narrow">
|
||||
<label class="tl">display.presetname</label>
|
||||
</div>
|
||||
|
||||
<div class="dialog_bar">
|
||||
<input type="text" id="preset_name" class="input_wide" id="new preset">
|
||||
</div>
|
||||
|
||||
<div class="dialog_bar">
|
||||
<button type="button" class="large tl confirm_btn" onclick="DisplayMode.createPreset()">dialog.display_preset.create</button>
|
||||
<button type="button" class="large tl cancel_btn" onclick="hideDialog()">dialog.cancel</button>
|
||||
@ -444,9 +434,9 @@
|
||||
</h3>
|
||||
<ul v-if="category.open">
|
||||
|
||||
<li v-for="(setting, key) in category.items" v-on="setting.click ? {click: setting.click} : {}">
|
||||
<li v-for="(setting, key) in category.items" v-if="Condition(setting.condition)" v-on="setting.click ? {click: setting.click} : {}">
|
||||
<template v-if="setting.type === 'number'">
|
||||
<div class="setting_element"><input type="number" v-model="setting.value" v-on:input="saveSettings()"></div>
|
||||
<div class="setting_element"><input type="number" v-model.number="setting.value" v-on:input="saveSettings()"></div>
|
||||
</template>
|
||||
<template v-else-if="setting.type === 'click'">
|
||||
<div class="setting_element" v-html="Blockbench.getIconNode(setting.icon).outerHTML"></div>
|
||||
@ -699,6 +689,14 @@
|
||||
<ul id="menu_bar"></ul>
|
||||
<div class="toolbar_wrapper narrow tools"></div>
|
||||
<div class="toolbar_wrapper narrow tool_options"></div>
|
||||
<div id="mode_selector">
|
||||
<li
|
||||
v-for="mode in options"
|
||||
v-if="Condition(mode.condition)"
|
||||
v-bind:class="{selected: mode.selected}"
|
||||
v-on:click="mode.select()"
|
||||
>{{ mode.name }}</li>
|
||||
</div>
|
||||
</header>
|
||||
<div id="left_bar" class="sidebar">
|
||||
<div id="uv" class="panel selection_only">
|
||||
@ -754,55 +752,36 @@
|
||||
<div id="display_ref_bar" class="bar tabs_small reference_model_bar">
|
||||
</div>
|
||||
|
||||
<p class="tl">display.rotation</p><div class="tool head_right" onclick="DisplayMode.resetDisplaySettings('rotation')"><i class="material-icons">replay</i></div>
|
||||
<div class="bar">
|
||||
<input type="range" class="tool disp_range" id="rotation_x" name="" min="-180" max="180" step="1" value="0" oninput="DisplayMode.syncDispInput(this, 'rotation', 'x')">
|
||||
<input type="number" class="tool disp_text" id="rotation_x" oninput="DisplayMode.syncDispInput(this, 'rotation', 'x')" min="-180" max="180" step="0.5" value="0">
|
||||
</div>
|
||||
<div class="bar">
|
||||
<input type="range" class="tool disp_range" id="rotation_y" name="" min="-180" max="180" step="1" value="0" oninput="DisplayMode.syncDispInput(this, 'rotation', 'y')">
|
||||
<input type="number" class="tool disp_text" id="rotation_y" oninput="DisplayMode.syncDispInput(this, 'rotation', 'y')" min="-180" max="180" step="0.5" value="0">
|
||||
</div>
|
||||
<div class="bar">
|
||||
<input type="range" class="tool disp_range" id="rotation_z" name="" min="-180" max="180" step="1" value="0" oninput="DisplayMode.syncDispInput(this, 'rotation', 'z')">
|
||||
<input type="number" class="tool disp_text" id="rotation_z" oninput="DisplayMode.syncDispInput(this, 'rotation', 'z')" min="-180" max="180" step="0.5" value="0">
|
||||
</div>
|
||||
<div id="display_sliders">
|
||||
|
||||
<p class="tl">display.rotation</p><div class="tool head_right" v-on:click="resetChannel('rotation')"><i class="material-icons">replay</i></div>
|
||||
<div class="bar" v-for="axis in [0, 1, 2]">
|
||||
<input type="range" class="tool disp_range" v-model.number="slot.rotation[axis]" min="-180" max="180" step="1" value="0" @input="change" @input="change(axis, 'rotation')" @mousedown="start" @change="save">
|
||||
<input type="number" class="tool disp_text" v-model.number="slot.rotation[axis]" min="-180" max="180" step="0.5" value="0" @input="change(axis, 'rotation');save()" @mousedown="start">
|
||||
</div>
|
||||
|
||||
<p class="tl">display.translation</p><div class="tool head_right" v-on:click="resetChannel('translation')"><i class="material-icons">replay</i></div>
|
||||
<div class="bar" v-for="axis in [0, 1, 2]">
|
||||
<input type="range" class="tool disp_range" v-model.number="slot.translation[axis]"
|
||||
v-bind:min="Math.abs(slot.translation[axis]) < 10 ? -20 : (slot.translation[axis] > 0 ? -70*3+10 : -80)"
|
||||
v-bind:max="Math.abs(slot.translation[axis]) < 10 ? 20 : (slot.translation[axis] < 0 ? 70*3-10 : 80)"
|
||||
v-bind:step="Math.abs(slot.translation[axis]) < 10 ? 0.25 : 1"
|
||||
value="0" @input="change(axis, 'rotation')" @mousedown="start" @change="save">
|
||||
<input type="number" class="tool disp_text" v-model.number="slot.translation[axis]" min="-80" max="80" step="0.5" value="0" @input="change(axis, 'rotation');save()" @mousedown="start">
|
||||
</div>
|
||||
|
||||
<p class="tl">display.translation</p><div class="tool head_right" onclick="DisplayMode.resetDisplaySettings('translation')"><i class="material-icons">replay</i></div>
|
||||
<div class="bar">
|
||||
<input type="range" class="tool disp_range" id="translation_x" name="" min="-32" max="32" step="0.5" value="0" oninput="DisplayMode.syncDispInput(this, 'translation', 'x')">
|
||||
<input type="number" class="tool disp_text" id="translation_x" oninput="DisplayMode.syncDispInput(this, 'translation', 'x')" min="-80" max="80" step="0.5" value="0">
|
||||
</div>
|
||||
<div class="bar">
|
||||
<input type="range" class="tool disp_range" id="translation_y" name="" min="-32" max="32" step="0.5" value="0" oninput="DisplayMode.syncDispInput(this, 'translation', 'y')">
|
||||
<input type="number" class="tool disp_text" id="translation_y" oninput="DisplayMode.syncDispInput(this, 'translation', 'y')" min="-80" max="80" step="0.5" value="0">
|
||||
</div>
|
||||
<div class="bar">
|
||||
<input type="range" class="tool disp_range" id="translation_z" name="" min="-32" max="32" step="0.5" value="0" oninput="DisplayMode.syncDispInput(this, 'translation', 'z')">
|
||||
<input type="number" class="tool disp_text" id="translation_z" oninput="DisplayMode.syncDispInput(this, 'translation', 'z')" min="-80" max="80" step="0.5" value="0">
|
||||
</div>
|
||||
|
||||
<p class="tl">display.scale</p><div class="tool head_right" onclick="DisplayMode.resetDisplaySettings('scale')"><i class="material-icons">replay</i></div>
|
||||
<div class="bar">
|
||||
<div class="tool display_scale_invert" id="display_scale_invert_x" onclick="DisplayMode.syncDispMirror(this, 'x')">
|
||||
<i class="material-icons">check_box_outline_blank</i><div class="tooltip tl">display.mirror</div>
|
||||
<p class="tl">display.scale</p><div class="tool head_right" v-on:click="resetChannel('scale')"><i class="material-icons">replay</i></div>
|
||||
<div class="bar" v-for="axis in [0, 1, 2]">
|
||||
<div class="tool display_scale_invert" v-on:click="invert(axis)">
|
||||
<i class="material-icons">{{ slot.mirror[axis] ? 'check_box' : 'check_box_outline_blank' }}</i><div class="tooltip tl">display.mirror</div>
|
||||
</div>
|
||||
<input type="range" class="tool disp_range scaleRange" v-model.number="slot.scale[axis]" v-bind:id="'scale_range_'+axis"
|
||||
v-bind:min="slot.scale[axis] > 1 ? -2 : 0"
|
||||
v-bind:max="slot.scale[axis] > 1 ? 4 : 2"
|
||||
step="0.01"
|
||||
value="0" @input="change(axis, 'scale')" @mousedown="start" @change="save">
|
||||
<input type="number" class="tool disp_text" v-model.number="slot.scale[axis]" min="0" max="4" step="0.01" value="0" @input="change(axis, 'scale');save()" @mousedown="start">
|
||||
</div>
|
||||
<input type="range" class="tool disp_range scaleRange" id="scale_x" name="" min="-4" max="4" step="0.1" value="0" oninput="DisplayMode.syncDispInput(this, 'scaleRange', 'x', event)">
|
||||
<input type="number" class="tool disp_text scale" id="scale_x" oninput="DisplayMode.syncDispInput(this, 'scale', 'x')" step="0.1" min="-4" max="4">
|
||||
</div>
|
||||
<div class="bar">
|
||||
<div class="tool display_scale_invert" id="display_scale_invert_y" onclick="DisplayMode.syncDispMirror(this, 'x')">
|
||||
<i class="material-icons">check_box_outline_blank</i><div class="tooltip tl">display.mirror</div>
|
||||
</div>
|
||||
<input type="range" class="tool disp_range scaleRange" id="scale_y" name="" min="-4" max="4" step="0.1" value="0" oninput="DisplayMode.syncDispInput(this, 'scaleRange', 'y', event)">
|
||||
<input type="number" class="tool disp_text scale" id="scale_y" oninput="DisplayMode.syncDispInput(this, 'scale', 'y')" step="0.1" min="-4" max="4">
|
||||
</div>
|
||||
<div class="bar">
|
||||
<div class="tool display_scale_invert" id="display_scale_invert_z" onclick="DisplayMode.syncDispMirror(this, 'x')">
|
||||
<i class="material-icons">check_box_outline_blank</i><div class="tooltip tl">display.mirror</div>
|
||||
</div>
|
||||
<input type="range" class="tool disp_range scaleRange" id="scale_z" name="" min="-4" max="4" step="0.1" value="0" oninput="DisplayMode.syncDispInput(this, 'scaleRange', 'z', event)">
|
||||
<input type="number" class="tool disp_text scale" id="scale_z" oninput="DisplayMode.syncDispInput(this, 'scale', 'z')" step="0.1" min="-4" max="4">
|
||||
</div>
|
||||
</div>
|
||||
<div id="animations" class="panel">
|
||||
@ -854,12 +833,12 @@
|
||||
v-bind:class="{ selected: texture.selected, particle: texture.particle}"
|
||||
v-bind:texid="texture.id"
|
||||
class="texture"
|
||||
v-on:click.stop="texture.select()"
|
||||
v-on:click.stop="texture.select($event)"
|
||||
v-on:dblclick="texture.openMenu($event)"
|
||||
@contextmenu.prevent.stop="texture.showContextMenu($event)"
|
||||
>
|
||||
<div class="texture_icon_wrapper">
|
||||
<img v-bind:texid="texture.id" v-bind:src="texture.source" class="texture_icon" width="48px" alt="missing image" v-if="texture.show_icon" />
|
||||
<img v-bind:texid="texture.id" v-bind:src="texture.source" class="texture_icon" width="48px" alt="[E]" v-if="texture.show_icon" />
|
||||
<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>
|
||||
@ -945,6 +924,7 @@
|
||||
<div class="f_right">
|
||||
{{ Prop.fps }} FPS
|
||||
</div>
|
||||
<div id="status_progress" v-if="Prop.progress" v-bind:style="{width: Prop.progress*100+'%'}"></div>
|
||||
</div>
|
||||
<script>
|
||||
initCanvas()
|
||||
|
110
index.php
110
index.php
@ -13,7 +13,9 @@
|
||||
<style type="text/css" id="bbstyle"></style>
|
||||
</head>
|
||||
<body spellcheck="false">
|
||||
<div id="loading_error_message" style="display: none;">An error occurred while loading Blockbench</div>
|
||||
<div id="loading_error_message" style="display: none;">An error occurred while loading Blockbench
|
||||
<button onclick="Blockbench.reload()" class="large" style="display: block; margin-right: auto; margin-left: auto;">Reload</button>
|
||||
</div>
|
||||
<script>
|
||||
if (typeof module === 'object') {window.module = module; module = undefined;}//jQuery Fix
|
||||
var isApp = typeof require !== 'undefined'
|
||||
@ -28,6 +30,7 @@
|
||||
<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>
|
||||
@ -36,6 +39,7 @@
|
||||
<script src="js/util.js"></script>
|
||||
<script src="js/keyboard.js"></script>
|
||||
<script src="js/settings.js"></script>
|
||||
<script src="js/actions.js"></script>
|
||||
<script src="js/blockbench.js"></script>
|
||||
<script src="js/undo.js"></script>
|
||||
|
||||
@ -48,7 +52,6 @@
|
||||
</script>
|
||||
|
||||
<script src="js/api.js"></script>
|
||||
<script src="js/actions.js"></script>
|
||||
<script src="js/io.js"></script>
|
||||
<script src="js/elements.js"></script>
|
||||
<script src="js/preview.js"></script>
|
||||
@ -311,55 +314,44 @@
|
||||
<div class="dialog draggable paddinged" id="create_preset">
|
||||
<h2 class="dialog_handle tl">dialog.display_preset.title</h2>
|
||||
<div class="dialog_bar tl">dialog.display_preset.message</div>
|
||||
|
||||
<div class="dialog_bar">
|
||||
<input type="checkbox" id="thirdperson_righthand_save" checked>
|
||||
<label for="thirdperson_righthand_save" class="tl">display.slot.third_right</label>
|
||||
</div>
|
||||
|
||||
<div class="dialog_bar">
|
||||
<input type="checkbox" id="thirdperson_lefthand_save" checked>
|
||||
<label for="thirdperson_lefthand_save" class="tl">display.slot.third_left</label>
|
||||
</div>
|
||||
|
||||
<div class="dialog_bar">
|
||||
<input type="checkbox" id="firstperson_righthand_save" checked>
|
||||
<label for="firstperson_righthand_save" class="tl">display.slot.first_right</label>
|
||||
</div>
|
||||
|
||||
<div class="dialog_bar">
|
||||
<input type="checkbox" id="firstperson_lefthand_save" checked>
|
||||
<label for="firstperson_lefthand_save" class="tl">display.slot.first_left</label>
|
||||
</div>
|
||||
|
||||
<div class="dialog_bar">
|
||||
<input type="checkbox" id="head_save" checked>
|
||||
<label for="head_save" class="tl">display.slot.head</label>
|
||||
</div>
|
||||
|
||||
<div class="dialog_bar">
|
||||
<input type="checkbox" id="ground_save" checked>
|
||||
<label for="ground_save" class="tl">display.slot.ground</label>
|
||||
</div>
|
||||
|
||||
<div class="dialog_bar">
|
||||
<input type="checkbox" id="fixed_save" checked>
|
||||
<label for="fixed_save" class="tl">display.slot.frame</label>
|
||||
</div>
|
||||
|
||||
<div class="dialog_bar">
|
||||
<input type="checkbox" id="gui_save" checked>
|
||||
<label for="gui_save" class="tl">display.slot.gui</label>
|
||||
</div>
|
||||
|
||||
<div class="dialog_bar narrow">
|
||||
<label class="tl">display.presetname</label>
|
||||
</div>
|
||||
|
||||
<div class="dialog_bar">
|
||||
<input type="text" id="preset_name" class="input_wide" id="new preset">
|
||||
</div>
|
||||
|
||||
<div class="dialog_bar">
|
||||
<button type="button" class="large tl confirm_btn" onclick="DisplayMode.createPreset()">dialog.display_preset.create</button>
|
||||
<button type="button" class="large tl cancel_btn" onclick="hideDialog()">dialog.cancel</button>
|
||||
@ -458,9 +450,9 @@
|
||||
</h3>
|
||||
<ul v-if="category.open">
|
||||
|
||||
<li v-for="(setting, key) in category.items" v-on="setting.click ? {click: setting.click} : {}">
|
||||
<li v-for="(setting, key) in category.items" v-if="Condition(setting.condition)" v-on="setting.click ? {click: setting.click} : {}">
|
||||
<template v-if="setting.type === 'number'">
|
||||
<div class="setting_element"><input type="number" v-model="setting.value" v-on:input="saveSettings()"></div>
|
||||
<div class="setting_element"><input type="number" v-model.number="setting.value" v-on:input="saveSettings()"></div>
|
||||
</template>
|
||||
<template v-else-if="setting.type === 'click'">
|
||||
<div class="setting_element" v-html="Blockbench.getIconNode(setting.icon).outerHTML"></div>
|
||||
@ -713,6 +705,14 @@
|
||||
<ul id="menu_bar"></ul>
|
||||
<div class="toolbar_wrapper narrow tools"></div>
|
||||
<div class="toolbar_wrapper narrow tool_options"></div>
|
||||
<div id="mode_selector">
|
||||
<li
|
||||
v-for="mode in options"
|
||||
v-if="Condition(mode.condition)"
|
||||
v-bind:class="{selected: mode.selected}"
|
||||
v-on:click="mode.select()"
|
||||
>{{ mode.name }}</li>
|
||||
</div>
|
||||
</header>
|
||||
<div id="left_bar" class="sidebar">
|
||||
<div id="uv" class="panel selection_only">
|
||||
@ -768,55 +768,36 @@
|
||||
<div id="display_ref_bar" class="bar tabs_small reference_model_bar">
|
||||
</div>
|
||||
|
||||
<p class="tl">display.rotation</p><div class="tool head_right" onclick="DisplayMode.resetDisplaySettings('rotation')"><i class="material-icons">replay</i></div>
|
||||
<div class="bar">
|
||||
<input type="range" class="tool disp_range" id="rotation_x" name="" min="-180" max="180" step="1" value="0" oninput="DisplayMode.syncDispInput(this, 'rotation', 'x')">
|
||||
<input type="number" class="tool disp_text" id="rotation_x" oninput="DisplayMode.syncDispInput(this, 'rotation', 'x')" min="-180" max="180" step="0.5" value="0">
|
||||
</div>
|
||||
<div class="bar">
|
||||
<input type="range" class="tool disp_range" id="rotation_y" name="" min="-180" max="180" step="1" value="0" oninput="DisplayMode.syncDispInput(this, 'rotation', 'y')">
|
||||
<input type="number" class="tool disp_text" id="rotation_y" oninput="DisplayMode.syncDispInput(this, 'rotation', 'y')" min="-180" max="180" step="0.5" value="0">
|
||||
</div>
|
||||
<div class="bar">
|
||||
<input type="range" class="tool disp_range" id="rotation_z" name="" min="-180" max="180" step="1" value="0" oninput="DisplayMode.syncDispInput(this, 'rotation', 'z')">
|
||||
<input type="number" class="tool disp_text" id="rotation_z" oninput="DisplayMode.syncDispInput(this, 'rotation', 'z')" min="-180" max="180" step="0.5" value="0">
|
||||
</div>
|
||||
<div id="display_sliders">
|
||||
|
||||
<p class="tl">display.rotation</p><div class="tool head_right" v-on:click="resetChannel('rotation')"><i class="material-icons">replay</i></div>
|
||||
<div class="bar" v-for="axis in [0, 1, 2]">
|
||||
<input type="range" class="tool disp_range" v-model.number="slot.rotation[axis]" min="-180" max="180" step="1" value="0" @input="change" @input="change(axis, 'rotation')" @mousedown="start" @change="save">
|
||||
<input type="number" class="tool disp_text" v-model.number="slot.rotation[axis]" min="-180" max="180" step="0.5" value="0" @input="change(axis, 'rotation');save()" @mousedown="start">
|
||||
</div>
|
||||
|
||||
<p class="tl">display.translation</p><div class="tool head_right" v-on:click="resetChannel('translation')"><i class="material-icons">replay</i></div>
|
||||
<div class="bar" v-for="axis in [0, 1, 2]">
|
||||
<input type="range" class="tool disp_range" v-model.number="slot.translation[axis]"
|
||||
v-bind:min="Math.abs(slot.translation[axis]) < 10 ? -20 : (slot.translation[axis] > 0 ? -70*3+10 : -80)"
|
||||
v-bind:max="Math.abs(slot.translation[axis]) < 10 ? 20 : (slot.translation[axis] < 0 ? 70*3-10 : 80)"
|
||||
v-bind:step="Math.abs(slot.translation[axis]) < 10 ? 0.25 : 1"
|
||||
value="0" @input="change(axis, 'rotation')" @mousedown="start" @change="save">
|
||||
<input type="number" class="tool disp_text" v-model.number="slot.translation[axis]" min="-80" max="80" step="0.5" value="0" @input="change(axis, 'rotation');save()" @mousedown="start">
|
||||
</div>
|
||||
|
||||
<p class="tl">display.translation</p><div class="tool head_right" onclick="DisplayMode.resetDisplaySettings('translation')"><i class="material-icons">replay</i></div>
|
||||
<div class="bar">
|
||||
<input type="range" class="tool disp_range" id="translation_x" name="" min="-32" max="32" step="0.5" value="0" oninput="DisplayMode.syncDispInput(this, 'translation', 'x')">
|
||||
<input type="number" class="tool disp_text" id="translation_x" oninput="DisplayMode.syncDispInput(this, 'translation', 'x')" min="-80" max="80" step="0.5" value="0">
|
||||
</div>
|
||||
<div class="bar">
|
||||
<input type="range" class="tool disp_range" id="translation_y" name="" min="-32" max="32" step="0.5" value="0" oninput="DisplayMode.syncDispInput(this, 'translation', 'y')">
|
||||
<input type="number" class="tool disp_text" id="translation_y" oninput="DisplayMode.syncDispInput(this, 'translation', 'y')" min="-80" max="80" step="0.5" value="0">
|
||||
</div>
|
||||
<div class="bar">
|
||||
<input type="range" class="tool disp_range" id="translation_z" name="" min="-32" max="32" step="0.5" value="0" oninput="DisplayMode.syncDispInput(this, 'translation', 'z')">
|
||||
<input type="number" class="tool disp_text" id="translation_z" oninput="DisplayMode.syncDispInput(this, 'translation', 'z')" min="-80" max="80" step="0.5" value="0">
|
||||
</div>
|
||||
|
||||
<p class="tl">display.scale</p><div class="tool head_right" onclick="DisplayMode.resetDisplaySettings('scale')"><i class="material-icons">replay</i></div>
|
||||
<div class="bar">
|
||||
<div class="tool display_scale_invert" id="display_scale_invert_x" onclick="DisplayMode.syncDispMirror(this, 'x')">
|
||||
<i class="material-icons">check_box_outline_blank</i><div class="tooltip tl">display.mirror</div>
|
||||
<p class="tl">display.scale</p><div class="tool head_right" v-on:click="resetChannel('scale')"><i class="material-icons">replay</i></div>
|
||||
<div class="bar" v-for="axis in [0, 1, 2]">
|
||||
<div class="tool display_scale_invert" v-on:click="invert(axis)">
|
||||
<i class="material-icons">{{ slot.mirror[axis] ? 'check_box' : 'check_box_outline_blank' }}</i><div class="tooltip tl">display.mirror</div>
|
||||
</div>
|
||||
<input type="range" class="tool disp_range scaleRange" v-model.number="slot.scale[axis]" v-bind:id="'scale_range_'+axis"
|
||||
v-bind:min="slot.scale[axis] > 1 ? -2 : 0"
|
||||
v-bind:max="slot.scale[axis] > 1 ? 4 : 2"
|
||||
step="0.01"
|
||||
value="0" @input="change(axis, 'scale')" @mousedown="start" @change="save">
|
||||
<input type="number" class="tool disp_text" v-model.number="slot.scale[axis]" min="0" max="4" step="0.01" value="0" @input="change(axis, 'scale');save()" @mousedown="start">
|
||||
</div>
|
||||
<input type="range" class="tool disp_range scaleRange" id="scale_x" name="" min="-4" max="4" step="0.1" value="0" oninput="DisplayMode.syncDispInput(this, 'scaleRange', 'x', event)">
|
||||
<input type="number" class="tool disp_text scale" id="scale_x" oninput="DisplayMode.syncDispInput(this, 'scale', 'x')" step="0.1" min="-4" max="4">
|
||||
</div>
|
||||
<div class="bar">
|
||||
<div class="tool display_scale_invert" id="display_scale_invert_y" onclick="DisplayMode.syncDispMirror(this, 'x')">
|
||||
<i class="material-icons">check_box_outline_blank</i><div class="tooltip tl">display.mirror</div>
|
||||
</div>
|
||||
<input type="range" class="tool disp_range scaleRange" id="scale_y" name="" min="-4" max="4" step="0.1" value="0" oninput="DisplayMode.syncDispInput(this, 'scaleRange', 'y', event)">
|
||||
<input type="number" class="tool disp_text scale" id="scale_y" oninput="DisplayMode.syncDispInput(this, 'scale', 'y')" step="0.1" min="-4" max="4">
|
||||
</div>
|
||||
<div class="bar">
|
||||
<div class="tool display_scale_invert" id="display_scale_invert_z" onclick="DisplayMode.syncDispMirror(this, 'x')">
|
||||
<i class="material-icons">check_box_outline_blank</i><div class="tooltip tl">display.mirror</div>
|
||||
</div>
|
||||
<input type="range" class="tool disp_range scaleRange" id="scale_z" name="" min="-4" max="4" step="0.1" value="0" oninput="DisplayMode.syncDispInput(this, 'scaleRange', 'z', event)">
|
||||
<input type="number" class="tool disp_text scale" id="scale_z" oninput="DisplayMode.syncDispInput(this, 'scale', 'z')" step="0.1" min="-4" max="4">
|
||||
</div>
|
||||
</div>
|
||||
<div id="animations" class="panel">
|
||||
@ -868,12 +849,12 @@
|
||||
v-bind:class="{ selected: texture.selected, particle: texture.particle}"
|
||||
v-bind:texid="texture.id"
|
||||
class="texture"
|
||||
v-on:click.stop="texture.select()"
|
||||
v-on:click.stop="texture.select($event)"
|
||||
v-on:dblclick="texture.openMenu($event)"
|
||||
@contextmenu.prevent.stop="texture.showContextMenu($event)"
|
||||
>
|
||||
<div class="texture_icon_wrapper">
|
||||
<img v-bind:texid="texture.id" v-bind:src="texture.source" class="texture_icon" width="48px" alt="missing image" v-if="texture.show_icon" />
|
||||
<img v-bind:texid="texture.id" v-bind:src="texture.source" class="texture_icon" width="48px" alt="[E]" v-if="texture.show_icon" />
|
||||
<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>
|
||||
@ -959,6 +940,7 @@
|
||||
<div class="f_right">
|
||||
{{ Prop.fps }} FPS
|
||||
</div>
|
||||
<div id="status_progress" v-if="Prop.progress" v-bind:style="{width: Prop.progress*100+'%'}"></div>
|
||||
</div>
|
||||
<script>
|
||||
initCanvas()
|
||||
|
@ -482,7 +482,7 @@ THREE.OrbitControls = function ( object, preview ) {
|
||||
// console.log( 'handleMouseWheel' );
|
||||
|
||||
if ( event.deltaY < 0 ) {
|
||||
|
||||
|
||||
dollyOut( getZoomScale() );
|
||||
|
||||
} else if ( event.deltaY > 0 ) {
|
||||
|
File diff suppressed because it is too large
Load Diff
140
js/actions.js
140
js/actions.js
@ -146,6 +146,7 @@ class Action extends BarItem {
|
||||
this.menu_node = $(`<li>${this.name}</li>`).get(0)
|
||||
$(this.node).add(this.menu_node).prepend(this.icon_node)
|
||||
$(this.node).click(function(e) {scope.trigger(e)})
|
||||
|
||||
if (data.linked_setting) {
|
||||
this.toggleLinkedSetting(false)
|
||||
}
|
||||
@ -194,12 +195,14 @@ class Action extends BarItem {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Tool extends Action {
|
||||
constructor(data) {
|
||||
super(data)
|
||||
var scope = this;
|
||||
this.type = 'tool'
|
||||
this.toolbar = data.toolbar;
|
||||
this.alt_tool = data.alt_tool;
|
||||
this.selectFace = data.selectFace;
|
||||
this.selectCubes = data.selectCubes !== false;
|
||||
this.paintTool = data.paintTool;
|
||||
@ -224,6 +227,7 @@ class Tool extends Action {
|
||||
Toolbox.selected.onUnselect()
|
||||
}
|
||||
Toolbox.selected = this;
|
||||
delete Toolbox.original;
|
||||
|
||||
if (this.transformerMode) {
|
||||
Transformer.setMode(this.transformerMode)
|
||||
@ -234,7 +238,6 @@ class Tool extends Action {
|
||||
}
|
||||
if (this.toolbar && Toolbars[this.toolbar]) {
|
||||
Toolbars[this.toolbar].toPlace('tool_options')
|
||||
resizeWindow()
|
||||
} else {
|
||||
$('.toolbar_wrapper.tool_options > .toolbar').detach()
|
||||
}
|
||||
@ -382,7 +385,7 @@ class NumSlider extends Widget {
|
||||
var scope = this;
|
||||
var number = 0;
|
||||
//Math
|
||||
var offset = Math.round((event.clientX-scope.left)/50)
|
||||
var offset = Math.round((event.clientX-scope.left)/30)
|
||||
if (scope.uv === false) {
|
||||
offset *= canvasGridSize();
|
||||
}
|
||||
@ -461,7 +464,7 @@ class NumSlider extends Widget {
|
||||
if (!BARS.condition(this.condition)) return;
|
||||
var number = this.get();
|
||||
this.setValue(number)
|
||||
$('#nslide_head #nslide_offset').text(this.name+': '+number)
|
||||
$('#nslide_head #nslide_offset').text(this.name+': '+this.value)
|
||||
}
|
||||
}
|
||||
class BarSlider extends Widget {
|
||||
@ -643,9 +646,6 @@ class Toolbar {
|
||||
var items = data.children
|
||||
if (!force && BARS.stored[scope.id] && typeof BARS.stored[scope.id] === 'object') {
|
||||
items = BARS.stored[scope.id]
|
||||
if (this.id === 'tools' && !items.includes('animation_mode_tool')) {
|
||||
items.push('animation_mode_tool')
|
||||
}
|
||||
}
|
||||
if (items && items.constructor.name === 'Array') {
|
||||
var content = $(scope.node).find('div.content')
|
||||
@ -786,15 +786,7 @@ var BARS = {
|
||||
stored: {},
|
||||
editing_bar: undefined,
|
||||
action_definers: [],
|
||||
condition: function(condition, context) {
|
||||
if (condition === undefined) {
|
||||
return true;
|
||||
} else if (typeof condition === 'function') {
|
||||
return condition(context)
|
||||
} else {
|
||||
return !!condition
|
||||
}
|
||||
},
|
||||
condition: Condition,
|
||||
defineActions: function(definer) {
|
||||
BARS.action_definers.push(definer)
|
||||
},
|
||||
@ -837,7 +829,9 @@ var BARS = {
|
||||
selectFace: true,
|
||||
transformerMode: 'translate',
|
||||
toolbar: 'transform',
|
||||
keybind: new Keybind({key: 86})
|
||||
alt_tool: 'resize_tool',
|
||||
keybind: new Keybind({key: 86}),
|
||||
condition: () => Modes.id === 'edit' || Modes.id === 'animate' || Modes.id === 'display'
|
||||
})
|
||||
new Tool({
|
||||
id: 'resize_tool',
|
||||
@ -846,7 +840,20 @@ var BARS = {
|
||||
selectFace: true,
|
||||
transformerMode: 'scale',
|
||||
toolbar: 'transform',
|
||||
keybind: new Keybind({key: 83})
|
||||
alt_tool: 'move_tool',
|
||||
keybind: new Keybind({key: 83}),
|
||||
condition: () => Modes.id === 'edit' || Modes.id === 'animate' || Modes.id === 'display'
|
||||
})
|
||||
new Tool({
|
||||
id: 'rotate_tool',
|
||||
icon: 'sync',
|
||||
category: 'tools',
|
||||
selectFace: true,
|
||||
transformerMode: 'rotate',
|
||||
toolbar: 'transform',
|
||||
alt_tool: 'move_tool',
|
||||
keybind: new Keybind({key: 82}),
|
||||
condition: () => Modes.id === 'edit' || Modes.id === 'animate' || Modes.id === 'display'
|
||||
})
|
||||
new Tool({
|
||||
id: 'vertex_snap_tool',
|
||||
@ -857,6 +864,7 @@ var BARS = {
|
||||
selectCubes: true,
|
||||
cursor: 'copy',
|
||||
keybind: new Keybind({key: 88}),
|
||||
condition: () => Modes.id === 'edit',
|
||||
onCanvasClick: function(data) {
|
||||
Vertexsnap.canvasClick(data)
|
||||
},
|
||||
@ -877,47 +885,11 @@ var BARS = {
|
||||
scale: true
|
||||
}
|
||||
})
|
||||
new Tool({
|
||||
id: 'display_mode_tool',
|
||||
icon: 'icon-player',
|
||||
transformerMode: 'hidden',
|
||||
category: 'tools',
|
||||
selectCubes: false,
|
||||
condition: () => !Blockbench.entity_mode,
|
||||
onCanvasClick: function(data) {
|
||||
},
|
||||
onSelect: function() {
|
||||
enterDisplaySettings()
|
||||
},
|
||||
onUnselect: function() {
|
||||
exitDisplaySettings()
|
||||
}
|
||||
})
|
||||
new Tool({
|
||||
id: 'animation_mode_tool',
|
||||
icon: 'movie',
|
||||
transformerMode: 'hidden',
|
||||
category: 'tools',
|
||||
selectCubes: false,
|
||||
condition: () => Blockbench.entity_mode,
|
||||
onCanvasClick: function(data) {
|
||||
if (data.cube && data.cube.parent.type === 'group') {
|
||||
|
||||
data.cube.parent.select()
|
||||
}
|
||||
},
|
||||
onSelect: function() {
|
||||
Animator.join()
|
||||
},
|
||||
onUnselect: function() {
|
||||
Animator.leave()
|
||||
}
|
||||
})
|
||||
|
||||
new Action({
|
||||
id: 'swap_tools',
|
||||
icon: 'swap_horiz',
|
||||
category: 'tools',
|
||||
condition: () => !Animator.open,
|
||||
keybind: new Keybind({key: 32}),
|
||||
click: function () {
|
||||
if (Toolbox.selected.id === 'move_tool') {
|
||||
@ -944,6 +916,15 @@ var BARS = {
|
||||
shell.showItemInFolder(Prop.file_path)
|
||||
}
|
||||
})
|
||||
new Action({
|
||||
id: 'open_backup_folder',
|
||||
icon: 'fa-archive',
|
||||
category: 'file',
|
||||
condition: () => isApp,
|
||||
click: function (e) {
|
||||
shell.showItemInFolder(app.app.getPath('userData')+osfs+'backups'+osfs+'.')
|
||||
}
|
||||
})
|
||||
new Action({
|
||||
id: 'settings_window',
|
||||
icon: 'settings',
|
||||
@ -951,12 +932,6 @@ var BARS = {
|
||||
keybind: new Keybind({key: 69, ctrl: true}),
|
||||
click: function () {openSettings()}
|
||||
})
|
||||
new Action({
|
||||
id: 'plugins_window',
|
||||
icon: 'extension',
|
||||
category: 'blockbench',
|
||||
click: function () {showDialog('plugins')}
|
||||
})
|
||||
new Action({
|
||||
id: 'update_window',
|
||||
icon: 'update',
|
||||
@ -979,22 +954,6 @@ var BARS = {
|
||||
})
|
||||
|
||||
//Edit
|
||||
new Action({
|
||||
id: 'undo',
|
||||
icon: 'undo',
|
||||
category: 'edit',
|
||||
condition: () => (!display_mode),
|
||||
keybind: new Keybind({key: 90, ctrl: true}),
|
||||
click: function () {Undo.undo()}
|
||||
})
|
||||
new Action({
|
||||
id: 'redo',
|
||||
icon: 'redo',
|
||||
category: 'edit',
|
||||
condition: () => (!display_mode),
|
||||
keybind: new Keybind({key: 89, ctrl: true}),
|
||||
click: function () {Undo.redo()}
|
||||
})
|
||||
new Action({
|
||||
id: 'copy',
|
||||
icon: 'fa-clone',
|
||||
@ -1023,7 +982,7 @@ var BARS = {
|
||||
id: 'duplicate',
|
||||
icon: 'content_copy',
|
||||
category: 'edit',
|
||||
condition: () => (!display_mode && !Animator.open),
|
||||
condition: () => (!display_mode && !Animator.open && selected.length),
|
||||
keybind: new Keybind({key: 68, ctrl: true}),
|
||||
click: function () {
|
||||
duplicateCubes();
|
||||
@ -1033,7 +992,7 @@ var BARS = {
|
||||
id: 'delete',
|
||||
icon: 'delete',
|
||||
category: 'edit',
|
||||
condition: () => (!display_mode && !Animator.open),
|
||||
condition: () => (!display_mode && !Animator.open && selected.length),
|
||||
keybind: new Keybind({key: 46}),
|
||||
click: function () {
|
||||
deleteCubes();
|
||||
@ -1267,10 +1226,12 @@ var BARS = {
|
||||
children: [
|
||||
'move_tool',
|
||||
'resize_tool',
|
||||
'rotate_tool',
|
||||
'vertex_snap_tool',
|
||||
'brush_tool',
|
||||
'display_mode_tool',
|
||||
'animation_mode_tool'
|
||||
'fill_tool',
|
||||
'eraser',
|
||||
'color_picker'
|
||||
],
|
||||
default_place: true
|
||||
})
|
||||
@ -1500,6 +1461,25 @@ var BARS = {
|
||||
uv_dialog.all_editors.forEach((editor) => {
|
||||
editor.updateInterface()
|
||||
})
|
||||
BARS.updateToolToolbar()
|
||||
},
|
||||
updateToolToolbar: function() {
|
||||
if (!Toolbars || !Toolbars[Toolbox.selected.toolbar]) return;
|
||||
Toolbars[Toolbox.selected.toolbar].children.forEach(function(action) {
|
||||
if (action.type === 'numslider') {
|
||||
action.setWidth(40)
|
||||
}
|
||||
})
|
||||
if ($('div.tool_options .toolbar').length > 0) {
|
||||
var sliders = $('header .tool.nslide_tool').length
|
||||
var space = $(window).width() - $('div.tool_options .toolbar').offset().left - $('div.tool_options .toolbar').width() - $('#mode_selector').width() + 6
|
||||
var width = limitNumber(37 + space / sliders, 40, 80)
|
||||
Toolbars[Toolbox.selected.toolbar].children.forEach(function(action) {
|
||||
if (action.type === 'numslider') {
|
||||
action.setWidth(width)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
222
js/animations.js
222
js/animations.js
@ -117,6 +117,9 @@ class Animation {
|
||||
for (var uuid in this.bones) {
|
||||
this.bones[uuid].displayFrame(time)
|
||||
}
|
||||
if (selected_group) {
|
||||
centerTransformer()
|
||||
}
|
||||
}
|
||||
add() {
|
||||
if (!Animator.animations.includes(this)) {
|
||||
@ -174,9 +177,7 @@ class Animation {
|
||||
delete
|
||||
*/
|
||||
])
|
||||
/*
|
||||
|
||||
*/
|
||||
class BoneAnimator {
|
||||
constructor() {
|
||||
this.keyframes = []
|
||||
@ -200,26 +201,31 @@ class BoneAnimator {
|
||||
y: values[1],
|
||||
z: values[2]
|
||||
})
|
||||
if (values[3]) {
|
||||
keyframe.extend({w: values[3], isQuaternion: true})
|
||||
}
|
||||
} else if (typeof values === 'number' || typeof values === 'string') {
|
||||
keyframe.extend({
|
||||
x: values
|
||||
})
|
||||
} else {
|
||||
var ref = this.interpolate(time, channel)
|
||||
var ref = this.interpolate(time, channel, true)
|
||||
if (ref) {
|
||||
let e = 1e2
|
||||
ref.forEach((r, i) => {
|
||||
if (!isNaN(r)) {
|
||||
ref[i] = Math.round(parseFloat(r)*e)/e
|
||||
}
|
||||
})
|
||||
keyframe.extend({
|
||||
x: Math.round(ref[0]*e)/e,
|
||||
y: Math.round(ref[1]*e)/e,
|
||||
z: Math.round(ref[2]*e)/e,
|
||||
w: ref.length === 4 ? Math.round(ref[3]*e)/e : undefined,
|
||||
x: ref[0],
|
||||
y: ref[1],
|
||||
z: ref[2],
|
||||
w: ref.length === 4 ? ref[3] : undefined,
|
||||
isQuaternion: ref.length === 4
|
||||
})
|
||||
}
|
||||
}
|
||||
if (values.length > 3) {
|
||||
keyframe.extend({w: values[3], isQuaternion: true})
|
||||
}
|
||||
this.keyframes.push(keyframe)
|
||||
keyframe.parent = this;
|
||||
return keyframe;
|
||||
@ -270,7 +276,7 @@ class BoneAnimator {
|
||||
}
|
||||
return this;
|
||||
}
|
||||
interpolate(time, channel) {
|
||||
interpolate(time, channel, allow_expression) {
|
||||
var i = 0;
|
||||
var before = false
|
||||
var after = false
|
||||
@ -304,31 +310,28 @@ class BoneAnimator {
|
||||
} else {
|
||||
let alpha = Math.lerp(before.time, after.time, time)
|
||||
result = [
|
||||
before.calc('x') + (after.calc('x') - before.calc('x')) * alpha
|
||||
before.getLerp(after, 'x', alpha, allow_expression)
|
||||
]
|
||||
if (before.channel !== 'scale') {
|
||||
result[1] = (before.calc('y') + (after.calc('y') - before.calc('y')) * alpha)
|
||||
result[1] = before.getLerp(after, 'y', alpha, allow_expression)
|
||||
result[2] = before.getLerp(after, 'z', alpha, allow_expression)
|
||||
}
|
||||
if (before.channel !== 'scale') {
|
||||
result[2] = (before.calc('z') + (after.calc('z') - before.calc('z')) * alpha)
|
||||
}
|
||||
if (before.isQuaternion && after.isQuaternion) {
|
||||
result[3] = (before.calc('w') + (after.calc('w') - before.calc('w')) * alpha)
|
||||
if (before.isQuaternion && after.isQuaternion) {
|
||||
result[3] = before.getLerp(after, 'q', alpha, allow_expression)
|
||||
}
|
||||
}
|
||||
if (result && result.type === 'keyframe') {
|
||||
let keyframe = result
|
||||
let method = allow_expression ? 'get' : 'calc'
|
||||
result = [
|
||||
keyframe.calc('x')
|
||||
keyframe[method]('x')
|
||||
]
|
||||
if (keyframe.channel !== 'scale') {
|
||||
result[1] = keyframe.calc('y')
|
||||
}
|
||||
if (keyframe.channel !== 'scale') {
|
||||
result[2] = keyframe.calc('z')
|
||||
result[1] = keyframe[method]('y')
|
||||
result[2] = keyframe[method]('z')
|
||||
}
|
||||
if (keyframe.isQuaternion) {
|
||||
result[3] = keyframe.calc('w')
|
||||
result[3] = keyframe[method]('w')
|
||||
}
|
||||
}
|
||||
return result
|
||||
@ -346,6 +349,7 @@ class BoneAnimator {
|
||||
this.displayScale(result)
|
||||
}
|
||||
}
|
||||
this.group.getMesh().updateMatrixWorld()
|
||||
}
|
||||
select() {
|
||||
var duplicates;
|
||||
@ -422,6 +426,66 @@ class Keyframe {
|
||||
if (axis === 'x' || axis === 'y' || axis === 'z' || axis === 'w') {
|
||||
this[axis] = value
|
||||
}
|
||||
return this;
|
||||
}
|
||||
offset(axis, amount) {
|
||||
var value = this.get(axis)
|
||||
if (!value || value === '0') {
|
||||
this.set(axis, amount)
|
||||
}
|
||||
if (typeof value === 'number') {
|
||||
this.set(axis, value+amount)
|
||||
return value+amount
|
||||
}
|
||||
var start = value.match(/^-?\s*\d*(\.\d+)?\s*(\+|-)/)
|
||||
if (start) {
|
||||
var number = parseFloat( start[0].substr(0, start[0].length-1) ) + amount
|
||||
value = trimFloatNumber(number) + value.substr(start[0].length-1)
|
||||
} else {
|
||||
|
||||
var end = value.match(/(\+|-)\s*\d*(\.\d+)?\s*$/)
|
||||
if (end) {
|
||||
var number = (parseFloat( end[0] ) + amount)+''
|
||||
value = value.substr(0, end.index) + (number.substr(0,1)=='-'?'':'+') + trimFloatNumber(number)
|
||||
} else {
|
||||
value = trimFloatNumber(amount) +(value.substr(0,1)=='-'?'':'+')+ value
|
||||
}
|
||||
}
|
||||
this.set(axis, value)
|
||||
return value;
|
||||
|
||||
/*
|
||||
function iterate(string, index) {
|
||||
if (!isNaN(string)) {
|
||||
return [index, string.length]
|
||||
}
|
||||
var splices = splitUpMolang(string, ['+', '-'])
|
||||
if (!splices) return false;
|
||||
|
||||
var result = iterate(splices[1], index+splices[0].length)
|
||||
if (result) return result;
|
||||
|
||||
result = iterate(splices[0], index)
|
||||
if (result) return result;
|
||||
}
|
||||
|
||||
var p = iterate(value, 0)
|
||||
if (p) {
|
||||
value = value.substr(0, p[0]) + amount + value.substr(p[0]+p[1])
|
||||
this.set(axis, value)
|
||||
} else {
|
||||
amount = ''+amount
|
||||
if (amount.substr(0, 1) !== '-') amount = '+'+amount
|
||||
this.set(axis, value+amount)
|
||||
}*/
|
||||
}
|
||||
getLerp(other, axis, amount, allow_expression) {
|
||||
if (allow_expression && this.get(axis) === other.get(axis)) {
|
||||
return this.get(axis)
|
||||
} else {
|
||||
let calc = this.calc(axis)
|
||||
return calc + (other.calc(axis) - calc) * amount
|
||||
}
|
||||
}
|
||||
getArray() {
|
||||
if (this.channel === 'scale') {
|
||||
@ -531,6 +595,8 @@ class Keyframe {
|
||||
extend(data) {
|
||||
if (data.channel && Animator.possible_channels[data.channel]) {
|
||||
Merge.string(this, data, 'channel')
|
||||
} else if (typeof data.channel === 'number') {
|
||||
this.channel = Animator.channel_index[data.channel]
|
||||
}
|
||||
Merge.number(this, data, 'time')
|
||||
|
||||
@ -540,7 +606,7 @@ class Keyframe {
|
||||
Merge.string(this, data, 'w')
|
||||
Merge.boolean(this, data, 'isQuaternion')
|
||||
|
||||
this.channel_index = this.channel === 'rotation' ? 0 : (this.channel === 'position' ? 1 : 2)
|
||||
this.channel_index = Animator.channel_index.indexOf(this.channel)
|
||||
return this;
|
||||
}
|
||||
undoCopy() {
|
||||
@ -583,6 +649,7 @@ class Keyframe {
|
||||
*/
|
||||
])
|
||||
|
||||
|
||||
function updateKeyframeValue(obj) {
|
||||
var axis = $(obj).attr('axis')
|
||||
var value = $(obj).val()
|
||||
@ -614,10 +681,21 @@ function updateKeyframeSelection() {
|
||||
$('#keyframe_bar_y, #keyframe_bar_z').toggle(first.channel !== 'scale')
|
||||
$('#keyframe_bar_w').toggle(first.channel === 'rotation' && first.isQuaternion)
|
||||
|
||||
$('#keyframe_bar_x input').val(first['x'])
|
||||
$('#keyframe_bar_y input').val(first['y'])
|
||||
$('#keyframe_bar_z input').val(first['z'])
|
||||
$('#keyframe_bar_w input').val(first['w'])
|
||||
var values = [
|
||||
first.get('x'),
|
||||
first.get('y'),
|
||||
first.get('z'),
|
||||
first.get('w')
|
||||
]
|
||||
values.forEach((v, vi) => {
|
||||
if (typeof v === 'number') {
|
||||
values[vi] = trimFloatNumber(v)
|
||||
}
|
||||
})
|
||||
$('#keyframe_bar_x input').val(values[0])
|
||||
$('#keyframe_bar_y input').val(values[1])
|
||||
$('#keyframe_bar_z input').val(values[2])
|
||||
$('#keyframe_bar_w input').val(values[3])
|
||||
|
||||
BarItems.slider_keyframe_time.update()
|
||||
} else {
|
||||
@ -656,7 +734,7 @@ function removeSelectedKeyframes() {
|
||||
|
||||
const Animator = {
|
||||
possible_channels: {rotation: true, position: true, scale: true},
|
||||
channel_index: {rotation: true, position: true, scale: true},
|
||||
channel_index: ['rotation', 'position', 'scale'],
|
||||
open: false,
|
||||
animations: [],
|
||||
frame: 0,
|
||||
@ -669,12 +747,9 @@ const Animator = {
|
||||
|
||||
if (quad_previews.enabled) {
|
||||
quad_previews.enabled_before = true
|
||||
main_preview.fullscreen()
|
||||
}
|
||||
main_preview.fullscreen()
|
||||
main_preview.setNormalCamera()
|
||||
main_preview.camPers.position.set(-80, 40, -30)
|
||||
main_preview.camPers.setFocalLength(45)
|
||||
|
||||
|
||||
$('body').addClass('animation_mode')
|
||||
$('.m_edit').hide()
|
||||
@ -753,6 +828,9 @@ const Animator = {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!Animator.selected) {
|
||||
animation.select()
|
||||
}
|
||||
}
|
||||
if (isApp && file.path) {
|
||||
Prop.animation_path = file.path
|
||||
@ -819,12 +897,20 @@ const Timeline = {
|
||||
selected: [],//frames
|
||||
second: 0,
|
||||
playing: false,
|
||||
setTime: function(seconds) {
|
||||
setTime: function(seconds, editing) {
|
||||
seconds = limitNumber(seconds, 0, 1000)
|
||||
Timeline.vue._data.marker = seconds
|
||||
Timeline.second = seconds
|
||||
Timeline.setTimecode(seconds)
|
||||
if (!editing) {
|
||||
Timeline.setTimecode(seconds)
|
||||
}
|
||||
Timeline.updateSize()
|
||||
//Scroll
|
||||
var scroll = $('#timeline_inner').scrollLeft()
|
||||
var marker = Timeline.second * Timeline.vue._data.size + 8
|
||||
if (marker < scroll || marker > scroll + $('#timeline_inner').width()) {
|
||||
$('#timeline_inner').scrollLeft(marker-16)
|
||||
}
|
||||
},
|
||||
setTimecode: function(time) {
|
||||
let m = Math.floor(time/60)
|
||||
@ -882,7 +968,65 @@ const Timeline = {
|
||||
}).focusout(e => {
|
||||
Undo.finishEdit('edit keyframe')
|
||||
})
|
||||
$('#timeline_corner').click(e => {
|
||||
if ($('#timeline_corner').attr('contenteditable') == 'true') return;
|
||||
|
||||
$('#timeline_corner').attr('contenteditable', true).focus().select()
|
||||
var times = $('#timeline_corner').text().split(':')
|
||||
while (times.length < 3) {
|
||||
times.push('00')
|
||||
}
|
||||
var node = $('#timeline_corner').get(0).childNodes[0]
|
||||
var selection = window.getSelection();
|
||||
var range = document.createRange();
|
||||
|
||||
var sel = [0, node.length]
|
||||
if (e.offsetX < 24) {
|
||||
sel = [0, times[0].length]
|
||||
} else if (e.offsetX < 54) {
|
||||
sel = [times[0].length+1, times[1].length]
|
||||
} else if (e.offsetX < 80) {
|
||||
sel = [times[0].length+times[1].length+2, times[2].length]
|
||||
}
|
||||
sel[1] = limitNumber(sel[0]+sel[1], sel[0], node.length)
|
||||
|
||||
range.setStart(node, sel[0])
|
||||
range.setEnd(node, sel[1])
|
||||
selection.removeAllRanges();
|
||||
selection.addRange(range);
|
||||
|
||||
})
|
||||
.on('focusout keydown', e => {
|
||||
if (e.type === 'focusout' || Keybinds.extra.confirm.keybind.isTriggered(e) || Keybinds.extra.cancel.keybind.isTriggered(e)) {
|
||||
$('#timeline_corner').attr('contenteditable', false)
|
||||
Timeline.setTimecode(Timeline.second)
|
||||
}
|
||||
})
|
||||
.on('keyup', e => {
|
||||
var times = $('#timeline_corner').text().split(':')
|
||||
times.forEach((t, i) => {
|
||||
times[i] = parseInt(t)
|
||||
if (isNaN(times[i])) {
|
||||
times[i] = 0
|
||||
}
|
||||
})
|
||||
while (times.length < 3) {
|
||||
times.push(0)
|
||||
}
|
||||
var seconds
|
||||
= times[0]*60
|
||||
+ limitNumber(times[1], 0, 59)
|
||||
+ limitNumber(times[2]/30, 0, 29)
|
||||
if (Math.abs(seconds-Timeline.second) > 1e-3 ) {
|
||||
Timeline.setTime(seconds, true)
|
||||
if (Animator.selected) {
|
||||
Animator.preview()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
Timeline.is_setup = true
|
||||
Timeline.setTime(0)
|
||||
},
|
||||
update: function() {
|
||||
//Draggable
|
||||
@ -1073,7 +1217,7 @@ BARS.defineActions(function() {
|
||||
condition: () => Animator.open,
|
||||
click: function () {
|
||||
var animation = new Animation({
|
||||
name: 'animation.' + (Project.parent.replace(/geometry./, '')||'model') + '.new'
|
||||
name: 'animation.' + (Project.parent||'model') + '.new'
|
||||
}).add().select()
|
||||
|
||||
}
|
||||
@ -1136,6 +1280,10 @@ BARS.defineActions(function() {
|
||||
condition: () => Animator.open,
|
||||
click: function () {
|
||||
|
||||
if (!Animator.selected) {
|
||||
Blockbench.showQuickMessage('message.no_animation_selected')
|
||||
return;
|
||||
}
|
||||
if (Timeline.playing) {
|
||||
Timeline.pause()
|
||||
} else {
|
||||
|
71
js/api.js
71
js/api.js
@ -74,6 +74,7 @@ class API {
|
||||
return jq.get(0)
|
||||
}
|
||||
showQuickMessage(message, time) {
|
||||
$('#quick_message_box').remove()
|
||||
var quick_message_box = $('<div id="quick_message_box" class="hidden"></div>')
|
||||
$('body').append(quick_message_box)
|
||||
|
||||
@ -99,6 +100,9 @@ class API {
|
||||
Prop.file_name = Prop.file_name_alt||''
|
||||
}
|
||||
}
|
||||
setProgress(progress, time, bar) {
|
||||
setProgressBar(bar, progress||0, time)
|
||||
}
|
||||
showMessage(message, location) {
|
||||
if (location === 'status_bar') {
|
||||
Blockbench.showStatusMessage(message)
|
||||
@ -277,6 +281,8 @@ class API {
|
||||
} else {
|
||||
reader.readAsDataURL(file)
|
||||
}
|
||||
} else if (options.readtype === 'buffer') {
|
||||
reader.readAsArrayBuffer(file)
|
||||
} else /*text*/ {
|
||||
reader.readAsText(file)
|
||||
}
|
||||
@ -367,6 +373,7 @@ class API {
|
||||
content
|
||||
startpath
|
||||
savetype
|
||||
project_file
|
||||
custom_writer
|
||||
*/
|
||||
if (Blockbench.isWeb) {
|
||||
@ -386,6 +393,10 @@ class API {
|
||||
var blob = new Blob([options.content], {type: "text/plain;charset=utf-8"});
|
||||
saveAs(blob, file_name, {autoBOM: true})
|
||||
}
|
||||
if (options.project_file) {
|
||||
Prop.project_saved = true;
|
||||
setProjectTitle(options.name)
|
||||
}
|
||||
if (typeof cb === 'function') {
|
||||
cb()
|
||||
}
|
||||
@ -399,31 +410,51 @@ class API {
|
||||
? options.startpath.replace(/\.\w+$/, '')
|
||||
: options.name
|
||||
}, function (file_path) {
|
||||
if (file_path === undefined) {
|
||||
Blockbench.writeFile(file_path, options, cb)
|
||||
})
|
||||
}
|
||||
}
|
||||
writeFile(file_path, options, cb) {
|
||||
/*
|
||||
content
|
||||
savetype
|
||||
project_file
|
||||
custom_writer
|
||||
*/
|
||||
if (!isApp || file_path === undefined) {
|
||||
return;
|
||||
}
|
||||
if (options.savetype === 'image' && typeof options.content === 'string') {
|
||||
if (options.content.substr(0, 10) === 'data:image') {
|
||||
options.content = nativeImage.createFromDataURL(options.content).toPNG()
|
||||
} else {
|
||||
options.content = nativeImage.createFromPath(options.content).toPNG()
|
||||
}
|
||||
}
|
||||
if (options.custom_writer) {
|
||||
options.custom_writer(options.content, file_path)
|
||||
} else {
|
||||
fs.writeFile(file_path, options.content, function (err) {
|
||||
if (err) {
|
||||
console.log('Error exporting file: '+err)
|
||||
return;
|
||||
}
|
||||
if (options.savetype === 'image' && typeof options.content === 'string') {
|
||||
if (options.content.substr(0, 10) === 'data:image') {
|
||||
options.content = nativeImage.createFromDataURL(options.content).toPNG()
|
||||
} else {
|
||||
options.content = nativeImage.createFromPath(options.content).toPNG()
|
||||
}
|
||||
}
|
||||
if (options.custom_writer) {
|
||||
options.custom_writer(options.content, file_path)
|
||||
} else {
|
||||
fs.writeFile(file_path, options.content, function (err) {
|
||||
if (err) {
|
||||
console.log('Error exporting file: '+err)
|
||||
return;
|
||||
}
|
||||
if (cb) {
|
||||
cb(file_path)
|
||||
}
|
||||
})
|
||||
if (cb) {
|
||||
cb(file_path)
|
||||
}
|
||||
})
|
||||
}
|
||||
if (options.project_file) {
|
||||
Prop.file_path = file_path
|
||||
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})
|
||||
Blockbench.showQuickMessage(tl('message.save_file', [Project.name]))
|
||||
if (Blockbench.hasFlag('close_after_saving')) {
|
||||
closeBlockbenchWindow()
|
||||
}
|
||||
}
|
||||
}
|
||||
//Flags
|
||||
addFlag(flag) {
|
||||
|
273
js/app.js
273
js/app.js
@ -27,7 +27,7 @@ $(document).ready(function() {
|
||||
if (fs.existsSync(app.app.getPath('userData')+osfs+'backups') === false) {
|
||||
fs.mkdirSync( app.app.getPath('userData')+osfs+'backups')
|
||||
}
|
||||
createBackup()
|
||||
createBackup(true)
|
||||
$('.web_only').remove()
|
||||
if (__dirname.includes('C:\\xampp\\htdocs\\blockbench\\web')) {
|
||||
Blockbench.addFlag('dev')
|
||||
@ -206,10 +206,6 @@ function changeImageEditor(texture) {
|
||||
dialog.hide()
|
||||
}
|
||||
}).show()
|
||||
/*
|
||||
Ask for file IF
|
||||
_other selected
|
||||
*/
|
||||
}
|
||||
function selectImageEditorFile(texture) {
|
||||
app.dialog.showOpenDialog(currentwindow, {
|
||||
@ -254,79 +250,80 @@ function openDefaultTexturePath() {
|
||||
}
|
||||
function findEntityTexture(mob, return_path) {
|
||||
var textures = {
|
||||
'geometry.chicken': 'chicken',
|
||||
'geometry.blaze': 'blaze',
|
||||
'geometry.llamaspit': 'llama/spit',
|
||||
'geometry.llama': 'llama/llama_creamy',
|
||||
'geometry.dragon': 'dragon/dragon',
|
||||
'geometry.ghast': 'ghast/ghast',
|
||||
'geometry.slime': 'slime/slime',
|
||||
'geometry.slime.armor': 'slime/slime',
|
||||
'geometry.lavaslime': 'slime/magmacube',
|
||||
'geometry.silverfish': 'silverfish',
|
||||
'geometry.shulker': 'shulker/shulker_undyed',
|
||||
'geometry.rabbit': 'rabbit/brown',
|
||||
'geometry.horse': 'horse/horse_brown',
|
||||
'geometry.horse.v2': 'horse2/horse_brown',
|
||||
'geometry.humanoid': 'steve',
|
||||
'geometry.creeper': 'creeper/creeper',
|
||||
'geometry.enderman': 'enderman/enderman',
|
||||
'geometry.zombie': 'zombie/zombie',
|
||||
'geometry.zombie.husk': 'zombie/husk',
|
||||
'geometry.zombie.drowned': 'zombie/drowned',
|
||||
'geometry.pigzombie': 'pig/pigzombie',
|
||||
'geometry.pigzombie.baby': 'pig/pigzombie',
|
||||
'geometry.skeleton': 'skeleton/skeleton',
|
||||
'geometry.skeleton.wither': 'skeleton/wither_skeleton',
|
||||
'geometry.skeleton.stray': 'skeleton/stray',
|
||||
'geometry.squid': 'squid',
|
||||
'geometry.spider': 'spider/spider',
|
||||
'geometry.cow': 'cow/cow',
|
||||
'geometry.mooshroom': 'cow/mooshroom',
|
||||
'geometry.sheep.sheared': 'sheep/sheep',
|
||||
'geometry.sheep': 'sheep/sheep',
|
||||
'geometry.phantom': 'phantom',
|
||||
'geometry.pig': 'pig/pig',
|
||||
'geometry.bat': 'bat',
|
||||
'geometry.dolphin': 'dolphin',
|
||||
'geometry.irongolem': 'iron_golem',
|
||||
'geometry.snowgolem': 'snow_golem',
|
||||
'geometry.zombie.villager': 'zombie_villager/zombie_farmer',
|
||||
'geometry.evoker': 'illager/evoker',
|
||||
'geometry.vex': 'vex/vex',
|
||||
'geometry.vindicator': 'vindicator',
|
||||
'geometry.wolf': 'wolf/wolf',
|
||||
'geometry.ocelot': 'cat/ocelot',
|
||||
'geometry.cat': 'cat/siamese',
|
||||
'geometry.trident': 'trident',
|
||||
'geometry.guardian': 'guardian',
|
||||
'geometry.polarbear': 'polarbear',
|
||||
'geometry.turtle': 'sea_turtle',
|
||||
'geometry.villager': 'villager/farmer',
|
||||
'geometry.villager.witch': 'witch',
|
||||
'geometry.witherBoss': 'wither_boss/wither',
|
||||
'geometry.agent': 'agent',
|
||||
'geometry.armor_stand': 'armor_stand',
|
||||
'geometry.parrot': 'parrot/parrot_red_blue',
|
||||
'geometry.bed': 'bed/white',
|
||||
'geometry.player_head': 'steve',
|
||||
'geometry.mob_head': 'skeleton/skeleton',
|
||||
'geometry.dragon_head': 'dragon/dragon',
|
||||
'geometry.boat': 'boat/boat_oak',
|
||||
'geometry.minecart': 'minecart',
|
||||
'geometry.cod': 'fish/fish',
|
||||
'geometry.pufferfish.small': 'fish/pufferfish',
|
||||
'geometry.pufferfish.mid': 'fish/pufferfish',
|
||||
'geometry.pufferfish.large': 'fish/pufferfish',
|
||||
'geometry.salmon': 'fish/salmon',
|
||||
'geometry.tropicalfish_a': 'fish/tropical_a',
|
||||
'geometry.tropicalfish_b': 'fish/tropical_b',
|
||||
'geometry.endermite': 'endermite',
|
||||
'geometry.panda': 'panda/panda',
|
||||
'chicken': 'chicken',
|
||||
'blaze': 'blaze',
|
||||
'llamaspit': 'llama/spit',
|
||||
'llama': 'llama/llama_creamy',
|
||||
'dragon': 'dragon/dragon',
|
||||
'ghast': 'ghast/ghast',
|
||||
'slime': 'slime/slime',
|
||||
'slime.armor': 'slime/slime',
|
||||
'lavaslime': 'slime/magmacube',
|
||||
'silverfish': 'silverfish',
|
||||
'shulker': 'shulker/shulker_undyed',
|
||||
'rabbit': 'rabbit/brown',
|
||||
'horse': 'horse/horse_brown',
|
||||
'horse.v2': 'horse2/horse_brown',
|
||||
'humanoid': 'steve',
|
||||
'creeper': 'creeper/creeper',
|
||||
'enderman': 'enderman/enderman',
|
||||
'zombie': 'zombie/zombie',
|
||||
'zombie.husk': 'zombie/husk',
|
||||
'zombie.drowned': 'zombie/drowned',
|
||||
'pigzombie': 'pig/pigzombie',
|
||||
'pigzombie.baby': 'pig/pigzombie',
|
||||
'skeleton': 'skeleton/skeleton',
|
||||
'skeleton.wither': 'skeleton/wither_skeleton',
|
||||
'skeleton.stray': 'skeleton/stray',
|
||||
'squid': 'squid',
|
||||
'spider': 'spider/spider',
|
||||
'cow': 'cow/cow',
|
||||
'mooshroom': 'cow/mooshroom',
|
||||
'sheep.sheared': 'sheep/sheep',
|
||||
'sheep': 'sheep/sheep',
|
||||
'phantom': 'phantom',
|
||||
'pig': 'pig/pig',
|
||||
'bat': 'bat',
|
||||
'dolphin': 'dolphin',
|
||||
'irongolem': 'iron_golem',
|
||||
'snowgolem': 'snow_golem',
|
||||
'zombie.villager': 'zombie_villager/zombie_farmer',
|
||||
'evoker': 'illager/evoker',
|
||||
'vex': 'vex/vex',
|
||||
'vindicator': 'vindicator',
|
||||
'wolf': 'wolf/wolf',
|
||||
'ocelot': 'cat/ocelot',
|
||||
'cat': 'cat/siamese',
|
||||
'trident': 'trident',
|
||||
'guardian': 'guardian',
|
||||
'polarbear': 'polarbear',
|
||||
'turtle': 'sea_turtle',
|
||||
'villager': 'villager/farmer',
|
||||
'villager.witch': 'witch',
|
||||
'witherBoss': 'wither_boss/wither',
|
||||
'agent': 'agent',
|
||||
'armor_stand': 'armor_stand',
|
||||
'parrot': 'parrot/parrot_red_blue',
|
||||
'bed': 'bed/white',
|
||||
'player_head': 'steve',
|
||||
'mob_head': 'skeleton/skeleton',
|
||||
'dragon_head': 'dragon/dragon',
|
||||
'boat': 'boat/boat_oak',
|
||||
'minecart': 'minecart',
|
||||
'cod': 'fish/fish',
|
||||
'pufferfish.small': 'fish/pufferfish',
|
||||
'pufferfish.mid': 'fish/pufferfish',
|
||||
'pufferfish.large': 'fish/pufferfish',
|
||||
'salmon': 'fish/salmon',
|
||||
'tropicalfish_a': 'fish/tropical_a',
|
||||
'tropicalfish_b': 'fish/tropical_b',
|
||||
'endermite': 'endermite',
|
||||
'panda': 'panda/panda',
|
||||
}
|
||||
var path = textures[mob.split(':')[0]]
|
||||
mob = mob.split(':')[0].replace(/^geometry\./, '')
|
||||
var path = textures[mob]
|
||||
if (!path) {
|
||||
path = mob.split(':')[0].replace('geometry.', '')
|
||||
path = mob
|
||||
}
|
||||
if (path) {
|
||||
var texture_path = Prop.file_path.split(osfs)
|
||||
@ -368,68 +365,30 @@ function findBedrockAnimation() {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
//Writers
|
||||
function saveFile(props) {
|
||||
if (Prop.file_path) {
|
||||
Prop.project_saved = true;
|
||||
setProjectTitle(pathToName(Prop.file_path, false))
|
||||
addRecentProject({name: pathToName(Prop.file_path, true), path: Prop.file_path})
|
||||
var extension = pathToExtension(Prop.file_path)
|
||||
|
||||
if (Blockbench.entity_mode === false) {
|
||||
if (extension === 'jpm') {
|
||||
BarItems.export_optifine_part.trigger()
|
||||
} else {
|
||||
var content = buildBlockModel()
|
||||
fs.writeFile(Prop.file_path, content, function (err) {
|
||||
if (err) {
|
||||
console.log('Error Saving File: '+err)
|
||||
}
|
||||
if (props && props.closeAfter) {
|
||||
preventClosing = false
|
||||
setTimeout(function() {
|
||||
currentwindow.close()
|
||||
}, 12)
|
||||
}
|
||||
Blockbench.showQuickMessage(tl('message.save_file', [pathToName(Prop.file_path, true)]))
|
||||
})
|
||||
}
|
||||
Blockbench.writeFile(Prop.file_path, {
|
||||
project_file: true,
|
||||
content: buildBlockModel()
|
||||
})
|
||||
} else {
|
||||
if (extension === 'jem') {
|
||||
BarItems.export_optifine_full.trigger()
|
||||
} else {
|
||||
var content = buildEntityModel({raw: true})
|
||||
writeFileEntity(content, Prop.file_path)
|
||||
}
|
||||
writeFileEntity(buildEntityModel({raw: true}), Prop.file_path)
|
||||
}
|
||||
} else {
|
||||
if (Blockbench.entity_mode === false) {
|
||||
Blockbench.export({
|
||||
type: 'JSON Model',
|
||||
extensions: ['json'],
|
||||
name: Project.name||'model',
|
||||
startpath: Prop.file_path,
|
||||
custom_writer: function(content, path) {
|
||||
Prop.file_path = path
|
||||
Project.name = pathToName(path, true)
|
||||
saveFile(props)
|
||||
}
|
||||
})
|
||||
BarItems.export_blockmodel.trigger()
|
||||
} else {
|
||||
var content = buildEntityModel({raw: true});
|
||||
Blockbench.export({
|
||||
type: 'JSON Entity Model',
|
||||
extensions: ['json'],
|
||||
name: Project.name,
|
||||
startpath: Prop.file_path,
|
||||
content: content,
|
||||
custom_writer: writeFileEntity
|
||||
})
|
||||
BarItems.export_entity.trigger()
|
||||
}
|
||||
}
|
||||
}
|
||||
function writeFileEntity(content, filepath) {
|
||||
Prop.file_path = filepath
|
||||
var model_name = 'geometry.' + (Project.parent.replace(/^geometry\./, '')||'unknown')
|
||||
fs.readFile(filepath, 'utf-8', function (errx, data) {
|
||||
var obj = {}
|
||||
if (!errx) {
|
||||
@ -482,8 +441,6 @@ function writeFileEntity(content, filepath) {
|
||||
}
|
||||
}
|
||||
}
|
||||
var model_name = Project.parent
|
||||
if (model_name == '') model_name = 'geometry.unknown'
|
||||
obj[model_name] = content
|
||||
content = autoStringify(obj)
|
||||
|
||||
@ -495,6 +452,9 @@ function writeFileEntity(content, filepath) {
|
||||
Prop.project_saved = true;
|
||||
setProjectTitle(pathToName(filepath, false))
|
||||
addRecentProject({name: pathToName(filepath, 'mobs_id'), path: filepath})
|
||||
if (Blockbench.hasFlag('close_after_saving')) {
|
||||
closeBlockbenchWindow()
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
@ -503,18 +463,15 @@ function writeFileObj(content, filepath) {
|
||||
return;
|
||||
}
|
||||
var content = buildOBJModel(pathToName(filepath, false))
|
||||
|
||||
//OBJECT
|
||||
fs.writeFile(filepath, content.obj, function (err) {})
|
||||
|
||||
//MATERIAL
|
||||
fs.writeFile(filepath.split('.obj').join('.mtl'), content.mtl, function (err) {})
|
||||
|
||||
//IMAGES
|
||||
if (settings.obj_textures.value === true) {
|
||||
for (var key in content.images) {
|
||||
var texture = content.images[key]
|
||||
if (content.images.hasOwnProperty(key) && texture.path) {
|
||||
if (texture && texture.path) {
|
||||
if (texture.mode === 'link') {
|
||||
var native_image_instance = nativeImage.createFromPath(texture.path)
|
||||
} else {
|
||||
@ -533,6 +490,8 @@ function writeFileObj(content, filepath) {
|
||||
}
|
||||
Blockbench.showQuickMessage('message.save_obj')
|
||||
}
|
||||
|
||||
|
||||
//Open
|
||||
function readFile(filepath, makeNew) {
|
||||
fs.readFile(filepath, 'utf-8', function (err, data) {
|
||||
@ -552,7 +511,34 @@ function readFile(filepath, makeNew) {
|
||||
function createBackup(init) {
|
||||
setTimeout(createBackup, limitNumber(parseFloat(settings.backup_interval.value), 1, 10e8)*60000)
|
||||
|
||||
var duration = parseInt(settings.backup_retain.value)+1
|
||||
var folder_path = app.app.getPath('userData')+osfs+'backups'
|
||||
var d = new Date()
|
||||
var days = d.getDate() + (d.getMonth()+1)*30.44 + (d.getYear()-100)*365.25
|
||||
|
||||
if (init) {
|
||||
fs.readdir(folder_path, (err, files) => {
|
||||
if (!err) {
|
||||
files.forEach((name, i) => {
|
||||
var date = name.split('_')[1]
|
||||
if (date) {
|
||||
var nums = date.split('.')
|
||||
nums.forEach((n, ni) => {
|
||||
nums[ni] = parseInt(n)
|
||||
})
|
||||
var b_days = nums[0] + nums[1]*30.44 + nums[2]*365.25
|
||||
if (!isNaN(b_days) && days - b_days > duration) {
|
||||
try {
|
||||
fs.unlinkSync(folder_path +osfs+ name)
|
||||
} catch (err) {console.log(err)}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
if (init || elements.length === 0) return;
|
||||
|
||||
var model = buildBlockModel({
|
||||
backup: true,
|
||||
raw: true,
|
||||
@ -561,15 +547,15 @@ function createBackup(init) {
|
||||
comment: false,
|
||||
groups: true
|
||||
})
|
||||
var d = new Date()
|
||||
var file_name = 'backup_'+d.getDate()+'.'+(d.getMonth()+1)+'.'+(d.getYear()-100)+'_'+d.getHours()+'.'+d.getMinutes()
|
||||
var file_path = app.app.getPath('userData')+osfs+'backups'+osfs+file_name+'.json'
|
||||
var file_path = folder_path+osfs+file_name+'.json'
|
||||
|
||||
fs.writeFile(file_path, JSON.stringify(model), function (err) {
|
||||
if (err) {
|
||||
console.log('Error creating backup: '+err)
|
||||
}
|
||||
})
|
||||
//trimBackups
|
||||
}
|
||||
|
||||
//Zoom
|
||||
@ -593,7 +579,7 @@ window.onbeforeunload = function() {
|
||||
}
|
||||
}
|
||||
function showSaveDialog(close) {
|
||||
if (Blockbench.flags.includes('allow_reload')) {
|
||||
if (Blockbench.hasFlag('allow_reload')) {
|
||||
close = false
|
||||
}
|
||||
var unsaved_textures = 0;
|
||||
@ -611,26 +597,29 @@ function showSaveDialog(close) {
|
||||
noLink: true
|
||||
})
|
||||
if (answer === 0) {
|
||||
saveFile({closeAfter: close})
|
||||
return false;
|
||||
if (close === true) {
|
||||
Blockbench.addFlag('close_after_saving')
|
||||
}
|
||||
BarItems.save.trigger()
|
||||
return true;
|
||||
} else if (answer === 2) {
|
||||
return false;
|
||||
} else {
|
||||
if (close === true) {
|
||||
preventClosing = false
|
||||
setTimeout(function() {
|
||||
currentwindow.close()
|
||||
}, 12)
|
||||
closeBlockbenchWindow()
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if (close === true) {
|
||||
preventClosing = false
|
||||
setTimeout(function() {
|
||||
currentwindow.close()
|
||||
}, 12)
|
||||
closeBlockbenchWindow()
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
function closeBlockbenchWindow() {
|
||||
preventClosing = false
|
||||
setTimeout(function() {
|
||||
currentwindow.close()
|
||||
}, 12)
|
||||
}
|
||||
|
228
js/blockbench.js
228
js/blockbench.js
@ -1,4 +1,4 @@
|
||||
const appVersion = '2.2.2'
|
||||
const appVersion = '2.3.0'
|
||||
var osfs = '/'
|
||||
var File, i;
|
||||
const elements = [];
|
||||
@ -24,6 +24,7 @@ const Prop = {
|
||||
project_saved: true,
|
||||
fps: 0,
|
||||
zoom: 100,
|
||||
progress: 0,
|
||||
facing: 'north'
|
||||
}
|
||||
const Project = {
|
||||
@ -118,6 +119,7 @@ function initializeApp() {
|
||||
|
||||
setupInterface()
|
||||
setupDragHandlers()
|
||||
Modes.options.edit.select()
|
||||
Blockbench.setup_successful = true
|
||||
}
|
||||
function setupVue() {
|
||||
@ -196,7 +198,53 @@ function setupVue() {
|
||||
el: '#project_settings',
|
||||
data: {Project}
|
||||
})
|
||||
//project_vue._data.Project = Project
|
||||
|
||||
DisplayMode.vue = new Vue({
|
||||
el: '#display_sliders',
|
||||
data: {
|
||||
slot: new DisplaySlot()
|
||||
},
|
||||
methods: {
|
||||
isMirrored: (axis) => {
|
||||
if (display[display_slot]) {
|
||||
return display[display_slot].scale[axis] < 0;
|
||||
}
|
||||
},
|
||||
change: (axis, channel) => {
|
||||
if (channel === 'scale') {
|
||||
var val = limitNumber(DisplayMode.slot.scale[axis], 0, 4)
|
||||
DisplayMode.slot.scale[axis] = val;
|
||||
if (holding_shift) {
|
||||
DisplayMode.slot.scale[0] = val;
|
||||
DisplayMode.slot.scale[1] = val;
|
||||
DisplayMode.slot.scale[2] = val;
|
||||
}
|
||||
} else if (channel === 'translation') {
|
||||
DisplayMode.slot.translation[axis] = limitNumber(DisplayMode.slot.translation[axis], -80, 80)
|
||||
} else {
|
||||
DisplayMode.slot.rotation[axis] = Math.trimDeg(DisplayMode.slot.rotation[axis])
|
||||
}
|
||||
DisplayMode.updateDisplayBase()
|
||||
},
|
||||
resetChannel: (channel) => {
|
||||
Undo.initEdit({display_slots: [display_slot]})
|
||||
DisplayMode.slot.extend({[channel]: [0, 0, 0]})
|
||||
Undo.finishEdit('reset display')
|
||||
},
|
||||
invert: (axis) => {
|
||||
Undo.initEdit({display_slots: [display_slot]})
|
||||
DisplayMode.slot.mirror[axis] = !DisplayMode.slot.mirror[axis];
|
||||
DisplayMode.slot.update()
|
||||
Undo.finishEdit('mirror display')
|
||||
},
|
||||
start: () => {
|
||||
Undo.initEdit({display_slots: [display_slot]})
|
||||
},
|
||||
save: () => {
|
||||
Undo.finishEdit('change_display')
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
Animator.vue = new Vue({
|
||||
el: '#animations_list',
|
||||
@ -204,7 +252,6 @@ function setupVue() {
|
||||
animations: Animator.animations
|
||||
}
|
||||
})
|
||||
//project_vue._data.Project = Project
|
||||
|
||||
|
||||
Timeline.vue = new Vue({
|
||||
@ -222,13 +269,19 @@ function setupVue() {
|
||||
el: '#status_bar',
|
||||
data: {Prop}
|
||||
})
|
||||
//project_vue._data.Prop = Prop
|
||||
|
||||
Modes.vue = new Vue({
|
||||
el: '#mode_selector',
|
||||
data: {
|
||||
options: Modes.options
|
||||
}
|
||||
})
|
||||
}
|
||||
function canvasGridSize(shift, ctrl) {
|
||||
if (!shift && !ctrl) {
|
||||
return 16 / limitNumber(settings.edit_size.value, 1, 64)
|
||||
return 16 / limitNumber(settings.edit_size.value, 1, 1024)
|
||||
} else if (ctrl && shift) {
|
||||
var basic = 16 / limitNumber(settings.edit_size.value, 1, 64)
|
||||
var basic = 16 / limitNumber(settings.edit_size.value, 1, 1024)
|
||||
var control = 16 / limitNumber(settings.ctrl_size.value, 1, 1024)
|
||||
var shift = 16 / limitNumber(settings.shift_size.value, 1, 1024)
|
||||
control = basic / control
|
||||
@ -281,13 +334,17 @@ function updateSelection() {
|
||||
Transformer.detach()
|
||||
Transformer.hoverAxis = null;
|
||||
|
||||
if (display_mode) {
|
||||
DisplayMode.centerTransformer()
|
||||
}
|
||||
|
||||
elements.forEach(function(obj) {
|
||||
var is_in_selection = selected.includes(obj)
|
||||
if (is_in_selection !== obj.selected) {
|
||||
obj.selected = is_in_selection
|
||||
}
|
||||
if (obj.selected === true) {
|
||||
if (Toolbox.selected.transformerMode !== 'hidden' && obj.visibility === true) {
|
||||
if (Toolbox.selected.transformerMode !== 'hidden' && obj.visibility === true && (Toolbox.selected.transformerMode !== 'rotate' || !Blockbench.entity_mode)) {
|
||||
Transformer.attach(obj.getMesh())
|
||||
}
|
||||
}
|
||||
@ -318,6 +375,9 @@ function updateSelection() {
|
||||
if (settings.origin_size.value > 0 && selected_group.visibility) {
|
||||
selected_group.getMesh().add(rot_origin)
|
||||
}
|
||||
if (Toolbox.selected.transformerMode === 'rotate') {
|
||||
Transformer.attach(selected_group.getMesh())
|
||||
}
|
||||
} else {
|
||||
$('.selection_only#options').css('visibility', 'hidden')
|
||||
}
|
||||
@ -426,6 +486,92 @@ function createSelection() {
|
||||
}
|
||||
hideDialog()
|
||||
}
|
||||
//Modes
|
||||
class Mode extends KeybindItem {
|
||||
constructor(data) {
|
||||
super(data)
|
||||
this.id = data.id;
|
||||
this.name = data.name || tl('mode.'+this.id);
|
||||
this.selected = false
|
||||
this.default_tool = data.default_tool;
|
||||
this.selectCubes = data.selectCubes !== false
|
||||
this.condition = data.condition;
|
||||
this.onSelect = data.onSelect;
|
||||
this.onUnselect = data.onUnselect;
|
||||
this.category = data.category;
|
||||
Modes.options[this.id] = this;
|
||||
}
|
||||
select() {
|
||||
if (typeof Modes.selected.onUnselect === 'function') {
|
||||
Modes.selected.onUnselect()
|
||||
}
|
||||
if (Modes.selected.selected) {
|
||||
Modes.selected.selected = false
|
||||
}
|
||||
if (typeof this.onSelect === 'function') {
|
||||
this.onSelect()
|
||||
}
|
||||
this.selected = true;
|
||||
Modes.id = this.id
|
||||
Modes.selected = this;
|
||||
updateInterface()
|
||||
Canvas.updateRenderSides()
|
||||
resizeWindow()
|
||||
if (BarItems[this.default_tool]) {
|
||||
BarItems[this.default_tool].select()
|
||||
} else {
|
||||
BarItems.move_tool.select()
|
||||
}
|
||||
updateSelection()
|
||||
}
|
||||
trigger() {
|
||||
if (Condition(this.condition)) {
|
||||
this.select()
|
||||
}
|
||||
}
|
||||
}
|
||||
const Modes = {
|
||||
id: 'edit',
|
||||
selected: false,
|
||||
options: {},
|
||||
};
|
||||
BARS.defineActions(function() {
|
||||
new Mode({
|
||||
id: 'edit',
|
||||
default_tool: 'move_tool',
|
||||
keybind: new Keybind({key: 49})
|
||||
})
|
||||
new Mode({
|
||||
id: 'paint',
|
||||
default_tool: 'brush_tool',
|
||||
keybind: new Keybind({key: 50})
|
||||
})
|
||||
new Mode({
|
||||
id: 'display',
|
||||
selectCubes: false,
|
||||
default_tool: 'move_tool',
|
||||
keybind: new Keybind({key: 51}),
|
||||
condition: () => !Blockbench.entity_mode,
|
||||
onSelect: () => {
|
||||
enterDisplaySettings()
|
||||
},
|
||||
onUnselect: () => {
|
||||
exitDisplaySettings()
|
||||
},
|
||||
})
|
||||
new Mode({
|
||||
id: 'animate',
|
||||
default_tool: 'move_tool',
|
||||
keybind: new Keybind({key: 51}),
|
||||
condition: () => Blockbench.entity_mode,
|
||||
onSelect: () => {
|
||||
Animator.join()
|
||||
},
|
||||
onUnselect: () => {
|
||||
Animator.leave()
|
||||
}
|
||||
})
|
||||
})
|
||||
//Misc
|
||||
var Screencam = {
|
||||
fullScreen: function(options, cb) {
|
||||
@ -461,7 +607,7 @@ var Screencam = {
|
||||
var is_gif = dataUrl.substr(5, 9) == 'image/gif'
|
||||
img.src = dataUrl
|
||||
|
||||
var btns = [tl('dialog.save')]
|
||||
var btns = [tl('dialog.cancel'), tl('dialog.save')]
|
||||
if (!is_gif) {
|
||||
btns.push(tl('message.screenshot.clipboard'))
|
||||
}
|
||||
@ -469,10 +615,10 @@ var Screencam = {
|
||||
translateKey: 'screenshot',
|
||||
icon: img,
|
||||
buttons: btns,
|
||||
confirm: 0,
|
||||
cancel: btns.length-1
|
||||
confirm: 1,
|
||||
cancel: 0
|
||||
}, function(result) {
|
||||
if (result === 0) {
|
||||
if (result === 1) {
|
||||
app.dialog.showSaveDialog(currentwindow, {filters: [ {name: tl('data.image'), extensions: [is_gif ? 'gif' : 'png']} ]}, function (fileName) {
|
||||
if (fileName === undefined) {
|
||||
return;
|
||||
@ -480,7 +626,7 @@ var Screencam = {
|
||||
//fs.writeFile(fileName, screenshot.toPNG(), function (err) {})
|
||||
fs.writeFile(fileName, Buffer(dataUrl.split(',')[1],'base64'), err => {})
|
||||
})
|
||||
} else if (result === 1) {
|
||||
} else if (result === 2) {
|
||||
clipboard.writeImage(screenshot)
|
||||
}
|
||||
})
|
||||
@ -501,31 +647,81 @@ var Screencam = {
|
||||
if (typeof options !== 'object') {
|
||||
options = {}
|
||||
}
|
||||
if (!options.length) {
|
||||
options.length = 1000
|
||||
}
|
||||
var interval = options.fps ? (1000/options.fps) : 100
|
||||
var gif = new GIF({
|
||||
repeat: options.repeat,
|
||||
quality: options.quality,
|
||||
transparent: 0x000000,
|
||||
})
|
||||
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 = () => {
|
||||
if (!options.silent) {
|
||||
Blockbench.setProgress(0)
|
||||
Blockbench.setStatusBarText()
|
||||
}
|
||||
Screencam.returnScreenshot(reader.result, cb)
|
||||
}
|
||||
reader.readAsDataURL(blob)
|
||||
})
|
||||
gif.addFrame(quad_previews.current.canvas)
|
||||
if (!options.silent) {
|
||||
Blockbench.setStatusBarText(tl('status_bar.recording_gif'))
|
||||
gif.on('progress', Blockbench.setProgress)
|
||||
}
|
||||
var frames = 0;
|
||||
var loop = setInterval(() => {
|
||||
gif.addFrame(quad_previews.current.canvas, {delay: interval})
|
||||
var img = new Image()
|
||||
img.src = quad_previews.current.canvas.toDataURL()
|
||||
img.onload = () => {
|
||||
gif.addFrame(img, {delay: interval})
|
||||
}
|
||||
Blockbench.setProgress(interval*frames/options.length)
|
||||
frames++;
|
||||
}, interval)
|
||||
|
||||
setTimeout(() => {
|
||||
clearInterval(loop)
|
||||
if (!options.silent) {
|
||||
Blockbench.setStatusBarText(tl('status_bar.processing_gif'))
|
||||
}
|
||||
gif.render()
|
||||
if (Animator.open && Timeline.playing) {
|
||||
Timeline.pause()
|
||||
}
|
||||
}, options.length || 1000)
|
||||
}, options.length)
|
||||
}
|
||||
}
|
||||
var Clipbench = {
|
||||
@ -974,6 +1170,7 @@ const entityMode = {
|
||||
//UI Changes
|
||||
$('.block_mode_only').hide()
|
||||
$('.entity_mode_only').show()
|
||||
Modes.options.edit.select()
|
||||
//UV
|
||||
main_uv.buildDom().setToMainSlot().setFace('north')
|
||||
main_uv.autoGrid = true
|
||||
@ -999,6 +1196,7 @@ const entityMode = {
|
||||
//UI Changes
|
||||
$('.block_mode_only').show()
|
||||
$('.entity_mode_only').hide()
|
||||
Modes.options.edit.select()
|
||||
//Update
|
||||
if (textures.length) {
|
||||
textures[0].load()
|
||||
|
338
js/display.js
338
js/display.js
@ -11,8 +11,60 @@ const DisplayMode = {};
|
||||
|
||||
|
||||
|
||||
(function() {
|
||||
class DisplaySlot {
|
||||
constructor(id, data) {
|
||||
this.rotation = [0, 0, 0];
|
||||
this.translation = [0, 0, 0];
|
||||
this.scale = [1, 1, 1];
|
||||
this.mirror = [false, false, false]
|
||||
if (data) this.extend(data)
|
||||
}
|
||||
copy() {
|
||||
return {
|
||||
rotation: this.rotation.slice(),
|
||||
translation: this.translation.slice(),
|
||||
scale: this.scale.slice(),
|
||||
mirror: this.mirror.slice()
|
||||
}
|
||||
}
|
||||
export() {
|
||||
var build = {}
|
||||
if (!this.rotation.allEqual(0)) build.rotation = this.rotation
|
||||
if (!this.translation.allEqual(0)) build.translation = this.translation
|
||||
if (!this.scale.allEqual(1) || !this.mirror.allEqual(false)) {
|
||||
build.scale = this.scale.slice()
|
||||
if (!this.mirror.allEqual(false)) {
|
||||
build.scale.forEach((s, i) => {
|
||||
build.scale[i] *= s ? -1 : 1;
|
||||
})
|
||||
}
|
||||
}
|
||||
if (Object.keys(build).length) {
|
||||
return build;
|
||||
}
|
||||
}
|
||||
extend(data) {
|
||||
if (!data) return this;
|
||||
for (var i = 0; i < 3; i++) {
|
||||
if (data.rotation) Merge.number(this.rotation, data.rotation, i)
|
||||
if (data.translation) Merge.number(this.translation, data.translation, i)
|
||||
if (data.mirror) Merge.boolean(this.mirror, data.mirror, i)
|
||||
if (data.scale) Merge.number(this.scale, data.scale, i)
|
||||
if (data.scale && data.scale[i] < 0) this.mirror[i] = true;
|
||||
}
|
||||
this.update()
|
||||
return this;
|
||||
}
|
||||
update() {
|
||||
if (this === DisplayMode.slot) {
|
||||
DisplayMode.vue.$forceUpdate()
|
||||
DisplayMode.updateDisplayBase()
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
(function() {
|
||||
|
||||
class refModel {
|
||||
constructor(id) {
|
||||
@ -1223,20 +1275,22 @@ enterDisplaySettings = function() { //Enterung Display Setting Mode, changes th
|
||||
display_preview.setNormalCamera()
|
||||
display_preview.camPers.position.set(-80, 40, -30)
|
||||
display_preview.camPers.setFocalLength(45)
|
||||
|
||||
|
||||
$('body').addClass('display_mode')
|
||||
$('.m_edit').hide()
|
||||
$('.m_disp').show()
|
||||
$('#display_bar input#thirdperson_righthand').prop("checked", true)
|
||||
updateInterface()
|
||||
//return;
|
||||
|
||||
DisplayMode.loadThirdRight()
|
||||
|
||||
buildGrid()
|
||||
setShading()
|
||||
DisplayMode.loadThirdRight()
|
||||
Canvas.updateRenderSides()
|
||||
resizeWindow()
|
||||
display_area.updateMatrixWorld()
|
||||
display_base.updateMatrixWorld()
|
||||
DisplayMode.centerTransformer()
|
||||
if (outlines.children.length) {
|
||||
outlines.children.length = 0
|
||||
Canvas.updateAllPositions()
|
||||
@ -1260,6 +1314,7 @@ exitDisplaySettings = function() { //Enterung Display Setting Mode, changes the
|
||||
if (quad_previews.enabled_before) {
|
||||
openQuadView()
|
||||
}
|
||||
scene.add(Transformer)
|
||||
buildGrid()
|
||||
setShading()
|
||||
Canvas.updateRenderSides()
|
||||
@ -1276,135 +1331,51 @@ function axisIndex(index) {
|
||||
}
|
||||
}
|
||||
function resetDisplayBase() {
|
||||
display_base.rotation['x'] = Math.PI / (180 / 0.1);
|
||||
display_base.rotation['y'] = Math.PI / (180 / 0.1);
|
||||
display_base.rotation['z'] = Math.PI / (180 / 0.1);
|
||||
|
||||
display_base.position['x'] = 0;
|
||||
display_base.position['y'] = 0;
|
||||
display_base.position['z'] = 0;
|
||||
|
||||
display_base.scale['x'] = 1;
|
||||
display_base.scale['y'] = 1;
|
||||
display_base.scale['z'] = 1;
|
||||
display_base.rotation.x = Math.PI / (180 / 0.1);
|
||||
display_base.rotation.y = Math.PI / (180 / 0.1);
|
||||
display_base.rotation.z = Math.PI / (180 / 0.1);
|
||||
display_base.position.x = 0;
|
||||
display_base.position.y = 0;
|
||||
display_base.position.z = 0;
|
||||
display_base.scale.x = 1;
|
||||
display_base.scale.y = 1;
|
||||
display_base.scale.z = 1;
|
||||
}
|
||||
|
||||
DisplayMode.centerTransformer = function() {
|
||||
display_scene.add(Transformer)
|
||||
Transformer.attach(display_base)
|
||||
|
||||
DisplayMode.syncDispInput = function(obj, sender, axis, event) {//Syncs Range and Input, calls the change functions
|
||||
var val = $(obj).val()
|
||||
var range_val;
|
||||
if (typeof val === 'string' || val instanceof String) {
|
||||
val = parseFloat(val.replace(/[^-.0-9]/g, ""))
|
||||
}
|
||||
if (isNaN(val)) val = 0
|
||||
display_base.getWorldPosition(Transformer.position)
|
||||
|
||||
if (sender === 'rotation') {
|
||||
val = limitNumber(val, -180, 180)
|
||||
$(obj).siblings('input').val(val)
|
||||
dispRotate(val, axis)
|
||||
return;
|
||||
} else if (sender === 'translation') {
|
||||
val = limitNumber(val, -80, 80)
|
||||
$(obj).siblings('input').val(val);
|
||||
dispTranslate(val, axis)
|
||||
return;
|
||||
} else if (sender === 'scaleRange') {
|
||||
//From Range to Real
|
||||
range_val = val
|
||||
if (val >= 0) {
|
||||
val = (val*(3/4))+1
|
||||
if (val >=4) val = 4
|
||||
} else {
|
||||
val = (val+4)/4
|
||||
}
|
||||
$(obj).parent().find('input.scale').val(val)
|
||||
|
||||
} else if (sender === 'scale') {
|
||||
//From Input(Real) to Range
|
||||
if (display[display_slot].scale == undefined) {
|
||||
display[display_slot].scale = [1,1,1]
|
||||
}
|
||||
if (val >= 1) {
|
||||
range_val = (Math.abs(val)-1)*(4/3)
|
||||
} else {
|
||||
range_val =(Math.abs(val)*4)-4
|
||||
}
|
||||
}
|
||||
|
||||
if (holding_shift === true) {
|
||||
dispScale(val, 'x')
|
||||
dispScale(val, 'y')
|
||||
dispScale(val, 'z')
|
||||
$('.panel#display input.scale').val(Math.abs(val))
|
||||
$('.panel#display input.scaleRange').val(range_val)
|
||||
if (Toolbox.selected.transformerMode === 'translate') {
|
||||
Transformer.rotation.copy(display_area.rotation)
|
||||
} else if (Toolbox.selected.transformerMode === 'scale') {
|
||||
var q = display_base.getWorldQuaternion(new THREE.Quaternion())
|
||||
Transformer.rotation.setFromQuaternion(q)
|
||||
} else {
|
||||
dispScale(val, axis)
|
||||
$(obj).parent().find('input.scaleRange').val(range_val)
|
||||
Transformer.rotation.set(0, 0, 0)
|
||||
}
|
||||
Transformer.update()
|
||||
}
|
||||
DisplayMode.syncDispMirror = function(node, axis) {
|
||||
if (!display[display_slot].scale) {
|
||||
return;
|
||||
}
|
||||
var axis = (node.id||'x').substr(-1)
|
||||
display_base.scale[axis] = display[display_slot].scale[axisIndex(axis)] *= -1
|
||||
DisplayMode.load(display_slot)
|
||||
}
|
||||
function dispRotate(val, axis) { //Change the actual thing
|
||||
if (display[display_slot].rotation == undefined) {
|
||||
display[display_slot].rotation = [0,0,0]
|
||||
}
|
||||
display[display_slot].rotation[axisIndex(axis)] = val
|
||||
if (display_slot === 'thirdperson_lefthand' && axis === 'y') val *= (-1)
|
||||
if (display_slot === 'firstperson_lefthand' && axis === 'y') val *= (-1)
|
||||
if (display_slot === 'thirdperson_lefthand' && axis === 'z') val *= (-1)
|
||||
if (display_slot === 'firstperson_lefthand' && axis === 'z') val *= (-1)
|
||||
display_base.rotation[axis] = Math.PI / (180 / val);
|
||||
}
|
||||
function dispTranslate(val, axis) { //Change the actual thing
|
||||
if (display[display_slot].translation == undefined) {
|
||||
display[display_slot].translation = [0,0,0]
|
||||
}
|
||||
display[display_slot].translation[axisIndex(axis)] = val
|
||||
if (display_slot === 'thirdperson_lefthand' && axis === 'x') val *= (-1)
|
||||
if (display_slot === 'firstperson_lefthand' && axis === 'x') val *= (-1)
|
||||
display_base.position[axis] = val
|
||||
}
|
||||
function dispScale(val, axis) { //Change the actual thing
|
||||
if (display[display_slot].scale == undefined) {
|
||||
display[display_slot].scale = [1,1,1]
|
||||
}
|
||||
var scale_tag = display[display_slot].scale
|
||||
var is_inverse = scale_tag[axisIndex(axis)] < 0
|
||||
DisplayMode.updateDisplayBase = function(slot) {
|
||||
if (!slot) slot = display[display_slot]
|
||||
|
||||
val = limitNumber(val, 0.001, 4)
|
||||
scale_tag[axisIndex(axis)] = val * (is_inverse ? -1 : 1)
|
||||
if (val == 0) val = 0.001
|
||||
display_base.scale[axis] = val * (is_inverse ? -1 : 1)
|
||||
display_base.rotation.x = Math.PI / (180 / slot.rotation[0]);
|
||||
display_base.rotation.y = Math.PI / (180 / slot.rotation[1]) * (display_slot.includes('lefthand') ? -1 : 1);
|
||||
display_base.rotation.z = Math.PI / (180 / slot.rotation[2]) * (display_slot.includes('lefthand') ? -1 : 1);
|
||||
|
||||
display_base.position.x = slot.translation[0] * (display_slot.includes('lefthand') ? -1 : 1);
|
||||
display_base.position.y = slot.translation[1];
|
||||
display_base.position.z = slot.translation[2];
|
||||
|
||||
display_base.scale.x = (slot.scale[0]||0.001) * (slot.mirror[0] ? -1 : 1);
|
||||
display_base.scale.y = (slot.scale[1]||0.001) * (slot.mirror[1] ? -1 : 1);
|
||||
display_base.scale.z = (slot.scale[2]||0.001) * (slot.mirror[2] ? -1 : 1);
|
||||
|
||||
DisplayMode.centerTransformer()
|
||||
}
|
||||
|
||||
DisplayMode.resetDisplaySettings = function(key) {
|
||||
delete display[display_slot][key]
|
||||
$('input#'+key+'_x').val(0)
|
||||
$('input#'+key+'_y').val(0)
|
||||
$('input#'+key+'_z').val(0)
|
||||
if (key == 'rotation') {
|
||||
display_base.rotation.x = Math.PI / (180 / 0);
|
||||
display_base.rotation.y = Math.PI / (180 / 0);
|
||||
display_base.rotation.z = Math.PI / (180 / 0);
|
||||
} else if (key == 'translation') {
|
||||
display_base.position.x = 0
|
||||
display_base.position.y = 0
|
||||
display_base.position.z = 0
|
||||
} else if (key == 'scale') {
|
||||
$('input#scale_x.scale').val(1)
|
||||
$('input#scale_y.scale').val(1)
|
||||
$('input#scale_z.scale').val(1)
|
||||
display_base.scale.x = 1
|
||||
display_base.scale.y = 1
|
||||
display_base.scale.z = 1
|
||||
}
|
||||
}
|
||||
|
||||
DisplayMode.applyPreset = function(preset, all) {
|
||||
if (preset == undefined) return;
|
||||
@ -1415,12 +1386,12 @@ DisplayMode.applyPreset = function(preset, all) {
|
||||
Blockbench.showQuickMessage('message.preset_no_info')
|
||||
return;
|
||||
};
|
||||
Undo.initEdit({display_slots: slots})
|
||||
slots.forEach(function(sl) {
|
||||
if (!preset.areas[sl]) return;
|
||||
if (typeof display[sl] !== 'object') display[sl] = {}
|
||||
$.extend(true, display[sl], preset.areas[sl])
|
||||
DisplayMode.slot.extend(preset.areas[sl])
|
||||
})
|
||||
DisplayMode.load(display_slot)
|
||||
DisplayMode.updateDisplayBase()
|
||||
Undo.finishEdit('apply display preset')
|
||||
}
|
||||
DisplayMode.createPreset = function() {
|
||||
var name = $('input#preset_name').val()
|
||||
@ -1435,12 +1406,19 @@ DisplayMode.createPreset = function() {
|
||||
|
||||
displayReferenceObjects.slots.forEach(function(s) {
|
||||
if ($('#'+s+'_save').is(':checked')) {
|
||||
preset.areas[s] = display[s]
|
||||
preset.areas[s] = display[s].copy()
|
||||
}
|
||||
})
|
||||
hideDialog()
|
||||
localStorage.setItem('display_presets', JSON.stringify(display_presets))
|
||||
}
|
||||
DisplayMode.loadJSON = function(data) {
|
||||
for (var slot in data) {
|
||||
if (displayReferenceObjects.slots.includes(slot)) {
|
||||
display[slot] = new DisplaySlot().extend(data[slot])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var setDisplayArea = DisplayMode.setBase = function(x, y, z, rx, ry, rz, sx, sy, sz) {//Sets the Work Area to the given Space
|
||||
@ -1455,39 +1433,22 @@ var setDisplayArea = DisplayMode.setBase = function(x, y, z, rx, ry, rz, sx, sy,
|
||||
display_area.scale['x'] = sx;
|
||||
display_area.scale['y'] = sy;
|
||||
display_area.scale['z'] = sz;
|
||||
|
||||
display_area.updateMatrixWorld()
|
||||
|
||||
DisplayMode.centerTransformer()
|
||||
}
|
||||
DisplayMode.groundAnimation = function() {
|
||||
display_area.rotation.y += 0.015
|
||||
ground_timer += 1
|
||||
display_area.position.y = 13.5 + Math.sin(Math.PI * (ground_timer / 100)) * Math.PI/2
|
||||
DisplayMode.centerTransformer()
|
||||
if (ground_timer === 200) ground_timer = 0;
|
||||
}
|
||||
|
||||
function getDisplayNumber(key, mode, axis) {
|
||||
var def = 0
|
||||
if (mode == 'scale') {
|
||||
def = 1
|
||||
}
|
||||
if (display[key] == undefined) {
|
||||
return def;
|
||||
}
|
||||
if (display[key][mode] == undefined) {
|
||||
return def;
|
||||
}
|
||||
if (display[key][mode][axis] != undefined) {
|
||||
var val = display[key][mode][axis];
|
||||
if (mode == 'scale' && val == 0) {
|
||||
val = 0.001;
|
||||
}
|
||||
return val;
|
||||
} else {
|
||||
return def;
|
||||
}
|
||||
}
|
||||
function loadDisp(key) { //Loads The Menu and slider values, common for all Radio Buttons
|
||||
display_slot = key
|
||||
//enterScene(key)
|
||||
resetDisplayBase()
|
||||
|
||||
if (key !== 'gui' && display_preview.isOrtho === true) {
|
||||
display_preview.setNormalCamera()
|
||||
}
|
||||
@ -1498,37 +1459,12 @@ function loadDisp(key) { //Loads The Menu and slider values, common for all Radi
|
||||
display_preview.camPers.setFocalLength(45)
|
||||
|
||||
if (display[key] == undefined) {
|
||||
display[key] = {}
|
||||
display[key] = new DisplaySlot()
|
||||
}
|
||||
$('input#rotation_x').val(getDisplayNumber(key, 'rotation', 0))
|
||||
$('input#rotation_y').val(getDisplayNumber(key, 'rotation', 1))
|
||||
$('input#rotation_z').val(getDisplayNumber(key, 'rotation', 2))
|
||||
|
||||
$('input#translation_x').val(getDisplayNumber(key, 'translation', 0))
|
||||
$('input#translation_y').val(getDisplayNumber(key, 'translation', 1))
|
||||
$('input#translation_z').val(getDisplayNumber(key, 'translation', 2))
|
||||
|
||||
$('input#scale_x').val(Math.abs(getDisplayNumber(key, 'scale', 0)))
|
||||
$('input#scale_y').val(Math.abs(getDisplayNumber(key, 'scale', 1)))
|
||||
$('input#scale_z').val(Math.abs(getDisplayNumber(key, 'scale', 2)))
|
||||
DisplayMode.syncDispInput($('input#scale_x'), 'scale')
|
||||
DisplayMode.syncDispInput($('input#scale_y'), 'scale')
|
||||
DisplayMode.syncDispInput($('input#scale_z'), 'scale')
|
||||
$('#display_scale_invert_x i').text(getDisplayNumber(key, 'scale', 0) > 0 ? 'check_box_outline_blank' : 'check_box')
|
||||
$('#display_scale_invert_y i').text(getDisplayNumber(key, 'scale', 1) > 0 ? 'check_box_outline_blank' : 'check_box')
|
||||
$('#display_scale_invert_z i').text(getDisplayNumber(key, 'scale', 2) > 0 ? 'check_box_outline_blank' : 'check_box')
|
||||
|
||||
display_base.rotation['x'] = Math.PI / (180 / getDisplayNumber(key, 'rotation', 0));
|
||||
display_base.rotation['y'] = Math.PI / (180 / getDisplayNumber(key, 'rotation', 1));
|
||||
display_base.rotation['z'] = Math.PI / (180 / getDisplayNumber(key, 'rotation', 2));
|
||||
|
||||
display_base.position['x'] = getDisplayNumber(key, 'translation', 0);
|
||||
display_base.position['y'] = getDisplayNumber(key, 'translation', 1);
|
||||
display_base.position['z'] = getDisplayNumber(key, 'translation', 2);
|
||||
|
||||
display_base.scale['x'] = getDisplayNumber(key, 'scale', 0);
|
||||
display_base.scale['y'] = getDisplayNumber(key, 'scale', 1);
|
||||
display_base.scale['z'] = getDisplayNumber(key, 'scale', 2);
|
||||
DisplayMode.vue._data.slot = display[key]
|
||||
DisplayMode.slot = display[key]
|
||||
DisplayMode.updateDisplayBase()
|
||||
DisplayMode.centerTransformer()
|
||||
|
||||
}
|
||||
DisplayMode.loadThirdRight = function() { //Loader
|
||||
@ -1537,9 +1473,6 @@ DisplayMode.loadThirdRight = function() { //Loader
|
||||
}
|
||||
DisplayMode.loadThirdLeft = function() { //Loader
|
||||
loadDisp('thirdperson_lefthand')
|
||||
display_base.position['x'] = -getDisplayNumber('thirdperson_lefthand', 'translation', 0)
|
||||
display_base.rotation['y'] = Math.PI / (180 / -getDisplayNumber('thirdperson_lefthand', 'rotation', 1))
|
||||
display_base.rotation['z'] = Math.PI / (180 / -getDisplayNumber('thirdperson_lefthand', 'rotation', 2))
|
||||
displayReferenceObjects.bar(['player', 'zombie', 'baby_zombie', 'armor_stand', 'armor_stand_small'])
|
||||
}
|
||||
DisplayMode.loadFirstRight = function() { //Loader
|
||||
@ -1554,9 +1487,6 @@ DisplayMode.loadFirstRight = function() { //Loader
|
||||
}
|
||||
DisplayMode.loadFirstLeft = function() { //Loader
|
||||
loadDisp('firstperson_lefthand')
|
||||
display_base.position['x'] = -getDisplayNumber('firstperson_lefthand', 'translation', 0)
|
||||
display_base.rotation['y'] = Math.PI / (180 / -getDisplayNumber('firstperson_lefthand', 'rotation', 1))
|
||||
display_base.rotation['z'] = Math.PI / (180 / -getDisplayNumber('firstperson_lefthand', 'rotation', 2))
|
||||
setDisplayArea(-20.5, -8.4, -9, 0, 270, 0, 1,1,1)
|
||||
display_preview.camPers.setFocalLength(12)
|
||||
display_preview.camPers.position.set(-32.4, 0, 0)
|
||||
@ -1621,36 +1551,11 @@ DisplayMode.load = function(slot) {
|
||||
}
|
||||
|
||||
DisplayMode.copy = function() {
|
||||
var base_setting = {rotation: [0, 0, 0], translation: [0, 0, 0], scale: [1, 1, 1]}
|
||||
$.extend(true, base_setting, display[display_slot])
|
||||
display_clipboard = base_setting
|
||||
display_clipboard = DisplayMode.slot.copy()
|
||||
}
|
||||
DisplayMode.paste = function() {
|
||||
if (display_clipboard == undefined) return;
|
||||
|
||||
if (typeof display_clipboard.rotation === 'object' && display_clipboard.rotation.join('_') === '0_0_0') {
|
||||
delete display[display_slot].rotation;
|
||||
} else {
|
||||
display[display_slot].rotation = display_clipboard.rotation.slice();
|
||||
}
|
||||
|
||||
if (typeof display_clipboard.translation === 'object' && display_clipboard.translation.join('_') === '0_0_0') {
|
||||
delete display[display_slot].translation;
|
||||
} else {
|
||||
display[display_slot].translation = display_clipboard.translation.slice();
|
||||
}
|
||||
|
||||
if (typeof display_clipboard.scale === 'object' && display_clipboard.scale.join('_') === '1_1_1') {
|
||||
delete display[display_slot].scale;
|
||||
} else {
|
||||
display[display_slot].scale = display_clipboard.scale.slice();
|
||||
}
|
||||
/*
|
||||
var clear_content = {}
|
||||
$.extend(true, clear_content, display_clipboard)
|
||||
$.extend(true, display[slot], clear_content)
|
||||
*/
|
||||
DisplayMode.load(display_slot)
|
||||
DisplayMode.slot.extend(display_clipboard)
|
||||
DisplayMode.updateDisplayBase()
|
||||
}
|
||||
|
||||
window.changeDisplaySkin = function() {
|
||||
@ -1767,9 +1672,6 @@ function updateDisplaySkin() {
|
||||
}
|
||||
//displayReferenceObjects.refmodels.player.material
|
||||
}
|
||||
BARS.defineActions(function() {
|
||||
|
||||
})
|
||||
BARS.defineActions(function() {
|
||||
new Action({
|
||||
id: 'add_display_preset',
|
||||
|
@ -230,6 +230,18 @@ class OutlinerElement {
|
||||
scope.name = '_&/3%6-7A';
|
||||
scope.name = old_name;
|
||||
}
|
||||
getDepth() {
|
||||
var d = 0;
|
||||
function it(p) {
|
||||
if (p.parent) {
|
||||
d++;
|
||||
return it(p.parent)
|
||||
} else {
|
||||
return d-1;
|
||||
}
|
||||
}
|
||||
return it(this)
|
||||
}
|
||||
rename() {
|
||||
this.showInOutliner()
|
||||
var obj = $('#'+this.uuid+' > div.outliner_object > input.cube_name')
|
||||
@ -241,6 +253,27 @@ class OutlinerElement {
|
||||
this.old_name = this.name
|
||||
return this;
|
||||
}
|
||||
saveName(save) {
|
||||
var scope = this;
|
||||
if (save !== false && scope.name.length > 0) {
|
||||
var name = scope.name
|
||||
scope.name = scope.old_name
|
||||
if (scope.type === 'cube') {
|
||||
Undo.initEdit({cubes: [scope]})
|
||||
} else {
|
||||
Undo.initEdit({outliner: true})
|
||||
}
|
||||
scope.name = name
|
||||
delete scope.old_name
|
||||
if (Blockbench.entity_mode && scope.type === 'group') {
|
||||
scope.createUniqueName()
|
||||
}
|
||||
Undo.finishEdit('rename')
|
||||
} else {
|
||||
scope.name = scope.old_name
|
||||
delete scope.old_name
|
||||
}
|
||||
}
|
||||
isIconEnabled(btn) {
|
||||
switch (btn.id) {
|
||||
case 'visibility':
|
||||
@ -352,6 +385,7 @@ class Cube extends OutlinerElement {
|
||||
return this.rotation_axis;
|
||||
}
|
||||
}
|
||||
return this.rotation_axis;
|
||||
}
|
||||
getMesh() {
|
||||
return Canvas.meshes[this.uuid]
|
||||
@ -374,7 +408,7 @@ class Cube extends OutlinerElement {
|
||||
} else {
|
||||
starting_point = true
|
||||
}
|
||||
if (s.type === 'cube') {
|
||||
if (s.type !== 'group') {
|
||||
if (!selected.includes(s)) {
|
||||
selected.push(s)
|
||||
just_selected.push(s)
|
||||
@ -383,7 +417,7 @@ class Cube extends OutlinerElement {
|
||||
s.selectLow()
|
||||
}
|
||||
} else if (starting_point) {
|
||||
if (s.type === 'cube') {
|
||||
if (s.type !== 'group') {
|
||||
if (!selected.includes(s)) {
|
||||
selected.push(s)
|
||||
just_selected.push(s)
|
||||
@ -702,7 +736,7 @@ class Cube extends OutlinerElement {
|
||||
setColor(index) {
|
||||
this.color = index;
|
||||
if (this.visibility) {
|
||||
Canvas.adaptObjectFaces(obj)
|
||||
Canvas.adaptObjectFaces(this)
|
||||
}
|
||||
}
|
||||
showContextMenu(event) {
|
||||
@ -933,8 +967,10 @@ class Cube extends OutlinerElement {
|
||||
|
||||
Undo.initEdit({outliner: true, cubes: [], selection: true});
|
||||
cube.forSelected(function(obj) {
|
||||
obj.duplicate()
|
||||
obj.duplicate(false)
|
||||
})
|
||||
updateSelection()
|
||||
loadOutlinerDraggable()
|
||||
Undo.finishEdit('duplicate', {outliner: true, cubes: selected, selection: true})
|
||||
}},
|
||||
{name: 'generic.rename', icon: 'text_format', click: function(cube) {
|
||||
@ -1162,8 +1198,26 @@ class Group extends OutlinerElement {
|
||||
Undo.finishEdit('removed_group')
|
||||
}
|
||||
}
|
||||
index() {
|
||||
return -1;
|
||||
createUniqueName() {
|
||||
var scope = this;
|
||||
var others = getAllOutlinerGroups();
|
||||
var name = this.name.replace(/\d+$/, '');
|
||||
function check(n) {
|
||||
for (var i = 0; i < others.length; i++) {
|
||||
if (others[i] !== scope && others[i].name == n) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (check(this.name)) {
|
||||
return this.name;
|
||||
}
|
||||
for (var num = 2; num < 256; num++) {
|
||||
if (check(name+num)) {
|
||||
scope.name = name+num;
|
||||
return scope.name;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
resolve() {
|
||||
var scope = this;
|
||||
@ -1238,6 +1292,7 @@ class Group extends OutlinerElement {
|
||||
} else if (destination !== 'cache') {
|
||||
base_group.addTo(destination, false)
|
||||
}
|
||||
base_group.createUniqueName()
|
||||
Canvas.updatePositions()
|
||||
loadOutlinerDraggable()
|
||||
return base_group;
|
||||
@ -1735,6 +1790,9 @@ function addGroup() {
|
||||
var base_group = new Group({
|
||||
origin: add_group ? add_group.origin : undefined
|
||||
})
|
||||
if (Blockbench.entity_mode) {
|
||||
base_group.createUniqueName()
|
||||
}
|
||||
selected.forEach(function(s, i) {
|
||||
s.addTo(base_group, false)
|
||||
if (i === 0) {
|
||||
@ -1806,23 +1864,9 @@ function renameCubes(element) {
|
||||
function stopRenameCubes(save) {
|
||||
if (Blockbench.hasFlag('renaming')) {
|
||||
var uuid = $('.outliner_object input.renaming').parent().parent().attr('id')
|
||||
if (uuid) {
|
||||
var element = TreeElements.findRecursive('uuid', uuid)
|
||||
if (save !== false && element.name.length > 0) {
|
||||
var name = element.name
|
||||
element.name = element.old_name
|
||||
if (element.type === 'cube') {
|
||||
Undo.initEdit({cubes: [element]})
|
||||
} else {
|
||||
Undo.initEdit({outliner: true})
|
||||
}
|
||||
element.name = name
|
||||
delete element.old_name
|
||||
Undo.finishEdit('rename')
|
||||
} else {
|
||||
element.name = element.old_name
|
||||
delete element.old_name
|
||||
}
|
||||
var element = TreeElements.findRecursive('uuid', uuid)
|
||||
if (element) {
|
||||
element.saveName(save)
|
||||
}
|
||||
$('.outliner_object input.renaming').attr('disabled', true).removeClass('renaming')
|
||||
$('body').focus()
|
||||
|
@ -86,6 +86,11 @@ class Panel {
|
||||
var show = BARS.condition(this.condition)
|
||||
if (show) {
|
||||
$(this.node).show()
|
||||
if (Interface.data.left_bar.includes(this.id)) {
|
||||
this.width = Interface.data.left_bar_width
|
||||
} else if (Interface.data.right_bar.includes(this.id)) {
|
||||
this.width = Interface.data.right_bar_width
|
||||
}
|
||||
if (this.onResize) this.onResize()
|
||||
} else {
|
||||
$(this.node).hide()
|
||||
@ -99,6 +104,7 @@ class ResizeLine {
|
||||
this.horizontal = data.horizontal === true
|
||||
this.position = data.position
|
||||
this.condition = data.condition
|
||||
this.width = 0;
|
||||
var jq = $('<div class="resizer '+(data.horizontal ? 'horizontal' : 'vertical')+'"></div>')
|
||||
this.node = jq.get(0)
|
||||
$('body').append(this.node)
|
||||
@ -175,7 +181,7 @@ var Interface = {
|
||||
},
|
||||
get: function() {return Interface.data.left_bar_width},
|
||||
set: function(o, diff) {
|
||||
Interface.data.left_bar_width = limitNumber(o + diff, 64, $(window).width()- 240 - Interface.data.right_bar_width)
|
||||
Interface.data.left_bar_width = limitNumber(o + diff, 128, $(window).width()- 240 - Interface.data.right_bar_width)
|
||||
},
|
||||
position: function(line) {
|
||||
line.setPosition({
|
||||
@ -196,7 +202,7 @@ var Interface = {
|
||||
},
|
||||
get: function() {return Interface.data.right_bar_width},
|
||||
set: function(o, diff) {
|
||||
Interface.data.right_bar_width = limitNumber(o - diff, 64, $(window).width()- 240 - Interface.data.left_bar_width)
|
||||
Interface.data.right_bar_width = limitNumber(o - diff, 128, $(window).width()- 240 - Interface.data.left_bar_width)
|
||||
},
|
||||
position: function(line) {
|
||||
line.setPosition({
|
||||
@ -298,6 +304,9 @@ function setupInterface() {
|
||||
toolbars: {
|
||||
head: Toolbars.outliner
|
||||
},
|
||||
onResize: t => {
|
||||
getAllOutlinerObjects().forEach(o => o.updateElement())
|
||||
},
|
||||
menu: new Menu([
|
||||
'add_cube',
|
||||
'add_group',
|
||||
@ -349,6 +358,7 @@ function setupInterface() {
|
||||
Interface.status_bar.menu = new Menu([
|
||||
'project_window',
|
||||
'open_model_folder',
|
||||
'open_backup_folder',
|
||||
'save'
|
||||
])
|
||||
|
||||
@ -407,6 +417,7 @@ function setupInterface() {
|
||||
})
|
||||
|
||||
//Scrolling
|
||||
/*
|
||||
$('input[type="range"]').on('mousewheel', function () {
|
||||
var factor = event.deltaY > 0 ? -1 : 1
|
||||
var val = parseFloat($(event.target).val()) + parseFloat($(event.target).attr('step')) * factor
|
||||
@ -415,7 +426,7 @@ function setupInterface() {
|
||||
$(event.target).val(val)
|
||||
eval($(event.target).attr('oninput'))
|
||||
eval($(event.target).attr('onmouseup'))
|
||||
})
|
||||
})*/
|
||||
$('#timeline_inner').on('mousewheel', function() {
|
||||
if (event.ctrlKey) {
|
||||
var offset = 1 - event.deltaY/600
|
||||
@ -459,16 +470,16 @@ function updateInterface() {
|
||||
localStorage.setItem('interface_data', JSON.stringify(Interface.data))
|
||||
}
|
||||
function updateInterfacePanels() {
|
||||
for (var key in Interface.Panels) {
|
||||
var panel = Interface.Panels[key]
|
||||
panel.update()
|
||||
}
|
||||
var left_width = $('.sidebar#left_bar > .panel:visible').length ? Interface.data.left_bar_width : 0
|
||||
var right_width = $('.sidebar#right_bar > .panel:visible').length ? Interface.data.right_bar_width : 0
|
||||
$('body').css(
|
||||
'grid-template-columns',
|
||||
left_width+'px auto '+ right_width +'px'
|
||||
)
|
||||
for (var key in Interface.Panels) {
|
||||
var panel = Interface.Panels[key]
|
||||
panel.update()
|
||||
}
|
||||
$('.quad_canvas_wrapper.qcw_x').css('width', Interface.data.quad_view_x+'%')
|
||||
$('.quad_canvas_wrapper.qcw_y').css('height', Interface.data.quad_view_y+'%')
|
||||
$('.quad_canvas_wrapper:not(.qcw_x)').css('width', (100-Interface.data.quad_view_x)+'%')
|
||||
@ -635,12 +646,12 @@ function updateUIColor() {
|
||||
var c_grid = parseInt('0x'+app_colors.grid.hex.replace('#', ''))
|
||||
if (!gizmo_colors.grid || c_grid !== gizmo_colors.grid.getHex()) {
|
||||
gizmo_colors.grid = new THREE.Color( c_grid )
|
||||
try {
|
||||
three_grid.getObjectByName('grid').material.color = gizmo_colors.grid
|
||||
} catch(err) {}
|
||||
three_grid.children.forEach(c => {
|
||||
if (c.name === 'grid' && c.material) {
|
||||
c.material.color = gizmo_colors.grid;
|
||||
}
|
||||
})
|
||||
}
|
||||
//gizmo_colors.grid = new THREE.Color( parseInt('0x'+app_colors.accent.hex.replace('#', '')) )
|
||||
|
||||
|
||||
localStorage.setItem('app_colors', JSON.stringify(app_colors))
|
||||
}
|
||||
@ -659,7 +670,11 @@ function applyBBStyle(data) {
|
||||
|
||||
//UI Edit
|
||||
function setProgressBar(id, val, time) {
|
||||
$('#'+id+' > .progress_bar_inner').animate({width: val*488}, time-1)
|
||||
if (!id || id === 'main') {
|
||||
Prop.progress = val
|
||||
} else {
|
||||
$('#'+id+' > .progress_bar_inner').animate({width: val*488}, time-1)
|
||||
}
|
||||
if (isApp) {
|
||||
currentwindow.setProgressBar(val)
|
||||
}
|
||||
@ -679,12 +694,10 @@ $(document).keyup(function(event) {
|
||||
var splashScreen = {
|
||||
attempt: function(res) {
|
||||
//NOW: Internet Available! -- DOM Ready!
|
||||
|
||||
//Post Model
|
||||
if (!isApp && tryLoadPOSTModel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
//Show
|
||||
if (res[1] ||//Forced
|
||||
localStorage.getItem('welcomed_version') != appVersion//Updated
|
||||
@ -694,8 +707,15 @@ var splashScreen = {
|
||||
},
|
||||
show: function() {
|
||||
if (open_dialog) return;
|
||||
$('#welcome_content').load('https://www.blockbench.net/api/welcome/index.html', function() {
|
||||
$('#welcome_content').load('https://www.blockbench.net/api/welcome/index.html', () => {
|
||||
$('#welcome_screen #welcome_body').css('max-height', ($(window).height() - 478) + 'px')
|
||||
if (isApp) {
|
||||
$('#welcome_screen .open-in-browser').click((event) => {
|
||||
event.preventDefault();
|
||||
shell.openExternal(event.target.href);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
showDialog('welcome_screen')
|
||||
localStorage.setItem('welcomed_version', appVersion)
|
||||
})
|
||||
|
132
js/io.js
132
js/io.js
@ -25,6 +25,7 @@ function newProject(entity_mode) {
|
||||
Undo.index = 0;
|
||||
Painter.current = {};
|
||||
Animator.animations.length = 1;
|
||||
Animator.selected = undefined;
|
||||
Animator.animations.splice(0, 1);
|
||||
if (entity_mode) {
|
||||
entityMode.join();
|
||||
@ -86,7 +87,7 @@ function loadModel(data, filepath, add) {
|
||||
//Create New Project
|
||||
if (newProject() == false) return;
|
||||
Prop.file_path = filepath
|
||||
setProjectTitle(pathToName(filepath, true))
|
||||
setProjectTitle(pathToName(filepath))
|
||||
}
|
||||
Blockbench.addFlag('importing')
|
||||
var model = autoParseJSON(data)
|
||||
@ -122,7 +123,11 @@ function loadBlockModel(model, filepath, add) {
|
||||
})
|
||||
return;
|
||||
}
|
||||
Blockbench.entity_mode = false;
|
||||
if (model.mode === 'entity') {
|
||||
entityMode.join()
|
||||
} else {
|
||||
Blockbench.entity_mode = false;
|
||||
}
|
||||
saveSettings()
|
||||
|
||||
var previous_length = add ? elements.length : 0
|
||||
@ -134,7 +139,7 @@ function loadBlockModel(model, filepath, add) {
|
||||
|
||||
//Load
|
||||
if (model.display !== undefined) {
|
||||
display = model.display
|
||||
DisplayMode.loadJSON(model.display)
|
||||
}
|
||||
|
||||
var oid = elements.length
|
||||
@ -147,10 +152,16 @@ function loadBlockModel(model, filepath, add) {
|
||||
var uv_stated = false;
|
||||
for (var face in base_cube.faces) {
|
||||
if (obj.faces[face] === undefined) {
|
||||
|
||||
base_cube.faces[face].texture = null
|
||||
base_cube.faces[face].uv = [0,0,0,0]
|
||||
} else if (typeof obj.faces[face].uv === 'object') {
|
||||
uv_stated = true
|
||||
} else {
|
||||
if (typeof obj.faces[face].uv === 'object') {
|
||||
uv_stated = true
|
||||
}
|
||||
if (obj.faces[face].texture === '#missing') {
|
||||
delete base_cube.faces[face].texture;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!uv_stated) {
|
||||
@ -215,13 +226,14 @@ function loadBlockModel(model, filepath, add) {
|
||||
var path_arr = filepath.split(osfs)
|
||||
var index = path_arr.length - path_arr.indexOf('models')
|
||||
path_arr.splice(-index)
|
||||
|
||||
var texture_arr = model.textures
|
||||
var names = {}
|
||||
|
||||
for (var tex in texture_arr) {
|
||||
if (texture_arr.hasOwnProperty(tex)) {
|
||||
if (tex != 'particle') {
|
||||
var t = new Texture({id: tex}).fromJavaLink(texture_arr[tex], path_arr.slice()).add()
|
||||
var t = new Texture({id: tex}).fromJavaLink(texture_arr[tex], path_arr.slice()).add(false)
|
||||
names[texture_arr[tex]] = t
|
||||
}
|
||||
}
|
||||
@ -231,7 +243,7 @@ function loadBlockModel(model, filepath, add) {
|
||||
if (names[texture_arr.particle]) {
|
||||
names[texture_arr.particle].enableParticle()
|
||||
} else {
|
||||
new Texture({id: 'particle'}).fromJavaLink(texture_arr[tex], path_arr.slice()).add().enableParticle()
|
||||
new Texture({id: 'particle'}).fromJavaLink(texture_arr[tex], path_arr.slice()).add(false).enableParticle()
|
||||
}
|
||||
}
|
||||
//Get Rid Of ID overlapping
|
||||
@ -369,7 +381,7 @@ function loadJEMModel(model) {
|
||||
Canvas.updateAll()
|
||||
if (model.texture) {
|
||||
var path = Prop.file_path.replace(/\\[\w .-]+$/, '\\'+model.texture)
|
||||
new Texture().fromPath(path).add()
|
||||
new Texture().fromPath(path).add(false)
|
||||
}
|
||||
}
|
||||
function loadPEModelFile(data) {
|
||||
@ -537,7 +549,7 @@ function loadPEModel(data) {
|
||||
data = pe_list_data[0]
|
||||
}
|
||||
}
|
||||
Project.parent = data.name
|
||||
Project.parent = data.name.replace(/^geometry\./, '')
|
||||
Project.texture_width = 64
|
||||
Project.texture_height = 64
|
||||
|
||||
@ -641,8 +653,8 @@ function loadPEModel(data) {
|
||||
loadOutlinerDraggable()
|
||||
Canvas.updateAll()
|
||||
setProjectTitle()
|
||||
if (isApp && data.name) {
|
||||
findEntityTexture(data.name)
|
||||
if (isApp && Project.parent) {
|
||||
findEntityTexture(Project.parent)
|
||||
}
|
||||
}
|
||||
var Extruder = {
|
||||
@ -1025,17 +1037,10 @@ function buildBlockModel(options) {
|
||||
var new_display = {}
|
||||
var entries = 0;
|
||||
for (var key in display) {
|
||||
if (display.hasOwnProperty(key)) {
|
||||
if ((typeof display[key].scale === 'object' && display[key].scale.join('_') !== '1_1_1') ||
|
||||
display[key].rotation ||
|
||||
display[key].translation
|
||||
) {
|
||||
new_display[key] = display[key]
|
||||
entries++;
|
||||
if (new_display[key].scale && new_display[key].scale.join('_') === '1_1_1') {
|
||||
new_display[key].scale = undefined
|
||||
}
|
||||
}
|
||||
var slot = display[key].export()
|
||||
if (slot) {
|
||||
new_display[key] = display[key].export()
|
||||
entries++;
|
||||
}
|
||||
}
|
||||
if (entries) {
|
||||
@ -1130,7 +1135,7 @@ function buildEntityModel(options) {
|
||||
bones.push(bone)
|
||||
})
|
||||
|
||||
if (options.visible_box !== false) {
|
||||
if (bones.length && options.visible_box !== false) {
|
||||
var offset = new THREE.Vector3(8,8,8)
|
||||
visible_box.max.add(offset)
|
||||
visible_box.min.add(offset)
|
||||
@ -1152,13 +1157,15 @@ function buildEntityModel(options) {
|
||||
}
|
||||
entitymodel.visible_bounds_offset = [0, entitymodel.visible_bounds_height/2 , 0]
|
||||
}
|
||||
|
||||
entitymodel.bones = bones
|
||||
if (bones.length) {
|
||||
entitymodel.bones = bones
|
||||
}
|
||||
|
||||
if (options.raw) {
|
||||
return entitymodel
|
||||
} else {
|
||||
return autoStringify(entitymodel)
|
||||
var model_name = 'geometry.' + (Project.parent||'unknown')
|
||||
return autoStringify({[model_name]: entitymodel})
|
||||
}
|
||||
}
|
||||
function buildJPMModel(options) {
|
||||
@ -1312,10 +1319,10 @@ function buildClassModel(options) {
|
||||
return s+'F';
|
||||
}
|
||||
|
||||
var bones = []
|
||||
var bone_nr = 1
|
||||
var model_id = Project.parent.replace('geometry.', '') || 'unknown';
|
||||
var model_id = Project.parent.replace(/^geometry\./, '') || 'unknown';
|
||||
var all_groups = getAllOutlinerGroups()
|
||||
var renderers = {}
|
||||
|
||||
var loose_cubes = []
|
||||
TreeElements.forEach(obj => {
|
||||
@ -1345,9 +1352,9 @@ function buildClassModel(options) {
|
||||
rootBone: g.parent.type !== 'group',
|
||||
lines: [
|
||||
`${id} = new ModelRenderer(this);`,//Texture Offset
|
||||
`${id}.setRotationPoint(${F(-g.origin[0])}, ${F(24-g.origin[1])}, ${F(g.origin[2])});`,
|
||||
]
|
||||
}
|
||||
var origin = [-g.origin[0], -g.origin[1], g.origin[2]]
|
||||
//Rotation
|
||||
if (!g.rotation.allEqual(0)) {
|
||||
bone.lines.push(
|
||||
@ -1358,14 +1365,21 @@ function buildClassModel(options) {
|
||||
)
|
||||
}
|
||||
//Parent
|
||||
if (!bone.rootBone) {
|
||||
let parent_index = all_groups.indexOf(g.parent)
|
||||
if (parent_index >= 0) {
|
||||
bone.lines.push(
|
||||
`${ g.parent.name }.addChild(${id});`
|
||||
)
|
||||
}
|
||||
if (!bone.rootBone && all_groups.indexOf(g.parent) >= 0) {
|
||||
bone.lines.push(
|
||||
`${ g.parent.name }.addChild(${id});`
|
||||
)
|
||||
origin[0] += g.parent.origin[0]
|
||||
origin[1] += g.parent.origin[1]
|
||||
origin[2] -= g.parent.origin[2]
|
||||
} else {
|
||||
origin[1] += 24
|
||||
}
|
||||
//origin
|
||||
bone.lines.splice(1, 0,
|
||||
`${id}.setRotationPoint(${F(origin[0])}, ${F(origin[1])}, ${F(origin[2])});`
|
||||
)
|
||||
|
||||
//Boxes
|
||||
g.children.forEach((obj) => {
|
||||
if (obj.export === false || obj.type !== 'cube') return;
|
||||
@ -1387,7 +1401,7 @@ function buildClassModel(options) {
|
||||
)
|
||||
})
|
||||
|
||||
bones.push(bone)
|
||||
renderers[id] = bone;
|
||||
|
||||
})
|
||||
|
||||
@ -1404,29 +1418,29 @@ function buildClassModel(options) {
|
||||
'\nimport net.minecraft.entity.Entity;\n'+
|
||||
'\npublic class '+model_id+' extends ModelBase {'
|
||||
|
||||
bones.forEach((bone) => {
|
||||
model += `\n private final ModelRenderer ${bone.id};`;
|
||||
})
|
||||
for (var r_id in renderers) {
|
||||
model += `\n private final ModelRenderer ${r_id};`;
|
||||
}
|
||||
|
||||
model += '\n'+
|
||||
'\n public '+model_id+'() {'+
|
||||
'\n textureWidth = '+ (Project.texture_width || 32) +';'+
|
||||
'\n textureHeight = '+ (Project.texture_height|| 32) +';\n';
|
||||
|
||||
bones.forEach((bone) => {
|
||||
model += `\n ${bone.lines.join('\n ')}\n`;
|
||||
})
|
||||
for (var r_id in renderers) {
|
||||
model += `\n ${renderers[r_id].lines.join('\n ')}\n`;
|
||||
}
|
||||
|
||||
model +=
|
||||
' }\n'+
|
||||
'\n @Override'+
|
||||
'\n public void render(Entity entity, float f, float f1, float f2, float f3, float f4, float f5) {'
|
||||
|
||||
bones.forEach((bone) => {
|
||||
if (bone.rootBone) {
|
||||
model += `\n ${bone.id}.render(f5);`;
|
||||
for (var r_id in renderers) {
|
||||
if (renderers[r_id].rootBone) {
|
||||
model += `\n ${r_id}.render(f5);`;
|
||||
}
|
||||
})
|
||||
}
|
||||
model +=
|
||||
'\n }'+
|
||||
'\n public void setRotationAngle(ModelRenderer modelRenderer, float x, float y, float z) {'+
|
||||
@ -1555,6 +1569,7 @@ function autoParseJSON(data, feedback) {
|
||||
}
|
||||
|
||||
BARS.defineActions(function() {
|
||||
//New
|
||||
new Action({
|
||||
id: 'new_block_model',
|
||||
icon: 'insert_drive_file',
|
||||
@ -1572,6 +1587,7 @@ BARS.defineActions(function() {
|
||||
showDialog('project_settings');
|
||||
}
|
||||
})
|
||||
//Import
|
||||
new Action({
|
||||
id: 'open_model',
|
||||
icon: 'assessment',
|
||||
@ -1617,9 +1633,9 @@ BARS.defineActions(function() {
|
||||
}, function(files) {
|
||||
if (files.length) {
|
||||
if (isApp) {
|
||||
new Texture().fromPath(files[0].path).add().fillParticle()
|
||||
new Texture().fromPath(files[0].path).add(false).fillParticle()
|
||||
} else {
|
||||
new Texture().fromDataURL(files[0].content).add().fillParticle()
|
||||
new Texture().fromDataURL(files[0].content).add(false).fillParticle()
|
||||
}
|
||||
showDialog('image_extruder')
|
||||
Extruder.drawImage(isApp ? files[0].path : files[0].content)
|
||||
@ -1627,6 +1643,7 @@ BARS.defineActions(function() {
|
||||
})
|
||||
}
|
||||
})
|
||||
//Export
|
||||
new Action({
|
||||
id: 'export_blockmodel',
|
||||
icon: 'insert_drive_file',
|
||||
@ -1634,20 +1651,13 @@ BARS.defineActions(function() {
|
||||
keybind: new Keybind({key: 83, ctrl: true, shift: true}),
|
||||
condition: function() {return !Blockbench.entity_mode},
|
||||
click: function () {
|
||||
var content = buildBlockModel()
|
||||
Blockbench.export({
|
||||
type: 'JSON Model',
|
||||
extensions: ['json'],
|
||||
name: Project.name||'model',
|
||||
startpath: Prop.file_path,
|
||||
content: content
|
||||
}, (path) => {
|
||||
Prop.project_saved = true
|
||||
if (isApp && path) {
|
||||
Prop.file_path = path
|
||||
setProjectTitle(pathToName(Prop.file_path, true))
|
||||
addRecentProject({name: pathToName(path, true), path: path})
|
||||
}
|
||||
project_file: true,
|
||||
content: buildBlockModel()
|
||||
})
|
||||
}
|
||||
})
|
||||
@ -1658,14 +1668,14 @@ BARS.defineActions(function() {
|
||||
keybind: new Keybind({key: 83, ctrl: true, shift: true}),
|
||||
condition: function() {return Blockbench.entity_mode},
|
||||
click: function () {
|
||||
var content = buildEntityModel({raw: true});
|
||||
Blockbench.export({
|
||||
type: 'JSON Entity Model',
|
||||
extensions: ['json'],
|
||||
name: Project.name,
|
||||
startpath: Prop.file_path,
|
||||
content: content,
|
||||
custom_writer: writeFileEntity
|
||||
content: buildEntityModel({raw: isApp}),
|
||||
project_file: true,
|
||||
custom_writer: isApp ? writeFileEntity : undefined
|
||||
})
|
||||
}
|
||||
})
|
||||
|
@ -245,7 +245,16 @@ $(document).keydown(function(e) {
|
||||
if (e.ctrlKey === true && e.which == 73 && isApp) {
|
||||
app.getCurrentWindow().toggleDevTools()
|
||||
used = true
|
||||
} else if (e.which === 18 && Toolbox.selected.alt_tool && !Toolbox.original) {
|
||||
//Alt Tool
|
||||
var orig = Toolbox.selected;
|
||||
var alt = BarItems[Toolbox.selected.alt_tool]
|
||||
if (alt && Condition(alt)) {
|
||||
alt.select()
|
||||
Toolbox.original = orig
|
||||
}
|
||||
}
|
||||
//Keybinds
|
||||
if (!input_focus) {
|
||||
Keybinds.actions.forEach(function(action) {
|
||||
if (
|
||||
@ -260,7 +269,7 @@ $(document).keydown(function(e) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//Dialog
|
||||
if (open_dialog) {
|
||||
if (Keybinds.extra.confirm.keybind.isTriggered(e)) {
|
||||
$('.dialog#'+open_dialog).find('.confirm_btn:not([disabled])').click()
|
||||
@ -269,6 +278,7 @@ $(document).keydown(function(e) {
|
||||
$('.dialog#'+open_dialog).find('.cancel_btn:not([disabled])').click()
|
||||
used = true
|
||||
}
|
||||
//Menu
|
||||
} else if (open_menu) {
|
||||
|
||||
used = open_menu.keyNavigate(e)||used
|
||||
@ -289,4 +299,8 @@ $(document).keydown(function(e) {
|
||||
|
||||
$(document).keyup(function(e) {
|
||||
holding_shift = false;
|
||||
if (e.which === 18 && Toolbox.original && Toolbox.original.alt_tool) {
|
||||
Toolbox.original.select()
|
||||
delete Toolbox.original;
|
||||
}
|
||||
});
|
73
js/molang.js
73
js/molang.js
@ -45,28 +45,43 @@ TODO:
|
||||
Support for negative numbers
|
||||
*/
|
||||
|
||||
function parseMolang(string) {
|
||||
if (typeof string === 'number') {
|
||||
return isNaN(string) ? 0 : string
|
||||
}
|
||||
function splitUp(s, char) {
|
||||
var i = 0;
|
||||
var level = 0
|
||||
while (i < s.length) {
|
||||
let c = s[i];
|
||||
if (c === '(') {
|
||||
level++;
|
||||
} else if (c === ')') {
|
||||
level--;
|
||||
} else if (level === 0 && s.substr(i, char.length) === char) {
|
||||
function splitUpMolang(s, char, inverse) {
|
||||
var direction = inverse ? -1 : 1;
|
||||
var i = inverse ? s.length-1 : 0;
|
||||
var level = 0;
|
||||
var is_string = typeof char === 'string'
|
||||
while (inverse ? i >= 0 : i < s.length) {
|
||||
let c = s[i];
|
||||
if (c === '(') {
|
||||
level += direction;
|
||||
} else if (c === ')') {
|
||||
level -= direction;
|
||||
} else if (level === 0) {
|
||||
var letters = s.substr(i, char.length)
|
||||
if (is_string && letters === char) {
|
||||
return [
|
||||
s.substr(0, i),
|
||||
s.substr(i+char.length)
|
||||
];
|
||||
} else if (!is_string) {
|
||||
for (var xi = 0; xi < char.length; xi++) {
|
||||
if (char[xi] === letters) {
|
||||
return [
|
||||
s.substr(0, i),
|
||||
s.substr(i+char[xi].length)
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
i += direction;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function parseMolang(string) {
|
||||
if (typeof string === 'number') {
|
||||
return isNaN(string) ? 0 : string
|
||||
}
|
||||
function iterate(s) {
|
||||
//Spaces and brackets
|
||||
@ -74,12 +89,12 @@ function parseMolang(string) {
|
||||
if (s.substr(0, 1) === '(' && s.substr(-1) === ')') {
|
||||
s = s.substr(1, s.length-2)
|
||||
}
|
||||
let split = splitUp(s, '&&')
|
||||
let split = splitUpMolang(s, '&&')
|
||||
// a ? b : c
|
||||
split = splitUp(s, '?')
|
||||
split = splitUpMolang(s, '?')
|
||||
if (split) {
|
||||
let condition = iterate(split[0])
|
||||
let ab = splitUp(split[1], ':')
|
||||
let ab = splitUpMolang(split[1], ':')
|
||||
if (ab.length) {
|
||||
return iterate(ab[condition?0:1])
|
||||
}
|
||||
@ -88,40 +103,40 @@ function parseMolang(string) {
|
||||
if (split) {
|
||||
return iterate(split[0]) && iterate(split[1]) ? 1 : 0
|
||||
}
|
||||
split = splitUp(s, '||')
|
||||
split = splitUpMolang(s, '||')
|
||||
if (split) {
|
||||
return iterate(split[0]) || iterate(split[1]) ? 1 : 0
|
||||
}
|
||||
split = splitUp(s, '<')
|
||||
split = splitUpMolang(s, '<')
|
||||
if (split) {
|
||||
return iterate(split[0]) < iterate(split[1]) ? 1 : 0
|
||||
}
|
||||
split = splitUp(s, '<==')
|
||||
split = splitUpMolang(s, '<==')
|
||||
if (split) {
|
||||
return iterate(split[0]) <= iterate(split[1]) ? 1 : 0
|
||||
}
|
||||
split = splitUp(s, '>')
|
||||
split = splitUpMolang(s, '>')
|
||||
if (split) {
|
||||
return iterate(split[0]) < iterate(split[1]) ? 1 : 0
|
||||
}
|
||||
split = splitUp(s, '>==')
|
||||
split = splitUpMolang(s, '>==')
|
||||
if (split) {
|
||||
return iterate(split[0]) <= iterate(split[1]) ? 1 : 0
|
||||
}
|
||||
split = splitUp(s, '===')
|
||||
split = splitUpMolang(s, '===')
|
||||
if (split) {
|
||||
return iterate(split[0]) === iterate(split[1]) ? 1 : 0
|
||||
}
|
||||
split = splitUp(s, '!==')
|
||||
split = splitUpMolang(s, '!==')
|
||||
if (split) {
|
||||
return iterate(split[0]) !== iterate(split[1]) ? 1 : 0
|
||||
}
|
||||
|
||||
split = splitUp(s, '+')
|
||||
split = splitUpMolang(s, '+', true)
|
||||
if (split) {
|
||||
return iterate(split[0]) + iterate(split[1])
|
||||
}
|
||||
split = splitUp(s, '-')
|
||||
split = splitUpMolang(s, '-', true)
|
||||
if (split) {
|
||||
if (split[0].length === 0) {
|
||||
return -iterate(split[1])
|
||||
@ -129,11 +144,11 @@ function parseMolang(string) {
|
||||
return iterate(split[0]) - iterate(split[1])
|
||||
}
|
||||
}
|
||||
split = splitUp(s, '*')
|
||||
split = splitUpMolang(s, '*')
|
||||
if (split) {
|
||||
return iterate(split[0]) * iterate(split[1])
|
||||
}
|
||||
split = splitUp(s, '/')
|
||||
split = splitUpMolang(s, '/')
|
||||
if (split) {
|
||||
return iterate(split[0]) / iterate(split[1])
|
||||
}
|
||||
|
489
js/painter.js
489
js/painter.js
@ -14,32 +14,64 @@ class BBPainter {
|
||||
if (!options.no_undo) {
|
||||
Undo.initEdit({textures: [texture], bitmap: true})
|
||||
}
|
||||
var instance = Painter.current[options.method === 'canvas' ? 'canvas' : 'image']
|
||||
Painter.current[options.method === 'canvas' ? 'image' : 'canvas'] = undefined
|
||||
|
||||
if (options.use_cache &&
|
||||
texture === Painter.current.texture &&
|
||||
typeof Painter.current.image === 'object'
|
||||
typeof instance === 'object'
|
||||
) {
|
||||
Painter.current.image = cb(Painter.current.image) || Painter.current.image
|
||||
//IS CACHED
|
||||
if (options.method !== 'canvas') {
|
||||
instance = cb(instance) || instance
|
||||
} else {
|
||||
cb(instance)
|
||||
}
|
||||
if (options.no_update === true) {
|
||||
return;
|
||||
}
|
||||
Painter.current.image.getBase64(Jimp.MIME_PNG, function(a, dataUrl){
|
||||
texture.updateSource(dataUrl)
|
||||
if (!options.no_undo) {
|
||||
Undo.finishEdit('edit_texture')
|
||||
}
|
||||
})
|
||||
} else {
|
||||
Painter.current.texture = texture
|
||||
Jimp.read(Buffer.from(texture.source.replace('data:image/png;base64,', ''), 'base64')).then(function(image) {
|
||||
image = cb(image) || image
|
||||
Painter.current.image = image
|
||||
image.getBase64(Jimp.MIME_PNG, function(a, dataUrl){
|
||||
|
||||
if (options.method !== 'canvas') {
|
||||
Painter.current.image.getBase64(Jimp.MIME_PNG, function(a, dataUrl){
|
||||
texture.updateSource(dataUrl)
|
||||
if (!options.no_undo) {
|
||||
Undo.finishEdit('edit_texture')
|
||||
}
|
||||
})
|
||||
})
|
||||
} else {
|
||||
texture.updateSource(instance.toDataURL())
|
||||
if (!options.no_undo) {
|
||||
Undo.finishEdit('edit_texture')
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (options.method !== 'canvas') {
|
||||
Painter.current.texture = texture
|
||||
Jimp.read(Buffer.from(texture.source.replace('data:image/png;base64,', ''), 'base64')).then(function(image) {
|
||||
image = cb(image) || image
|
||||
Painter.current.image = image
|
||||
image.getBase64(Jimp.MIME_PNG, function(a, dataUrl){
|
||||
texture.updateSource(dataUrl)
|
||||
if (!options.no_undo) {
|
||||
Undo.finishEdit('edit_texture')
|
||||
}
|
||||
})
|
||||
})
|
||||
} else {
|
||||
Painter.current.texture = texture
|
||||
var c = Painter.current.canvas = document.createElement('canvas')
|
||||
var ctx = c.getContext('2d');
|
||||
c.width = texture.res;
|
||||
c.height = texture.img.naturalHeight;
|
||||
ctx.drawImage(texture.img, 0, 0)
|
||||
|
||||
cb(c)
|
||||
|
||||
texture.updateSource(c.toDataURL())
|
||||
if (!options.no_undo) {
|
||||
Undo.finishEdit('edit_texture')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
startBrushCanvas(data, event) {
|
||||
@ -53,7 +85,7 @@ class BBPainter {
|
||||
var y = Math.floor( (1-data.intersects[0].uv.y) * texture.img.naturalHeight )
|
||||
Painter.startBrush(texture, x, y, data.cube.faces[data.face].uv, event)
|
||||
}
|
||||
if (event.altKey === false && texture) {
|
||||
if (Toolbox.selected.id !== 'color_picker' && texture) {
|
||||
document.addEventListener('mousemove', Painter.moveBrushCanvas, false );
|
||||
document.addEventListener('mouseup', Painter.stopBrushCanvas, false );
|
||||
}
|
||||
@ -67,7 +99,7 @@ class BBPainter {
|
||||
var end_x = x = Math.floor( data.intersects[0].uv.x * texture.img.naturalWidth )
|
||||
var end_y = y = Math.floor( (1-data.intersects[0].uv.y) * texture.img.naturalHeight )
|
||||
if (x === Painter.current.x && y === Painter.current.y) {
|
||||
//return
|
||||
return
|
||||
}
|
||||
if (Painter.current.face !== data.face || Painter.current.cube !== data.cube) {
|
||||
Painter.current.x = x
|
||||
@ -75,6 +107,9 @@ class BBPainter {
|
||||
Painter.current.face = data.face
|
||||
Painter.current.cube = data.cube
|
||||
new_face = true
|
||||
if (texture !== Painter.current.texture) {
|
||||
Undo.current_save.addTexture(texture)
|
||||
}
|
||||
}
|
||||
var diff = {
|
||||
x: x - (Painter.current.x||x),
|
||||
@ -91,6 +126,7 @@ class BBPainter {
|
||||
Painter.useBrush(texture, x, y, data.cube.faces[data.face].uv, i < length-1)
|
||||
i++;
|
||||
}
|
||||
|
||||
Painter.current.x = end_x
|
||||
Painter.current.y = end_y
|
||||
}
|
||||
@ -102,7 +138,7 @@ class BBPainter {
|
||||
Painter.stopBrush()
|
||||
}
|
||||
startBrush(texture, x, y, uvTag, event) {
|
||||
if (event.altKey === false) {
|
||||
if (Toolbox.selected.id !== 'color_picker') {
|
||||
Undo.initEdit({textures: [texture], bitmap: true})
|
||||
Painter.brushChanges = false
|
||||
Painter.useBrush(texture, x, y, uvTag)
|
||||
@ -129,64 +165,83 @@ class BBPainter {
|
||||
Painter.currentPixel = [x, y]
|
||||
Painter.brushChanges = true
|
||||
|
||||
texture.edit(function(image) {
|
||||
var color = BarItems.brush_color.get().toRgb()
|
||||
texture.edit(function(canvas) {
|
||||
var ctx = canvas.getContext('2d')
|
||||
ctx.save()
|
||||
|
||||
var color = BarItems.brush_color.get().toRgb();//.toRgbString()
|
||||
var size = BarItems.slider_brush_size.get();
|
||||
var softness = BarItems.slider_brush_softness.get()/100;
|
||||
var b_opacity = BarItems.slider_brush_opacity.get()/100;
|
||||
var brush_mode = BarItems.brush_mode.get()
|
||||
var tool = Toolbox.selected.id;
|
||||
var noise = BarItems.brush_mode.get() == 'noise';
|
||||
|
||||
ctx.beginPath();
|
||||
if (uvTag) {
|
||||
Painter.editing_area = [
|
||||
var rect = Painter.editing_area = [
|
||||
uvTag[0] / 16 * texture.img.naturalWidth,
|
||||
uvTag[1] / 16 * texture.img.naturalHeight,
|
||||
uvTag[2] / 16 * texture.img.naturalWidth,
|
||||
uvTag[3] / 16 * texture.img.naturalHeight
|
||||
]
|
||||
} else {
|
||||
Painter.editing_area = [0, 0, texture.red, texture.red]
|
||||
var rect = Painter.editing_area = [0, 0, texture.red, texture.red]
|
||||
}
|
||||
for (var t = 0; t < 2; t++) {
|
||||
if (rect[t] > rect[t+2]) {
|
||||
[rect[t], rect[t+2]] = [rect[t+2], rect[t]]
|
||||
}
|
||||
}
|
||||
ctx.rect(rect[0], rect[1], rect[2] - rect[0], rect[3] - rect[1])
|
||||
|
||||
if (Painter.editing_area[0] > Painter.editing_area[2]) {
|
||||
var sw = Painter.editing_area[2]
|
||||
Painter.editing_area[2] = Painter.editing_area[0]
|
||||
Painter.editing_area[0] = sw
|
||||
}
|
||||
if (Painter.editing_area[1] > Painter.editing_area[3]) {
|
||||
var sw = Painter.editing_area[3]
|
||||
Painter.editing_area[3] = Painter.editing_area[1]
|
||||
Painter.editing_area[1] = sw
|
||||
}
|
||||
if (tool === 'fill_tool') {
|
||||
|
||||
if (brush_mode === 'brush') {
|
||||
Painter.editCircle(image, x, y, size, softness, function(pxcolor, opacity) {
|
||||
var result_color = Painter.combineColors(pxcolor, color, opacity*b_opacity);
|
||||
return result_color;
|
||||
})
|
||||
} else if (brush_mode === 'noise') {
|
||||
Painter.editCircle(image, x, y, size, softness, function(pxcolor, opacity) {
|
||||
var result_color = Painter.combineColors(pxcolor, color, opacity*b_opacity*Math.random());
|
||||
return result_color;
|
||||
})
|
||||
} else if (brush_mode === 'eraser') {
|
||||
Painter.editCircle(image, x, y, size, softness, function(pxcolor, opacity) {
|
||||
return {r: pxcolor.r, g: pxcolor.g, b: pxcolor.b, a: pxcolor.a*(1-b_opacity*opacity)};
|
||||
})
|
||||
} else if (brush_mode === 'fill') {
|
||||
Painter.editFace(image, x, y, function(pxcolor) {
|
||||
return Painter.combineColors(pxcolor, color, 1)
|
||||
})
|
||||
ctx.fillStyle = BarItems.brush_color.get().toRgbString()
|
||||
ctx.fill()
|
||||
|
||||
} else {
|
||||
ctx.clip()
|
||||
/*ctx.beginPath();
|
||||
ctx.moveTo((Painter.current.x||x)+.5, (Painter.current.y||y)+.5)
|
||||
ctx.lineTo(x+.5, y+.5)
|
||||
if (softness) {
|
||||
ctx.filter = `blur(${ softness*size/2 }px)`;
|
||||
} else {
|
||||
ctx.imageSmoothingEnabled = false
|
||||
}
|
||||
ctx.lineWidth = size
|
||||
ctx.lineCap = 'round'
|
||||
if (brush_mode === 'eraser') {
|
||||
ctx.globalCompositeOperation = 'destination-out'
|
||||
ctx.strokeStyle = 'rgba(0,0,0,0)';
|
||||
} else {
|
||||
ctx.strokeStyle = color
|
||||
}
|
||||
ctx.stroke()*/
|
||||
if (tool === 'brush_tool') {
|
||||
Painter.editCircle(ctx, x, y, size, softness, function(pxcolor, opacity) {
|
||||
var result_color = Painter.combineColors(pxcolor, color, opacity*b_opacity*(noise?Math.random():1));
|
||||
return result_color;
|
||||
})
|
||||
} else if (tool === 'eraser') {
|
||||
Painter.editCircle(ctx, x, y, size, softness, function(pxcolor, opacity) {
|
||||
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
|
||||
}, {no_undo: true, use_cache: true, no_update: no_update})
|
||||
Painter.editing_area = undefined;
|
||||
|
||||
}, {method: 'canvas', no_undo: true, use_cache: true, no_update: no_update});
|
||||
}
|
||||
}
|
||||
stopBrush() {
|
||||
if (Painter.brushChanges) {
|
||||
Undo.finishEdit('paint')
|
||||
Painter.brushChanges = false
|
||||
Undo.finishEdit('paint');
|
||||
Painter.brushChanges = false;
|
||||
}
|
||||
Painter.currentPixel = [-1, -1]
|
||||
Painter.currentPixel = [-1, -1];
|
||||
}
|
||||
combineColors(base, added, opacity) {
|
||||
if (typeof base === 'number') base = Jimp.intToRGBA(base)
|
||||
@ -204,6 +259,21 @@ class BBPainter {
|
||||
added.a = original_a
|
||||
return mix;
|
||||
}
|
||||
scanCanvas(ctx, x, y, w, h, cb) {
|
||||
var arr = ctx.getImageData(x, y, w, h)
|
||||
for (var i = 0; i < arr.data.length; i += 4) {
|
||||
var pixel = arr.data.slice(i, i+4)
|
||||
|
||||
var px = (i/4) % w
|
||||
var py = Math.floor((i/4) / w)
|
||||
pixel = cb(x+px, y+py, pixel)||pixel
|
||||
|
||||
pixel.forEach((p, pi) => {
|
||||
arr.data[i+pi] = p
|
||||
})
|
||||
}
|
||||
ctx.putImageData(arr, x, y)
|
||||
}
|
||||
drawRectangle(image, color, rect) {
|
||||
var color = Jimp.intToRGBA(color)
|
||||
image.scan(rect.x, rect.y, rect.w, rect.h, function (x, y, idx) {
|
||||
@ -252,14 +322,15 @@ class BBPainter {
|
||||
|
||||
});
|
||||
}
|
||||
editCircle(image, x, y, r, s, editPx) {
|
||||
editCircle(ctx, x, y, r, s, editPx) {
|
||||
r = Math.round(r)
|
||||
|
||||
image.scan(x-r-1, y-r-1, 2*r+3, 2*r+3, function (px, py, idx) {
|
||||
Painter.scanCanvas(ctx, x-r-1, y-r-1, 2*r+3, 2*r+3, function (px, py, pixel) {
|
||||
|
||||
if (px >= this.bitmap.width ||
|
||||
|
||||
if (px >= ctx.canvas.width ||
|
||||
px < 0 ||
|
||||
py >= this.bitmap.height ||
|
||||
py >= ctx.canvas.height ||
|
||||
py < 0
|
||||
) {
|
||||
return;
|
||||
@ -272,7 +343,7 @@ class BBPainter {
|
||||
px+0.02 < Math.floor(Painter.editing_area[0]) ||
|
||||
py+0.02 < Math.floor(Painter.editing_area[1]) ||
|
||||
px+0.02 >= Painter.editing_area[2] ||
|
||||
py+0.02 >= Painter.editing_area[3]
|
||||
py+0.02 >= Painter.editing_area[3]
|
||||
)
|
||||
) {
|
||||
return;
|
||||
@ -292,15 +363,15 @@ class BBPainter {
|
||||
|
||||
if (opacity > 0) {
|
||||
var result_color = editPx({
|
||||
r:this.bitmap.data[idx+0],
|
||||
g:this.bitmap.data[idx+1],
|
||||
b:this.bitmap.data[idx+2],
|
||||
a:this.bitmap.data[idx+3]/255
|
||||
r: pixel[0],
|
||||
g: pixel[1],
|
||||
b: pixel[2],
|
||||
a: pixel[3]/255
|
||||
}, opacity)
|
||||
this.bitmap.data[idx+0] = result_color.r
|
||||
this.bitmap.data[idx+1] = result_color.g
|
||||
this.bitmap.data[idx+2] = result_color.b
|
||||
this.bitmap.data[idx+3] = result_color.a*255
|
||||
pixel[0] = result_color.r
|
||||
pixel[1] = result_color.g
|
||||
pixel[2] = result_color.b
|
||||
pixel[3] = result_color.a*255
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -399,6 +470,9 @@ class BBPainter {
|
||||
if (options.color === undefined) {
|
||||
options.color = new tinycolor().toRgb()
|
||||
}
|
||||
if (Blockbench.entity_mode) {
|
||||
options.texture = textures[0]
|
||||
}
|
||||
var texture = new Texture({
|
||||
mode: 'bitmap',
|
||||
keep_size: true,
|
||||
@ -422,19 +496,28 @@ class BBPainter {
|
||||
return texture;
|
||||
}
|
||||
if (options.entity_template === true) {
|
||||
Painter.generateTemplate(options.res, options.color, makeTexture)
|
||||
Undo.initEdit({textures: [], cubes: Blockbench.entity_mode ? elements : selected, uv_only: true})
|
||||
Painter.generateTemplate(options.res, options.color, makeTexture, options.texture)
|
||||
Undo.finishEdit({textures: [texture], cubes: Blockbench.entity_mode ? elements : selected, uv_only: true})
|
||||
} else {
|
||||
Undo.initEdit({textures: []})
|
||||
Painter.generateBlank(options.res, options.res, options.color, makeTexture)
|
||||
Undo.finishEdit({textures: [texture]})
|
||||
}
|
||||
}
|
||||
generateBlank(height, width, color, cb) {
|
||||
new Jimp(height, width, color.toInteger(), function(err, image) {
|
||||
image.getBase64("image/png", function(a, dataUrl){
|
||||
cb(dataUrl)
|
||||
})
|
||||
})
|
||||
var canvas = document.createElement('canvas')
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
var ctx = canvas.getContext('2d')
|
||||
|
||||
ctx.fillStyle = new tinycolor(color).toRgbString()
|
||||
ctx.fillRect(0, 0, width, height)
|
||||
|
||||
cb(canvas.toDataURL())
|
||||
|
||||
}
|
||||
generateTemplate(res, background_color, cb) {
|
||||
generateTemplate(res, background_color, cb, texture) {
|
||||
function cubeTempl(obj) {
|
||||
var min = Blockbench.entity_mode ? 0 : 1
|
||||
this.x = obj.size(0, true) || min
|
||||
@ -448,7 +531,7 @@ class BBPainter {
|
||||
}
|
||||
|
||||
var res_multiple = res / 16
|
||||
var bone_temps = []
|
||||
var templates = []
|
||||
var max_x_pos = 0
|
||||
var line_y_pos = 0;
|
||||
var valid_cubes = 0;
|
||||
@ -467,7 +550,6 @@ class BBPainter {
|
||||
cubes.splice(i,1)
|
||||
} else {
|
||||
obj.template_size = (obj.size(2, true) + obj.size(1, true)) + (obj.size(2, true) + obj.size(0, true))*2
|
||||
//obj.template_size = (obj.size(2, true) + obj.size(0, true))
|
||||
avg_size += obj.template_size
|
||||
}
|
||||
i--;
|
||||
@ -479,7 +561,7 @@ class BBPainter {
|
||||
|
||||
i = 0
|
||||
var ox = 0
|
||||
cubes.forEach(function(obj) {
|
||||
cubes.forEach(function(obj) {
|
||||
if (ox >= line_length) {
|
||||
o = 0
|
||||
ox = 0
|
||||
@ -528,9 +610,9 @@ class BBPainter {
|
||||
}
|
||||
//size of widest bone
|
||||
max_x_pos = Math.max(max_x_pos, filled_x_pos)
|
||||
templates.push(t)
|
||||
})
|
||||
line_y_pos += max_height
|
||||
bone_temps.push(temps)
|
||||
})
|
||||
//Cancel if no cubes
|
||||
if (valid_cubes == 0) {
|
||||
@ -551,92 +633,112 @@ class BBPainter {
|
||||
if (background_color.getAlpha() != 0) {
|
||||
background_color = background_color.toInteger()
|
||||
}
|
||||
var canvas = document.createElement('canvas')
|
||||
canvas.width = canvas.height = max_size*res_multiple;
|
||||
var ctx = canvas.getContext('2d')
|
||||
ctx.imageSmoothingEnabled = false;
|
||||
|
||||
|
||||
function drawTemplateRectangle(image, border_color, color, coords) {
|
||||
function drawTemplateRectangle(border_color, color, coords) {
|
||||
if (typeof background_color === 'number') {
|
||||
border_color = background_color
|
||||
color = undefined
|
||||
}
|
||||
Painter.drawRectangle(image, border_color, {
|
||||
x: coords.x*res_multiple,
|
||||
y: coords.y*res_multiple,
|
||||
w: coords.w*res_multiple,
|
||||
h: coords.h*res_multiple
|
||||
})
|
||||
ctx.fillStyle = border_color
|
||||
ctx.fillRect(
|
||||
coords.x*res_multiple,
|
||||
coords.y*res_multiple,
|
||||
coords.w*res_multiple,
|
||||
coords.h*res_multiple
|
||||
)
|
||||
if (coords.w <= 2 || coords.h <= 2 || !color) return;
|
||||
Painter.drawRectangle(image, color, {
|
||||
x: coords.x * res_multiple + 1,
|
||||
y: coords.y * res_multiple + 1,
|
||||
w: coords.w * res_multiple - 2,
|
||||
h: coords.h * res_multiple - 2
|
||||
})
|
||||
|
||||
ctx.fillStyle = color
|
||||
ctx.fillRect(
|
||||
coords.x * res_multiple + 1,
|
||||
coords.y * res_multiple + 1,
|
||||
coords.w * res_multiple - 2,
|
||||
coords.h * res_multiple - 2
|
||||
)
|
||||
}
|
||||
function drawTexture(face, coords) {
|
||||
if (!Blockbench.entity_mode) {
|
||||
if (face.texture === undefined || face.texture === null) return;
|
||||
texture = getTextureById(face.texture)
|
||||
}
|
||||
if (!texture || !texture.img) return;
|
||||
var uv = face.uv;
|
||||
var src = getRectangle(uv[0], uv[1], uv[2], uv[3])
|
||||
ctx.drawImage(
|
||||
texture.img,
|
||||
src.ax/16 * texture.img.naturalWidth,
|
||||
src.ay/16 * texture.img.naturalHeight,
|
||||
src.x /16 * texture.img.naturalWidth,
|
||||
src.y /16 * texture.img.naturalHeight,
|
||||
coords.x*res_multiple,
|
||||
coords.y*res_multiple,
|
||||
coords.w*res_multiple,
|
||||
coords.h*res_multiple
|
||||
)
|
||||
}
|
||||
|
||||
var face_data = {
|
||||
up: {c1: 0xb4d4e1ff, c2: 0xecf8fdff, place: t => {return {x: t.posx+t.z, y: t.posy, w: t.x, h: t.z}}},
|
||||
down: {c1: 0x536174ff, c2: 0x6e788cff, place: t => {return {x: t.posx+t.z+t.x, y: t.posy, w: t.x, h: t.z}}},
|
||||
east: {c1: 0x43e88dff, c2: 0x7BFFA3ff, place: t => {return {x: t.posx, y: t.posy+t.z, w: t.z, h: t.y}}},
|
||||
north: {c1: 0x5bbcf4ff, c2: 0x7BD4FFff, place: t => {return {x: t.posx+t.z, y: t.posy+t.z, w: t.x, h: t.y}}},
|
||||
west: {c1: 0xf48686ff, c2: 0xFFA7A4ff, place: t => {return {x: t.posx+t.z+t.x, y: t.posy+t.z, w: t.z, h: t.y}}},
|
||||
south: {c1: 0xf8dd72ff, c2: 0xFFF899ff, place: t => {return {x: t.posx+t.z+t.x+t.z,y: t.posy+t.z, w: t.x, h: t.y}}},
|
||||
up: {c1: '#b4d4e1', c2: '#ecf8fd', place: t => {return {x: t.posx+t.z, y: t.posy, w: t.x, h: t.z}}},
|
||||
down: {c1: '#536174', c2: '#6e788c', place: t => {return {x: t.posx+t.z+t.x, y: t.posy, w: t.x, h: t.z}}},
|
||||
east: {c1: '#43e88d', c2: '#7BFFA3', place: t => {return {x: t.posx, y: t.posy+t.z, w: t.z, h: t.y}}},
|
||||
north: {c1: '#5bbcf4', c2: '#7BD4FF', place: t => {return {x: t.posx+t.z, y: t.posy+t.z, w: t.x, h: t.y}}},
|
||||
west: {c1: '#f48686', c2: '#FFA7A4', place: t => {return {x: t.posx+t.z+t.x, y: t.posy+t.z, w: t.z, h: t.y}}},
|
||||
south: {c1: '#f8dd72', c2: '#FFF899', place: t => {return {x: t.posx+t.z+t.x+t.z,y: t.posy+t.z, w: t.x, h: t.y}}},
|
||||
}
|
||||
|
||||
//Drawing
|
||||
new Jimp(max_size*res_multiple, max_size*res_multiple, 0, function(err, image) {
|
||||
|
||||
bone_temps.forEach(function(bt) {
|
||||
bt.forEach(function(t) {
|
||||
|
||||
for (var face in face_data) {
|
||||
let d = face_data[face]
|
||||
if (!options.use_texture || (t.obj.faces[face].texture)) {
|
||||
//Colored
|
||||
drawTemplateRectangle(image, d.c1, d.c2, d.place(t))
|
||||
} else {
|
||||
//Texture
|
||||
}
|
||||
}
|
||||
|
||||
let obj = t.obj
|
||||
obj.uv_offset[0] = t.posx
|
||||
obj.uv_offset[1] = t.posy
|
||||
|
||||
if (!Blockbench.entity_mode) {
|
||||
var size = obj.size(undefined, true)
|
||||
|
||||
var face_list = [
|
||||
{face: 'north', fIndex: 10, from: [size[2], size[2]], size: [size[0], size[1]]},
|
||||
{face: 'east', fIndex: 0, from: [0, size[2]], size: [size[2], size[1]]},
|
||||
{face: 'south', fIndex: 8, from: [size[2]*2 + size[0], size[2]], size: [size[0], size[1]]},
|
||||
{face: 'west', fIndex: 2, from: [size[2] + size[0], size[2]], size: [size[2], size[1]]},
|
||||
{face: 'up', fIndex: 4, from: [size[2]+size[0], size[2]], size: [-size[0], -size[2]]},
|
||||
{face: 'down', fIndex: 6, from: [size[2]+size[0]*2, 0], size: [-size[0], size[2]]}
|
||||
]
|
||||
|
||||
face_list.forEach(function(f) {
|
||||
|
||||
obj.faces[f.face].uv[0] = (f.from[0] + Math.floor(obj.uv_offset[0]+0.0000001)) / max_size * 16,
|
||||
obj.faces[f.face].uv[1] = (f.from[1] + Math.floor(obj.uv_offset[1]+0.0000001)) / max_size * 16,
|
||||
obj.faces[f.face].uv[2] = (f.from[0] + f.size[0] + Math.floor(obj.uv_offset[0]+0.0000001)) / max_size * 16,
|
||||
obj.faces[f.face].uv[3] = (f.from[1] + f.size[1] + Math.floor(obj.uv_offset[1]+0.0000001)) / max_size * 16
|
||||
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
image.getBase64("image/png", function(a, dataUrl){
|
||||
var texture = cb(dataUrl)
|
||||
entityMode.setResolution(max_size, max_size, true)
|
||||
if (texture && !Blockbench.entity_mode) {
|
||||
bone_temps.forEach(function(bt) {
|
||||
bt.forEach(function(t) {
|
||||
t.obj.applyTexture(texture, true)
|
||||
t.obj.autouv = 0
|
||||
})
|
||||
})
|
||||
templates.forEach(function(t) {
|
||||
for (var face in face_data) {
|
||||
let d = face_data[face]
|
||||
if (options.use_texture || !t.obj.faces[face].texture) {
|
||||
//Colored
|
||||
drawTemplateRectangle(d.c1, d.c2, d.place(t))
|
||||
} else {
|
||||
//Texture
|
||||
drawTexture(t.obj.faces[face], d.place(t))
|
||||
}
|
||||
})
|
||||
}
|
||||
let obj = t.obj
|
||||
obj.uv_offset[0] = t.posx
|
||||
obj.uv_offset[1] = t.posy
|
||||
|
||||
if (!Blockbench.entity_mode) {
|
||||
var size = obj.size(undefined, true)
|
||||
|
||||
var face_list = [
|
||||
{face: 'north', fIndex: 10, from: [size[2], size[2]], size: [size[0], size[1]]},
|
||||
{face: 'east', fIndex: 0, from: [0, size[2]], size: [size[2], size[1]]},
|
||||
{face: 'south', fIndex: 8, from: [size[2]*2 + size[0], size[2]], size: [size[0], size[1]]},
|
||||
{face: 'west', fIndex: 2, from: [size[2] + size[0], size[2]], size: [size[2], size[1]]},
|
||||
{face: 'up', fIndex: 4, from: [size[2]+size[0], size[2]], size: [-size[0], -size[2]]},
|
||||
{face: 'down', fIndex: 6, from: [size[2]+size[0]*2, 0], size: [-size[0], size[2]]}
|
||||
]
|
||||
|
||||
face_list.forEach(function(f) {
|
||||
|
||||
obj.faces[f.face].uv[0] = (f.from[0] + Math.floor(obj.uv_offset[0]+0.0000001)) / max_size * 16,
|
||||
obj.faces[f.face].uv[1] = (f.from[1] + Math.floor(obj.uv_offset[1]+0.0000001)) / max_size * 16,
|
||||
obj.faces[f.face].uv[2] = (f.from[0] + f.size[0] + Math.floor(obj.uv_offset[0]+0.0000001)) / max_size * 16,
|
||||
obj.faces[f.face].uv[3] = (f.from[1] + f.size[1] + Math.floor(obj.uv_offset[1]+0.0000001)) / max_size * 16
|
||||
|
||||
})
|
||||
}
|
||||
})
|
||||
var dataUrl = canvas.toDataURL()
|
||||
var texture = cb(dataUrl)
|
||||
entityMode.setResolution(max_size, max_size, true)
|
||||
if (texture && !Blockbench.entity_mode) {
|
||||
templates.forEach(function(t) {
|
||||
t.obj.applyTexture(texture, true)
|
||||
t.obj.autouv = 0
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
var Painter = new BBPainter()
|
||||
@ -648,11 +750,83 @@ BARS.defineActions(function() {
|
||||
icon: 'fa-paint-brush',
|
||||
category: 'tools',
|
||||
toolbar: 'brush',
|
||||
alt_tool: 'color_picker',
|
||||
selectFace: true,
|
||||
transformerMode: 'hidden',
|
||||
paintTool: true,
|
||||
allowWireframe: false,
|
||||
keybind: new Keybind({key: 66}),
|
||||
condition: () => Modes.id === 'paint',
|
||||
onCanvasClick: function(data) {
|
||||
Painter.startBrushCanvas(data, data.event)
|
||||
},
|
||||
onSelect: function() {
|
||||
BarItems.slider_brush_size.update()
|
||||
BarItems.slider_brush_softness.update()
|
||||
BarItems.slider_brush_opacity.update()
|
||||
$('.UVEditor').find('#uv_size').hide()
|
||||
},
|
||||
onUnselect: function() {
|
||||
$('.UVEditor').find('#uv_size').show()
|
||||
}
|
||||
})
|
||||
new Tool({
|
||||
id: 'fill_tool',
|
||||
icon: 'format_color_fill',
|
||||
category: 'tools',
|
||||
toolbar: 'brush',
|
||||
alt_tool: 'color_picker',
|
||||
selectFace: true,
|
||||
transformerMode: 'hidden',
|
||||
paintTool: true,
|
||||
allowWireframe: false,
|
||||
condition: () => Modes.id === 'paint',
|
||||
onCanvasClick: function(data) {
|
||||
Painter.startBrushCanvas(data, data.event)
|
||||
},
|
||||
onSelect: function() {
|
||||
BarItems.slider_brush_size.update()
|
||||
BarItems.slider_brush_softness.update()
|
||||
BarItems.slider_brush_opacity.update()
|
||||
$('.UVEditor').find('#uv_size').hide()
|
||||
},
|
||||
onUnselect: function() {
|
||||
$('.UVEditor').find('#uv_size').show()
|
||||
}
|
||||
})
|
||||
new Tool({
|
||||
id: 'eraser',
|
||||
icon: 'fa-eraser',
|
||||
category: 'tools',
|
||||
toolbar: 'brush',
|
||||
selectFace: true,
|
||||
transformerMode: 'hidden',
|
||||
paintTool: true,
|
||||
allowWireframe: false,
|
||||
condition: () => Modes.id === 'paint',
|
||||
onCanvasClick: function(data) {
|
||||
Painter.startBrushCanvas(data, data.event)
|
||||
},
|
||||
onSelect: function() {
|
||||
BarItems.slider_brush_size.update()
|
||||
BarItems.slider_brush_softness.update()
|
||||
BarItems.slider_brush_opacity.update()
|
||||
$('.UVEditor').find('#uv_size').hide()
|
||||
},
|
||||
onUnselect: function() {
|
||||
$('.UVEditor').find('#uv_size').show()
|
||||
}
|
||||
})
|
||||
new Tool({
|
||||
id: 'color_picker',
|
||||
icon: 'colorize',
|
||||
category: 'tools',
|
||||
toolbar: 'brush',
|
||||
selectFace: true,
|
||||
transformerMode: 'hidden',
|
||||
paintTool: true,
|
||||
allowWireframe: false,
|
||||
condition: () => Modes.id === 'paint',
|
||||
onCanvasClick: function(data) {
|
||||
Painter.startBrushCanvas(data, data.event)
|
||||
},
|
||||
@ -666,33 +840,31 @@ BARS.defineActions(function() {
|
||||
$('.UVEditor').find('#uv_size').show()
|
||||
}
|
||||
})
|
||||
//Noise ? grain
|
||||
//Color Picker colorize
|
||||
//Eraser fa-eraser
|
||||
//Fill format_color_fill
|
||||
|
||||
new ColorPicker({
|
||||
id: 'brush_color',
|
||||
condition: () => (Toolbox && ['brush_tool', 'color_picker', 'fill_tool'].includes(Toolbox.selected.id)),
|
||||
palette: true
|
||||
})
|
||||
new BarSelect({
|
||||
id: 'brush_mode',
|
||||
condition: () => Toolbox && (Toolbox.selected.id === 'brush_tool' || Toolbox.selected.id === 'eraser'),
|
||||
options: {
|
||||
brush: true,
|
||||
noise: true,
|
||||
eraser: true,
|
||||
fill: true
|
||||
noise: true
|
||||
}
|
||||
})
|
||||
|
||||
new NumSlider({
|
||||
id: 'slider_brush_size',
|
||||
condition: () => (Toolbox && ['brush_tool', 'eraser'].includes(Toolbox.selected.id)),
|
||||
settings: {
|
||||
min: 1, max: 20, step: 1, default: 1,
|
||||
}
|
||||
})
|
||||
new NumSlider({
|
||||
id: 'slider_brush_softness',
|
||||
condition: () => (Toolbox && ['brush_tool', 'eraser'].includes(Toolbox.selected.id)),
|
||||
settings: {
|
||||
min: 0, max: 100, default: 0,
|
||||
interval: function(event) {
|
||||
@ -710,6 +882,7 @@ BARS.defineActions(function() {
|
||||
})
|
||||
new NumSlider({
|
||||
id: 'slider_brush_opacity',
|
||||
condition: () => (Toolbox && ['brush_tool', 'eraser'].includes(Toolbox.selected.id)),
|
||||
settings: {
|
||||
min: 0, max: 100, default: 100,
|
||||
interval: function(event) {
|
||||
|
@ -350,6 +350,15 @@ function switchPluginTabs(installed) {
|
||||
}
|
||||
|
||||
BARS.defineActions(function() {
|
||||
new Action({
|
||||
id: 'plugins_window',
|
||||
icon: 'extension',
|
||||
category: 'blockbench',
|
||||
click: function () {
|
||||
showDialog('plugins')
|
||||
$('#plugin_list').css('max-height', limitNumber($(window).height()-300, 80, 600)+'px')
|
||||
}
|
||||
})
|
||||
new Action({
|
||||
id: 'load_plugin',
|
||||
icon: 'fa-file-code-o',
|
||||
|
446
js/preview.js
446
js/preview.js
@ -7,11 +7,10 @@ var scene, main_preview, previews,
|
||||
display_scene, display_area, display_base;
|
||||
var framespersecond = 0;
|
||||
var display_mode = false;
|
||||
var cubes = new THREE.Group();
|
||||
var doRender = false;
|
||||
var quad_previews = {};
|
||||
var three_grid = new THREE.Object3D();
|
||||
var rot_origin = new THREE.Object3D();
|
||||
const three_grid = new THREE.Object3D();
|
||||
const rot_origin = new THREE.Object3D();
|
||||
var gizmo_colors = {
|
||||
r: new THREE.Color(0xfd3043),
|
||||
g: new THREE.Color(0x26ec45),
|
||||
@ -45,6 +44,7 @@ class Preview {
|
||||
this.controls.maxDistance = 320;
|
||||
this.controls.target.set(0,-3,0);
|
||||
this.controls.enableKeys = false;
|
||||
this.controls.zoomSpeed = 1.5
|
||||
|
||||
//Keybinds
|
||||
this.controls.mouseButtons.ZOOM = undefined;
|
||||
@ -69,7 +69,7 @@ class Preview {
|
||||
this.mouse = new THREE.Vector2();
|
||||
this.canvas.addEventListener('mousedown', function(event) { scope.click(event)}, false)
|
||||
this.canvas.addEventListener('mousemove', function(event) { scope.static_rclick = false}, false)
|
||||
this.canvas.addEventListener('contextmenu', function(event) { scope.showContextMenu(event)}, false)
|
||||
this.canvas.addEventListener('mouseup', function(event) { scope.showContextMenu(event)}, false)
|
||||
this.canvas.addEventListener('dblclick', function() {Toolbox.toggleTransforms()}, false)
|
||||
this.canvas.addEventListener('touchstart', function() { scope.onTouchStart()}, false)
|
||||
this.canvas.addEventListener('mouseenter', function() { scope.occupyTransformer()}, false)
|
||||
@ -301,12 +301,18 @@ class Preview {
|
||||
var data = this.raycast(event)
|
||||
if (data) {
|
||||
this.static_rclick = false
|
||||
if (Toolbox.selected.selectCubes && data.type === 'cube') {
|
||||
if (Toolbox.selected.selectCubes && Modes.selected.selectCubes && data.type === 'cube') {
|
||||
if (Toolbox.selected.selectFace) {
|
||||
main_uv.setFace(data.face)
|
||||
}
|
||||
Blockbench.dispatchEvent( 'canvas_select', data )
|
||||
data.cube.select(event)
|
||||
if (Animator.open || (Toolbox.selected.id === 'rotate_tool' && Blockbench.entity_mode)) {
|
||||
if (data.cube.parent.type === 'group') {
|
||||
data.cube.parent.select()
|
||||
}
|
||||
} else {
|
||||
data.cube.select(event)
|
||||
}
|
||||
}
|
||||
if (typeof Toolbox.selected.onCanvasClick === 'function') {
|
||||
Toolbox.selected.onCanvasClick(data)
|
||||
@ -345,7 +351,7 @@ class Preview {
|
||||
return this;
|
||||
}
|
||||
showContextMenu(event) {
|
||||
if (this.static_rclick) {
|
||||
if (this.static_rclick && event.which === 3) {
|
||||
var data = this.raycast()
|
||||
if (data && data.cube) {
|
||||
data.cube.showContextMenu(event)
|
||||
@ -597,6 +603,10 @@ class Preview {
|
||||
obj.was_visible = obj.visible
|
||||
obj.visible = false
|
||||
})
|
||||
var ground_anim_before = ground_animation
|
||||
if (display_mode && ground_animation) {
|
||||
ground_animation = false
|
||||
}
|
||||
|
||||
setTimeout(function() {
|
||||
|
||||
@ -619,6 +629,9 @@ class Preview {
|
||||
obj.visible = obj.was_visible
|
||||
delete obj.was_visible
|
||||
})
|
||||
if (display_mode && ground_anim_before) {
|
||||
ground_animation = ground_anim_before
|
||||
}
|
||||
|
||||
}, 40)
|
||||
}
|
||||
@ -650,7 +663,7 @@ class Preview {
|
||||
changeDisplaySkin()
|
||||
}},
|
||||
{icon: 'wallpaper', name: 'menu.preview.background', children: function(preview) {
|
||||
var has_background = !!main_preview.background.image
|
||||
var has_background = !!preview.background.image
|
||||
return [
|
||||
{icon: 'folder', name: 'menu.preview.background.load', click: function(preview) {
|
||||
Blockbench.import({
|
||||
@ -672,7 +685,7 @@ class Preview {
|
||||
}},
|
||||
{
|
||||
name: 'menu.preview.background.lock',
|
||||
condition: has_background && preview.background.lock !== null,
|
||||
condition: (has_background && preview.background.lock !== null && preview.isOrtho),
|
||||
icon: preview.background.lock?'check_box':'check_box_outline_blank',
|
||||
click: function(preview) {
|
||||
preview.background.lock = !preview.background.lock
|
||||
@ -747,9 +760,16 @@ function initCanvas() {
|
||||
display_scene = new THREE.Scene();
|
||||
display_area = new THREE.Object3D();
|
||||
display_base = new THREE.Object3D();
|
||||
|
||||
display_scene.add(display_area)
|
||||
display_area.add(display_base)
|
||||
display_base.add(scene)
|
||||
|
||||
scene.name = 'scene'
|
||||
display_base.name = 'display_base'
|
||||
display_area.name = 'display_area'
|
||||
display_scene.name = 'display_scene'
|
||||
|
||||
scene.position.set(-8,-8,-8)
|
||||
|
||||
scene.add(Vertexsnap.vertexes)
|
||||
@ -813,7 +833,6 @@ function initCanvas() {
|
||||
//TransformControls
|
||||
Transformer = new THREE.TransformControls(main_preview.camPers, main_preview.canvas)
|
||||
Transformer.setSize(0.5)
|
||||
Transformer.setTranslationSnap(canvasGridSize())
|
||||
scene.add(Transformer)
|
||||
main_preview.occupyTransformer()
|
||||
|
||||
@ -917,7 +936,7 @@ function animate() {
|
||||
prev.render()
|
||||
})
|
||||
framespersecond++;
|
||||
if (display_mode === true && ground_animation === true) {
|
||||
if (display_mode === true && ground_animation === true && !Transformer.hoverAxis) {
|
||||
DisplayMode.groundAnimation()
|
||||
}
|
||||
}
|
||||
@ -937,22 +956,7 @@ function resizeWindow(event) {
|
||||
if (Animator.open) {
|
||||
Timeline.updateSize()
|
||||
}
|
||||
if (!Toolbars || !Toolbars[Toolbox.selected.toolbar]) return;
|
||||
Toolbars[Toolbox.selected.toolbar].children.forEach(function(action) {
|
||||
if (action.type === 'numslider') {
|
||||
action.setWidth(40)
|
||||
}
|
||||
})
|
||||
if ($('div.tool_options .toolbar').length > 0) {
|
||||
var sliders = $('header .tool.nslide_tool').length
|
||||
var space = $(window).width() - $('div.tool_options .toolbar').offset().left - $('div.tool_options .toolbar').width()
|
||||
var width = limitNumber(37 + space / sliders, 40, 80)
|
||||
Toolbars[Toolbox.selected.toolbar].children.forEach(function(action) {
|
||||
if (action.type === 'numslider') {
|
||||
action.setWidth(width)
|
||||
}
|
||||
})
|
||||
}
|
||||
BARS.updateToolToolbar()
|
||||
}
|
||||
$(window).resize(resizeWindow)
|
||||
|
||||
@ -975,55 +979,54 @@ function buildGrid() {
|
||||
if (display_mode === true && settings.display_grid.value === false) return;
|
||||
|
||||
three_grid.name = 'grid_group'
|
||||
var size, step;
|
||||
var grid_color = new THREE.Color(parseInt('0x'+app_colors.grid.hex.replace('#', ''), 16))
|
||||
var line_material = new THREE.LineBasicMaterial({color: grid_color});
|
||||
gizmo_colors.grid = new THREE.Color(parseInt('0x'+app_colors.grid.hex.replace('#', ''), 16))
|
||||
var material;
|
||||
|
||||
northMarkMaterial.color = grid_color
|
||||
northMarkMaterial.color = gizmo_colors.grid
|
||||
|
||||
function setupAxisLine(origin, length, axis) {
|
||||
var color = 'rgb'[getAxisNumber(axis)]
|
||||
var geometry = new THREE.Geometry();
|
||||
var material = new THREE.LineBasicMaterial({color: gizmo_colors[color]});
|
||||
|
||||
var dest = new THREE.Vector3().copy(origin)
|
||||
dest[axis] += length
|
||||
geometry.vertices.push(origin)
|
||||
geometry.vertices.push(dest)
|
||||
|
||||
var line = new THREE.Line( geometry, material);
|
||||
line.name = 'axis_line_'+axis;
|
||||
three_grid.add(line)
|
||||
}
|
||||
//Axis Lines
|
||||
if (settings.base_grid.value || settings.full_grid.value)
|
||||
if (Blockbench.entity_mode || !settings.full_grid.value) {
|
||||
var length = Blockbench.entity_mode
|
||||
? (settings.full_grid.value ? 24 : 8)
|
||||
: 16
|
||||
setupAxisLine(new THREE.Vector3( 0, 0.001, 0), length, 'x')
|
||||
setupAxisLine(new THREE.Vector3( 0, 0.001, 0), length, 'z')
|
||||
|
||||
} else {
|
||||
setupAxisLine(new THREE.Vector3( -16, 0.001, -16), 48, 'x')
|
||||
setupAxisLine(new THREE.Vector3( -16, 0.001, -16), 48, 'z')
|
||||
}
|
||||
|
||||
|
||||
if (settings.full_grid.value === true) {
|
||||
size = 24
|
||||
step = canvasGridSize();
|
||||
|
||||
var geometry = new THREE.Geometry();
|
||||
|
||||
for ( var i = - size; i <= size; i += step) {
|
||||
geometry.vertices.push(new THREE.Vector3( -size, 0, i))
|
||||
geometry.vertices.push(new THREE.Vector3( size, 0, i))
|
||||
geometry.vertices.push(new THREE.Vector3(i, 0, -size))
|
||||
geometry.vertices.push(new THREE.Vector3(i, 0, size))
|
||||
}
|
||||
var line = new THREE.Line( geometry, line_material, THREE.LinePieces);
|
||||
//Grid
|
||||
var grid = new THREE.GridHelper(48, 48/canvasGridSize(), gizmo_colors.grid, gizmo_colors.grid)
|
||||
if (Blockbench.entity_mode === true) {
|
||||
line.position.set(0,0,0)
|
||||
grid.position.set(0,0,0)
|
||||
} else {
|
||||
line.position.set(8,0,8)
|
||||
grid.position.set(8,0,8)
|
||||
}
|
||||
three_grid.add(line)
|
||||
line.name = 'grid'
|
||||
|
||||
|
||||
//Axis Helpers
|
||||
geometry = new THREE.Geometry();
|
||||
material = new THREE.LineBasicMaterial({color: gizmo_colors.r});
|
||||
geometry.vertices.push(new THREE.Vector3( -16, 0.001, -16))
|
||||
geometry.vertices.push(new THREE.Vector3( 32, 0.001, -16))
|
||||
x_axis = new THREE.Line( geometry, material, THREE.LinePieces);
|
||||
three_grid.add(x_axis)
|
||||
|
||||
geometry = new THREE.Geometry();
|
||||
material = new THREE.LineBasicMaterial({color: gizmo_colors.b});
|
||||
geometry.vertices.push(new THREE.Vector3( -16, 0.001, -16))
|
||||
geometry.vertices.push(new THREE.Vector3( -16, 0.001, 32))
|
||||
z_axis = new THREE.Line( geometry, material, THREE.LinePieces);
|
||||
three_grid.add(z_axis)
|
||||
three_grid.add(grid)
|
||||
grid.name = 'grid'
|
||||
|
||||
//North
|
||||
geometry = new THREE.PlaneGeometry(5, 5)
|
||||
var north_mark = new THREE.Mesh(geometry, northMarkMaterial)
|
||||
|
||||
if (Blockbench.entity_mode === true) {
|
||||
north_mark.position.set(0,0,-27)
|
||||
} else {
|
||||
@ -1034,65 +1037,28 @@ function buildGrid() {
|
||||
|
||||
} else {
|
||||
if (settings.large_grid.value === true) {
|
||||
var geometry_big = new THREE.Geometry();
|
||||
size = 24
|
||||
step = 16;
|
||||
|
||||
for ( var i = - size; i <= size; i += step) {
|
||||
geometry_big.vertices.push(new THREE.Vector3( -size, 0, i))
|
||||
geometry_big.vertices.push(new THREE.Vector3( size, 0, i))
|
||||
geometry_big.vertices.push(new THREE.Vector3(i, 0, -size))
|
||||
geometry_big.vertices.push(new THREE.Vector3(i, 0, size))
|
||||
}
|
||||
|
||||
var line_big = new THREE.Line( geometry_big, line_material, THREE.LinePieces);
|
||||
//Grid
|
||||
var grid = new THREE.GridHelper(48, 3, gizmo_colors.grid, gizmo_colors.grid)
|
||||
if (Blockbench.entity_mode === true) {
|
||||
line_big.position.set(0,0,0)
|
||||
grid.position.set(0,0,0)
|
||||
} else {
|
||||
line_big.position.set(8,0,8)
|
||||
grid.position.set(8,0,8)
|
||||
}
|
||||
line_big.name = 'grid'
|
||||
three_grid.add(line_big)
|
||||
|
||||
grid.name = 'grid'
|
||||
three_grid.add(grid)
|
||||
}
|
||||
|
||||
|
||||
if (settings.base_grid.value === true) {
|
||||
size = 8
|
||||
step = canvasGridSize();
|
||||
//Grid
|
||||
var grid = new THREE.GridHelper(16, 16/canvasGridSize(), gizmo_colors.grid, gizmo_colors.grid)
|
||||
|
||||
var geometry = new THREE.Geometry();
|
||||
|
||||
for ( var i = - size; i <= size; i += step) {
|
||||
geometry.vertices.push(new THREE.Vector3( -size, 0, i))
|
||||
geometry.vertices.push(new THREE.Vector3( size, 0, i))
|
||||
geometry.vertices.push(new THREE.Vector3(i, 0, -size))
|
||||
geometry.vertices.push(new THREE.Vector3(i, 0, size))
|
||||
}
|
||||
var line = new THREE.Line( geometry, line_material, THREE.LinePieces);
|
||||
if (Blockbench.entity_mode === true) {
|
||||
line.position.set(0,0,0)
|
||||
grid.position.set(0,0,0)
|
||||
} else {
|
||||
line.position.set(8,0,8)
|
||||
grid.position.set(8,0,8)
|
||||
}
|
||||
three_grid.add(line)
|
||||
|
||||
line.name = 'grid'
|
||||
|
||||
//Axis Helpers
|
||||
geometry = new THREE.Geometry();
|
||||
material = new THREE.LineBasicMaterial({color: '#EE4040'});
|
||||
geometry.vertices.push(new THREE.Vector3( 0, 0.001, 0))
|
||||
geometry.vertices.push(new THREE.Vector3( (Blockbench.entity_mode ? 8 : 16), 0.001, 0))
|
||||
x_axis = new THREE.Line( geometry, material, THREE.LinePieces);
|
||||
three_grid.add(x_axis)
|
||||
|
||||
geometry = new THREE.Geometry();
|
||||
material = new THREE.LineBasicMaterial({color: '#547CEA'});
|
||||
geometry.vertices.push(new THREE.Vector3( 0, 0.001, 0))
|
||||
geometry.vertices.push(new THREE.Vector3( 0, 0.001, (Blockbench.entity_mode ? 8 : 16)))
|
||||
z_axis = new THREE.Line( geometry, material, THREE.LinePieces);
|
||||
three_grid.add(z_axis)
|
||||
grid.name = 'grid'
|
||||
three_grid.add(grid)
|
||||
|
||||
//North
|
||||
geometry = new THREE.PlaneGeometry(2.4, 2.4)
|
||||
@ -1109,82 +1075,100 @@ function buildGrid() {
|
||||
if (settings.large_box.value === true) {
|
||||
var geometry_box = new THREE.EdgesGeometry(new THREE.BoxBufferGeometry(48, 48, 48));
|
||||
|
||||
var line_material = new THREE.LineBasicMaterial({color: gizmo_colors.grid});
|
||||
var large_box = new THREE.LineSegments( geometry_box, line_material);
|
||||
if (Blockbench.entity_mode === true) {
|
||||
large_box.position.set(0,8,0)
|
||||
} else {
|
||||
large_box.position.set(8,8,8)
|
||||
}
|
||||
large_box.name = 'peter'
|
||||
large_box.name = 'grid'
|
||||
three_grid.add(large_box)
|
||||
}
|
||||
scene.add(three_grid)
|
||||
}
|
||||
function centerTransformer(offset) {
|
||||
if (selected.length === 0) return;
|
||||
var first_obj
|
||||
|
||||
var rotate_tool = Toolbox.selected.transformerMode === 'rotate'
|
||||
|
||||
//Getting Center
|
||||
if (Animator.open && selected_group) {
|
||||
var g_mesh = selected_group.getMesh()
|
||||
|
||||
var center = [0, 0, 0]
|
||||
var i = 0;
|
||||
selected.forEach(function(obj) {
|
||||
var m = obj.getMesh()
|
||||
if (obj.visibility && m) {
|
||||
var pos = new THREE.Vector3(
|
||||
obj.from[0] + obj.size(0)/2,
|
||||
obj.from[1] + obj.size(1)/2,
|
||||
obj.from[2] + obj.size(2)/2
|
||||
)
|
||||
if (!Blockbench.entity_mode) {
|
||||
g_mesh.getWorldPosition(Transformer.position)
|
||||
Transformer.position.x += 8;
|
||||
Transformer.position.y += 8;
|
||||
Transformer.position.z += 8;
|
||||
Transformer.rotation.set(0, 0, 0)
|
||||
Transformer.update()
|
||||
|
||||
pos.x -= obj.origin[0]
|
||||
pos.y -= obj.origin[1]
|
||||
pos.z -= obj.origin[2]
|
||||
var r = m.getWorldQuaternion(new THREE.Quaternion())
|
||||
pos.applyQuaternion(r)
|
||||
pos.x += obj.origin[0]
|
||||
pos.y += obj.origin[1]
|
||||
pos.z += obj.origin[2]
|
||||
} else {
|
||||
TreeElements.forEach((obj) => {
|
||||
if (obj.type === 'group') {
|
||||
let mesh = obj.getMesh()
|
||||
if (obj.visibility && mesh) {
|
||||
mesh.updateMatrixWorld()
|
||||
}
|
||||
}
|
||||
})
|
||||
var r = m.getWorldQuaternion(new THREE.Quaternion())
|
||||
pos.applyQuaternion(r)
|
||||
pos.add(m.getWorldPosition(new THREE.Vector3()))
|
||||
pos.x += 8
|
||||
pos.y += 8
|
||||
pos.z += 8
|
||||
}
|
||||
|
||||
center[0] += pos.x
|
||||
center[1] += pos.y
|
||||
center[2] += pos.z
|
||||
|
||||
if (!first_obj) {
|
||||
first_obj = obj
|
||||
}
|
||||
}
|
||||
})
|
||||
if (!first_obj) {
|
||||
//if (!rotate_tool) {
|
||||
// var quat = new THREE.Quaternion()
|
||||
// g_mesh.getWorldQuaternion(quat)
|
||||
// Transformer.rotation.setFromQuaternion(quat, 'ZYX')
|
||||
//} else {
|
||||
//}
|
||||
return;
|
||||
}
|
||||
i = 0;
|
||||
while (i < 3) {
|
||||
center[i] = center[i] / selected.length
|
||||
i++;
|
||||
|
||||
//Getting Center
|
||||
if (Blockbench.entity_mode) {
|
||||
Canvas.updateAllBones()
|
||||
}
|
||||
if (!rotate_tool) {
|
||||
var first_obj
|
||||
var center = [0, 0, 0]
|
||||
var i = 0;
|
||||
selected.forEach(function(obj) {
|
||||
var m = obj.getMesh()
|
||||
if (obj.visibility && m) {
|
||||
var pos = new THREE.Vector3(
|
||||
obj.from[0] + obj.size(0)/2,
|
||||
obj.from[1] + obj.size(1)/2,
|
||||
obj.from[2] + obj.size(2)/2
|
||||
)
|
||||
if (!Blockbench.entity_mode) {
|
||||
|
||||
pos.x -= obj.origin[0]
|
||||
pos.y -= obj.origin[1]
|
||||
pos.z -= obj.origin[2]
|
||||
var r = m.getWorldQuaternion(new THREE.Quaternion())
|
||||
pos.applyQuaternion(r)
|
||||
pos.x += obj.origin[0]
|
||||
pos.y += obj.origin[1]
|
||||
pos.z += obj.origin[2]
|
||||
} else {
|
||||
var r = m.getWorldQuaternion(new THREE.Quaternion())
|
||||
pos.applyQuaternion(r)
|
||||
pos.add(m.getWorldPosition(new THREE.Vector3()))
|
||||
pos.x += 8
|
||||
pos.y += 8
|
||||
pos.z += 8
|
||||
}
|
||||
|
||||
center[0] += pos.x
|
||||
center[1] += pos.y
|
||||
center[2] += pos.z
|
||||
|
||||
if (!first_obj) {
|
||||
first_obj = obj
|
||||
}
|
||||
}
|
||||
})
|
||||
if (!first_obj) {
|
||||
return;
|
||||
}
|
||||
i = 0;
|
||||
while (i < 3) {
|
||||
center[i] = center[i] / selected.length
|
||||
i++;
|
||||
}
|
||||
} else {
|
||||
var first_obj = selected[0]
|
||||
var center = first_obj.origin
|
||||
}
|
||||
var vec = new THREE.Vector3(center[0], center[1], center[2])
|
||||
|
||||
|
||||
|
||||
//Position + Rotation
|
||||
if (Blockbench.entity_mode === false) {
|
||||
|
||||
@ -1193,13 +1177,25 @@ function centerTransformer(offset) {
|
||||
Transformer.position.copy(vec)
|
||||
|
||||
var mesh = first_obj.getMesh()
|
||||
if (mesh && Blockbench.globalMovement === false) {
|
||||
if (mesh && Blockbench.globalMovement === false && !rotate_tool) {
|
||||
Transformer.rotation.copy(mesh.rotation)
|
||||
}
|
||||
} else {
|
||||
|
||||
//Entity Mode
|
||||
|
||||
if (selected_group && rotate_tool) {
|
||||
var mesh = selected_group.getMesh()
|
||||
if (mesh) {
|
||||
mesh.getWorldPosition(Transformer.position)
|
||||
}
|
||||
Transformer.position.x += 8
|
||||
Transformer.position.y += 8
|
||||
Transformer.position.z += 8
|
||||
|
||||
Transformer.rotation.set(0, 0, 0)
|
||||
return;
|
||||
}
|
||||
|
||||
var group;
|
||||
if (selected_group) {
|
||||
group = selected_group
|
||||
@ -1225,7 +1221,7 @@ function centerTransformer(offset) {
|
||||
vec.z += group.origin[2]
|
||||
}
|
||||
Transformer.position.copy(vec)
|
||||
if (Blockbench.globalMovement === false) {
|
||||
if (Blockbench.globalMovement === false && !rotate_tool) {
|
||||
var rotation = new THREE.Quaternion()
|
||||
first_obj.getMesh().getWorldQuaternion(rotation)
|
||||
Transformer.rotation.setFromQuaternion( rotation )
|
||||
@ -1233,10 +1229,7 @@ function centerTransformer(offset) {
|
||||
Transformer.rotation.set(0, 0, 0)
|
||||
}
|
||||
}
|
||||
|
||||
if (offset !== undefined) {
|
||||
//Transformer.position.add(offset)
|
||||
}
|
||||
Transformer.update()
|
||||
}
|
||||
//Display
|
||||
function getRescalingFactor(angle) {
|
||||
@ -1334,6 +1327,7 @@ class CanvasController {
|
||||
updateAll() {
|
||||
updateNslideValues()
|
||||
Canvas.clear()
|
||||
Canvas.updateAllBones()
|
||||
elements.forEach(function(s) {
|
||||
if (s.visibility == true) {
|
||||
Canvas.addCube(s)
|
||||
@ -1343,11 +1337,7 @@ class CanvasController {
|
||||
}
|
||||
updateAllPositions(leave_selection) {
|
||||
updateNslideValues()
|
||||
elements.forEach(function(obj) {
|
||||
if (obj.visibility == true) {
|
||||
Canvas.adaptObjectPosition(obj)
|
||||
}
|
||||
})
|
||||
elements.forEach(Canvas.adaptObjectPosition)
|
||||
if (leave_selection !== true) {
|
||||
updateSelection()
|
||||
}
|
||||
@ -1432,15 +1422,13 @@ class CanvasController {
|
||||
updateNslideValues()
|
||||
var arr = selected.slice()
|
||||
if (Blockbench.entity_mode && selected_group) {
|
||||
selected_group.children.forEach(function(s) {
|
||||
if (s.type === 'cube') {
|
||||
if (!arr.includes(s)) {
|
||||
arr.push(s)
|
||||
}
|
||||
selected_group.forEachChild(obj => {
|
||||
if (obj.type === 'cube') {
|
||||
arr.safePush(obj)
|
||||
}
|
||||
})
|
||||
if (arr.length === selected.length) {
|
||||
Canvas.ascendElementPosition(selected_group)
|
||||
Canvas.updateAllBones()
|
||||
}
|
||||
}
|
||||
arr.forEach(function(obj) {
|
||||
@ -1487,6 +1475,37 @@ class CanvasController {
|
||||
outlines.add(line)
|
||||
})
|
||||
}
|
||||
updateAllBones() {
|
||||
|
||||
getAllOutlinerGroups().forEach((obj) => {
|
||||
let mesh = obj.getMesh()
|
||||
if (obj.visibility && mesh) {
|
||||
|
||||
mesh.rotation.reorder('ZYX')
|
||||
obj.rotation.forEach(function(n, i) {
|
||||
mesh.rotation[getAxisLetter(i)] = Math.PI / (180 / n) * (i == 2 ? -1 : 1)
|
||||
})
|
||||
mesh.position.fromArray(obj.origin)
|
||||
mesh.scale.x = mesh.scale.y = mesh.scale.z = 1
|
||||
|
||||
if (obj.parent.type === 'group') {
|
||||
|
||||
mesh.position.x -= obj.parent.origin[0]
|
||||
mesh.position.y -= obj.parent.origin[1]
|
||||
mesh.position.z -= obj.parent.origin[2]
|
||||
|
||||
var parent_mesh = obj.parent.getMesh()
|
||||
parent_mesh.add(mesh)
|
||||
} else {
|
||||
scene.add(mesh)
|
||||
}
|
||||
mesh.updateMatrixWorld()
|
||||
|
||||
mesh.fix_position = mesh.position.clone()
|
||||
mesh.fix_rotation = mesh.rotation.clone()
|
||||
}
|
||||
})
|
||||
}
|
||||
//Object handlers
|
||||
addCube(obj) {
|
||||
//This does NOT remove old cubes
|
||||
@ -1505,7 +1524,9 @@ class CanvasController {
|
||||
Canvas.buildOutline(obj)
|
||||
}
|
||||
adaptObjectPosition(obj, mesh, parent) {
|
||||
if (!mesh) mesh = obj.getMesh()
|
||||
if (!obj.visibility) return;
|
||||
|
||||
if (!mesh || mesh > 0) mesh = obj.getMesh()
|
||||
|
||||
function setSize(geo) {
|
||||
if (Blockbench.entity_mode && obj.inflate !== undefined) {
|
||||
@ -1527,8 +1548,14 @@ class CanvasController {
|
||||
if (Blockbench.entity_mode) {
|
||||
mesh.position.set(0, 0, 0)
|
||||
mesh.rotation.reorder('YZX')
|
||||
Canvas.ascendElementPosition(obj, mesh)
|
||||
|
||||
if (obj.parent.type === 'group') {
|
||||
obj.parent.getMesh().add(mesh)
|
||||
mesh.position.x -= obj.parent.origin[0]
|
||||
mesh.position.y -= obj.parent.origin[1]
|
||||
mesh.position.z -= obj.parent.origin[2]
|
||||
} else {
|
||||
scene.add(mesh)
|
||||
}
|
||||
} else {
|
||||
if (obj.rotation !== undefined) {
|
||||
|
||||
@ -1561,8 +1588,6 @@ class CanvasController {
|
||||
if (!mesh) {
|
||||
mesh = obj.getMesh()
|
||||
}
|
||||
if (!mesh) {
|
||||
}
|
||||
if (obj.type === 'group') {
|
||||
mesh.rotation.reorder('ZYX')
|
||||
obj.rotation.forEach(function(n, i) {
|
||||
@ -1595,23 +1620,9 @@ class CanvasController {
|
||||
}
|
||||
iterate(el, elmesh)
|
||||
}
|
||||
getOutlineMesh(mesh) {
|
||||
var vs = mesh.geometry.vertices
|
||||
var geometry = new THREE.Geometry()
|
||||
geometry.vertices = [
|
||||
vs[2], vs[3],
|
||||
vs[6], vs[7],
|
||||
vs[2], vs[0],
|
||||
vs[1], vs[4],
|
||||
vs[5], vs[0],
|
||||
vs[5], vs[7],
|
||||
vs[6], vs[4],
|
||||
vs[1], vs[3]
|
||||
]
|
||||
return new THREE.Line(geometry, Canvas.outlineMaterial)
|
||||
}
|
||||
adaptObjectFaces(obj, mesh) {
|
||||
if (!mesh) mesh = obj.getMesh()
|
||||
if (!mesh) return;
|
||||
if (!Prop.wireframe) {
|
||||
var materials = []
|
||||
this.face_order.forEach(function(face) {
|
||||
@ -1753,6 +1764,22 @@ class CanvasController {
|
||||
mesh.geometry.elementsNeedUpdate = true;
|
||||
return mesh.geometry
|
||||
}
|
||||
//Outline
|
||||
getOutlineMesh(mesh) {
|
||||
var vs = mesh.geometry.vertices
|
||||
var geometry = new THREE.Geometry()
|
||||
geometry.vertices = [
|
||||
vs[2], vs[3],
|
||||
vs[6], vs[7],
|
||||
vs[2], vs[0],
|
||||
vs[1], vs[4],
|
||||
vs[5], vs[0],
|
||||
vs[5], vs[7],
|
||||
vs[6], vs[4],
|
||||
vs[1], vs[3]
|
||||
]
|
||||
return new THREE.Line(geometry, Canvas.outlineMaterial)
|
||||
}
|
||||
buildOutline(obj) {
|
||||
if (obj.visibility == false) return;
|
||||
var mesh = obj.getMesh();
|
||||
@ -1768,6 +1795,7 @@ class CanvasController {
|
||||
line.name = obj.uuid+'_outline';
|
||||
line.visible = obj.selected;
|
||||
line.renderOrder = 2;
|
||||
line.frustumCulled = false;
|
||||
mesh.outline = line;
|
||||
mesh.add(line);
|
||||
}
|
||||
@ -1800,7 +1828,7 @@ BARS.defineActions(function() {
|
||||
category: 'view',
|
||||
click: function () {
|
||||
var lines = [
|
||||
{label: 'dialog.create_gif.length', node: '<input class="dark_bordered half" type="number" value="10" id="gif_length">'},
|
||||
{label: 'dialog.create_gif.length', node: '<input class="dark_bordered half" type="number" value="10" step="0.25" id="gif_length">'},
|
||||
{label: 'dialog.create_gif.fps', node: '<input class="dark_bordered half" type="number" value="10" id="gif_fps">'},
|
||||
{label: 'dialog.create_gif.compression', node: '<input class="dark_bordered half" type="number" value="4" id="gif_quality">'},
|
||||
]
|
||||
@ -1814,7 +1842,7 @@ BARS.defineActions(function() {
|
||||
lines: lines,
|
||||
onConfirm: function() {
|
||||
var jq = $(dialog.object)
|
||||
var length = parseInt( jq.find('#gif_length').val() )
|
||||
var length = parseFloat( jq.find('#gif_length').val() )
|
||||
var fps = parseInt( jq.find('#gif_fps').val() )
|
||||
var quality = parseInt( jq.find('#gif_quality').val() )
|
||||
if (jq.find('#gif_play_animation').is(':checked')) {
|
||||
@ -1823,7 +1851,7 @@ BARS.defineActions(function() {
|
||||
Screencam.createGif({
|
||||
length: limitNumber(length, 0.1, 240)*1000,
|
||||
fps: limitNumber(fps, 0.5, 30),
|
||||
quality: limitNumber(fps, 0, 30),
|
||||
quality: limitNumber(quality, 0, 30),
|
||||
}, Screencam.returnScreenshot)
|
||||
dialog.hide()
|
||||
}
|
||||
|
@ -7,31 +7,32 @@ function settingSetup() {
|
||||
settings_old = {}
|
||||
settings = {
|
||||
//General
|
||||
language: {value: 'en', type: 'select', options: Language.options},
|
||||
show_actions: {value: false},
|
||||
backup_interval: {value: 10, type: 'number'},
|
||||
language: {value: 'en', type: 'select', options: Language.options},
|
||||
backup_interval: {value: 10, type: 'number', condition: isApp},
|
||||
backup_retain: {value: 30, type: 'number', condition: isApp},
|
||||
//Preview
|
||||
origin_size: {category: 'preview', value: 10, type: 'number'},
|
||||
control_size: {category: 'preview', value: 10, type: 'number'},
|
||||
//focal_length: {category: 'preview', value: 70, type: 'number'},
|
||||
display_skin: {category: 'preview', value: false, type: 'click', condition: isApp, icon: 'icon-player', click: function() { changeDisplaySkin() }},
|
||||
seethrough_outline: {category: 'preview', value: false},
|
||||
shading: {category: 'preview', value: true},
|
||||
transparency: {category: 'preview', value: true},
|
||||
texture_fps: {category: 'preview', value: 2, type: 'number'},
|
||||
//Grid
|
||||
base_grid: {category: 'grid', value: true,},
|
||||
large_grid: {category: 'grid', value: false},
|
||||
full_grid: {category: 'grid', value: false},
|
||||
large_box: {category: 'grid', value: false},
|
||||
display_grid: {category: 'grid', value: false},
|
||||
//Edit
|
||||
undo_limit: {category: 'edit', value: 80, type: 'number'},
|
||||
undo_limit: {category: 'edit', value: 128, type: 'number'},
|
||||
restricted_canvas: {category: 'edit', value: true},
|
||||
limited_rotation: {category: 'edit', value: true},
|
||||
local_move: {category: 'edit', value: true},
|
||||
canvas_unselect: {category: 'edit', value: false},
|
||||
paint_side_restrict:{category: 'edit', value: true},
|
||||
image_editor: {category: 'edit', value: false, type: 'click', condition: isApp, icon: 'fa-pencil-square', click: function() {changeImageEditor() }},
|
||||
//Grid
|
||||
base_grid: {category: 'grid', value: true,},
|
||||
large_grid: {category: 'grid', value: false},
|
||||
full_grid: {category: 'grid', value: false},
|
||||
large_box: {category: 'grid', value: false},
|
||||
display_grid: {category: 'grid', value: false},
|
||||
//Snapping
|
||||
edit_size: {category: 'snapping', value: 16, type: 'number'},
|
||||
shift_size: {category: 'snapping', value: 64, type: 'number'},
|
||||
@ -247,6 +248,12 @@ function saveSettings(force_update) {
|
||||
if (hasSettingChanged('texture_fps')) {
|
||||
TextureAnimator.updateSpeed()
|
||||
}
|
||||
/*
|
||||
if (hasSettingChanged('focal_length')) {
|
||||
previews.forEach(p => {
|
||||
p.camPers.setFocalLength(2000/limitNumber(settings.focal_length.value, 10, 200))
|
||||
})
|
||||
}*/
|
||||
if (hasSettingChanged('restricted_canvas') && settings.restricted_canvas.value && Blockbench.entity_mode === false) {
|
||||
moveIntoBox(undefined, false)
|
||||
}
|
||||
|
@ -29,16 +29,15 @@ class Texture {
|
||||
var c = 0
|
||||
var duplicates = false;
|
||||
while (c < textures.length) {
|
||||
if (textures[c].id === i) {
|
||||
if (textures[c].id == i) {
|
||||
duplicates = true;
|
||||
}
|
||||
c++;
|
||||
}
|
||||
//var matches = $.grep(textures, function(e) {return e.id == i})
|
||||
if (duplicates === true) {
|
||||
i++;
|
||||
} else {
|
||||
this.id = i;
|
||||
this.id = i.toString();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -193,13 +192,19 @@ class Texture {
|
||||
}
|
||||
fromJavaLink(link, path_array) {
|
||||
if (typeof link !== 'string' || (link.substr(0, 1) === '#' && !link.includes('/'))) {
|
||||
this.load()
|
||||
this.load();
|
||||
return this;
|
||||
}
|
||||
if (link.substr(0, 22) === 'data:image/png;base64,') {
|
||||
this.fromDataURL(link)
|
||||
return this;
|
||||
}
|
||||
if (isApp && (link.substr(1, 2) === ':\\' || link.substr(1, 2) === ':/')) {
|
||||
var path = link.replace(/\\|\//g, osfs).replace(/\?\d+/g, '')
|
||||
this.fromPath(path)
|
||||
return this;
|
||||
}
|
||||
var can_load = !!path_array.length
|
||||
var spaces = link.split(':')
|
||||
if (spaces.length > 1) {
|
||||
this.namespace = spaces[0]
|
||||
@ -208,8 +213,16 @@ class Texture {
|
||||
}
|
||||
path_array.push('textures', link.replace(/\//g, osfs))
|
||||
var path = path_array.join(osfs)+'.png'
|
||||
if (path) {
|
||||
if (path && can_load) {
|
||||
this.fromPath(path)
|
||||
} else {
|
||||
this.path = path
|
||||
this.folder = link.replace(/\\/g, '/').split('/')
|
||||
this.folder = this.folder.splice(0, this.folder.length-1).join('/')
|
||||
this.name = pathToName(path, true)
|
||||
this.mode = 'link'
|
||||
this.saved = true
|
||||
this.load()
|
||||
}
|
||||
return this;
|
||||
}
|
||||
@ -296,7 +309,7 @@ class Texture {
|
||||
delete this.isDefault
|
||||
}
|
||||
} else {
|
||||
var path = settings.default_path.value + osfs + this.folder + osfs + this.name
|
||||
var path = settings.default_path.value + osfs + this.folder.replace(/\//g, osfs) + osfs + this.name
|
||||
if (fs.existsSync(path)) {
|
||||
this.fromPath(path)
|
||||
return true;
|
||||
@ -333,7 +346,8 @@ class Texture {
|
||||
img.tex = tex;
|
||||
img.tex.magFilter = THREE.NearestFilter
|
||||
img.tex.minFilter = THREE.NearestFilter
|
||||
this.tex.needsUpdate = true;
|
||||
img.tex.needsUpdate = true;
|
||||
scope.img = img
|
||||
Canvas.materials[scope.uuid].map = tex
|
||||
}
|
||||
return this;
|
||||
@ -390,7 +404,7 @@ class Texture {
|
||||
this.refresh(true)
|
||||
}
|
||||
startWatcher() {
|
||||
if (this.mode !== 'link' || !isApp || !fs.existsSync(this.path)) {
|
||||
if (this.mode !== 'link' || !isApp || !this.path.match(/\.[a-zA-Z]+$/) || !fs.existsSync(this.path)) {
|
||||
return;
|
||||
}
|
||||
var scope = this;
|
||||
@ -438,11 +452,13 @@ class Texture {
|
||||
return this;
|
||||
}
|
||||
//Management
|
||||
select() {
|
||||
textures.forEach(function(s) {
|
||||
s.selected = false;
|
||||
select(event) {
|
||||
textures.forEach(s => {
|
||||
if (s.selected) s.selected = false;
|
||||
})
|
||||
Prop.active_panel = 'textures'
|
||||
if (event) {
|
||||
Prop.active_panel = 'textures'
|
||||
}
|
||||
this.selected = true
|
||||
textures.selected = this
|
||||
return this;
|
||||
@ -480,14 +496,20 @@ class Texture {
|
||||
}
|
||||
return this;
|
||||
}
|
||||
remove() {
|
||||
remove(no_update) {
|
||||
if (!no_update) {
|
||||
Undo.initEdit({textures: [this]})
|
||||
}
|
||||
this.stopWatcher()
|
||||
textures.splice(textures.indexOf(this), 1)
|
||||
Canvas.updateAllFaces()
|
||||
$('#uv_frame').css('background', 'transparent')
|
||||
TextureAnimator.updateButton()
|
||||
hideDialog()
|
||||
BARS.updateConditions()
|
||||
if (!no_update) {
|
||||
Canvas.updateAllFaces()
|
||||
$('#uv_frame').css('background', 'transparent')
|
||||
TextureAnimator.updateButton()
|
||||
hideDialog()
|
||||
BARS.updateConditions()
|
||||
Undo.finishEdit('remove_textures', {textures: []})
|
||||
}
|
||||
}
|
||||
//Use
|
||||
enableParticle() {
|
||||
@ -656,18 +678,17 @@ class Texture {
|
||||
return this;
|
||||
}
|
||||
toBitmap(cb) {
|
||||
//Converts texture to bitmap
|
||||
//Unsaves it
|
||||
var scope = this;
|
||||
if (isApp && scope.mode === 'link') {
|
||||
Jimp.read(scope.source).then(function (image) {
|
||||
image.getBase64(Jimp.MIME_PNG, function(err, dataUrl) {
|
||||
scope.mode = 'bitmap'
|
||||
scope.saved = false
|
||||
scope.source = dataUrl
|
||||
cb()
|
||||
})
|
||||
})
|
||||
var canvas = document.createElement('canvas')
|
||||
canvas.width = scope.img.naturalWidth;
|
||||
canvas.height = scope.img.naturalHeight;
|
||||
var ctx = canvas.getContext('2d');
|
||||
ctx.drawImage(scope.img, 0, 0)
|
||||
scope.mode = 'bitmap'
|
||||
scope.saved = false
|
||||
scope.source = canvas.toDataURL('image/png')
|
||||
cb()
|
||||
}
|
||||
}
|
||||
edit(cb, options) {
|
||||
|
222
js/transform.js
222
js/transform.js
@ -158,37 +158,36 @@ function moveIntoBox(list, value_before) {
|
||||
Undo.finishEdit('restrict', {cubes: selected, settings: {restricted_canvas: true}})
|
||||
}
|
||||
//Movement
|
||||
function moveCube(obj, val, axis) {
|
||||
function moveCube(obj, val, axis, move_origin) {
|
||||
//Obj = Direct - val = Total - Axis = Number
|
||||
val = limitToBox(val)
|
||||
val = limitToBox(val + obj.size(axis))
|
||||
var size = obj.size(axis)
|
||||
var difference = val - obj.to[axis]
|
||||
if (!Blockbench.entity_mode || !Blockbench.globalMovement) {
|
||||
|
||||
//Move
|
||||
if (Blockbench.globalMovement && Blockbench.entity_mode && !move_origin) {
|
||||
var m = new THREE.Vector3()
|
||||
m[getAxisLetter(axis)] = difference
|
||||
|
||||
var rotation = new THREE.Quaternion()
|
||||
obj.getMesh().getWorldQuaternion(rotation)
|
||||
m.applyQuaternion(rotation.inverse())
|
||||
|
||||
obj.from[0] += m.x;
|
||||
obj.from[1] += m.y;
|
||||
obj.from[2] += m.z;
|
||||
obj.to[0] += m.x;
|
||||
obj.to[1] += m.y;
|
||||
obj.to[2] += m.z;
|
||||
|
||||
} else {
|
||||
obj.to[axis] = val
|
||||
obj.from[axis] = val - size
|
||||
}
|
||||
if (Blockbench.globalMovement) {
|
||||
if (!Blockbench.entity_mode) {
|
||||
obj.origin[axis] += difference
|
||||
} else {
|
||||
var m = new THREE.Vector3()
|
||||
m[getAxisLetter(axis)] = difference
|
||||
|
||||
|
||||
|
||||
var rotation = new THREE.Quaternion()
|
||||
obj.getMesh().getWorldQuaternion(rotation)
|
||||
m.applyQuaternion(rotation.inverse())
|
||||
|
||||
|
||||
obj.from[0] += m.x;
|
||||
obj.from[1] += m.y;
|
||||
obj.from[2] += m.z;
|
||||
obj.to[0] += m.x;
|
||||
obj.to[1] += m.y;
|
||||
obj.to[2] += m.z;
|
||||
}
|
||||
//Origin
|
||||
if (Blockbench.globalMovement && !Blockbench.entity_mode) {
|
||||
obj.origin[axis] += difference
|
||||
}
|
||||
obj.mapAutoUV()
|
||||
}
|
||||
@ -404,6 +403,92 @@ function centerCubes(axis, update) {
|
||||
}
|
||||
}
|
||||
|
||||
function getRotationInterval(event) {
|
||||
if (settings.limited_rotation.value && !Blockbench.entity_mode) {
|
||||
return 22.5;
|
||||
} else if (event.shiftKey && event.ctrlKey) {
|
||||
return 0.25;
|
||||
} else if (event.shiftKey) {
|
||||
return 45;
|
||||
} else if (event.ctrlKey) {
|
||||
return 1;
|
||||
} else {
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
function rotateOnAxis(value, fixed, axis) {
|
||||
if (Blockbench.entity_mode) {
|
||||
if (!selected_group) return;
|
||||
if (!fixed) {
|
||||
value = value + selected_group.rotation[axis]
|
||||
}
|
||||
value = Math.trimDeg(value)
|
||||
selected_group.rotation[axis] = value
|
||||
Canvas.updateAllBones()
|
||||
return;
|
||||
}
|
||||
//Warning
|
||||
if (settings.limited_rotation.value && settings.dialog_rotation_limit.value) {
|
||||
var i = 0;
|
||||
while (i < selected.length) {
|
||||
if (selected[i].rotation[(axis+1)%3] ||
|
||||
selected[i].rotation[(axis+2)%3]
|
||||
) {
|
||||
i = Infinity
|
||||
|
||||
Blockbench.showMessageBox({
|
||||
title: tl('message.rotation_limit.title'),
|
||||
icon: 'rotate_right',
|
||||
message: tl('message.rotation_limit.message'),
|
||||
buttons: [tl('dialog.ok'), tl('dialog.dontshowagain')]
|
||||
}, function(r) {
|
||||
if (r === 1) {
|
||||
settings.dialog_rotation_limit.value = false
|
||||
saveSettings()
|
||||
}
|
||||
})
|
||||
return;
|
||||
//Gotta stop the numslider here
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
var axis_letter = getAxisLetter(axis)
|
||||
var origin = selected[0].origin
|
||||
selected.forEach(function(obj, i) {
|
||||
if (!obj.rotation.equals([0,0,0])) {
|
||||
origin = obj.origin
|
||||
}
|
||||
})
|
||||
selected.forEach(function(obj, i) {
|
||||
if (obj.rotation.equals([0,0,0])) {
|
||||
obj.origin = origin
|
||||
}
|
||||
var obj_val = value;
|
||||
if (!fixed) {
|
||||
obj_val += obj.rotation[axis]
|
||||
}
|
||||
obj_val = obj_val % 360
|
||||
if (settings.limited_rotation.value) {
|
||||
//Limit To 1 Axis
|
||||
obj.rotation[(axis+1)%3] = 0
|
||||
obj.rotation[(axis+2)%3] = 0
|
||||
//Limit Angle
|
||||
obj_val = Math.round(obj_val/22.5)*22.5
|
||||
if (obj_val > 45 || obj_val < -45) {
|
||||
|
||||
let f = obj_val > 45
|
||||
obj.roll(axis, f!=(axis==1) ? 1 : 3)
|
||||
obj_val = f ? -22.5 : 22.5;
|
||||
}
|
||||
} else {
|
||||
obj_val = Math.trimDeg(obj_val)
|
||||
}
|
||||
obj.rotation[axis] = obj_val
|
||||
obj.rotation_axis = axis_letter
|
||||
})
|
||||
}
|
||||
|
||||
BARS.defineActions(function() {
|
||||
function moveOnAxis(value, fixed, axis) {
|
||||
selected.forEach(function(obj, i) {
|
||||
@ -531,7 +616,7 @@ BARS.defineActions(function() {
|
||||
Undo.finishEdit('resize')
|
||||
}
|
||||
})
|
||||
|
||||
//Inflage
|
||||
new NumSlider({
|
||||
id: 'slider_inflate',
|
||||
condition: function() {return Blockbench.entity_mode && selected.length},
|
||||
@ -555,91 +640,7 @@ BARS.defineActions(function() {
|
||||
Undo.finishEdit('inflate')
|
||||
}
|
||||
})
|
||||
|
||||
function rotateOnAxis(value, fixed, axis) {
|
||||
if (Blockbench.entity_mode) {
|
||||
if (!selected_group) return;
|
||||
if (!fixed) {
|
||||
value = value + selected_group.rotation[axis]
|
||||
}
|
||||
value = value % 360
|
||||
selected_group.rotation[axis] = value
|
||||
Canvas.updatePositions()
|
||||
return;
|
||||
}
|
||||
//Warning
|
||||
if (settings.limited_rotation.value && settings.dialog_rotation_limit.value) {
|
||||
var i = 0;
|
||||
while (i < selected.length) {
|
||||
if (selected[i].rotation[(axis+1)%3] ||
|
||||
selected[i].rotation[(axis+2)%3]
|
||||
) {
|
||||
i = Infinity
|
||||
|
||||
Blockbench.showMessageBox({
|
||||
title: tl('message.rotation_limit.title'),
|
||||
icon: 'rotate_right',
|
||||
message: tl('message.rotation_limit.message'),
|
||||
buttons: [tl('dialog.ok'), tl('dialog.dontshowagain')]
|
||||
}, function(r) {
|
||||
if (r === 1) {
|
||||
settings.dialog_rotation_limit.value = false
|
||||
saveSettings()
|
||||
}
|
||||
})
|
||||
return;
|
||||
//Gotta stop the numslider here
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
var axis_letter = getAxisLetter(axis)
|
||||
var origin = selected[0].origin
|
||||
selected.forEach(function(obj, i) {
|
||||
if (!obj.rotation.equals([0,0,0])) {
|
||||
origin = obj.origin
|
||||
}
|
||||
})
|
||||
selected.forEach(function(obj, i) {
|
||||
if (obj.rotation.equals([0,0,0])) {
|
||||
obj.origin = origin
|
||||
}
|
||||
var obj_val = value;
|
||||
if (!fixed) {
|
||||
obj_val += obj.rotation[axis]
|
||||
}
|
||||
obj_val = obj_val % 360
|
||||
if (settings.limited_rotation.value) {
|
||||
//Limit To 1 Axis
|
||||
obj.rotation[(axis+1)%3] = 0
|
||||
obj.rotation[(axis+2)%3] = 0
|
||||
//Limit Angle
|
||||
obj_val = Math.round(obj_val/22.5)*22.5
|
||||
if (obj_val > 45 || obj_val < -45) {
|
||||
|
||||
let f = obj_val > 45
|
||||
obj.roll(axis, f!=(axis==1) ? 1 : 3)
|
||||
obj_val = f ? -22.5 : 22.5;
|
||||
}
|
||||
}
|
||||
obj.rotation[axis] = obj_val
|
||||
obj.rotation_axis = axis_letter
|
||||
})
|
||||
Canvas.updatePositions()
|
||||
}
|
||||
function getRotationInterval(event) {
|
||||
if (settings.limited_rotation.value && !Blockbench.entity_mode) {
|
||||
return 22.5;
|
||||
} else if (event.shiftKey && event.ctrlKey) {
|
||||
return 0.25;
|
||||
} else if (event.shiftKey) {
|
||||
return 45;
|
||||
} else if (event.ctrlKey) {
|
||||
return 1;
|
||||
} else {
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
//Rotation
|
||||
new NumSlider({
|
||||
id: 'slider_rotation_x',
|
||||
condition: function() {return !!(Blockbench.entity_mode ? selected_group : selected.length)},
|
||||
@ -649,6 +650,7 @@ BARS.defineActions(function() {
|
||||
},
|
||||
change: function(value, fixed) {
|
||||
rotateOnAxis(value, fixed, 0)
|
||||
Canvas.updatePositions()
|
||||
},
|
||||
onBefore: function() {
|
||||
Undo.initEdit({cubes: selected, group: selected_group})
|
||||
@ -667,6 +669,7 @@ BARS.defineActions(function() {
|
||||
},
|
||||
change: function(value, fixed) {
|
||||
rotateOnAxis(value, fixed, 1)
|
||||
Canvas.updatePositions()
|
||||
},
|
||||
onBefore: function() {
|
||||
Undo.initEdit({cubes: selected, group: selected_group})
|
||||
@ -685,6 +688,7 @@ BARS.defineActions(function() {
|
||||
},
|
||||
change: function(value, fixed) {
|
||||
rotateOnAxis(value, fixed, 2)
|
||||
Canvas.updatePositions()
|
||||
},
|
||||
onBefore: function() {
|
||||
Undo.initEdit({cubes: selected, group: selected_group})
|
||||
|
@ -7,6 +7,7 @@
|
||||
class="outliner_object" v-on:dblclick="node.rename($event)"
|
||||
v-on:click="node.select($event, true)" v-on:touchstart="node.select($event)" :title="node.title"
|
||||
v-bind:class="{ cube: node.type === \'cube\', group: node.type === \'group\', selected: node.selected }"
|
||||
v-bind:style="{'padding-left': (node.getDepth ? limitNumber(node.getDepth(), 0, (Interface.Panels.outliner.width-124) / 20) * 20 : 0)+'px'}"
|
||||
>` +
|
||||
//Opener
|
||||
|
||||
|
41
js/undo.js
41
js/undo.js
@ -142,6 +142,13 @@ var Undo = {
|
||||
scope.keyframes[kf.uuid] = kf.undoCopy()
|
||||
})
|
||||
}
|
||||
|
||||
if (aspects.display_slots) {
|
||||
scope.display_slots = {}
|
||||
aspects.display_slots.forEach(slot => {
|
||||
scope.display_slots[slot] = display[slot].copy()
|
||||
})
|
||||
}
|
||||
},
|
||||
loadSave: function(save, reference) {
|
||||
if (save.cubes) {
|
||||
@ -323,6 +330,38 @@ var Undo = {
|
||||
}
|
||||
updateKeyframeSelection()
|
||||
}
|
||||
|
||||
if (save.display_slots) {
|
||||
for (var slot in save.display_slots) {
|
||||
if (!display[slot]) {
|
||||
display[slot] = new DisplaySlot()
|
||||
}
|
||||
display[slot].extend(save.display_slots[slot]).update()
|
||||
}
|
||||
}
|
||||
updateSelection()
|
||||
}
|
||||
}
|
||||
}
|
||||
Undo.save.prototype.addTexture = function(texture) {
|
||||
if (!this.textures) return;
|
||||
if (this.aspects.textures.safePush(texture)) {
|
||||
this.textures[texture.uuid] = texture.getUndoCopy(this.aspects.bitmap)
|
||||
}
|
||||
}
|
||||
BARS.defineActions(function() {
|
||||
|
||||
new Action({
|
||||
id: 'undo',
|
||||
icon: 'undo',
|
||||
category: 'edit',
|
||||
keybind: new Keybind({key: 90, ctrl: true}),
|
||||
click: function () {Undo.undo()}
|
||||
})
|
||||
new Action({
|
||||
id: 'redo',
|
||||
icon: 'redo',
|
||||
category: 'edit',
|
||||
keybind: new Keybind({key: 89, ctrl: true}),
|
||||
click: function () {Undo.redo()}
|
||||
})
|
||||
})
|
106
js/util.js
106
js/util.js
@ -48,6 +48,18 @@ function useBedrockFlipFix(axis) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
const Condition = function(condition, context) {
|
||||
if (condition !== undefined && condition !== null && condition.condition !== undefined) {
|
||||
condition = condition.condition
|
||||
}
|
||||
if (condition === undefined) {
|
||||
return true;
|
||||
} else if (typeof condition === 'function') {
|
||||
return condition(context)
|
||||
} else {
|
||||
return !!condition
|
||||
}
|
||||
}
|
||||
var cl = console.log
|
||||
var asyncLoop = function(o){
|
||||
var i=-1;
|
||||
@ -85,6 +97,9 @@ Math.lerp = function(a,b,m) {
|
||||
Math.isBetween = function(n, a, b) {
|
||||
return (n - a) * (n - b) <= 0
|
||||
}
|
||||
Math.trimDeg = function(a) {
|
||||
return (a+180*15)%360-180
|
||||
}
|
||||
function trimFloatNumber(val) {
|
||||
if (val == '') return val;
|
||||
var string = val.toFixed(4)
|
||||
@ -154,8 +169,10 @@ function doRectanglesOverlap(rect1, rect2) {
|
||||
//Array
|
||||
Array.prototype.safePush = function(item) {
|
||||
if (!this.includes(item)) {
|
||||
this.push(item)
|
||||
this.push(item);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Array.prototype.equals = function (array) {
|
||||
if (!array)
|
||||
@ -342,50 +359,51 @@ tinycolor.prototype.toInt = function() {
|
||||
var rgba = this.toRgb()
|
||||
return Jimp.rgbaToInt(rgba.r, rgba.g, rgba.b, rgba.a)
|
||||
}
|
||||
function getAverageRGB(imgEl) {
|
||||
function getAverageRGB(imgEl, blockSize) {
|
||||
|
||||
var blockSize = 5, // only visit every 5 pixels
|
||||
defaultRGB = {r:0,g:0,b:0}, // for non-supporting envs
|
||||
canvas = document.createElement('canvas'),
|
||||
context = canvas.getContext && canvas.getContext('2d'),
|
||||
data, width, height,
|
||||
i = -4,
|
||||
length,
|
||||
rgb = {r:0,g:0,b:0},
|
||||
count = 0;
|
||||
|
||||
if (!context) {
|
||||
return defaultRGB;
|
||||
var defaultRGB = {r:0,g:0,b:0}, // for non-supporting envs
|
||||
canvas = document.createElement('canvas'),
|
||||
context = canvas.getContext && canvas.getContext('2d'),
|
||||
data, width, height,
|
||||
i = -4,
|
||||
length,
|
||||
rgb = {r:0,g:0,b:0},
|
||||
count = 0;
|
||||
|
||||
if (!context) {
|
||||
return defaultRGB;
|
||||
}
|
||||
|
||||
height = canvas.height = imgEl.naturalHeight || imgEl.offsetHeight || imgEl.height;
|
||||
width = canvas.width = imgEl.naturalWidth || imgEl.offsetWidth || imgEl.width;
|
||||
|
||||
context.drawImage(imgEl, 0, 0);
|
||||
|
||||
try {
|
||||
data = context.getImageData(0, 0, width, height);
|
||||
} catch(e) {
|
||||
/* security error, img on diff domain */alert('x');
|
||||
return defaultRGB;
|
||||
}
|
||||
|
||||
length = data.data.length;
|
||||
|
||||
if (!blockSize) blockSize = Math.ceil(length/64)
|
||||
|
||||
while ( (i += blockSize * 4) < length ) {
|
||||
if (data.data[i+3] > 0) {
|
||||
++count;
|
||||
rgb.r += data.data[i];
|
||||
rgb.g += data.data[i+1];
|
||||
rgb.b += data.data[i+2];
|
||||
}
|
||||
|
||||
height = canvas.height = imgEl.naturalHeight || imgEl.offsetHeight || imgEl.height;
|
||||
width = canvas.width = imgEl.naturalWidth || imgEl.offsetWidth || imgEl.width;
|
||||
|
||||
context.drawImage(imgEl, 0, 0);
|
||||
|
||||
try {
|
||||
data = context.getImageData(0, 0, width, height);
|
||||
} catch(e) {
|
||||
/* security error, img on diff domain */alert('x');
|
||||
return defaultRGB;
|
||||
}
|
||||
|
||||
length = data.data.length;
|
||||
|
||||
while ( (i += blockSize * 4) < length ) {
|
||||
if (data.data[i+3] > 0) {
|
||||
++count;
|
||||
rgb.r += data.data[i];
|
||||
rgb.g += data.data[i+1];
|
||||
rgb.b += data.data[i+2];
|
||||
}
|
||||
}
|
||||
|
||||
// ~~ used to floor values
|
||||
rgb.r = ~~(rgb.r/count);
|
||||
rgb.g = ~~(rgb.g/count);
|
||||
rgb.b = ~~(rgb.b/count);
|
||||
|
||||
return rgb;
|
||||
}
|
||||
|
||||
// ~~ used to floor values
|
||||
rgb.r = ~~(rgb.r/count);
|
||||
rgb.g = ~~(rgb.g/count);
|
||||
rgb.b = ~~(rgb.b/count);
|
||||
|
||||
return rgb;
|
||||
}
|
||||
|
||||
|
4
js/uv.js
4
js/uv.js
@ -1109,7 +1109,7 @@ class UVEditor {
|
||||
uv: tag.uv.slice(),
|
||||
face: face
|
||||
}
|
||||
if (tag.texture) new_tag.texture = tag.texture
|
||||
if (tag.texture !== undefined) new_tag.texture = tag.texture
|
||||
if (tag.cullface) new_tag.cullface = tag.cullface
|
||||
if (tag.rotation) new_tag.rotation = tag.rotation
|
||||
if (tag.enabled !== undefined) new_tag.enabled = tag.enabled
|
||||
@ -1144,7 +1144,7 @@ class UVEditor {
|
||||
var target = obj.faces[face]
|
||||
target.uv = tag.uv.slice()
|
||||
|
||||
if (tag.texture || target.texture) target.texture = tag.texture
|
||||
if (tag.texture !== undefined || target.texture !== undefined) target.texture = tag.texture
|
||||
if (tag.cullface || target.cullface) target.cullface = tag.cullface
|
||||
if (tag.rotation || target.rotation) target.rotation = tag.rotation
|
||||
if (tag.enabled !== undefined || target.enabled !== undefined) target.enabled = tag.enabled
|
||||
|
24
js/web.js
24
js/web.js
@ -2,7 +2,6 @@
|
||||
$.getScript("lib/file_saver.js");
|
||||
})()
|
||||
|
||||
|
||||
$(document).ready(function() {
|
||||
$('.open-in-browser').click((event) => {
|
||||
event.preventDefault();
|
||||
@ -10,8 +9,6 @@ $(document).ready(function() {
|
||||
});
|
||||
})
|
||||
|
||||
|
||||
|
||||
function tryLoadPOSTModel() {
|
||||
if ($('#post_model').text() !== '') {
|
||||
if ($('#post_textures').text() !== '') {
|
||||
@ -40,20 +37,7 @@ function tryLoadPOSTModel() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//Saver
|
||||
function writeFileEntity() {
|
||||
var obj = {}
|
||||
var model_name = Project.parent
|
||||
if (model_name == '') model_name = 'geometry.unknown'
|
||||
obj[model_name] = buildEntityModel({raw: true})
|
||||
|
||||
var data = autoStringify(obj)
|
||||
var blob = new Blob([data], {type: "text/plain;charset=utf-8"});
|
||||
saveAs(blob, 'mobs.json', {autoBOM: true})
|
||||
Blockbench.showQuickMessage('Saved as bedrock entity model')
|
||||
}
|
||||
function writeFileObj() {
|
||||
var delay = 40
|
||||
var content = buildOBJModel('model')
|
||||
@ -99,9 +83,11 @@ function writeFileObj() {
|
||||
}
|
||||
|
||||
function saveFile() {
|
||||
var data = buildBlockModel()
|
||||
var blob = new Blob([data], {type: "text/plain;charset=utf-8"});
|
||||
saveAs(blob, 'model.json', {autoBOM: true})
|
||||
if (Blockbench.entity_mode === false) {
|
||||
BarItems.export_blockmodel.trigger()
|
||||
} else {
|
||||
BarItems.export_entity.trigger()
|
||||
}
|
||||
}
|
||||
|
||||
//Misc
|
||||
|
36
lang/de.json
36
lang/de.json
@ -99,7 +99,7 @@
|
||||
"message.restart_to_update": "Starte Blockbench neu, um die Änderungen wirksam werden zu lassen.",
|
||||
"message.save_file": "Gespeichert als %0",
|
||||
"message.save_obj": "Gespeichert als .obj Modell",
|
||||
"message.save_entity": "Gespeichert als Bedrock TIermodell",
|
||||
"message.save_entity": "Gespeichert als Bedrock Entitymodell",
|
||||
"message.rename_cubes": "Elemente umbenennen",
|
||||
"dialog.project.title": "Projekt",
|
||||
"dialog.project.name": "Dateiname",
|
||||
@ -354,8 +354,6 @@
|
||||
"action.brush_tool.desc": "Werkzeug zum Malen auf Texturen an Elementen oder im UV Fenster",
|
||||
"action.vertex_snap_tool": "Eckpunktmagnet",
|
||||
"action.vertex_snap_tool.desc": "Verbindet die Ecken von 2 Elementen indem es das eine verschiebt",
|
||||
"action.display_mode_tool": "Anzeigemodus",
|
||||
"action.display_mode_tool.desc": "Verändern, wie das Modell im Spiel positioniert ist",
|
||||
"action.swap_tools": "Werkzeuge wechseln",
|
||||
"action.swap_tools.desc": "Wechselt zwischen dem Verschieben- und Größenwerkzeug",
|
||||
"action.project_window": "Projekt...",
|
||||
@ -363,7 +361,7 @@
|
||||
"action.new_block_model": "Neues Modell",
|
||||
"action.new_block_model.desc": "Erstellt ein neues Block- oder Gegenstandsmodell",
|
||||
"action.new_entity_model": "Neues Tiermodell",
|
||||
"action.new_entity_model.desc": "Erstellt ein neues Bedrock Tiermodell",
|
||||
"action.new_entity_model.desc": "Erstellt ein neues Bedrock Entitymodell",
|
||||
"action.open_model": "Modell Öffnen",
|
||||
"action.open_model.desc": "Öffne ein Modell von deinem Computer",
|
||||
"action.add_model": "Modell hinzufügen",
|
||||
@ -375,9 +373,9 @@
|
||||
"action.export_entity": "Bedrock Tier exportieren",
|
||||
"action.export_entity.desc": "Das aktuelle Modell als Tier zu einer mobs.json Datei hinzufügen",
|
||||
"action.export_optifine_part": "OptiFine JPM exportieren",
|
||||
"action.export_optifine_part.desc": "Einen Tier-Komponenten für OptiFine exportieren",
|
||||
"action.export_optifine_part.desc": "Einen Entity-Komponenten für OptiFine exportieren",
|
||||
"action.export_optifine_full": "OptiFine JEM exportieren",
|
||||
"action.export_optifine_full.desc": "Ein vollständiges Tiermodell für OptiFine exportieren",
|
||||
"action.export_optifine_full.desc": "Ein vollständiges Entitymodell für OptiFine exportieren",
|
||||
"action.export_obj": "OBJ Modell exportieren",
|
||||
"action.export_obj.desc": "Ein Wavefront OBJ Modell exportieren zur Weiterverwendung in anderen Programmen oder zum Hochladen auf Sketchfab",
|
||||
"action.save": "Speichern",
|
||||
@ -648,10 +646,8 @@
|
||||
"dialog.update.latest": "Aktuelle Version",
|
||||
"dialog.update.installed": "Installierte Version",
|
||||
"dialog.update.update": "Aktualisieren",
|
||||
"action.brush_mode.brush": "Pinsel",
|
||||
"action.brush_mode.brush": "Rund",
|
||||
"action.brush_mode.noise": "Rauschen",
|
||||
"action.brush_mode.eraser": "Radierer",
|
||||
"action.brush_mode.fill": "Füllen",
|
||||
"action.vertex_snap_mode.move": "Verschieben",
|
||||
"action.vertex_snap_mode.scale": "Größe ändern",
|
||||
"action.open_model_folder": "Modellordner öffnen",
|
||||
@ -732,8 +728,6 @@
|
||||
"category.uv": "UV",
|
||||
"status_bar.saved": "Modell ist gespeichert",
|
||||
"status_bar.unsaved": "Es gibt ungespeicherte Änderungen",
|
||||
"action.animation_mode_tool": "Animation",
|
||||
"action.animation_mode_tool.desc": "Erstelle eigene Animationen für dieses Modell",
|
||||
"action.move_up": "Hoch verschieben",
|
||||
"action.move_up.desc": "Verschiebt die ausgewählten Elemente relativ zur Kameraperspektive nach oben",
|
||||
"action.move_down": "Runter verschieben",
|
||||
@ -811,5 +805,23 @@
|
||||
"action.export_class_entity": "Java Entity exportieren",
|
||||
"action.export_class_entity.desc": "Exportiert das Modell als Java Class.",
|
||||
"settings.seethrough_outline": "Durchscheinende Auswahl",
|
||||
"settings.seethrough_outline.desc": "Zeige Auswahl durch Objekte hindurch an"
|
||||
"settings.seethrough_outline.desc": "Zeige Auswahl durch Objekte hindurch an",
|
||||
"mode.edit": "Modellieren",
|
||||
"mode.paint": "Malen",
|
||||
"mode.display": "Vorschau",
|
||||
"mode.animate": "Animieren",
|
||||
"status_bar.recording_gif": "GIF wird aufgezeichnet",
|
||||
"status_bar.processing_gif": "GIF wird verarbeitet",
|
||||
"settings.backup_retain": "Backup Speicherdauer",
|
||||
"settings.backup_retain.desc": "Festlegen, wie viele Tage Blockbench alte Backups speichert",
|
||||
"action.rotate_tool": "Drehen",
|
||||
"action.rotate_tool.desc": "Werkzeug zum Auswählen und Drehen von Elementen",
|
||||
"action.fill_tool": "Farbeimer",
|
||||
"action.fill_tool.desc": "Farbeimer zum einfarbigen Ausfüllen von Oberflächen",
|
||||
"action.eraser": "Radiergummi",
|
||||
"action.eraser.desc": "Raddiergummi zum Ersetzen der Farben durch Transparenz",
|
||||
"action.color_picker": "Farbpipette",
|
||||
"action.color_picker.desc": "Wählt die Farbe eines Pixels der Textur aus.",
|
||||
"action.open_backup_folder": "Backup-Ordner öffnen",
|
||||
"action.open_backup_folder.desc": "Öffnet den Backup-Ordner von Blockbench"
|
||||
}
|
42
lang/en.json
42
lang/en.json
@ -22,6 +22,11 @@
|
||||
"generic.delete": "Delete",
|
||||
"generic.rename": "Rename",
|
||||
|
||||
"mode.edit": "Edit",
|
||||
"mode.paint": "Paint",
|
||||
"mode.display": "Display",
|
||||
"mode.animate": "Animate",
|
||||
|
||||
"keys.ctrl": "Control",
|
||||
"keys.shift": "Shift",
|
||||
"keys.alt": "Alt",
|
||||
@ -58,6 +63,8 @@
|
||||
"status_bar.saved":"Model is saved",
|
||||
"status_bar.unsaved":"There are unsaved changes",
|
||||
"status_bar.vertex_distance":"Distance: %0",
|
||||
"status_bar.recording_gif":"Recording GIF",
|
||||
"status_bar.processing_gif":"Processing GIF",
|
||||
|
||||
"message.rotation_limit.title": "Rotation Limits",
|
||||
"message.rotation_limit.message": "Rotations are limited by Minecraft to one axis and 22.5 degree increments. Rotating on a different axis will clear all rotations on the other axes. Disable the option \"Restricted Rotation\" if you are modeling for other purposes and need free rotations.",
|
||||
@ -300,11 +307,13 @@
|
||||
"settings.category.export": "Export",
|
||||
|
||||
"settings.language": "Language",
|
||||
"settings.language.desc": "Interface language. Restart Blockbench to apply changes.",
|
||||
"settings.language.desc": "Interface language. Restart Blockbench to apply changes",
|
||||
"settings.show_actions": "Display Actions",
|
||||
"settings.show_actions.desc": "Display every action in the status bar",
|
||||
"settings.backup_interval": "Backup Interval",
|
||||
"settings.backup_interval.desc": "Interval of the automatic backups in minutes",
|
||||
"settings.backup_retain": "Backup Retain Duration",
|
||||
"settings.backup_retain.desc": "Set how long Blockbench retains old backups in days",
|
||||
|
||||
"settings.origin_size": "Rotation Origin",
|
||||
"settings.origin_size.desc": "Size of the rotation origin",
|
||||
@ -428,10 +437,8 @@
|
||||
|
||||
"action.brush_mode": "Brush Mode",
|
||||
"action.brush_mode.desc": "Mode of the brush",
|
||||
"action.brush_mode.brush": "Brush",
|
||||
"action.brush_mode.brush": "Round",
|
||||
"action.brush_mode.noise": "Noise",
|
||||
"action.brush_mode.eraser": "Eraser",
|
||||
"action.brush_mode.fill": "Fill",
|
||||
"action.brush_color": "Color",
|
||||
"action.brush_color.desc": "Color of the brush",
|
||||
"action.slider_brush_size": "Size",
|
||||
@ -461,14 +468,19 @@
|
||||
"action.move_tool.desc": "Tool to select and move elements",
|
||||
"action.resize_tool": "Resize",
|
||||
"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.brush_tool": "Paint Brush",
|
||||
"action.brush_tool.desc": "Tool to paint on bitmap textures on surfaces or the UV editor.",
|
||||
"action.brush_tool.desc": "Tool to paint on bitmap textures on surfaces or the UV editor",
|
||||
"action.fill_tool": "Paint Bucket",
|
||||
"action.fill_tool.desc": "Paint bucket to fill entire faces with one color",
|
||||
"action.eraser": "Eraser",
|
||||
"action.eraser.desc": "Eraser tool to replace colors on a texture with transparency",
|
||||
"action.color_picker": "Color Picker",
|
||||
"action.color_picker.desc": "Tool to pick the color of pixels on your texture",
|
||||
|
||||
"action.vertex_snap_tool": "Vertex Snap",
|
||||
"action.vertex_snap_tool.desc": "Move one cube to another cube by connecting two vertices.",
|
||||
"action.display_mode_tool": "Display",
|
||||
"action.display_mode_tool.desc": "Change how the model will look when held by players",
|
||||
"action.animation_mode_tool": "Animation",
|
||||
"action.animation_mode_tool.desc": "Define custom animations for the model",
|
||||
"action.vertex_snap_tool.desc": "Move one cube to another cube by connecting two vertices",
|
||||
"action.swap_tools": "Swap Tools",
|
||||
"action.swap_tools.desc": "Switch between the move and resize tool",
|
||||
|
||||
@ -476,6 +488,8 @@
|
||||
"action.project_window.desc": "Opens the project window, where you can edit metadata of your model",
|
||||
"action.open_model_folder": "Open Model Folder",
|
||||
"action.open_model_folder.desc": "Opens the folder that the model is contained in",
|
||||
"action.open_backup_folder": "Open Backup Folder",
|
||||
"action.open_backup_folder.desc": "Opens the Blockbench backup folder",
|
||||
"action.new_block_model": "New Model",
|
||||
"action.new_block_model.desc": "Creates a new block/item model",
|
||||
"action.new_entity_model": "New Entity Model",
|
||||
@ -492,10 +506,10 @@
|
||||
"action.export_entity.desc": "Add the current model as an entity to a mobs.json file",
|
||||
"action.export_class_entity": "Export Java Entity",
|
||||
"action.export_class_entity.desc": "Export the entity model as a Java class",
|
||||
"action.export_optifine_part": "Export Optifine JPM",
|
||||
"action.export_optifine_part.desc": "Export an entity part model for Optifine",
|
||||
"action.export_optifine_full": "Export Optifine JEM",
|
||||
"action.export_optifine_full.desc": "Export a full Optifine entity model",
|
||||
"action.export_optifine_part": "Export OptiFine JPM",
|
||||
"action.export_optifine_part.desc": "Export an entity part model for OptiFine",
|
||||
"action.export_optifine_full": "Export OptiFine JEM",
|
||||
"action.export_optifine_full.desc": "Export a full OptiFine entity model",
|
||||
"action.export_obj": "Export OBJ Model",
|
||||
"action.export_obj.desc": "Export a Wavefront OBJ model for use in other programs or to upload to Sketchfab",
|
||||
"action.save": "Save",
|
||||
|
28
lang/es.json
28
lang/es.json
@ -354,8 +354,6 @@
|
||||
"action.brush_tool.desc": "Herramienta para pintar en texturas bitmap en superficies o en el editor de UV",
|
||||
"action.vertex_snap_tool": "Imán para Vértices",
|
||||
"action.vertex_snap_tool.desc": "Mover un cubo a otro cubo al conectar 2 vértices.",
|
||||
"action.display_mode_tool": "Visualización",
|
||||
"action.display_mode_tool.desc": "Cambiar cómo del modelo se verá cuando esté sujetado por jugadores",
|
||||
"action.swap_tools": "Cambiar Herramientas",
|
||||
"action.swap_tools.desc": "Cambiar entre la herramienta para mover y para reescalar",
|
||||
"action.project_window": "Proyecto...",
|
||||
@ -650,8 +648,6 @@
|
||||
"dialog.update.update": "Actualizar",
|
||||
"action.brush_mode.brush": "Pincel",
|
||||
"action.brush_mode.noise": "Ruido",
|
||||
"action.brush_mode.eraser": "Goma",
|
||||
"action.brush_mode.fill": "Rellenar",
|
||||
"action.vertex_snap_mode.move": "Mover",
|
||||
"action.vertex_snap_mode.scale": "Reescalar",
|
||||
"action.open_model_folder": "Abrir la Carpeta del Modelo",
|
||||
@ -732,8 +728,6 @@
|
||||
"category.uv": "UV",
|
||||
"status_bar.saved": "El modelo está guardado",
|
||||
"status_bar.unsaved": "Hay cambios sin guardar",
|
||||
"action.animation_mode_tool": "Animación",
|
||||
"action.animation_mode_tool.desc": "Define animaciones personalizadas para este modelo",
|
||||
"action.move_up": "Mover Hacia Arriba",
|
||||
"action.move_up.desc": "Mueve los cubos seleccionados hacia arriba relativo al ángulo actual de la cámara",
|
||||
"action.move_down": "Mover Hacia Abajo",
|
||||
@ -810,6 +804,24 @@
|
||||
"dialog.toolbar_edit.hidden": "Oculto",
|
||||
"action.export_class_entity": "Exportar Entidad de Java",
|
||||
"action.export_class_entity.desc": "Exporta el modelo de entidad como una clase de Java",
|
||||
"settings.seethrough_outline": "X-Ray Outlines",
|
||||
"settings.seethrough_outline.desc": "Show outlines through objects"
|
||||
"settings.seethrough_outline": "Bordes Rayos-X",
|
||||
"settings.seethrough_outline.desc": "Mostrar los bordes a través de los objetos",
|
||||
"mode.edit": "Editar",
|
||||
"mode.paint": "Pintar",
|
||||
"mode.display": "Mostrar",
|
||||
"mode.animate": "Animar",
|
||||
"status_bar.recording_gif": "Grabando GIF",
|
||||
"status_bar.processing_gif": "Procesando GIF",
|
||||
"settings.backup_retain": "Mantenimiento de Backups",
|
||||
"settings.backup_retain.desc": "Ajustar cuanto tiempo Blockbench mantiene backups viejos en días",
|
||||
"action.rotate_tool": "Rotar",
|
||||
"action.rotate_tool.desc": "Herramienta para seleccionar y rotar elementos",
|
||||
"action.fill_tool": "Cubo de Pintura",
|
||||
"action.fill_tool.desc": "Herramienta para rellenar caras enteras con un color",
|
||||
"action.eraser": "Borrador",
|
||||
"action.eraser.desc": "Herramienta para reemplazar colores en una textura por transparencia",
|
||||
"action.color_picker": "Seleccionador de Color",
|
||||
"action.color_picker.desc": "Herramienta para seleccionar el color de píxeles en tu textura",
|
||||
"action.open_backup_folder": "Abrir Carpeta de Backups",
|
||||
"action.open_backup_folder.desc": "Abre la carpeta de backups de Blockbench"
|
||||
}
|
26
lang/fr.json
26
lang/fr.json
@ -354,8 +354,6 @@
|
||||
"action.brush_tool.desc": "Outil pour peindre sur des textures bitmap, des surfaces ou l'éditeur UV.",
|
||||
"action.vertex_snap_tool": "Vertex Snap",
|
||||
"action.vertex_snap_tool.desc": "Déplacez un cube vers un autre en connectant les deux sommets.",
|
||||
"action.display_mode_tool": "Affichage",
|
||||
"action.display_mode_tool.desc": "Changer l'apparence du modèle lorsqu'il est tenu par un joueur",
|
||||
"action.swap_tools": "Outils d'échange",
|
||||
"action.swap_tools.desc": "Basculer entre le déplacement et l'outil de redimensionnement",
|
||||
"action.project_window": "Projet...",
|
||||
@ -650,8 +648,6 @@
|
||||
"dialog.update.update": "Mettre à jour",
|
||||
"action.brush_mode.brush": "Brosse",
|
||||
"action.brush_mode.noise": "Bruit",
|
||||
"action.brush_mode.eraser": "Gomme",
|
||||
"action.brush_mode.fill": "Remplir",
|
||||
"action.vertex_snap_mode.move": "Déplacer",
|
||||
"action.vertex_snap_mode.scale": "Échelle",
|
||||
"action.open_model_folder": "Ouvrir le dossier de modèle",
|
||||
@ -732,8 +728,6 @@
|
||||
"category.uv": "UV",
|
||||
"status_bar.saved": "Le modèle est enregistré",
|
||||
"status_bar.unsaved": "Il y a des modifications non enregistrées",
|
||||
"action.animation_mode_tool": "Animation",
|
||||
"action.animation_mode_tool.desc": "Définir des animations personnalisées pour le modèle",
|
||||
"action.move_up": "Déplacer vers le haut",
|
||||
"action.move_up.desc": "Déplacer les cubes sélectionnés vers le haut par rapport à l'angle de caméra actuel",
|
||||
"action.move_down": "Déplacer vers le bas",
|
||||
@ -811,5 +805,23 @@
|
||||
"action.export_class_entity": "Export Java Entity",
|
||||
"action.export_class_entity.desc": "Export the entity model as a Java class",
|
||||
"settings.seethrough_outline": "X-Ray Outlines",
|
||||
"settings.seethrough_outline.desc": "Show outlines through objects"
|
||||
"settings.seethrough_outline.desc": "Show outlines through objects",
|
||||
"mode.edit": "Edit",
|
||||
"mode.paint": "Paint",
|
||||
"mode.display": "Display",
|
||||
"mode.animate": "Animate",
|
||||
"status_bar.recording_gif": "Recording GIF",
|
||||
"status_bar.processing_gif": "Processing GIF",
|
||||
"settings.backup_retain": "Backup Retain Duration",
|
||||
"settings.backup_retain.desc": "Set how long Blockbench retains old backups in days",
|
||||
"action.rotate_tool": "Rotate",
|
||||
"action.rotate_tool.desc": "Tool to select and rotate elements",
|
||||
"action.fill_tool": "Paint Bucket",
|
||||
"action.fill_tool.desc": "Paint bucket to fill entire faces with one color",
|
||||
"action.eraser": "Eraser",
|
||||
"action.eraser.desc": "Eraser tool to replace colors on a texture with transparency",
|
||||
"action.color_picker": "Color Picker",
|
||||
"action.color_picker.desc": "Tool to pick the color of pixels on your texture",
|
||||
"action.open_backup_folder": "Open Backup Folder",
|
||||
"action.open_backup_folder.desc": "Opens the Blockbench backup folder"
|
||||
}
|
30
lang/ja.json
30
lang/ja.json
@ -354,8 +354,6 @@
|
||||
"action.brush_tool.desc": "テクスチャまたはUVエディタにペイントする",
|
||||
"action.vertex_snap_tool": "頂点スナップ",
|
||||
"action.vertex_snap_tool.desc": "2つのブロックの頂点を接続する",
|
||||
"action.display_mode_tool": "表示",
|
||||
"action.display_mode_tool.desc": "プレイヤーが持ってるときのモデルの変更",
|
||||
"action.swap_tools": "スワップツール",
|
||||
"action.swap_tools.desc": "移動ツールとサイズ変更ツールを切り替える",
|
||||
"action.project_window": "プロジェクト…",
|
||||
@ -650,8 +648,6 @@
|
||||
"dialog.update.update": "更新する",
|
||||
"action.brush_mode.brush": "ブラシ",
|
||||
"action.brush_mode.noise": "ノイズ",
|
||||
"action.brush_mode.eraser": "消しゴム",
|
||||
"action.brush_mode.fill": "塗りつぶす",
|
||||
"action.vertex_snap_mode.move": "移動",
|
||||
"action.vertex_snap_mode.scale": "サイズ",
|
||||
"action.open_model_folder": "モデルフォルダを開く",
|
||||
@ -732,8 +728,6 @@
|
||||
"category.uv": "UV",
|
||||
"status_bar.saved": "モデルが保存されています",
|
||||
"status_bar.unsaved": "変更が保存されていません",
|
||||
"action.animation_mode_tool": "アニメーション",
|
||||
"action.animation_mode_tool.desc": "モデルのカスタムアニメーション",
|
||||
"action.move_up": "上に移動",
|
||||
"action.move_up.desc": "選択したキューブを上に移動する",
|
||||
"action.move_down": "下に移動",
|
||||
@ -794,7 +788,7 @@
|
||||
"action.camera_reset.desc": "現在のプレビューをデフォルトのカメラアングルにリセットする",
|
||||
"panel.variable_placeholders": "可変プレースホルダ",
|
||||
"panel.variable_placeholders.info": "プレビューする変数を 名前 = 値で表示する",
|
||||
"status_bar.vertex_distance": "キョリ:%0",
|
||||
"status_bar.vertex_distance": "間隔:%0",
|
||||
"dialog.create_gif.title": "レコードGIF",
|
||||
"dialog.create_gif.length": "長さ(秒)",
|
||||
"dialog.create_gif.fps": "FPS",
|
||||
@ -810,6 +804,24 @@
|
||||
"dialog.toolbar_edit.hidden": "隠す",
|
||||
"action.export_class_entity": "Java Entityをエクスポート",
|
||||
"action.export_class_entity.desc": "エンティティモデルをjava としてエクスポートする",
|
||||
"settings.seethrough_outline": "X-Ray Outlines",
|
||||
"settings.seethrough_outline.desc": "Show outlines through objects"
|
||||
"settings.seethrough_outline": "X-Rey アウトライン",
|
||||
"settings.seethrough_outline.desc": "オブジェクトを通してアウトラインを表示する",
|
||||
"mode.edit": "Edit",
|
||||
"mode.paint": "Paint",
|
||||
"mode.display": "Display",
|
||||
"mode.animate": "Animate",
|
||||
"status_bar.recording_gif": "Recording GIF",
|
||||
"status_bar.processing_gif": "Processing GIF",
|
||||
"settings.backup_retain": "Backup Retain Duration",
|
||||
"settings.backup_retain.desc": "Set how long Blockbench retains old backups in days",
|
||||
"action.rotate_tool": "Rotate",
|
||||
"action.rotate_tool.desc": "Tool to select and rotate elements",
|
||||
"action.fill_tool": "Paint Bucket",
|
||||
"action.fill_tool.desc": "Paint bucket to fill entire faces with one color",
|
||||
"action.eraser": "Eraser",
|
||||
"action.eraser.desc": "Eraser tool to replace colors on a texture with transparency",
|
||||
"action.color_picker": "Color Picker",
|
||||
"action.color_picker.desc": "Tool to pick the color of pixels on your texture",
|
||||
"action.open_backup_folder": "Open Backup Folder",
|
||||
"action.open_backup_folder.desc": "Opens the Blockbench backup folder"
|
||||
}
|
30
lang/nl.json
30
lang/nl.json
@ -354,8 +354,6 @@
|
||||
"action.brush_tool.desc": "Gereedschap om te tekenen op bitmap texturen op oppervlakken of in de UV editor.",
|
||||
"action.vertex_snap_tool": "Hoeken Snap",
|
||||
"action.vertex_snap_tool.desc": "Beweeg een kubus naar een ander kubus door twee hoeken te verbinden",
|
||||
"action.display_mode_tool": "Uitzicht",
|
||||
"action.display_mode_tool.desc": "Verander hoe het model eruit zal zien wanneer het door spelers wordt vastgehouden",
|
||||
"action.swap_tools": "Verwissel Gereedschap",
|
||||
"action.swap_tools.desc": "Verwissel verplaats en vergroot gereedschap",
|
||||
"action.project_window": "Project...",
|
||||
@ -650,8 +648,6 @@
|
||||
"dialog.update.update": "Update",
|
||||
"action.brush_mode.brush": "Penseel",
|
||||
"action.brush_mode.noise": "Lawaai ",
|
||||
"action.brush_mode.eraser": "Gum",
|
||||
"action.brush_mode.fill": "Vul",
|
||||
"action.vertex_snap_mode.move": "Beweeg",
|
||||
"action.vertex_snap_mode.scale": "Schaal",
|
||||
"action.open_model_folder": "Open Model Map",
|
||||
@ -732,12 +728,10 @@
|
||||
"category.uv": "UV",
|
||||
"status_bar.saved": "Model is opgeslagen",
|
||||
"status_bar.unsaved": "Er zijn onopgeslagen veranderingen",
|
||||
"action.animation_mode_tool": "Animatie",
|
||||
"action.animation_mode_tool.desc": "Defineer custom animaties voor het model",
|
||||
"action.move_up": "Beweeg omhoog",
|
||||
"action.move_up.desc": "Move the selected cubes up relative to the current camera angle",
|
||||
"action.move_up.desc": "Beweeg de geselecteerde kubussen omhoog in opzicht van de huidige camerahoek",
|
||||
"action.move_down": "Beweeg naar beneden",
|
||||
"action.move_down.desc": "Move the selected cubes down relative to the current camera angle",
|
||||
"action.move_down.desc": "Beweeg de geselecteerde kubussen naar beneden ten opzichte van de huidige camerahoek",
|
||||
"action.move_left": "Beweeg Naar Links",
|
||||
"action.move_left.desc": "Move the selected cubes left relative to the current camera angle",
|
||||
"action.move_right": "Beweeg Naar Rechts",
|
||||
@ -811,5 +805,23 @@
|
||||
"action.export_class_entity": "Export Java Entity",
|
||||
"action.export_class_entity.desc": "Export the entity model as a Java class",
|
||||
"settings.seethrough_outline": "X-Ray Outlines",
|
||||
"settings.seethrough_outline.desc": "Show outlines through objects"
|
||||
"settings.seethrough_outline.desc": "Show outlines through objects",
|
||||
"mode.edit": "Edit",
|
||||
"mode.paint": "Paint",
|
||||
"mode.display": "Display",
|
||||
"mode.animate": "Animate",
|
||||
"status_bar.recording_gif": "Recording GIF",
|
||||
"status_bar.processing_gif": "Processing GIF",
|
||||
"settings.backup_retain": "Backup Retain Duration",
|
||||
"settings.backup_retain.desc": "Set how long Blockbench retains old backups in days",
|
||||
"action.rotate_tool": "Rotate",
|
||||
"action.rotate_tool.desc": "Tool to select and rotate elements",
|
||||
"action.fill_tool": "Paint Bucket",
|
||||
"action.fill_tool.desc": "Paint bucket to fill entire faces with one color",
|
||||
"action.eraser": "Eraser",
|
||||
"action.eraser.desc": "Eraser tool to replace colors on a texture with transparency",
|
||||
"action.color_picker": "Color Picker",
|
||||
"action.color_picker.desc": "Tool to pick the color of pixels on your texture",
|
||||
"action.open_backup_folder": "Open Backup Folder",
|
||||
"action.open_backup_folder.desc": "Opens the Blockbench backup folder"
|
||||
}
|
26
lang/pl.json
26
lang/pl.json
@ -354,8 +354,6 @@
|
||||
"action.brush_tool.desc": "Narzędzie do malowania na teksturach bitmapowych na powierzniach lub w edytorze UV.",
|
||||
"action.vertex_snap_tool": "Przyciąganie wierzchołków",
|
||||
"action.vertex_snap_tool.desc": "Przesuń jedną kostkę do innej przez połączenie dwóch wierzchołków.",
|
||||
"action.display_mode_tool": "Wyświetlanie",
|
||||
"action.display_mode_tool.desc": "Zmień wygląd modelu, kiedy trzyma go gracz",
|
||||
"action.swap_tools": "Przełącz narzędzia",
|
||||
"action.swap_tools.desc": "Przełącz się pomiędzy narzędziem przesuwania i zmiany rozmiaru",
|
||||
"action.project_window": "Projekt...",
|
||||
@ -650,8 +648,6 @@
|
||||
"dialog.update.update": "Aktualizacja",
|
||||
"action.brush_mode.brush": "Szczotka",
|
||||
"action.brush_mode.noise": "Mieszanie",
|
||||
"action.brush_mode.eraser": "Gumka",
|
||||
"action.brush_mode.fill": "Wypełnij",
|
||||
"action.vertex_snap_mode.move": "Przesuń",
|
||||
"action.vertex_snap_mode.scale": "Skaluj",
|
||||
"action.open_model_folder": "Otwórz folder modelu",
|
||||
@ -732,8 +728,6 @@
|
||||
"category.uv": "UV",
|
||||
"status_bar.saved": "Model jest zapisany",
|
||||
"status_bar.unsaved": "Istnieją niezapisane zmiany",
|
||||
"action.animation_mode_tool": "Animacja",
|
||||
"action.animation_mode_tool.desc": "Zdefiniuj własne animacje dla modelu",
|
||||
"action.move_up": "Przesuń w górę",
|
||||
"action.move_up.desc": "Przesuń zaznaczone kostki w górę, względem aktualnego kąta kamery",
|
||||
"action.move_down": "Przesuń w dół",
|
||||
@ -811,5 +805,23 @@
|
||||
"action.export_class_entity": "Export Java Entity",
|
||||
"action.export_class_entity.desc": "Export the entity model as a Java class",
|
||||
"settings.seethrough_outline": "X-Ray Outlines",
|
||||
"settings.seethrough_outline.desc": "Show outlines through objects"
|
||||
"settings.seethrough_outline.desc": "Show outlines through objects",
|
||||
"mode.edit": "Edit",
|
||||
"mode.paint": "Paint",
|
||||
"mode.display": "Display",
|
||||
"mode.animate": "Animate",
|
||||
"status_bar.recording_gif": "Recording GIF",
|
||||
"status_bar.processing_gif": "Processing GIF",
|
||||
"settings.backup_retain": "Backup Retain Duration",
|
||||
"settings.backup_retain.desc": "Set how long Blockbench retains old backups in days",
|
||||
"action.rotate_tool": "Rotate",
|
||||
"action.rotate_tool.desc": "Tool to select and rotate elements",
|
||||
"action.fill_tool": "Paint Bucket",
|
||||
"action.fill_tool.desc": "Paint bucket to fill entire faces with one color",
|
||||
"action.eraser": "Eraser",
|
||||
"action.eraser.desc": "Eraser tool to replace colors on a texture with transparency",
|
||||
"action.color_picker": "Color Picker",
|
||||
"action.color_picker.desc": "Tool to pick the color of pixels on your texture",
|
||||
"action.open_backup_folder": "Open Backup Folder",
|
||||
"action.open_backup_folder.desc": "Opens the Blockbench backup folder"
|
||||
}
|
28
lang/ru.json
28
lang/ru.json
@ -354,8 +354,6 @@
|
||||
"action.brush_tool.desc": "Инструмент для рисования на текстурах, на гранях кубов или в редакторе UV",
|
||||
"action.vertex_snap_tool": "Вершинная привязка",
|
||||
"action.vertex_snap_tool.desc": "Перемещение одного куба к другому, соединяя две их вершины",
|
||||
"action.display_mode_tool": "Отображение",
|
||||
"action.display_mode_tool.desc": "Изменение вида модели в руках игроков",
|
||||
"action.swap_tools": "Смена инструмента",
|
||||
"action.swap_tools.desc": "Переключение между инструментом перемещения и изменения размера",
|
||||
"action.project_window": "Проект...",
|
||||
@ -650,8 +648,6 @@
|
||||
"dialog.update.update": "Обновление",
|
||||
"action.brush_mode.brush": "Кисть",
|
||||
"action.brush_mode.noise": "Шум",
|
||||
"action.brush_mode.eraser": "Ластик",
|
||||
"action.brush_mode.fill": "Заливка",
|
||||
"action.vertex_snap_mode.move": "Перемещение",
|
||||
"action.vertex_snap_mode.scale": "Масштабирование",
|
||||
"action.open_model_folder": "Открыть расположение модели",
|
||||
@ -732,8 +728,6 @@
|
||||
"category.uv": "UV",
|
||||
"status_bar.saved": "Модель сохранена",
|
||||
"status_bar.unsaved": "Есть несохранённые изменения",
|
||||
"action.animation_mode_tool": "Анимация",
|
||||
"action.animation_mode_tool.desc": "Определить пользовательские анимации для модели",
|
||||
"action.move_up": "Двигать вверх",
|
||||
"action.move_up.desc": "Двигать выбранные кубы вверх относительно камеры",
|
||||
"action.move_down": "Двигать вниз",
|
||||
@ -810,6 +804,24 @@
|
||||
"dialog.toolbar_edit.hidden": "Спрятано",
|
||||
"action.export_class_entity": "Экспортировать сущность Java",
|
||||
"action.export_class_entity.desc": "Экспортировать модель сущности как класс Java",
|
||||
"settings.seethrough_outline": "X-Ray Outlines",
|
||||
"settings.seethrough_outline.desc": "Show outlines through objects"
|
||||
"settings.seethrough_outline": "Рентгенные контуры",
|
||||
"settings.seethrough_outline.desc": "Показывать контуры через объекты",
|
||||
"mode.edit": "Изменить",
|
||||
"mode.paint": "Красить",
|
||||
"mode.display": "Предпросмотр",
|
||||
"mode.animate": "Анимировать",
|
||||
"status_bar.recording_gif": "Recording GIF",
|
||||
"status_bar.processing_gif": "Processing GIF",
|
||||
"settings.backup_retain": "Продолжительность хранения автосохранений",
|
||||
"settings.backup_retain.desc": "Set how long Blockbench retains old backups in days",
|
||||
"action.rotate_tool": "Вращать",
|
||||
"action.rotate_tool.desc": "Tool to select and rotate elements",
|
||||
"action.fill_tool": "Paint Bucket",
|
||||
"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.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"
|
||||
}
|
26
lang/sv.json
26
lang/sv.json
@ -354,8 +354,6 @@
|
||||
"action.brush_tool.desc": "Verktyg att måla på bitmaptexturer på ytor eller UV-redigeraren.",
|
||||
"action.vertex_snap_tool": "Vortex Snap",
|
||||
"action.vertex_snap_tool.desc": "Flytta en kub till en annan kub genom att koppla samman två hörn.",
|
||||
"action.display_mode_tool": "Visa",
|
||||
"action.display_mode_tool.desc": "Ändra hur modellen ser ut när den hålls utav spelare",
|
||||
"action.swap_tools": "Byt verktyg",
|
||||
"action.swap_tools.desc": "Växla mellan flytt och storleks verktygen",
|
||||
"action.project_window": "Projekt...",
|
||||
@ -650,8 +648,6 @@
|
||||
"dialog.update.update": "Uppdatera",
|
||||
"action.brush_mode.brush": "Pensel",
|
||||
"action.brush_mode.noise": "Brus",
|
||||
"action.brush_mode.eraser": "Suddgummi",
|
||||
"action.brush_mode.fill": "Fyll",
|
||||
"action.vertex_snap_mode.move": "Flytta",
|
||||
"action.vertex_snap_mode.scale": "Skala",
|
||||
"action.open_model_folder": "Öppna modellmapp",
|
||||
@ -732,8 +728,6 @@
|
||||
"category.uv": "UV",
|
||||
"status_bar.saved": "Modellen är sparad",
|
||||
"status_bar.unsaved": "Det finns osparade ändringar",
|
||||
"action.animation_mode_tool": "Animation",
|
||||
"action.animation_mode_tool.desc": "Definiera anpassade animationer för modellen",
|
||||
"action.move_up": "Flytta upp",
|
||||
"action.move_up.desc": "Flytta de valda kuberna upp relativt till den nuvarande kameravinkeln",
|
||||
"action.move_down": "Flytta ner",
|
||||
@ -811,5 +805,23 @@
|
||||
"action.export_class_entity": "Export Java Entity",
|
||||
"action.export_class_entity.desc": "Export the entity model as a Java class",
|
||||
"settings.seethrough_outline": "X-Ray Outlines",
|
||||
"settings.seethrough_outline.desc": "Show outlines through objects"
|
||||
"settings.seethrough_outline.desc": "Show outlines through objects",
|
||||
"mode.edit": "Edit",
|
||||
"mode.paint": "Paint",
|
||||
"mode.display": "Display",
|
||||
"mode.animate": "Animate",
|
||||
"status_bar.recording_gif": "Recording GIF",
|
||||
"status_bar.processing_gif": "Processing GIF",
|
||||
"settings.backup_retain": "Backup Retain Duration",
|
||||
"settings.backup_retain.desc": "Set how long Blockbench retains old backups in days",
|
||||
"action.rotate_tool": "Rotate",
|
||||
"action.rotate_tool.desc": "Tool to select and rotate elements",
|
||||
"action.fill_tool": "Paint Bucket",
|
||||
"action.fill_tool.desc": "Paint bucket to fill entire faces with one color",
|
||||
"action.eraser": "Eraser",
|
||||
"action.eraser.desc": "Eraser tool to replace colors on a texture with transparency",
|
||||
"action.color_picker": "Color Picker",
|
||||
"action.color_picker.desc": "Tool to pick the color of pixels on your texture",
|
||||
"action.open_backup_folder": "Open Backup Folder",
|
||||
"action.open_backup_folder.desc": "Opens the Blockbench backup folder"
|
||||
}
|
30
lang/zh.json
30
lang/zh.json
@ -348,14 +348,12 @@
|
||||
"action.vertex_snap_mode.desc": "选择“顶点捕捉”将元素移动到所选位置或调整其大小",
|
||||
"action.move_tool": "移动",
|
||||
"action.move_tool.desc": "选择和移动元素的工具",
|
||||
"action.resize_tool": "调整",
|
||||
"action.resize_tool": "尺寸",
|
||||
"action.resize_tool.desc": "选择和调整元素大小的工具",
|
||||
"action.brush_tool": "笔刷",
|
||||
"action.brush_tool.desc": "在模型表面或UV编辑器中绘制贴图的工具",
|
||||
"action.vertex_snap_tool": "顶点捕捉",
|
||||
"action.vertex_snap_tool.desc": "通过连接两个顶点将一个立方体移动到另一个立方体",
|
||||
"action.display_mode_tool": "显示",
|
||||
"action.display_mode_tool.desc": "对玩家手持物品时的模型位置调整",
|
||||
"action.swap_tools": "交换工具",
|
||||
"action.swap_tools.desc": "在移动和调整工具之间交换",
|
||||
"action.project_window": "项目...",
|
||||
@ -516,7 +514,7 @@
|
||||
"action.reload.desc": "重载 Blockbench,这将删除所有未保存的进度",
|
||||
"menu.file": "文件",
|
||||
"menu.edit": "编辑",
|
||||
"menu.transform": "调整",
|
||||
"menu.transform": "尺寸",
|
||||
"menu.filter": "插件目录",
|
||||
"menu.display": "物品显示",
|
||||
"menu.view": "视图",
|
||||
@ -650,8 +648,6 @@
|
||||
"dialog.update.update": "更新",
|
||||
"action.brush_mode.brush": "笔刷",
|
||||
"action.brush_mode.noise": "像素点",
|
||||
"action.brush_mode.eraser": "橡皮擦",
|
||||
"action.brush_mode.fill": "油漆桶",
|
||||
"action.vertex_snap_mode.move": "移动",
|
||||
"action.vertex_snap_mode.scale": "规模",
|
||||
"action.open_model_folder": "打开模型文件夹",
|
||||
@ -732,8 +728,6 @@
|
||||
"category.uv": "UV",
|
||||
"status_bar.saved": "模型已保存",
|
||||
"status_bar.unsaved": "有未保存的更改",
|
||||
"action.animation_mode_tool": "动画",
|
||||
"action.animation_mode_tool.desc": "为模型定义自定义动画",
|
||||
"action.move_up": "上移",
|
||||
"action.move_up.desc": "相对于当前摄像机角度向上移动选定的立方体",
|
||||
"action.move_down": "下移",
|
||||
@ -811,5 +805,23 @@
|
||||
"action.export_class_entity": "导出java实体(?",
|
||||
"action.export_class_entity.desc": "作为java class导出模型",
|
||||
"settings.seethrough_outline": "X-Ray Outlines",
|
||||
"settings.seethrough_outline.desc": "Show outlines through objects"
|
||||
"settings.seethrough_outline.desc": "Show outlines through objects",
|
||||
"mode.edit": "Edit",
|
||||
"mode.paint": "Paint",
|
||||
"mode.display": "Display",
|
||||
"mode.animate": "Animate",
|
||||
"status_bar.recording_gif": "Recording GIF",
|
||||
"status_bar.processing_gif": "Processing GIF",
|
||||
"settings.backup_retain": "Backup Retain Duration",
|
||||
"settings.backup_retain.desc": "Set how long Blockbench retains old backups in days",
|
||||
"action.rotate_tool": "Rotate",
|
||||
"action.rotate_tool.desc": "Tool to select and rotate elements",
|
||||
"action.fill_tool": "Paint Bucket",
|
||||
"action.fill_tool.desc": "Paint bucket to fill entire faces with one color",
|
||||
"action.eraser": "Eraser",
|
||||
"action.eraser.desc": "Eraser tool to replace colors on a texture with transparency",
|
||||
"action.color_picker": "Color Picker",
|
||||
"action.color_picker.desc": "Tool to pick the color of pixels on your texture",
|
||||
"action.open_backup_folder": "Open Backup Folder",
|
||||
"action.open_backup_folder.desc": "Opens the Blockbench backup folder"
|
||||
}
|
94045
lib/three.js
94045
lib/three.js
File diff suppressed because one or more lines are too long
66
lib/three_custom.js
Normal file
66
lib/three_custom.js
Normal file
@ -0,0 +1,66 @@
|
||||
THREE.BoxGeometry.prototype.from = function(arr) {
|
||||
/*
|
||||
vertices[0] //south east up
|
||||
vertices[1] //north east up
|
||||
vertices[2] //south east down
|
||||
vertices[3] //north east down
|
||||
vertices[4] //north west up
|
||||
vertices[5] //south west up
|
||||
vertices[6] //north west down
|
||||
vertices[7] //south west down
|
||||
*/
|
||||
//X
|
||||
this.vertices[4].setX(arr[0])
|
||||
this.vertices[5].setX(arr[0])
|
||||
this.vertices[6].setX(arr[0])
|
||||
this.vertices[7].setX(arr[0])
|
||||
//Y
|
||||
this.vertices[2].setY(arr[1])
|
||||
this.vertices[3].setY(arr[1])
|
||||
this.vertices[6].setY(arr[1])
|
||||
this.vertices[7].setY(arr[1])
|
||||
//Z
|
||||
this.vertices[1].setZ(arr[2])
|
||||
this.vertices[3].setZ(arr[2])
|
||||
this.vertices[4].setZ(arr[2])
|
||||
this.vertices[6].setZ(arr[2])
|
||||
|
||||
this.verticesNeedUpdate = true
|
||||
}
|
||||
THREE.BoxGeometry.prototype.to = function(arr) {
|
||||
//X
|
||||
this.vertices[0].setX(arr[0])
|
||||
this.vertices[1].setX(arr[0])
|
||||
this.vertices[2].setX(arr[0])
|
||||
this.vertices[3].setX(arr[0])
|
||||
//Y
|
||||
this.vertices[0].setY(arr[1])
|
||||
this.vertices[1].setY(arr[1])
|
||||
this.vertices[4].setY(arr[1])
|
||||
this.vertices[5].setY(arr[1])
|
||||
//Z
|
||||
this.vertices[0].setZ(arr[2])
|
||||
this.vertices[2].setZ(arr[2])
|
||||
this.vertices[5].setZ(arr[2])
|
||||
this.vertices[7].setZ(arr[2])
|
||||
|
||||
this.verticesNeedUpdate = true
|
||||
}
|
||||
Object.assign( THREE.Euler.prototype, {
|
||||
setFromDegreeArray: function ( arr, invert ) {
|
||||
|
||||
this._x = Math.degToRad(arr[0]) * (invert ? -1 : 1);
|
||||
this._y = Math.degToRad(arr[1]) * (invert ? -1 : 1);
|
||||
this._z = Math.degToRad(arr[2]) * (invert ? -1 : 1);
|
||||
|
||||
this.onChangeCallback();
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
})
|
||||
//22138 Init Log
|
||||
//17264 ProgramLog message
|
||||
//22319 WebGL Error
|
||||
//AxesHelper
|
||||
//44584 Grid Color { color: color1 }
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "Blockbench",
|
||||
"description": "Minecraft Block Model Editor",
|
||||
"version": "2.2.2",
|
||||
"version": "2.3.0",
|
||||
"license": "MIT",
|
||||
"author": {
|
||||
"name": "JannisX11",
|
||||
|
Loading…
x
Reference in New Issue
Block a user