mirror of
https://github.com/JannisX11/blockbench.git
synced 2025-03-19 17:01:55 +08:00
v2.4.0
This commit is contained in:
parent
cb1f09919b
commit
293238948a
@ -72,6 +72,7 @@
|
||||
text-transform: none;
|
||||
line-height: 1;
|
||||
font-size: 1.4em;
|
||||
max-width: 24px;
|
||||
|
||||
Better Font Rendering ===========
|
||||
-webkit-font-smoothing: antialiased;
|
||||
@ -656,6 +657,9 @@
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
body.display_mode .single_canvas_wrapper {
|
||||
position: relative;
|
||||
}
|
||||
.quad_canvas_wrapper {
|
||||
height: 50%;
|
||||
width: 50%;
|
||||
@ -714,7 +718,6 @@
|
||||
.tool {
|
||||
height: 32px;
|
||||
width: 40px;
|
||||
padding-top: 4px;
|
||||
margin-left: 1px;
|
||||
margin-right: 1px;
|
||||
background: transparent;
|
||||
@ -725,6 +728,10 @@
|
||||
float: left;
|
||||
color: var(--color-text);
|
||||
}
|
||||
.tool i {
|
||||
display: inline-block;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.tool.sel {
|
||||
border-bottom: 4px solid var(--color-accent);
|
||||
@ -790,7 +797,7 @@
|
||||
padding-right: 5px;
|
||||
padding-top: 2px;
|
||||
color: var(--color-text_acc);
|
||||
margin-top: -3px;
|
||||
margin-top: 32px;
|
||||
display: none;
|
||||
background: var(--color-bright_ui);
|
||||
white-space: nowrap;
|
||||
@ -871,10 +878,12 @@
|
||||
cursor: default;
|
||||
text-align: center;
|
||||
font-size: 0.9em;
|
||||
padding-top: 5px;
|
||||
float: left;
|
||||
overflow: hidden;
|
||||
}
|
||||
.panel#uv .tabs_small label {
|
||||
padding-top: 4px;
|
||||
}
|
||||
|
||||
.tabs_small {
|
||||
background-color: transparent;
|
||||
@ -1060,8 +1069,74 @@
|
||||
background-color: var(--color-text);
|
||||
}
|
||||
|
||||
/*Action Select*/
|
||||
#action_selector {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
left: 0;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
top: 200px;
|
||||
width: 360px;
|
||||
height: 42px;
|
||||
box-shadow: 0 0 5px black;
|
||||
}
|
||||
#action_selector > input {
|
||||
width: 100%;
|
||||
height: 42px;
|
||||
padding: 5px;
|
||||
padding-left: 12px;
|
||||
background-color: var(--color-ui);
|
||||
border: 1px solid var(--color-border);
|
||||
}
|
||||
#action_selector > i {
|
||||
position: absolute;
|
||||
right: 6px;
|
||||
top: 9px;
|
||||
}
|
||||
#action_selector > ul {
|
||||
background-color: var(--color-bright_ui);
|
||||
color: var(--color-text_acc);
|
||||
min-height: 20px;
|
||||
width: 300px;
|
||||
margin-left: 8px;
|
||||
box-shadow: 0 0 5px black;
|
||||
max-height: 400px;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
#action_selector > ul > li {
|
||||
padding: 4px;
|
||||
}
|
||||
#action_selector > ul > li.selected {
|
||||
background-color: var(--color-accent);
|
||||
}
|
||||
#action_selector > ul > li div.icon_wrapper {
|
||||
display: inline-block;
|
||||
height: 26px;
|
||||
vertical-align: text-top;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#bar_item_list {
|
||||
max-height: 400px;
|
||||
margin-bottom: 20px;
|
||||
overflow-y: scroll;
|
||||
min-height: 80px;
|
||||
border: 1px solid var(--color-border);
|
||||
border-right: none;
|
||||
}
|
||||
#bar_item_list li {
|
||||
padding: 4px;
|
||||
}
|
||||
#bar_item_list li:hover {
|
||||
color: var(--color-light);
|
||||
}
|
||||
|
||||
/*Textures*/
|
||||
.texture {
|
||||
height: 50px;
|
||||
@ -1583,7 +1658,7 @@
|
||||
color: var(--color-light);
|
||||
}
|
||||
|
||||
#keybindlist li div:first-child {
|
||||
#keybindlist li > div:first-child {
|
||||
background: transparent;
|
||||
width: calc(52% - 28px);
|
||||
text-align: right;
|
||||
@ -2051,7 +2126,7 @@
|
||||
font-size: 0.9em;
|
||||
padding: 3px;
|
||||
float: left;
|
||||
margin-top: 7px;
|
||||
margin-top: 6px;
|
||||
}
|
||||
#plugin_list li .title i.plugin_expand_icon {
|
||||
display: none;
|
||||
|
75
index.html
75
index.html
@ -19,7 +19,7 @@
|
||||
<script>
|
||||
if (typeof module === 'object') {window.module = module; module = undefined;}//jQuery Fix
|
||||
const isApp = typeof require !== 'undefined';
|
||||
const appVersion = '2.3.2';
|
||||
const appVersion = '2.4.0';
|
||||
</script>
|
||||
<script src="lib/vue.min.js"></script>
|
||||
<script src="lib/vue_sortable.js"></script>
|
||||
@ -38,10 +38,10 @@
|
||||
|
||||
<script src="js/language.js"></script>
|
||||
<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/keyboard.js"></script>
|
||||
<script src="js/settings.js"></script>
|
||||
<script src="js/undo.js"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
@ -107,8 +107,8 @@
|
||||
</div>
|
||||
</div>
|
||||
<ul class="list" id="plugin_list">
|
||||
<li v-for="plugin in installedPlugins" v-bind:plugin="plugin.id" v-bind:class="{testing: plugin.fromFile, expanded: plugin.expanded}">
|
||||
<div class="title" v-on:click="toggleInfo(plugin)">
|
||||
<li v-for="plugin in plugin_search" v-bind:plugin="plugin.id" v-bind:class="{testing: plugin.fromFile, expanded: plugin.expanded}">
|
||||
<div class="title" v-on:click="plugin.toggleInfo()">
|
||||
<i v-if="plugin.icon.substr(0,3) !== 'fa-' " class="material-icons plugin_icon">{{ plugin.icon }}</i>
|
||||
<i v-else class="fa fa_big plugin_icon" v-bind:class="plugin.icon"></i>
|
||||
|
||||
@ -116,9 +116,9 @@
|
||||
<i v-else class="material-icons plugin_expand_icon">expand_more</i>
|
||||
{{ plugin.title }}
|
||||
</div>
|
||||
<div class="button_bar" v-if="checkIfInstallable(plugin) === true">
|
||||
<button type="button" class="" v-on:click="uninstall(plugin)" v-if="plugin.installed"><i class="material-icons">delete</i><span class="tl">dialog.plugins.uninstall</span></button>
|
||||
<button type="button" class="" v-on:click="install(plugin)" v-else><i class="material-icons">add</i><span class="tl">dialog.plugins.install</span></button>
|
||||
<div class="button_bar" v-if="plugin.isInstallable()">
|
||||
<button type="button" class="" v-on:click="plugin.uninstall()" v-if="plugin.installed"><i class="material-icons">delete</i><span class="tl">dialog.plugins.uninstall</span></button>
|
||||
<button type="button" class="" v-on:click="plugin.download()" v-else><i class="material-icons">add</i><span class="tl">dialog.plugins.install</span></button>
|
||||
<button type="button" class="local_only" v-on:click="plugin.reload()" v-if="plugin.installed && plugin.fromFile && isApp"><i class="material-icons">refresh</i><span class="tl">dialog.plugins.reload</span></button>
|
||||
</div>
|
||||
<div class="button_bar tiny tl" v-else>{{ checkIfInstallable(plugin) }}</div>
|
||||
@ -126,14 +126,14 @@
|
||||
<div class="author">{{ tl('dialog.plugins.author', [plugin.author]) }}</div>
|
||||
<div class="description">{{ plugin.description }}</div>
|
||||
<div v-if="plugin.expanded" class="about" v-html="plugin.about"><button>a</button></div>
|
||||
<div v-if="plugin.expanded" class="tl" v-on:click="toggleInfo(plugin)" style="text-decoration: underline;">dialog.plugins.show_less</div>
|
||||
<div v-if="plugin.expanded" class="tl" v-on:click="plugin.toggleInfo()" style="text-decoration: underline;">dialog.plugins.show_less</div>
|
||||
</li>
|
||||
<div class="no_plugin_message tl" v-if="installedPlugins.length < 1 && showAll === false">dialog.plugins.none_installed</div>
|
||||
<div class="no_plugin_message tl" v-if="installedPlugins.length < 1 && showAll === true" id="plugin_available_empty">dialog.plugins.none_available</div>
|
||||
<div class="no_plugin_message tl" v-if="plugin_search.length < 1 && showAll === false">dialog.plugins.none_installed</div>
|
||||
<div class="no_plugin_message tl" v-if="plugin_search.length < 1 && showAll === true" id="plugin_available_empty">dialog.plugins.none_available</div>
|
||||
</ul>
|
||||
|
||||
<div class="dialog_bar">
|
||||
<button type="button" class="large cancel_btn confirm_btn uc_btn tl" onclick="saveInstalledPlugins()">dialog.close</button>
|
||||
<button type="button" class="large cancel_btn confirm_btn uc_btn tl" onclick="saveInstalledPlugins();hideDialog();">dialog.close</button>
|
||||
</div>
|
||||
<div id="dialog_close_button" onclick="$('.dialog#'+open_dialog).find('.cancel_btn:not([disabled])').click()"><i class="material-icons">clear</i></div>
|
||||
</div>
|
||||
@ -145,8 +145,8 @@
|
||||
<li v-for="item in currentBar" v-bind:title="item.name" :key="item.id||item">
|
||||
<div v-if="typeof item === 'string'" class="toolbar_separator"></div>
|
||||
<div v-else class="tool">
|
||||
<span class="icon_wrapper" v-bind:style="{opacity: BARS.condition(item.condition) ? 1 : 0.4}" v-html="Blockbench.getIconNode(item.icon, item.color).outerHTML"></span>
|
||||
<div class="tooltip">{{item.name + (BARS.condition(item.condition) ? '' : ' (' + tl('dialog.toolbar_edit.hidden') + ')' )}}</div>
|
||||
<span class="icon_wrapper" v-bind:style="{opacity: BARS.condition(item.condition) ? 1 : 0.4}" v-html="Blockbench.getIconNode(item.icon, item.color).outerHTML"></span>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
@ -167,7 +167,7 @@
|
||||
</ul>
|
||||
|
||||
<div class="dialog_bar">
|
||||
<button type="button" class="large cancel_btn confirm_btn uc_btn tl" onclick="saveInstalledPlugins()">dialog.close</button>
|
||||
<button type="button" class="large cancel_btn confirm_btn uc_btn tl" onclick="saveInstalledPlugins();hideDialog();">dialog.close</button>
|
||||
</div>
|
||||
<div id="dialog_close_button" onclick="$('.dialog#'+open_dialog).find('.cancel_btn:not([disabled])').click()"><i class="material-icons">clear</i></div>
|
||||
</div>
|
||||
@ -228,10 +228,10 @@
|
||||
<div id="texture_menu_thumbnail"></div>
|
||||
|
||||
<div class="bar">
|
||||
<div class="tool link_only" onclick="textures.selected.reopen()"><i class="material-icons">file_upload</i><div class="tooltip tl">menu.texture.change</div></div>
|
||||
<div class="tool link_only" onclick="textures.selected.refresh(true)"><i class="material-icons">refresh</i><div class="tooltip tl">menu.texture.refresh</div></div>
|
||||
<div class="tool link_only" onclick="textures.selected.openFolder()"><i class="material-icons">folder</i><div class="tooltip tl">menu.texture.folder</div></div>
|
||||
<div class="tool" onclick="textures.selected.remove()"><i class="material-icons">delete</i><div class="tooltip tl">menu.texture.delete</div></div>
|
||||
<div class="tool link_only" onclick="textures.selected.reopen()"><div class="tooltip tl">menu.texture.change</div><i class="material-icons">file_upload</i></div>
|
||||
<div class="tool link_only" onclick="textures.selected.refresh(true)"><div class="tooltip tl">menu.texture.refresh</div><i class="material-icons">refresh</i></div>
|
||||
<div class="tool link_only" onclick="textures.selected.openFolder()"><div class="tooltip tl">menu.texture.folder</div><i class="material-icons">folder</i></div>
|
||||
<div class="tool" onclick="textures.selected.remove()"><div class="tooltip tl">menu.texture.delete</div><i class="material-icons">delete</i></div>
|
||||
</div>
|
||||
|
||||
<p class="multiline_text" id="te_path">path</p>
|
||||
@ -291,6 +291,7 @@
|
||||
<div class="dialog_bar">
|
||||
<button type="button" onclick="scaleAll(true)" class="large confirm_btn tl">dialog.scale.confirm</button>
|
||||
<button type="button" class="large cancel_btn tl" onclick="cancelScaleAll()">dialog.cancel</button>
|
||||
<button type="button" class="large hidden tl" id="scale_overflow_btn" onclick="scaleAllSelectOverflow()">dialog.scale.select_overflow</button>
|
||||
</div>
|
||||
<div id="dialog_close_button" onclick="$('.dialog#'+open_dialog).find('.cancel_btn:not([disabled])').click()"><i class="material-icons">clear</i></div>
|
||||
</div>
|
||||
@ -474,12 +475,12 @@
|
||||
<div>{{action.name}}</div>
|
||||
<div class="keybindslot" v-on:click.stop="record(action)">{{ action.keybind ? action.keybind.label : '' }}</div>
|
||||
<div class="tool" v-on:click="reset(action)">
|
||||
<i class="material-icons">replay</i>
|
||||
<div class="tooltip tl">keybindings.reset</div>
|
||||
<i class="material-icons">replay</i>
|
||||
</div>
|
||||
<div class="tool" v-on:click="clear(action)">
|
||||
<i class="material-icons">clear</i>
|
||||
<div class="tooltip tl">keybindings.clear</div>
|
||||
<i class="material-icons">clear</i>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
@ -681,6 +682,17 @@
|
||||
|
||||
<div id="plugin_dialog_wrapper"></div>
|
||||
|
||||
<div id="action_selector" v-if="open">
|
||||
<input type="text" v-model="search_input">
|
||||
<i class="material-icons" id="action_search_bar_icon">search</i>
|
||||
<ul>
|
||||
<li v-for="(item, i) in actions" v-on:click="ActionControl.click(item, $event)" v-bind:class="{selected: i === index}" v-on:mouseenter="index = i">
|
||||
<div class="icon_wrapper normal" v-html="Blockbench.getIconNode(item.icon, item.color).outerHTML"></div>
|
||||
{{ item.name }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<header>
|
||||
<div id="title">
|
||||
<span>Blockbench</span>
|
||||
@ -727,26 +739,26 @@
|
||||
<p class="tl">display.slot</p>
|
||||
<div id="display_bar" class="bar tabs_small">
|
||||
<input class="hidden" type="radio" name="display" id="thirdperson_righthand" checked>
|
||||
<label class="tool" for="thirdperson_righthand" onclick="DisplayMode.loadThirdRight()"><i class="material-icons">accessibility</i><div class="tooltip tl">display.slot.third_right</div></label>
|
||||
<label class="tool" for="thirdperson_righthand" onclick="DisplayMode.loadThirdRight()"><div class="tooltip tl">display.slot.third_right</div><i class="material-icons">accessibility</i></label>
|
||||
<input class="hidden" type="radio" name="display" id="thirdperson_lefthand">
|
||||
<label class="tool" for="thirdperson_lefthand" onclick="DisplayMode.loadThirdLeft()"><i class="material-icons">accessibility</i><div class="tooltip tl">display.slot.third_left</div></label>
|
||||
<label class="tool" for="thirdperson_lefthand" onclick="DisplayMode.loadThirdLeft()"><div class="tooltip tl">display.slot.third_left</div><i class="material-icons">accessibility</i></label>
|
||||
|
||||
<input class="hidden" type="radio" name="display" id="firstperson_righthand">
|
||||
<label class="tool" for="firstperson_righthand" onclick="DisplayMode.loadFirstRight()"><i class="material-icons">person</i><div class="tooltip tl">display.slot.first_right</div></label>
|
||||
<label class="tool" for="firstperson_righthand" onclick="DisplayMode.loadFirstRight()"><div class="tooltip tl">display.slot.first_right</div><i class="material-icons">person</i></label>
|
||||
<input class="hidden" type="radio" name="display" id="firstperson_lefthand">
|
||||
<label class="tool" for="firstperson_lefthand" onclick="DisplayMode.loadFirstLeft()"><i class="material-icons">person</i><div class="tooltip tl">display.slot.first_left</div></label>
|
||||
<label class="tool" for="firstperson_lefthand" onclick="DisplayMode.loadFirstLeft()"><div class="tooltip tl">display.slot.first_left</div><i class="material-icons">person</i></label>
|
||||
|
||||
<input class="hidden" type="radio" name="display" id="head">
|
||||
<label class="tool" for="head" onclick="DisplayMode.loadHead()"><i class="material-icons">sentiment_satisfied</i><div class="tooltip tl">display.slot.head</div></label>
|
||||
<label class="tool" for="head" onclick="DisplayMode.loadHead()"><div class="tooltip tl">display.slot.head</div><i class="material-icons">sentiment_satisfied</i></label>
|
||||
|
||||
<input class="hidden" type="radio" name="display" id="ground">
|
||||
<label class="tool" for="ground" onclick="DisplayMode.loadGround()"><i class="icon-ground"></i><div class="tooltip tl">display.slot.ground</div></label>
|
||||
<label class="tool" for="ground" onclick="DisplayMode.loadGround()"><div class="tooltip tl">display.slot.ground</div><i class="icon-ground"></i></label>
|
||||
|
||||
<input class="hidden" type="radio" name="display" id="fixed">
|
||||
<label class="tool" for="fixed" onclick="DisplayMode.loadFixed()"><i class="material-icons">filter_frames</i><div class="tooltip tl">display.slot.frame</div></label>
|
||||
<label class="tool" for="fixed" onclick="DisplayMode.loadFixed()"><div class="tooltip tl">display.slot.frame</div><i class="material-icons">filter_frames</i></label>
|
||||
|
||||
<input class="hidden" type="radio" name="display" id="gui">
|
||||
<label class="tool" for="gui" onclick="DisplayMode.loadGUI()"><i class="material-icons">border_style</i><div class="tooltip tl">display.slot.gui</div></label>
|
||||
<label class="tool" for="gui" onclick="DisplayMode.loadGUI()"><div class="tooltip tl">display.slot.gui</div><i class="material-icons">border_style</i></label>
|
||||
</div>
|
||||
<p class="reference_model_bar tl">display.reference</p>
|
||||
<div id="display_ref_bar" class="bar tabs_small reference_model_bar">
|
||||
@ -773,7 +785,8 @@
|
||||
<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 class="tooltip tl">display.mirror</div>
|
||||
<i class="material-icons">{{ slot.mirror[axis] ? 'check_box' : 'check_box_outline_blank' }}</i>
|
||||
</div>
|
||||
<input type="range" class="tool disp_range scaleRange" v-model.number="slot.scale[axis]" v-bind:trigger_type="'scale.'+axis" v-bind:id="'scale_range_'+axis"
|
||||
v-bind:min="slot.scale[axis] > 1 ? -2 : 0"
|
||||
@ -831,7 +844,7 @@
|
||||
<li
|
||||
v-for="texture in textures"
|
||||
v-bind:class="{ selected: texture.selected, particle: texture.particle}"
|
||||
v-bind:texid="texture.id"
|
||||
v-bind:texid="texture.uuid"
|
||||
class="texture"
|
||||
v-on:click.stop="texture.select($event)"
|
||||
v-on:dblclick="texture.openMenu($event)"
|
||||
@ -909,7 +922,7 @@
|
||||
<div id="timeline_lines"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="status_bar">
|
||||
<div id="status_bar" @contextmenu="Interface.status_bar.menu.show(event);console.log(true);">
|
||||
<div id="status_saved">
|
||||
<i class="material-icons" v-if="Prop.project_saved" v-bind:title="tl('status_bar.saved')">check</i>
|
||||
<i class="material-icons" v-else v-bind:title="tl('status_bar.unsaved')">close</i>
|
||||
|
78
index.php
78
index.php
@ -19,7 +19,7 @@
|
||||
<script>
|
||||
if (typeof module === 'object') {window.module = module; module = undefined;}//jQuery Fix
|
||||
const isApp = typeof require !== 'undefined';
|
||||
const appVersion = '2.3.2';
|
||||
const appVersion = '2.4.0';
|
||||
</script>
|
||||
<script src="lib/vue.min.js"></script>
|
||||
<script src="lib/vue_sortable.js"></script>
|
||||
@ -38,10 +38,10 @@
|
||||
|
||||
<script src="js/language.js"></script>
|
||||
<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/keyboard.js"></script>
|
||||
<script src="js/settings.js"></script>
|
||||
<script src="js/undo.js"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
@ -66,7 +66,7 @@
|
||||
<script src="js/molang.js"></script>
|
||||
<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><?php
|
||||
if ( $_SERVER['REQUEST_METHOD'] == 'POST' ) {
|
||||
$model = $_POST['model'];
|
||||
@ -85,6 +85,7 @@
|
||||
?></div>
|
||||
<div style="display: none;"></div>
|
||||
|
||||
|
||||
<div id="blackout" onclick="$('.dialog#'+open_dialog).find('.cancel_btn:not([disabled])').click()"></div>
|
||||
|
||||
<div class="dialog draggable" id="welcome_screen">
|
||||
@ -122,8 +123,8 @@
|
||||
</div>
|
||||
</div>
|
||||
<ul class="list" id="plugin_list">
|
||||
<li v-for="plugin in installedPlugins" v-bind:plugin="plugin.id" v-bind:class="{testing: plugin.fromFile, expanded: plugin.expanded}">
|
||||
<div class="title" v-on:click="toggleInfo(plugin)">
|
||||
<li v-for="plugin in plugin_search" v-bind:plugin="plugin.id" v-bind:class="{testing: plugin.fromFile, expanded: plugin.expanded}">
|
||||
<div class="title" v-on:click="plugin.toggleInfo()">
|
||||
<i v-if="plugin.icon.substr(0,3) !== 'fa-' " class="material-icons plugin_icon">{{ plugin.icon }}</i>
|
||||
<i v-else class="fa fa_big plugin_icon" v-bind:class="plugin.icon"></i>
|
||||
|
||||
@ -131,9 +132,9 @@
|
||||
<i v-else class="material-icons plugin_expand_icon">expand_more</i>
|
||||
{{ plugin.title }}
|
||||
</div>
|
||||
<div class="button_bar" v-if="checkIfInstallable(plugin) === true">
|
||||
<button type="button" class="" v-on:click="uninstall(plugin)" v-if="plugin.installed"><i class="material-icons">delete</i><span class="tl">dialog.plugins.uninstall</span></button>
|
||||
<button type="button" class="" v-on:click="install(plugin)" v-else><i class="material-icons">add</i><span class="tl">dialog.plugins.install</span></button>
|
||||
<div class="button_bar" v-if="plugin.isInstallable()">
|
||||
<button type="button" class="" v-on:click="plugin.uninstall()" v-if="plugin.installed"><i class="material-icons">delete</i><span class="tl">dialog.plugins.uninstall</span></button>
|
||||
<button type="button" class="" v-on:click="plugin.download()" v-else><i class="material-icons">add</i><span class="tl">dialog.plugins.install</span></button>
|
||||
<button type="button" class="local_only" v-on:click="plugin.reload()" v-if="plugin.installed && plugin.fromFile && isApp"><i class="material-icons">refresh</i><span class="tl">dialog.plugins.reload</span></button>
|
||||
</div>
|
||||
<div class="button_bar tiny tl" v-else>{{ checkIfInstallable(plugin) }}</div>
|
||||
@ -141,14 +142,14 @@
|
||||
<div class="author">{{ tl('dialog.plugins.author', [plugin.author]) }}</div>
|
||||
<div class="description">{{ plugin.description }}</div>
|
||||
<div v-if="plugin.expanded" class="about" v-html="plugin.about"><button>a</button></div>
|
||||
<div v-if="plugin.expanded" class="tl" v-on:click="toggleInfo(plugin)" style="text-decoration: underline;">dialog.plugins.show_less</div>
|
||||
<div v-if="plugin.expanded" class="tl" v-on:click="plugin.toggleInfo()" style="text-decoration: underline;">dialog.plugins.show_less</div>
|
||||
</li>
|
||||
<div class="no_plugin_message tl" v-if="installedPlugins.length < 1 && showAll === false">dialog.plugins.none_installed</div>
|
||||
<div class="no_plugin_message tl" v-if="installedPlugins.length < 1 && showAll === true" id="plugin_available_empty">dialog.plugins.none_available</div>
|
||||
<div class="no_plugin_message tl" v-if="plugin_search.length < 1 && showAll === false">dialog.plugins.none_installed</div>
|
||||
<div class="no_plugin_message tl" v-if="plugin_search.length < 1 && showAll === true" id="plugin_available_empty">dialog.plugins.none_available</div>
|
||||
</ul>
|
||||
|
||||
<div class="dialog_bar">
|
||||
<button type="button" class="large cancel_btn confirm_btn uc_btn tl" onclick="saveInstalledPlugins()">dialog.close</button>
|
||||
<button type="button" class="large cancel_btn confirm_btn uc_btn tl" onclick="saveInstalledPlugins();hideDialog();">dialog.close</button>
|
||||
</div>
|
||||
<div id="dialog_close_button" onclick="$('.dialog#'+open_dialog).find('.cancel_btn:not([disabled])').click()"><i class="material-icons">clear</i></div>
|
||||
</div>
|
||||
@ -160,8 +161,8 @@
|
||||
<li v-for="item in currentBar" v-bind:title="item.name" :key="item.id||item">
|
||||
<div v-if="typeof item === 'string'" class="toolbar_separator"></div>
|
||||
<div v-else class="tool">
|
||||
<span class="icon_wrapper" v-bind:style="{opacity: BARS.condition(item.condition) ? 1 : 0.4}" v-html="Blockbench.getIconNode(item.icon, item.color).outerHTML"></span>
|
||||
<div class="tooltip">{{item.name + (BARS.condition(item.condition) ? '' : ' (' + tl('dialog.toolbar_edit.hidden') + ')' )}}</div>
|
||||
<span class="icon_wrapper" v-bind:style="{opacity: BARS.condition(item.condition) ? 1 : 0.4}" v-html="Blockbench.getIconNode(item.icon, item.color).outerHTML"></span>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
@ -182,7 +183,7 @@
|
||||
</ul>
|
||||
|
||||
<div class="dialog_bar">
|
||||
<button type="button" class="large cancel_btn confirm_btn uc_btn tl" onclick="saveInstalledPlugins()">dialog.close</button>
|
||||
<button type="button" class="large cancel_btn confirm_btn uc_btn tl" onclick="saveInstalledPlugins();hideDialog();">dialog.close</button>
|
||||
</div>
|
||||
<div id="dialog_close_button" onclick="$('.dialog#'+open_dialog).find('.cancel_btn:not([disabled])').click()"><i class="material-icons">clear</i></div>
|
||||
</div>
|
||||
@ -243,10 +244,10 @@
|
||||
<div id="texture_menu_thumbnail"></div>
|
||||
|
||||
<div class="bar">
|
||||
<div class="tool link_only" onclick="textures.selected.reopen()"><i class="material-icons">file_upload</i><div class="tooltip tl">menu.texture.change</div></div>
|
||||
<div class="tool link_only" onclick="textures.selected.refresh(true)"><i class="material-icons">refresh</i><div class="tooltip tl">menu.texture.refresh</div></div>
|
||||
<div class="tool link_only" onclick="textures.selected.openFolder()"><i class="material-icons">folder</i><div class="tooltip tl">menu.texture.folder</div></div>
|
||||
<div class="tool" onclick="textures.selected.remove()"><i class="material-icons">delete</i><div class="tooltip tl">menu.texture.delete</div></div>
|
||||
<div class="tool link_only" onclick="textures.selected.reopen()"><div class="tooltip tl">menu.texture.change</div><i class="material-icons">file_upload</i></div>
|
||||
<div class="tool link_only" onclick="textures.selected.refresh(true)"><div class="tooltip tl">menu.texture.refresh</div><i class="material-icons">refresh</i></div>
|
||||
<div class="tool link_only" onclick="textures.selected.openFolder()"><div class="tooltip tl">menu.texture.folder</div><i class="material-icons">folder</i></div>
|
||||
<div class="tool" onclick="textures.selected.remove()"><div class="tooltip tl">menu.texture.delete</div><i class="material-icons">delete</i></div>
|
||||
</div>
|
||||
|
||||
<p class="multiline_text" id="te_path">path</p>
|
||||
@ -306,6 +307,7 @@
|
||||
<div class="dialog_bar">
|
||||
<button type="button" onclick="scaleAll(true)" class="large confirm_btn tl">dialog.scale.confirm</button>
|
||||
<button type="button" class="large cancel_btn tl" onclick="cancelScaleAll()">dialog.cancel</button>
|
||||
<button type="button" class="large hidden tl" id="scale_overflow_btn" onclick="scaleAllSelectOverflow()">dialog.scale.select_overflow</button>
|
||||
</div>
|
||||
<div id="dialog_close_button" onclick="$('.dialog#'+open_dialog).find('.cancel_btn:not([disabled])').click()"><i class="material-icons">clear</i></div>
|
||||
</div>
|
||||
@ -489,12 +491,12 @@
|
||||
<div>{{action.name}}</div>
|
||||
<div class="keybindslot" v-on:click.stop="record(action)">{{ action.keybind ? action.keybind.label : '' }}</div>
|
||||
<div class="tool" v-on:click="reset(action)">
|
||||
<i class="material-icons">replay</i>
|
||||
<div class="tooltip tl">keybindings.reset</div>
|
||||
<i class="material-icons">replay</i>
|
||||
</div>
|
||||
<div class="tool" v-on:click="clear(action)">
|
||||
<i class="material-icons">clear</i>
|
||||
<div class="tooltip tl">keybindings.clear</div>
|
||||
<i class="material-icons">clear</i>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
@ -696,6 +698,17 @@
|
||||
|
||||
<div id="plugin_dialog_wrapper"></div>
|
||||
|
||||
<div id="action_selector" v-if="open">
|
||||
<input type="text" v-model="search_input">
|
||||
<i class="material-icons" id="action_search_bar_icon">search</i>
|
||||
<ul>
|
||||
<li v-for="(item, i) in actions" v-on:click="ActionControl.click(item, $event)" v-bind:class="{selected: i === index}" v-on:mouseenter="index = i">
|
||||
<div class="icon_wrapper normal" v-html="Blockbench.getIconNode(item.icon, item.color).outerHTML"></div>
|
||||
{{ item.name }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<header>
|
||||
<div id="title">
|
||||
<span>Blockbench</span>
|
||||
@ -742,26 +755,26 @@
|
||||
<p class="tl">display.slot</p>
|
||||
<div id="display_bar" class="bar tabs_small">
|
||||
<input class="hidden" type="radio" name="display" id="thirdperson_righthand" checked>
|
||||
<label class="tool" for="thirdperson_righthand" onclick="DisplayMode.loadThirdRight()"><i class="material-icons">accessibility</i><div class="tooltip tl">display.slot.third_right</div></label>
|
||||
<label class="tool" for="thirdperson_righthand" onclick="DisplayMode.loadThirdRight()"><div class="tooltip tl">display.slot.third_right</div><i class="material-icons">accessibility</i></label>
|
||||
<input class="hidden" type="radio" name="display" id="thirdperson_lefthand">
|
||||
<label class="tool" for="thirdperson_lefthand" onclick="DisplayMode.loadThirdLeft()"><i class="material-icons">accessibility</i><div class="tooltip tl">display.slot.third_left</div></label>
|
||||
<label class="tool" for="thirdperson_lefthand" onclick="DisplayMode.loadThirdLeft()"><div class="tooltip tl">display.slot.third_left</div><i class="material-icons">accessibility</i></label>
|
||||
|
||||
<input class="hidden" type="radio" name="display" id="firstperson_righthand">
|
||||
<label class="tool" for="firstperson_righthand" onclick="DisplayMode.loadFirstRight()"><i class="material-icons">person</i><div class="tooltip tl">display.slot.first_right</div></label>
|
||||
<label class="tool" for="firstperson_righthand" onclick="DisplayMode.loadFirstRight()"><div class="tooltip tl">display.slot.first_right</div><i class="material-icons">person</i></label>
|
||||
<input class="hidden" type="radio" name="display" id="firstperson_lefthand">
|
||||
<label class="tool" for="firstperson_lefthand" onclick="DisplayMode.loadFirstLeft()"><i class="material-icons">person</i><div class="tooltip tl">display.slot.first_left</div></label>
|
||||
<label class="tool" for="firstperson_lefthand" onclick="DisplayMode.loadFirstLeft()"><div class="tooltip tl">display.slot.first_left</div><i class="material-icons">person</i></label>
|
||||
|
||||
<input class="hidden" type="radio" name="display" id="head">
|
||||
<label class="tool" for="head" onclick="DisplayMode.loadHead()"><i class="material-icons">sentiment_satisfied</i><div class="tooltip tl">display.slot.head</div></label>
|
||||
<label class="tool" for="head" onclick="DisplayMode.loadHead()"><div class="tooltip tl">display.slot.head</div><i class="material-icons">sentiment_satisfied</i></label>
|
||||
|
||||
<input class="hidden" type="radio" name="display" id="ground">
|
||||
<label class="tool" for="ground" onclick="DisplayMode.loadGround()"><i class="icon-ground"></i><div class="tooltip tl">display.slot.ground</div></label>
|
||||
<label class="tool" for="ground" onclick="DisplayMode.loadGround()"><div class="tooltip tl">display.slot.ground</div><i class="icon-ground"></i></label>
|
||||
|
||||
<input class="hidden" type="radio" name="display" id="fixed">
|
||||
<label class="tool" for="fixed" onclick="DisplayMode.loadFixed()"><i class="material-icons">filter_frames</i><div class="tooltip tl">display.slot.frame</div></label>
|
||||
<label class="tool" for="fixed" onclick="DisplayMode.loadFixed()"><div class="tooltip tl">display.slot.frame</div><i class="material-icons">filter_frames</i></label>
|
||||
|
||||
<input class="hidden" type="radio" name="display" id="gui">
|
||||
<label class="tool" for="gui" onclick="DisplayMode.loadGUI()"><i class="material-icons">border_style</i><div class="tooltip tl">display.slot.gui</div></label>
|
||||
<label class="tool" for="gui" onclick="DisplayMode.loadGUI()"><div class="tooltip tl">display.slot.gui</div><i class="material-icons">border_style</i></label>
|
||||
</div>
|
||||
<p class="reference_model_bar tl">display.reference</p>
|
||||
<div id="display_ref_bar" class="bar tabs_small reference_model_bar">
|
||||
@ -788,7 +801,8 @@
|
||||
<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 class="tooltip tl">display.mirror</div>
|
||||
<i class="material-icons">{{ slot.mirror[axis] ? 'check_box' : 'check_box_outline_blank' }}</i>
|
||||
</div>
|
||||
<input type="range" class="tool disp_range scaleRange" v-model.number="slot.scale[axis]" v-bind:trigger_type="'scale.'+axis" v-bind:id="'scale_range_'+axis"
|
||||
v-bind:min="slot.scale[axis] > 1 ? -2 : 0"
|
||||
@ -846,7 +860,7 @@
|
||||
<li
|
||||
v-for="texture in textures"
|
||||
v-bind:class="{ selected: texture.selected, particle: texture.particle}"
|
||||
v-bind:texid="texture.id"
|
||||
v-bind:texid="texture.uuid"
|
||||
class="texture"
|
||||
v-on:click.stop="texture.select($event)"
|
||||
v-on:dblclick="texture.openMenu($event)"
|
||||
@ -924,7 +938,7 @@
|
||||
<div id="timeline_lines"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="status_bar">
|
||||
<div id="status_bar" @contextmenu="Interface.status_bar.menu.show(event);console.log(true);">
|
||||
<div id="status_saved">
|
||||
<i class="material-icons" v-if="Prop.project_saved" v-bind:title="tl('status_bar.saved')">check</i>
|
||||
<i class="material-icons" v-else v-bind:title="tl('status_bar.unsaved')">close</i>
|
||||
|
@ -8,7 +8,6 @@ THREE.OBJExporter = function () {};
|
||||
THREE.OBJExporter.prototype = {
|
||||
|
||||
constructor: THREE.OBJExporter,
|
||||
|
||||
parse: function ( object, mtlFileName ) {
|
||||
|
||||
var output = '# Made in Blockbench '+appVersion+'\n';
|
||||
@ -44,13 +43,9 @@ THREE.OBJExporter.prototype = {
|
||||
vertex.applyMatrix4( mesh.matrixWorld );
|
||||
|
||||
output += 'v ' + vertex.x + ' ' + vertex.y + ' ' + vertex.z + '\n';
|
||||
|
||||
nbVertex ++;
|
||||
|
||||
}
|
||||
|
||||
// uvs
|
||||
|
||||
var faces = geometry.faces;
|
||||
var faceVertexUvs = geometry.faceVertexUvs[ 0 ];
|
||||
var hasVertexUvs = faces.length === faceVertexUvs.length;
|
||||
@ -64,15 +59,10 @@ THREE.OBJExporter.prototype = {
|
||||
for ( var j = 0, jl = vertexUvs.length; j < jl; j ++ ) {
|
||||
|
||||
var uv = vertexUvs[ j ];
|
||||
|
||||
output += 'vt ' + uv.x + ' ' + uv.y + '\n';
|
||||
|
||||
nbVertexUvs ++;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// normals
|
||||
@ -95,9 +85,7 @@ THREE.OBJExporter.prototype = {
|
||||
output += 'vn ' + normal.x + ' ' + normal.y + ' ' + normal.z + '\n';
|
||||
|
||||
nbNormals ++;
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
var normal = face.normal.clone();
|
||||
@ -106,69 +94,49 @@ THREE.OBJExporter.prototype = {
|
||||
for ( var j = 0; j < 3; j ++ ) {
|
||||
|
||||
output += 'vn ' + normal.x + ' ' + normal.y + ' ' + normal.z + '\n';
|
||||
|
||||
nbNormals ++;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// material
|
||||
for (var key in element.faces) {
|
||||
if (element.faces.hasOwnProperty(key)) {
|
||||
var id = element.faces[key].texture
|
||||
if (id !== undefined && id !== null) {
|
||||
id = id.replace('#', '')
|
||||
if (materials[id] === undefined) {
|
||||
materials[id] = getTextureById(id)
|
||||
}
|
||||
}
|
||||
for (var face in element.faces) {
|
||||
var tex = element.faces[face].getTexture()
|
||||
if (tex && tex.uuid && !materials[tex.id]) {
|
||||
materials[tex.id] = tex
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
for ( var i = 0, j = 1, l = faces.length; i < l; i ++, j += 3 ) {
|
||||
|
||||
var f_mat = getMtlFace(element, i)
|
||||
|
||||
if (f_mat) {
|
||||
|
||||
var face = faces[ i ];
|
||||
|
||||
if (i % 2 === 0) {
|
||||
output += f_mat
|
||||
}
|
||||
|
||||
output += 'f ';
|
||||
output += ( indexVertex + face.a + 1 ) + '/' + ( hasVertexUvs ? ( indexVertexUvs + j ) : '' ) + '/' + ( indexNormals + j ) + ' ';
|
||||
output += ( indexVertex + face.b + 1 ) + '/' + ( hasVertexUvs ? ( indexVertexUvs + j + 1 ) : '' ) + '/' + ( indexNormals + j + 1 ) + ' ';
|
||||
output += ( indexVertex + face.c + 1 ) + '/' + ( hasVertexUvs ? ( indexVertexUvs + j + 2 ) : '' ) + '/' + ( indexNormals + j + 2 ) + '\n';
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
console.warn( 'THREE.OBJExporter.parseMesh(): geometry type unsupported', mesh );
|
||||
// TODO: Support only BufferGeometry and use use setFromObject()
|
||||
|
||||
}
|
||||
|
||||
// update index
|
||||
indexVertex += nbVertex;
|
||||
indexVertexUvs += nbVertexUvs;
|
||||
indexNormals += nbNormals;
|
||||
|
||||
};
|
||||
|
||||
object.traverse( function ( child ) {
|
||||
|
||||
if ( child instanceof THREE.Mesh ) parseMesh( child );
|
||||
|
||||
} );
|
||||
|
||||
// mtl output
|
||||
@ -190,7 +158,6 @@ THREE.OBJExporter.prototype = {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
function getMtlFace(obj, index) {
|
||||
if (index % 2 == 1) index--;
|
||||
@ -204,14 +171,13 @@ function getMtlFace(obj, index) {
|
||||
case 6: key = 'down'; break;
|
||||
}
|
||||
|
||||
var id = obj.faces[key].texture
|
||||
var tex = obj.faces[key].getTexture()
|
||||
|
||||
if (id === null) {
|
||||
if (tex === null) {
|
||||
return false
|
||||
} else if (id === undefined) {
|
||||
} else if (typeof tex === 'string') {
|
||||
return 'usemtl none\n'
|
||||
} else {
|
||||
id = id.replace('#', '')
|
||||
return 'usemtl ' + id + '\n';
|
||||
return 'usemtl ' + tex.id + '\n';
|
||||
}
|
||||
}
|
@ -548,6 +548,7 @@
|
||||
|
||||
var _mode = "translate";
|
||||
var _dragging = false;
|
||||
var _has_groups = false;
|
||||
var _plane = "XY";
|
||||
var _gizmo = {
|
||||
|
||||
@ -866,7 +867,16 @@
|
||||
obj.oldScale = obj.size(axisnr)
|
||||
})
|
||||
}
|
||||
Undo.initEdit({cubes: selected})
|
||||
_has_groups = Blockbench.entity_mode && selected_group && selected_group.matchesSelection() && Toolbox.selected.transformerMode == 'translate';
|
||||
var rotate_group = Blockbench.entity_mode && selected_group && Toolbox.selected.transformerMode == 'rotate';
|
||||
|
||||
if (rotate_group) {
|
||||
Undo.initEdit({cubes: selected, group: selected_group})
|
||||
} else if (_has_groups) {
|
||||
Undo.initEdit({cubes: selected, outliner: true})
|
||||
} else {
|
||||
Undo.initEdit({cubes: selected})
|
||||
}
|
||||
|
||||
} else if (Modes.id === 'animate') {
|
||||
|
||||
@ -984,15 +994,17 @@
|
||||
})
|
||||
}
|
||||
if (!overlapping) {
|
||||
/*var group = Blockbench.entity_mode && selected_group && selected_group.matchesSelection();
|
||||
if (group) {
|
||||
selected_group.origin[axisNumber] += difference
|
||||
}*/
|
||||
if (_has_groups && Blockbench.globalMovement) {
|
||||
selected_group.forEachChild(g => {
|
||||
g.origin[axisNumber] += difference
|
||||
}, 'group', true)
|
||||
|
||||
}
|
||||
selected.forEach(function(obj, i) {
|
||||
var mesh = scope.objects[i]
|
||||
var valx = obj.from[axisNumber]
|
||||
valx += difference
|
||||
moveCube(obj, valx, axisNumber/*, group*/)
|
||||
moveCube(obj, valx, axisNumber, _has_groups)
|
||||
})
|
||||
Canvas.updatePositions(true)
|
||||
centerTransformer()
|
||||
|
204
js/actions.js
204
js/actions.js
@ -29,29 +29,26 @@ class BarItem {
|
||||
return !!this.condition
|
||||
}
|
||||
}
|
||||
addLabel(in_bar) {
|
||||
$(this.node).attr('title', this.description)
|
||||
addLabel(in_bar, action) {
|
||||
if (!action || this instanceof BarItem) {
|
||||
action = this;
|
||||
}
|
||||
$(action.node).attr('title', action.description)
|
||||
if (in_bar) {
|
||||
$(this.node).prepend('<label class="f_left in_toolbar">'+this.name+':</label>')
|
||||
$(action.node).prepend('<label class="f_left in_toolbar">'+action.name+':</label>')
|
||||
} else {
|
||||
$(this.node).append('<div class="tooltip">'+this.name+'</div>')
|
||||
$(action.node).prepend('<div class="tooltip">'+action.name+'</div>')
|
||||
.on('mouseenter', function() {
|
||||
|
||||
var tooltip = $(this).find('div.tooltip')
|
||||
if (!tooltip || typeof tooltip.offset() !== 'object') return;
|
||||
//Left
|
||||
if (tooltip.css('left') === '-4px') {
|
||||
tooltip.css('left', 'auto')
|
||||
}
|
||||
if (-tooltip.offset().left > 4) {
|
||||
tooltip.css('left', '-4px')
|
||||
}
|
||||
//Right
|
||||
if (tooltip.css('right') === '-4px') {
|
||||
tooltip.css('right', 'auto')
|
||||
}
|
||||
if ((tooltip.offset().left + tooltip.width()) - $(window).width() > 4) {
|
||||
tooltip.css('right', '-4px')
|
||||
|
||||
tooltip.css('margin-left', '0')
|
||||
var offset = tooltip.offset()
|
||||
offset.right = offset.left + parseInt(tooltip.css('width').replace(/px/, '')) - $(window).width()
|
||||
|
||||
if (offset.right > 4) {
|
||||
tooltip.css('margin-left', -offset.right+'px')
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -127,6 +124,7 @@ class Action extends BarItem {
|
||||
}
|
||||
this.keybind.setAction(this.id)
|
||||
this.work_in_dialog = data.work_in_dialog === true
|
||||
this.uses = 0;
|
||||
//Icon
|
||||
this.icon = data.icon
|
||||
this.color = data.color
|
||||
@ -142,9 +140,9 @@ class Action extends BarItem {
|
||||
this.icon_node = Blockbench.getIconNode(this.icon, this.color)
|
||||
this.node = $(`<div class="tool ${this.id}"></div>`).get(0)
|
||||
this.nodes = [this.node]
|
||||
this.addLabel(data.label)
|
||||
this.menu_node = $(`<li>${this.name}</li>`).get(0)
|
||||
$(this.node).add(this.menu_node).prepend(this.icon_node)
|
||||
$(this.node).add(this.menu_node).append(this.icon_node)
|
||||
this.addLabel(data.label)
|
||||
$(this.node).click(function(e) {scope.trigger(e)})
|
||||
|
||||
if (data.linked_setting) {
|
||||
@ -164,6 +162,7 @@ class Action extends BarItem {
|
||||
return true;
|
||||
}
|
||||
scope.click(event)
|
||||
scope.uses++;
|
||||
|
||||
$(scope.nodes).each(function() {
|
||||
$(this).css('color', 'var(--color-light)')
|
||||
@ -227,6 +226,7 @@ class Tool extends Action {
|
||||
}
|
||||
Toolbox.selected = this;
|
||||
delete Toolbox.original;
|
||||
this.uses++;
|
||||
|
||||
if (this.transformerMode) {
|
||||
Transformer.setMode(this.transformerMode)
|
||||
@ -309,8 +309,8 @@ class NumSlider extends Widget {
|
||||
}
|
||||
var scope = this;
|
||||
this.node = $( `<div class="tool wide widget nslide_tool">
|
||||
<div class="nslide" n-action="${this.id}"></div>
|
||||
<div class="tooltip">${this.name}</div>
|
||||
<div class="nslide" n-action="${this.id}"></div>
|
||||
</div>`).get(0);
|
||||
this.jq_outer = $(this.node)
|
||||
this.jq_inner = this.jq_outer.find('.nslide');
|
||||
@ -651,10 +651,15 @@ class Toolbar {
|
||||
var scope = this;
|
||||
this.children = [];
|
||||
this.default_children = data.children.slice()
|
||||
this.node = $('<div class="toolbar">'+
|
||||
var jq = $('<div class="toolbar">'+
|
||||
'<div class="content"></div>'+
|
||||
'<div class="tool toolbar_menu"><i class="material-icons">more_vert</i><div class="tooltip">'+tl('data.toolbar')+'</div></div>'+
|
||||
'</div>').get(0)
|
||||
'<div class="tool toolbar_menu"><i class="material-icons">more_vert</i></div>'+
|
||||
'</div>')
|
||||
this.node = jq.get(0)
|
||||
BarItem.prototype.addLabel(false, {
|
||||
name: tl('data.toolbar'),
|
||||
node: jq.find('.tool.toolbar_menu').get(0)
|
||||
})
|
||||
$(this.node).find('div.toolbar_menu').click(function(event) {scope.contextmenu(event)})
|
||||
if (data) {
|
||||
this.id = data.id
|
||||
@ -928,7 +933,12 @@ const BARS = {
|
||||
id: 'project_window',
|
||||
icon: 'featured_play_list',
|
||||
category: 'file',
|
||||
click: function () {showDialog('project_settings');}
|
||||
click: function () {
|
||||
showDialog('project_settings');
|
||||
if (Blockbench.entity_mode) {
|
||||
Undo.initEdit({resolution: true})
|
||||
}
|
||||
}
|
||||
})
|
||||
new Action({
|
||||
id: 'open_model_folder',
|
||||
@ -1005,10 +1015,18 @@ const BARS = {
|
||||
id: 'duplicate',
|
||||
icon: 'content_copy',
|
||||
category: 'edit',
|
||||
condition: () => (!display_mode && !Animator.open && selected.length),
|
||||
condition: () => (!display_mode && !Animator.open && (selected.length || selected_group)),
|
||||
keybind: new Keybind({key: 68, ctrl: true}),
|
||||
click: function () {
|
||||
duplicateCubes();
|
||||
if (selected_group && (selected_group.matchesSelection() || selected.length === 0)) {
|
||||
var cubes_before = elements.length
|
||||
Undo.initEdit({outliner: true, cubes: [], selection: true})
|
||||
var g = selected_group.duplicate()
|
||||
g.select().isOpen = true;
|
||||
Undo.finishEdit('duplicate_group', {outliner: true, cubes: elements.slice().slice(cubes_before), selection: true})
|
||||
} else {
|
||||
duplicateCubes();
|
||||
}
|
||||
}
|
||||
})
|
||||
new Action({
|
||||
@ -1080,7 +1098,7 @@ const BARS = {
|
||||
id: 'move_up',
|
||||
icon: 'arrow_upward',
|
||||
category: 'transform',
|
||||
condition: () => (selected.length && !open_interface && !open_menu),
|
||||
condition: () => (selected.length && !open_menu),
|
||||
keybind: new Keybind({key: 38, ctrl: null, shift: null}),
|
||||
click: function (e) {moveCubesRelative(-1, 2, e)}
|
||||
})
|
||||
@ -1088,7 +1106,7 @@ const BARS = {
|
||||
id: 'move_down',
|
||||
icon: 'arrow_downward',
|
||||
category: 'transform',
|
||||
condition: () => (selected.length && !open_interface && !open_menu),
|
||||
condition: () => (selected.length && !open_menu),
|
||||
keybind: new Keybind({key: 40, ctrl: null, shift: null}),
|
||||
click: function (e) {moveCubesRelative(1, 2, e)}
|
||||
})
|
||||
@ -1096,7 +1114,7 @@ const BARS = {
|
||||
id: 'move_left',
|
||||
icon: 'arrow_back',
|
||||
category: 'transform',
|
||||
condition: () => (selected.length && !open_interface && !open_menu),
|
||||
condition: () => (selected.length && !open_menu),
|
||||
keybind: new Keybind({key: 37, ctrl: null, shift: null}),
|
||||
click: function (e) {moveCubesRelative(-1, 0, e)}
|
||||
})
|
||||
@ -1104,7 +1122,7 @@ const BARS = {
|
||||
id: 'move_right',
|
||||
icon: 'arrow_forward',
|
||||
category: 'transform',
|
||||
condition: () => (selected.length && !open_interface && !open_menu),
|
||||
condition: () => (selected.length && !open_menu),
|
||||
keybind: new Keybind({key: 39, ctrl: null, shift: null}),
|
||||
click: function (e) {moveCubesRelative(1, 0, e)}
|
||||
})
|
||||
@ -1112,7 +1130,7 @@ const BARS = {
|
||||
id: 'move_forth',
|
||||
icon: 'keyboard_arrow_up',
|
||||
category: 'transform',
|
||||
condition: () => (selected.length && !open_interface && !open_menu),
|
||||
condition: () => (selected.length && !open_menu),
|
||||
keybind: new Keybind({key: 33, ctrl: null, shift: null}),
|
||||
click: function (e) {moveCubesRelative(-1, 1, e)}
|
||||
})
|
||||
@ -1120,7 +1138,7 @@ const BARS = {
|
||||
id: 'move_back',
|
||||
icon: 'keyboard_arrow_down',
|
||||
category: 'transform',
|
||||
condition: () => (selected.length && !open_interface && !open_menu),
|
||||
condition: () => (selected.length && !open_menu),
|
||||
keybind: new Keybind({key: 34, ctrl: null, shift: null}),
|
||||
click: function (e) {moveCubesRelative(1, 1, e)}
|
||||
})
|
||||
@ -1207,6 +1225,17 @@ const BARS = {
|
||||
click: function () {setZoomLevel('reset')}
|
||||
})
|
||||
|
||||
//Find Action
|
||||
new Action({
|
||||
id: 'select_action',
|
||||
icon: 'fullscreen',
|
||||
category: 'blockbench',
|
||||
condition: isApp,
|
||||
keybind: new Keybind({key: 70}),
|
||||
click: function () {
|
||||
ActionControl.select()
|
||||
}
|
||||
})
|
||||
|
||||
BARS.action_definers.forEach((definer) => {
|
||||
if (typeof definer === 'function') {
|
||||
@ -1218,7 +1247,7 @@ const BARS = {
|
||||
//
|
||||
Toolbars = {}
|
||||
var stored = localStorage.getItem('toolbars')
|
||||
if (stored) {
|
||||
if (stored && localStorage.getItem('welcomed_version') == appVersion) {
|
||||
stored = JSON.parse(stored)
|
||||
if (typeof stored === 'object') {
|
||||
BARS.stored = stored
|
||||
@ -1298,6 +1327,10 @@ const BARS = {
|
||||
'uv_auto',
|
||||
'uv_transparent',
|
||||
'uv_rotation',
|
||||
//Box
|
||||
'toggle_uv_overlay',
|
||||
'uv_shift',
|
||||
'toggle_mirror_uv',
|
||||
],
|
||||
default_place: true
|
||||
})
|
||||
@ -1367,6 +1400,7 @@ const BARS = {
|
||||
id: 'brush',
|
||||
children: [
|
||||
'brush_mode',
|
||||
'fill_mode',
|
||||
'brush_color',
|
||||
'slider_brush_size',
|
||||
'slider_brush_opacity',
|
||||
@ -1408,7 +1442,6 @@ const BARS = {
|
||||
},
|
||||
computed: {
|
||||
searchedBarItems() {
|
||||
|
||||
var name = $('#action_search_bar').val().toUpperCase()
|
||||
var list = [{
|
||||
icon: 'bookmark',
|
||||
@ -1472,6 +1505,44 @@ const BARS = {
|
||||
BARS.list._data.showAll = !BARS.list._data.showAll
|
||||
BARS.list._data.showAll = !BARS.list._data.showAll
|
||||
}
|
||||
|
||||
ActionControl.vue = new Vue({
|
||||
el: '#action_selector',
|
||||
data: {
|
||||
open: false,
|
||||
search_input: '',
|
||||
index: 0,
|
||||
length: 0,
|
||||
list: []
|
||||
},
|
||||
computed: {
|
||||
actions: function() {
|
||||
var search_input = this._data.search_input.toUpperCase()
|
||||
var list = this._data.list.empty()
|
||||
for (var i = 0; i < Keybinds.actions.length; i++) {
|
||||
var item = Keybinds.actions[i];
|
||||
if (
|
||||
search_input.length == 0 ||
|
||||
item.name.toUpperCase().includes(search_input) ||
|
||||
item.id.toUpperCase().includes(search_input)
|
||||
) {
|
||||
if (item instanceof Action && BARS.condition(item.condition)) {
|
||||
list.push(item)
|
||||
if (list.length > ActionControl.max_length) i = Infinity;
|
||||
}
|
||||
}
|
||||
}
|
||||
this._data.length = list.length;
|
||||
if (this._data.index < 0) {
|
||||
this._data.index = 0;
|
||||
}
|
||||
if (this._data.index >= list.length) {
|
||||
this._data.index = list.length-1;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
updateConditions: function() {
|
||||
for (var key in Toolbars) {
|
||||
@ -1505,6 +1576,57 @@ const BARS = {
|
||||
}
|
||||
}
|
||||
}
|
||||
const ActionControl = {
|
||||
get open() {return ActionControl.vue._data.open},
|
||||
set open(state) {ActionControl.vue._data.open = !!state},
|
||||
type: 'action_selector',
|
||||
max_length: 16,
|
||||
select: function() {
|
||||
ActionControl.open = true;
|
||||
open_interface = ActionControl;
|
||||
ActionControl.vue._data.index = 0;
|
||||
Vue.nextTick(_ => {
|
||||
$('#action_selector > input').focus().select();
|
||||
})
|
||||
},
|
||||
hide: function() {
|
||||
open_interface = false;
|
||||
ActionControl.open = false;
|
||||
},
|
||||
confirm: function(e) {
|
||||
var data = ActionControl.vue._data
|
||||
var action = data.list[data.index]
|
||||
ActionControl.hide()
|
||||
if (action) {
|
||||
action.trigger(e)
|
||||
}
|
||||
},
|
||||
cancel: function() {
|
||||
ActionControl.hide()
|
||||
},
|
||||
click: function(action, e) {
|
||||
action.trigger(e)
|
||||
ActionControl.hide()
|
||||
},
|
||||
handleKeys: function(e) {
|
||||
var data = ActionControl.vue._data
|
||||
|
||||
if (e.which === 38) {
|
||||
data.index--;
|
||||
if (data.index < 0) {
|
||||
data.index = data.length-1;
|
||||
}
|
||||
} else if (e.which === 40) {
|
||||
data.index++;
|
||||
if (data.index >= data.length) {
|
||||
data.index = 0;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//Menu
|
||||
class Menu {
|
||||
@ -1649,7 +1771,7 @@ class Menu {
|
||||
entry = $('<li>' + tl(s.name) + '</li>')
|
||||
entry.prepend(icon)
|
||||
if (typeof s.click === 'function') {
|
||||
entry.click(function() {s.click(context)})
|
||||
entry.click(function(e) {s.click(context, e)})
|
||||
}
|
||||
//Submenu
|
||||
if (typeof s.children == 'function' || typeof s.children == 'object') {
|
||||
@ -1838,7 +1960,7 @@ const MenuBar = {
|
||||
'project_window',
|
||||
{name: 'menu.file.new', id: 'new', icon: 'insert_drive_file', children: [
|
||||
'new_block_model',
|
||||
'new_entity_model'
|
||||
'new_entity_model',
|
||||
]},
|
||||
{name: 'menu.file.recent', id: 'recent', icon: 'history', condition: function() {return isApp && recent_projects.length}, children: function() {
|
||||
var arr = []
|
||||
@ -1848,8 +1970,8 @@ const MenuBar = {
|
||||
name: p.name,
|
||||
path: p.path,
|
||||
icon: entity ? 'view_list' : 'insert_drive_file',
|
||||
click: function() {
|
||||
readFile(p.path, true)
|
||||
click: function(c, event) {
|
||||
readFile(p.path, !event.shiftKey)
|
||||
}
|
||||
})
|
||||
})
|
||||
@ -1872,7 +1994,6 @@ const MenuBar = {
|
||||
'_',
|
||||
'settings_window',
|
||||
'update_window',
|
||||
'show_tip',
|
||||
'donate',
|
||||
'reload'
|
||||
])
|
||||
@ -1881,9 +2002,9 @@ const MenuBar = {
|
||||
'redo',
|
||||
'_',
|
||||
'add_cube',
|
||||
'add_group',
|
||||
'duplicate',
|
||||
'delete',
|
||||
'sort_outliner',
|
||||
'_',
|
||||
'local_move',
|
||||
'_',
|
||||
@ -1916,6 +2037,7 @@ const MenuBar = {
|
||||
'toggle_export',
|
||||
'toggle_autouv',
|
||||
'toggle_shade',
|
||||
'toggle_mirror_uv',
|
||||
'rename'
|
||||
]}
|
||||
|
||||
@ -2088,7 +2210,7 @@ const Keybinds = {
|
||||
Keybinds.save()
|
||||
}
|
||||
}
|
||||
if (localStorage.getItem('keybindings') && localStorage.getItem('welcomed_version') == appVersion) {
|
||||
if (localStorage.getItem('keybindings')) {
|
||||
try {
|
||||
Keybinds.stored = JSON.parse(localStorage.getItem('keybindings'))
|
||||
} catch (err) {}
|
||||
|
@ -120,6 +120,7 @@ class Animation {
|
||||
if (selected_group) {
|
||||
centerTransformer()
|
||||
}
|
||||
Blockbench.dispatchEvent('display_animation_frame')
|
||||
}
|
||||
add() {
|
||||
if (!Animator.animations.includes(this)) {
|
||||
@ -132,6 +133,7 @@ class Animation {
|
||||
Animator.selected = false
|
||||
}
|
||||
Animator.animations.remove(this)
|
||||
Blockbench.dispatchEvent('remove_animation', {animation: this})
|
||||
return this;
|
||||
}
|
||||
getMaxLength() {
|
||||
@ -1140,9 +1142,7 @@ const Timeline = {
|
||||
Timeline.loop()
|
||||
},
|
||||
loop: function() {
|
||||
if (Animator.selected) {
|
||||
Animator.selected.displayFrame(Timeline.second)
|
||||
}
|
||||
Animator.preview()
|
||||
if (Animator.selected && Timeline.second < (Animator.selected.length||1e3)) {
|
||||
Animator.interval = setTimeout(Timeline.loop, 16.66)
|
||||
Timeline.setTime(Timeline.second + 1/60)
|
||||
@ -1206,6 +1206,25 @@ const Timeline = {
|
||||
])
|
||||
}
|
||||
|
||||
onVueSetup(function() {
|
||||
Animator.vue = new Vue({
|
||||
el: '#animations_list',
|
||||
data: {
|
||||
animations: Animator.animations
|
||||
}
|
||||
})
|
||||
Timeline.vue = new Vue({
|
||||
el: '#timeline_inner',
|
||||
data: {
|
||||
size: 150,
|
||||
length: 10,
|
||||
timecodes: [],
|
||||
keyframes: [],
|
||||
marker: Timeline.second
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
BARS.defineActions(function() {
|
||||
new Action({
|
||||
id: 'add_animation',
|
||||
@ -1230,7 +1249,7 @@ BARS.defineActions(function() {
|
||||
var exp = new RegExp(osfs.replace('\\', '\\\\')+'models'+osfs.replace('\\', '\\\\'))
|
||||
var m_index = path.search(exp)
|
||||
if (m_index > 3) {
|
||||
path = path.substr(0, m_index) + osfs + 'animations' + osfs + pathToName(Prop.file_path, true)
|
||||
path = path.substr(0, m_index) + osfs + 'animations' + osfs + pathToName(Prop.file_path).replace(/\.geo/, '.animation')
|
||||
}
|
||||
}
|
||||
Blockbench.import({
|
||||
@ -1341,4 +1360,4 @@ BARS.defineActions(function() {
|
||||
keybind: new Keybind({key: 46}),
|
||||
click: function () {removeSelectedKeyframes()}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
51
js/api.js
51
js/api.js
@ -10,7 +10,12 @@ class API {
|
||||
this.drag_handlers = {}
|
||||
this.entity_mode = false
|
||||
if (isApp) {
|
||||
this.platform = require('os').platform()
|
||||
this.platform = process.platform
|
||||
switch (this.platform) {
|
||||
case 'win32': this.operating_system = 'Windows'; break;
|
||||
case 'darwin': this.operating_system = 'macOS'; break;
|
||||
default: this.operating_system = 'Linux'; break;
|
||||
}
|
||||
if (this.platform.includes('win32') === true) osfs = '\\'
|
||||
}
|
||||
}
|
||||
@ -32,7 +37,7 @@ class API {
|
||||
return Blockbench.entity_mode;
|
||||
}
|
||||
registerEdit() {
|
||||
console.error('Blockbench.registerEdit is outdated. Please use Undo.initEdit and Undo.finishEdit')
|
||||
console.warn('Blockbench.registerEdit is outdated. Please use Undo.initEdit and Undo.finishEdit')
|
||||
}
|
||||
|
||||
//Interface
|
||||
@ -189,7 +194,8 @@ class API {
|
||||
})
|
||||
}
|
||||
addMenuEntry(name, icon, click) {
|
||||
MenuBar.addAction({icon: icon, name: name, id: name, click: click}, 'filter')
|
||||
var action = new Action({icon: icon, name: name, id: name, click: click})
|
||||
MenuBar.addAction(action, 'filter')
|
||||
}
|
||||
removeMenuEntry(name) {
|
||||
MenuBar.removeAction('filter.'+name)
|
||||
@ -430,15 +436,10 @@ class API {
|
||||
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)
|
||||
}
|
||||
})
|
||||
fs.writeFileSync(file_path, options.content)
|
||||
if (cb) {
|
||||
cb(file_path)
|
||||
}
|
||||
}
|
||||
if (options.project_file) {
|
||||
Prop.file_path = file_path
|
||||
@ -654,18 +655,20 @@ document.body.ondrop = function(event) {
|
||||
(function() {
|
||||
var path = fileNames[i].path
|
||||
var this_i = i;
|
||||
fs.readFile(path, 'utf-8', function (err, data) {
|
||||
if (err) {
|
||||
console.log(err)
|
||||
if (!errant && handler.errorbox !== false) {
|
||||
Blockbench.showMessageBox({
|
||||
translateKey: 'file_not_found',
|
||||
icon: 'error_outline'
|
||||
})
|
||||
}
|
||||
errant = true
|
||||
return;
|
||||
var data;
|
||||
try {
|
||||
data = fs.readFileSync(path, 'utf-8')
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
if (!errant && handler.errorbox !== false) {
|
||||
Blockbench.showMessageBox({
|
||||
translateKey: 'file_not_found',
|
||||
icon: 'error_outline'
|
||||
})
|
||||
}
|
||||
errant = true
|
||||
}
|
||||
if (data) {
|
||||
results[this_i] = {
|
||||
name: pathToName(path, true),
|
||||
path: path,
|
||||
@ -675,7 +678,7 @@ document.body.ondrop = function(event) {
|
||||
if (result_count === fileNames.length) {
|
||||
handler.cb(results, event)
|
||||
}
|
||||
})
|
||||
}
|
||||
})()
|
||||
}
|
||||
} else {
|
||||
|
177
js/app.js
177
js/app.js
@ -24,17 +24,20 @@ $(document).ready(function() {
|
||||
shell.openExternal(event.target.href);
|
||||
return true;
|
||||
});
|
||||
Prop.zoom = 100 + currentwindow.webContents._getZoomLevel()*12
|
||||
if (fs.existsSync(app.getPath('userData')+osfs+'backups') === false) {
|
||||
fs.mkdirSync( app.getPath('userData')+osfs+'backups')
|
||||
}
|
||||
createBackup(true)
|
||||
$('.web_only').remove()
|
||||
if (__dirname.includes('C:\\xampp\\htdocs\\blockbench\\web')) {
|
||||
if (__dirname.includes('C:\\xampp\\htdocs\\blockbench')) {
|
||||
Blockbench.addFlag('dev')
|
||||
}
|
||||
})
|
||||
|
||||
getLatestVersion(true)
|
||||
});
|
||||
(function() {
|
||||
console.log('Electron '+process.versions.electron+', Node '+process.versions.node)
|
||||
getLatestVersion(true)
|
||||
})()
|
||||
//Called on start to show message
|
||||
function getLatestVersion(init) {
|
||||
if (process.platform == 'linux') return;
|
||||
@ -211,7 +214,7 @@ function changeImageEditor(texture) {
|
||||
function selectImageEditorFile(texture) {
|
||||
electron.dialog.showOpenDialog(currentwindow, {
|
||||
title: tl('message.image_editor.exe'),
|
||||
filters: [{name: 'Executable Program', extensions: ['exe']}]
|
||||
filters: [{name: 'Executable Program', extensions: ['exe', 'app']}]
|
||||
}, function(filePaths) {
|
||||
if (filePaths) {
|
||||
settings.image_editor.value = filePaths[0]
|
||||
@ -251,8 +254,6 @@ function openDefaultTexturePath() {
|
||||
}
|
||||
function findEntityTexture(mob, return_path) {
|
||||
var textures = {
|
||||
'chicken': 'chicken',
|
||||
'blaze': 'blaze',
|
||||
'llamaspit': 'llama/spit',
|
||||
'llama': 'llama/llama_creamy',
|
||||
'dragon': 'dragon/dragon',
|
||||
@ -260,7 +261,6 @@ function findEntityTexture(mob, return_path) {
|
||||
'slime': 'slime/slime',
|
||||
'slime.armor': 'slime/slime',
|
||||
'lavaslime': 'slime/magmacube',
|
||||
'silverfish': 'silverfish',
|
||||
'shulker': 'shulker/shulker_undyed',
|
||||
'rabbit': 'rabbit/brown',
|
||||
'horse': 'horse/horse_brown',
|
||||
@ -276,41 +276,30 @@ function findEntityTexture(mob, return_path) {
|
||||
'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',
|
||||
@ -318,7 +307,6 @@ function findEntityTexture(mob, return_path) {
|
||||
'salmon': 'fish/salmon',
|
||||
'tropicalfish_a': 'fish/tropical_a',
|
||||
'tropicalfish_b': 'fish/tropical_b',
|
||||
'endermite': 'endermite',
|
||||
'panda': 'panda/panda',
|
||||
}
|
||||
mob = mob.split(':')[0].replace(/^geometry\./, '')
|
||||
@ -388,85 +376,90 @@ function saveFile(props) {
|
||||
}
|
||||
}
|
||||
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 (content.bones && content.bones.length) {
|
||||
var has_parents = false;
|
||||
for (var i = 0; i < content.bones.length && !has_parents; i++) {
|
||||
if (content.bones[i].parent) has_parents = true;
|
||||
}
|
||||
if (has_parents) {
|
||||
obj.format_version = '1.8.0'
|
||||
}
|
||||
var data;
|
||||
try {
|
||||
data = fs.readFileSync(filepath, 'utf-8')
|
||||
} catch (err) {}
|
||||
var obj = {}
|
||||
if (content.bones && content.bones.length) {
|
||||
var has_parents = false;
|
||||
for (var i = 0; i < content.bones.length && !has_parents; i++) {
|
||||
if (content.bones[i].parent) has_parents = true;
|
||||
}
|
||||
if (!errx) {
|
||||
try {
|
||||
obj = JSON.parse(data.replace(/\/\*[^(\*\/)]*\*\/|\/\/.*/g, ''))
|
||||
} catch (err) {
|
||||
err = err+''
|
||||
var answer = electron.dialog.showMessageBox(currentwindow, {
|
||||
type: 'warning',
|
||||
buttons: [
|
||||
tl('message.bedrock_overwrite_error.backup_overwrite'),
|
||||
tl('message.bedrock_overwrite_error.overwrite'),
|
||||
tl('dialog.cancel')
|
||||
],
|
||||
title: 'Blockbench',
|
||||
message: tl('message.bedrock_overwrite_error.message'),
|
||||
detail: err,
|
||||
noLink: false
|
||||
})
|
||||
if (answer === 0) {
|
||||
var backup_file_name = pathToName(filepath, true) + ' backup ' + new Date().toLocaleString().split(':').join('_')
|
||||
backup_file_name = filepath.replace(pathToName(filepath, false), backup_file_name)
|
||||
fs.writeFile(backup_file_name, data, function (err2) {
|
||||
if (err2) {
|
||||
console.log('Error saving backup model: ', err2)
|
||||
}
|
||||
})
|
||||
}
|
||||
if (answer === 2) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (typeof obj === 'object') {
|
||||
for (var key in obj) {
|
||||
if (obj.hasOwnProperty(key) &&
|
||||
obj[key].bones &&
|
||||
typeof obj[key].bones === 'object' &&
|
||||
obj[key].bones.constructor.name === 'Array'
|
||||
) {
|
||||
obj[key].bones.forEach(function(bone) {
|
||||
if (typeof bone.cubes === 'object' &&
|
||||
bone.cubes.constructor.name === 'Array'
|
||||
) {
|
||||
bone.cubes.forEach(function(c, ci) {
|
||||
bone.cubes[ci] = new oneLiner(c)
|
||||
})
|
||||
}
|
||||
})
|
||||
if (has_parents) {
|
||||
obj.format_version = '1.8.0'
|
||||
}
|
||||
}
|
||||
if (data) {
|
||||
try {
|
||||
obj = JSON.parse(data.replace(/\/\*[^(\*\/)]*\*\/|\/\/.*/g, ''))
|
||||
} catch (err) {
|
||||
err = err+''
|
||||
var answer = electron.dialog.showMessageBox(currentwindow, {
|
||||
type: 'warning',
|
||||
buttons: [
|
||||
tl('message.bedrock_overwrite_error.backup_overwrite'),
|
||||
tl('message.bedrock_overwrite_error.overwrite'),
|
||||
tl('dialog.cancel')
|
||||
],
|
||||
title: 'Blockbench',
|
||||
message: tl('message.bedrock_overwrite_error.message'),
|
||||
detail: err,
|
||||
noLink: false
|
||||
})
|
||||
if (answer === 0) {
|
||||
var backup_file_name = pathToName(filepath, true) + ' backup ' + new Date().toLocaleString().split(':').join('_')
|
||||
backup_file_name = filepath.replace(pathToName(filepath, false), backup_file_name)
|
||||
fs.writeFile(backup_file_name, data, function (err2) {
|
||||
if (err2) {
|
||||
console.log('Error saving backup model: ', err2)
|
||||
}
|
||||
})
|
||||
}
|
||||
if (answer === 2) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (typeof obj === 'object') {
|
||||
for (var key in obj) {
|
||||
if (obj.hasOwnProperty(key) &&
|
||||
obj[key].bones &&
|
||||
typeof obj[key].bones === 'object' &&
|
||||
obj[key].bones.constructor.name === 'Array'
|
||||
) {
|
||||
obj[key].bones.forEach(function(bone) {
|
||||
if (typeof bone.cubes === 'object' &&
|
||||
bone.cubes.constructor.name === 'Array'
|
||||
) {
|
||||
bone.cubes.forEach(function(c, ci) {
|
||||
bone.cubes[ci] = new oneLiner(c)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
obj[model_name] = content
|
||||
content = autoStringify(obj)
|
||||
}
|
||||
obj[model_name] = content
|
||||
content = autoStringify(obj)
|
||||
|
||||
fs.writeFile(filepath, content, function (err) {
|
||||
if (err) {
|
||||
console.log('Error Saving Entity Model: '+err)
|
||||
}
|
||||
Blockbench.showQuickMessage('message.save_entity')
|
||||
Prop.project_saved = true;
|
||||
setProjectTitle(pathToName(filepath, false))
|
||||
addRecentProject({name: pathToName(filepath, 'mobs_id'), path: filepath})
|
||||
if (Blockbench.hasFlag('close_after_saving')) {
|
||||
closeBlockbenchWindow()
|
||||
}
|
||||
})
|
||||
})
|
||||
try {
|
||||
fs.writeFileSync(filepath, content)
|
||||
} catch (err) {
|
||||
console.log('Error Saving Entity Model: '+err)
|
||||
return;
|
||||
}
|
||||
Blockbench.showQuickMessage('message.save_entity')
|
||||
Prop.project_saved = true;
|
||||
setProjectTitle(pathToName(filepath, false))
|
||||
addRecentProject({name: pathToName(filepath, 'mobs_id'), path: filepath})
|
||||
if (Blockbench.hasFlag('close_after_saving')) {
|
||||
closeBlockbenchWindow()
|
||||
}
|
||||
}
|
||||
function writeFileObj(content, filepath) {
|
||||
if (filepath === undefined) {
|
||||
@ -566,7 +559,6 @@ function createBackup(init) {
|
||||
})
|
||||
//trimBackups
|
||||
}
|
||||
|
||||
//Zoom
|
||||
function setZoomLevel(mode) {
|
||||
switch (mode) {
|
||||
@ -628,6 +620,7 @@ function showSaveDialog(close) {
|
||||
}
|
||||
function closeBlockbenchWindow() {
|
||||
preventClosing = false;
|
||||
Blockbench.dispatchEvent('before_closing')
|
||||
|
||||
if (!Blockbench.hasFlag('update_restart')) {
|
||||
return currentwindow.close();
|
||||
|
197
js/blockbench.js
197
js/blockbench.js
@ -77,7 +77,10 @@ function initializeApp() {
|
||||
|
||||
//Misc
|
||||
translateUI()
|
||||
console.log('Blockbench ' + appVersion + (isApp ? ' Desktop' : ' Web ('+capitalizeFirstLetter(Blockbench.browser)+')'))
|
||||
console.log('Blockbench ' + appVersion + (isApp
|
||||
? (' Desktop (' + Blockbench.operating_system +')')
|
||||
: (' Web ('+capitalizeFirstLetter(Blockbench.browser)+')')
|
||||
))
|
||||
if (localStorage.getItem('donated') == 'true') {
|
||||
$('#donation_hint').remove()
|
||||
}
|
||||
@ -95,7 +98,11 @@ function initializeApp() {
|
||||
main_uv = new UVEditor('main_uv', false, true)
|
||||
main_uv.setToMainSlot()
|
||||
|
||||
setupVue()
|
||||
onVueSetup.funcs.forEach((func) => {
|
||||
if (typeof func === 'function') {
|
||||
func()
|
||||
}
|
||||
})
|
||||
|
||||
//JQuery UI
|
||||
$('#cubes_list').droppable({
|
||||
@ -114,9 +121,6 @@ function initializeApp() {
|
||||
$('#texture_list').contextmenu(function(event) {
|
||||
Interface.Panels.textures.menu.show(event)
|
||||
})
|
||||
$('#status_bar').contextmenu(function(event) {
|
||||
Interface.status_bar.menu.show(event)
|
||||
})
|
||||
$(window).on( "unload", saveLocalStorages)
|
||||
|
||||
setupInterface()
|
||||
@ -124,161 +128,13 @@ function initializeApp() {
|
||||
Modes.options.edit.select()
|
||||
Blockbench.setup_successful = true
|
||||
}
|
||||
function setupVue() {
|
||||
outliner = new Vue({
|
||||
el: '#cubes_list',
|
||||
data: {
|
||||
option: {
|
||||
root: {
|
||||
name: 'Model',
|
||||
isParent: true,
|
||||
isOpen: true,
|
||||
selected: false,
|
||||
onOpened: function () {},
|
||||
select: function() {},
|
||||
children: TreeElements
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
texturelist = new Vue({
|
||||
el: '#texture_list',
|
||||
data: {textures},
|
||||
methods: {
|
||||
toggleP: function(texture) {
|
||||
textures.forEach(function(t) {
|
||||
if (t !== texture) {
|
||||
t.particle = false;
|
||||
}
|
||||
})
|
||||
texture.particle = !texture.particle
|
||||
},
|
||||
selectT: function(item, event) {
|
||||
var index = textures.indexOf(item)
|
||||
textures[index].select()
|
||||
}
|
||||
}
|
||||
})
|
||||
texturelist._data.elements = textures
|
||||
|
||||
setupKeybindings()
|
||||
|
||||
var structure = {}
|
||||
for (var key in settings) {
|
||||
var category = settings[key].category
|
||||
if (!category) category = 'general'
|
||||
|
||||
if (!structure[category]) {
|
||||
structure[category] = {
|
||||
name: tl('settings.category.'+category),
|
||||
open: category === 'general',
|
||||
items: {}
|
||||
}
|
||||
}
|
||||
structure[category].items[key] = settings[key]
|
||||
function onVueSetup(func) {
|
||||
if (!onVueSetup.funcs) {
|
||||
onVueSetup.funcs = []
|
||||
}
|
||||
var settingslist = new Vue({
|
||||
el: 'ul#settingslist',
|
||||
data: {structure},
|
||||
methods: {
|
||||
saveSettings: function() {
|
||||
localStorage.setItem('settings', JSON.stringify(settings))
|
||||
},
|
||||
toggleCategory: function(category) {
|
||||
if (!category.open) {
|
||||
for (var ct in structure) {
|
||||
structure[ct].open = false
|
||||
}
|
||||
}
|
||||
category.open = !category.open
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
var project_vue = new Vue({
|
||||
el: '#project_settings',
|
||||
data: {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)||0;
|
||||
} else {
|
||||
DisplayMode.slot.rotation[axis] = Math.trimDeg(DisplayMode.slot.rotation[axis])||0;
|
||||
}
|
||||
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',
|
||||
data: {
|
||||
animations: Animator.animations
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
Timeline.vue = new Vue({
|
||||
el: '#timeline_inner',
|
||||
data: {
|
||||
size: 150,
|
||||
length: 10,
|
||||
timecodes: [],
|
||||
keyframes: [],
|
||||
marker: Timeline.second
|
||||
}
|
||||
})
|
||||
|
||||
var stats_bar_vue = new Vue({
|
||||
el: '#status_bar',
|
||||
data: {Prop}
|
||||
})
|
||||
|
||||
Modes.vue = new Vue({
|
||||
el: '#mode_selector',
|
||||
data: {
|
||||
options: Modes.options
|
||||
}
|
||||
})
|
||||
onVueSetup.funcs.push(func)
|
||||
}
|
||||
|
||||
function canvasGridSize(shift, ctrl) {
|
||||
if (!shift && !ctrl) {
|
||||
return 16 / limitNumber(settings.edit_size.value, 1, 1024)
|
||||
@ -335,7 +191,6 @@ function updateSelection() {
|
||||
}
|
||||
Transformer.detach()
|
||||
Transformer.hoverAxis = null;
|
||||
|
||||
if (display_mode) {
|
||||
DisplayMode.centerTransformer()
|
||||
}
|
||||
@ -361,12 +216,12 @@ function updateSelection() {
|
||||
//Interface
|
||||
if (selected.length > 0) {
|
||||
$('.selection_only').css('visibility', 'visible')
|
||||
main_uv.jquery.size.find('.uv_mapping_overlay').remove()
|
||||
main_uv.loadData()
|
||||
} else if (selected.length === 0) {
|
||||
} else {
|
||||
$('.selection_only').css('visibility', 'hidden')
|
||||
}
|
||||
BarItems.cube_counter.update()
|
||||
$('.uv_mapping_overlay').remove()
|
||||
updateNslideValues()
|
||||
//Misc
|
||||
Blockbench.globalMovement = isMovementGlobal()
|
||||
@ -536,6 +391,14 @@ const Modes = {
|
||||
selected: false,
|
||||
options: {},
|
||||
};
|
||||
onVueSetup(function() {
|
||||
Modes.vue = new Vue({
|
||||
el: '#mode_selector',
|
||||
data: {
|
||||
options: Modes.options
|
||||
}
|
||||
})
|
||||
});
|
||||
BARS.defineActions(function() {
|
||||
new Mode({
|
||||
id: 'edit',
|
||||
@ -987,7 +850,9 @@ var Vertexsnap = {
|
||||
cube.mesh.updateMatrixWorld()
|
||||
o_vertices.forEach(function(v, id) {
|
||||
var outline_color = '0x'+app_colors.accent.hex.replace('#', '')
|
||||
var mesh = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1), new THREE.MeshBasicMaterial({color: parseInt(outline_color)}))
|
||||
//Each vertex needs it's own material for hovering
|
||||
var material = new THREE.MeshBasicMaterial({color: parseInt(outline_color)})
|
||||
var mesh = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1), material)
|
||||
var pos = mesh.position.copy(v)
|
||||
pos.applyMatrix4(cube.mesh.matrixWorld)
|
||||
pos.addScalar(8)
|
||||
@ -1169,7 +1034,7 @@ const entityMode = {
|
||||
$('.entity_mode_only').show()
|
||||
Modes.options.edit.select()
|
||||
//UV
|
||||
main_uv.buildDom().setToMainSlot().setFace('north')
|
||||
//main_uv.buildDom(true).setToMainSlot().setFace('north')
|
||||
main_uv.autoGrid = true
|
||||
main_uv.setGrid()
|
||||
//Update
|
||||
@ -1186,7 +1051,11 @@ const entityMode = {
|
||||
//Rotation Menu
|
||||
$('input#cube_rotate').attr('min', '-67.5').attr('max', '67.5').attr('step', '22.5').removeClass('entity_mode')
|
||||
//UV
|
||||
main_uv.buildDom(true).setToMainSlot()
|
||||
//main_uv.buildDom(true).setToMainSlot()
|
||||
main_uv.autoGrid = false
|
||||
main_uv.showing_overlays = false
|
||||
main_uv.displayAllMappingOverlays()
|
||||
main_uv.setGrid()
|
||||
if (textures[0]) {
|
||||
textures[0].load()
|
||||
}
|
||||
|
113
js/display.js
113
js/display.js
@ -37,9 +37,10 @@ class DisplaySlot {
|
||||
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;
|
||||
})
|
||||
|
||||
for (var i = 0; i < 3; i++) {
|
||||
build.scale[i] *= this.mirror[i] ? -1 : 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Object.keys(build).length) {
|
||||
@ -53,6 +54,7 @@ class DisplaySlot {
|
||||
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)
|
||||
this.scale[i] = Math.abs(this.scale[i])
|
||||
if (data.scale && data.scale[i] < 0) this.mirror[i] = true;
|
||||
}
|
||||
this.update()
|
||||
@ -141,20 +143,14 @@ class refModel {
|
||||
break;
|
||||
case 'monitor':
|
||||
this.onload = function() {
|
||||
if (display_slot === 'firstperson_righthand') {
|
||||
setDisplayArea(-20.8, -8.4, 9, 0, 270, 0, 1,1,1)
|
||||
} else if (display_slot === 'firstperson_lefthand') {
|
||||
setDisplayArea(-20.5, -8.4, -9, 0, 270, 0, 1,1,1)
|
||||
}
|
||||
var side = display_slot.includes('left') ? -1 : 1;
|
||||
setDisplayArea(side*9, -8.4, 20.8, 0, 0, 0, 1,1,1)
|
||||
}
|
||||
break;
|
||||
case 'bow':
|
||||
this.onload = function() {
|
||||
if (display_slot === 'firstperson_righthand') {
|
||||
setDisplayArea(-24.7, -5.6, 5.4, 64, -115, 55, 1,1,1)
|
||||
} else if (display_slot === 'firstperson_lefthand') {
|
||||
setDisplayArea(-24.7, -5.6, -5.4, -64, -65, -55, 1,1,1)
|
||||
}
|
||||
var side = display_slot.includes('left') ? -1 : 1;
|
||||
setDisplayArea(side*5.4, -5.6, 24.7, side*64, side*-25, side*55, 1,1,1)
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -286,9 +282,9 @@ class refModel {
|
||||
//Body
|
||||
"size": [8, 12, 4],
|
||||
"pos": [0, 18, 0],
|
||||
"north": {"uv": [6.968, 5.032, 5.032, 7.968]},
|
||||
"north": {"uv": [5.032, 5.032, 6.968, 7.968]},
|
||||
"east": {"uv": [7.968, 5.032, 7.032, 7.968]},
|
||||
"south": {"uv": [9.968, 5.032, 8.032, 7.968]},
|
||||
"south": {"uv": [8.032, 5.032, 9.968, 7.968]},
|
||||
"west": {"uv": [4.968, 5.032, 4.032, 7.968]},
|
||||
"up": {"uv": [5.032, 4.968, 6.968, 4.032]},
|
||||
"down": {"uv": [7.032, 4.032, 8.968, 4.968]}
|
||||
@ -297,9 +293,9 @@ class refModel {
|
||||
//Body Layer
|
||||
"size": [8.5, 12.5, 4.5],
|
||||
"pos": [0, 18, 0],
|
||||
"north": {"uv": [6.968, 9.032, 5.032, 11.968]},
|
||||
"north": {"uv": [5.032, 9.032, 6.968, 11.968]},
|
||||
"east": {"uv": [7.968, 9.032, 7.032, 11.968]},
|
||||
"south": {"uv": [9.968, 9.032, 8.032, 11.968]},
|
||||
"south": {"uv": [8.032, 9.032, 9.968, 11.968]},
|
||||
"west": {"uv": [4.968, 9.032, 4.032, 11.968]},
|
||||
"up": {"uv": [5.032, 8.968, 6.968, 8.032]},
|
||||
"down": {"uv": [7.032, 8.032, 8.968, 8.968]}
|
||||
@ -1175,10 +1171,10 @@ class refModel {
|
||||
}
|
||||
buildMonitor() {
|
||||
this.buildModel([
|
||||
{"size": [0.1, 8, 8], "pos": [-31.2, 4.93, 0], "origin": [0, 0, 0], "north":{"uv":[0,0,0,0]},"east":{"uv":[0,0,0,0]},"south":{"uv":[0,0,0,0]},"west":{"uv":[0,0,16,16]},"up":{"uv":[0,0,0,0]},"down":{"uv":[0,0,0,0]}},
|
||||
{"size": [0.1, 8, 8], "pos": [-31.2, -4.93, 0], "origin": [0, 0, 0], "north":{"uv":[0,0,0,0]},"east":{"uv":[0,0,0,0]},"south":{"uv":[0,0,0,0]},"west":{"uv":[0,0,16,16]},"up":{"uv":[0,0,0,0]},"down":{"uv":[0,0,0,0]}},
|
||||
{"size": [0.1, 8, 8], "pos": [-31.2, 0, 5.65], "origin": [0, 0, 0], "north":{"uv":[0,0,0,0]},"east":{"uv":[0,0,0,0]},"south":{"uv":[0,0,0,0]},"west":{"uv":[0,0,16,16]},"up":{"uv":[0,0,0,0]},"down":{"uv":[0,0,0,0]}},
|
||||
{"size": [0.1, 8, 8], "pos": [-31.2, 0, -5.65], "origin": [0, 0, 0], "north":{"uv":[0,0,0,0]},"east":{"uv":[0,0,0,0]},"south":{"uv":[0,0,0,0]},"west":{"uv":[0,0,16,16]},"up":{"uv":[0,0,0,0]},"down":{"uv":[0,0,0,0]}}
|
||||
{"size": [8, 8, 0.1], "pos": [0, 4.93, 31.20], "origin": [0, 0, 0], "north":{"uv":[0,0,0,0]},"east":{"uv":[0,0,0,0]},"south":{"uv":[0,0,0,0]},"west":{"uv":[0,0,16,16]},"up":{"uv":[0,0,0,0]},"down":{"uv":[0,0,0,0]}},
|
||||
{"size": [8, 8, 0.1], "pos": [0, -4.93, 31.20], "origin": [0, 0, 0], "north":{"uv":[0,0,0,0]},"east":{"uv":[0,0,0,0]},"south":{"uv":[0,0,0,0]},"west":{"uv":[0,0,16,16]},"up":{"uv":[0,0,0,0]},"down":{"uv":[0,0,0,0]}},
|
||||
{"size": [8, 8, 0.1], "pos": [5.65, 0, 31.2], "origin": [0, 0, 0], "north":{"uv":[0,0,0,0]},"east":{"uv":[0,0,0,0]},"south":{"uv":[0,0,0,0]},"west":{"uv":[0,0,16,16]},"up":{"uv":[0,0,0,0]},"down":{"uv":[0,0,0,0]}},
|
||||
{"size": [8, 8, 0.1], "pos": [-5.65, 0, 31.2], "origin": [0, 0, 0], "north":{"uv":[0,0,0,0]},"east":{"uv":[0,0,0,0]},"south":{"uv":[0,0,0,0]},"west":{"uv":[0,0,16,16]},"up":{"uv":[0,0,0,0]},"down":{"uv":[0,0,0,0]}}
|
||||
], 'black')
|
||||
}
|
||||
buildBlock() {
|
||||
@ -1234,8 +1230,13 @@ window.displayReferenceObjects = {
|
||||
case 'icon-monitor': icon = 'fa fa-asterisk'; break;
|
||||
}
|
||||
var button = $(
|
||||
'<div><input class="hidden" type="radio" name="refmodel" id="'+ref.id+'"'+ (i === 0 ? ' selected' : '') +'>'+
|
||||
'<label class="tool" onclick="displayReferenceObjects.refmodels.'+ref.id+'.load()" for="'+ref.id+'"><i class="'+icon+'"></i><div class="tooltip">'+ref.name+'</div></label></div>'
|
||||
`<div>
|
||||
<input class="hidden" type="radio" name="refmodel" id="${ref.id}"${ i === 0 ? ' selected' : '' }>
|
||||
<label class="tool" onclick="displayReferenceObjects.refmodels.${ref.id}.load()" for="${ref.id}">
|
||||
<div class="tooltip">${ref.name}</div>
|
||||
<i class="${icon}"></i>
|
||||
</label>
|
||||
</div>`
|
||||
)
|
||||
$('#display_ref_bar').append(button)
|
||||
if (i === 0) {
|
||||
@ -1411,7 +1412,7 @@ DisplayMode.createPreset = function() {
|
||||
display_presets.push(preset)
|
||||
|
||||
displayReferenceObjects.slots.forEach(function(s) {
|
||||
if ($('#'+s+'_save').is(':checked')) {
|
||||
if ($('#'+s+'_save').is(':checked') && display[s]) {
|
||||
preset.areas[s] = display[s].copy()
|
||||
}
|
||||
})
|
||||
@ -1459,7 +1460,6 @@ function loadDisp(key) { //Loads The Menu and slider values, common for all Radi
|
||||
}
|
||||
display_preview.controls.enabled = true;
|
||||
ground_animation = false;
|
||||
$('input#translation_z').prop('disabled', false)
|
||||
$('#display_crosshair').detach()
|
||||
display_preview.camPers.setFocalLength(45)
|
||||
|
||||
@ -1481,9 +1481,8 @@ DisplayMode.loadThirdLeft = function() { //Loader
|
||||
}
|
||||
DisplayMode.loadFirstRight = function() { //Loader
|
||||
loadDisp('firstperson_righthand')
|
||||
setDisplayArea(-20.8, -8.4, 9, 0, 270, 0, 1,1,1)
|
||||
display_preview.camPers.setFocalLength(12)
|
||||
display_preview.camPers.position.set(-32.4, 0, 0)
|
||||
display_preview.camPers.position.set(0, 0, 32.4)
|
||||
display_preview.controls.target.set(0,0,0)
|
||||
display_preview.controls.enabled = false
|
||||
displayReferenceObjects.bar(['monitor', 'bow'])
|
||||
@ -1491,9 +1490,8 @@ DisplayMode.loadFirstRight = function() { //Loader
|
||||
}
|
||||
DisplayMode.loadFirstLeft = function() { //Loader
|
||||
loadDisp('firstperson_lefthand')
|
||||
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)
|
||||
display_preview.camPers.position.set(0, 0, 32.4)
|
||||
display_preview.controls.target.set(0,0,0)
|
||||
display_preview.controls.enabled = false
|
||||
displayReferenceObjects.bar(['monitor', 'bow'])
|
||||
@ -1508,7 +1506,6 @@ DisplayMode.loadGUI = function() { //Loader
|
||||
setDisplayArea(0, 0, 0, 0, 0, 0, 0.4, 0.4, 0.4)
|
||||
display_preview.camOrtho.zoom = 1
|
||||
display_preview.controls.target.set(0,0,0)
|
||||
//controls.enabled = false
|
||||
display_preview.setOrthographicCamera(2)
|
||||
display_preview.camOrtho.position.set(0,0,32)
|
||||
displayReferenceObjects.bar(['inventory_nine', 'inventory_full', 'hud'])
|
||||
@ -1688,11 +1685,67 @@ function updateDisplaySkin() {
|
||||
}
|
||||
//displayReferenceObjects.refmodels.player.material
|
||||
}
|
||||
|
||||
|
||||
onVueSetup(function() {
|
||||
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)||0;
|
||||
} else {
|
||||
DisplayMode.slot.rotation[axis] = Math.trimDeg(DisplayMode.slot.rotation[axis])||0;
|
||||
}
|
||||
DisplayMode.updateDisplayBase()
|
||||
},
|
||||
resetChannel: (channel) => {
|
||||
var v = channel === 'scale' ? 1 : 0;
|
||||
Undo.initEdit({display_slots: [display_slot]})
|
||||
DisplayMode.slot.extend({[channel]: [v, v, v]})
|
||||
if (channel === 'scale') {
|
||||
DisplayMode.slot.extend({mirror: [false, false, false]})
|
||||
}
|
||||
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')
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
BARS.defineActions(function() {
|
||||
new Action({
|
||||
id: 'add_display_preset',
|
||||
icon: 'add',
|
||||
category: 'display',
|
||||
condition: () => display_mode,
|
||||
click: function () {showDialog('create_preset')}
|
||||
})
|
||||
})
|
||||
|
255
js/elements.js
255
js/elements.js
@ -81,8 +81,46 @@ var selected_group;
|
||||
|
||||
//Cubes
|
||||
class Face {
|
||||
constructor() {
|
||||
constructor(direction, data) {
|
||||
this.direction = direction || 'north';
|
||||
this.reset()
|
||||
this.uv = [0, 0, canvasGridSize(), canvasGridSize()]
|
||||
if (data) {
|
||||
this.extend(data)
|
||||
}
|
||||
}
|
||||
extend(object) {
|
||||
if (object.texture === null) {
|
||||
this.texture = null
|
||||
} else {
|
||||
Merge.string(this, object, 'texture')
|
||||
}
|
||||
Merge.string(this, object, 'cullface')
|
||||
Merge.number(this, object, 'rotation')
|
||||
Merge.number(this, object, 'tint')
|
||||
if (object.uv) {
|
||||
Merge.number(this.uv, object.uv, 0)
|
||||
Merge.number(this.uv, object.uv, 1)
|
||||
Merge.number(this.uv, object.uv, 2)
|
||||
Merge.number(this.uv, object.uv, 3)
|
||||
}
|
||||
return this;
|
||||
}
|
||||
reset() {
|
||||
this.uv = [0, 0, 0, 0];
|
||||
this.rotation = 0;
|
||||
this.texture = false;
|
||||
this.cullface = '';
|
||||
this.enabled = true;
|
||||
this.tint = false;
|
||||
return this;
|
||||
}
|
||||
getTexture() {
|
||||
if (typeof this.texture === 'string') {
|
||||
return textures.findInArray('uuid', this.texture)
|
||||
} else {
|
||||
return this.texture;
|
||||
}
|
||||
}
|
||||
}
|
||||
class OutlinerElement {
|
||||
@ -129,14 +167,20 @@ class OutlinerElement {
|
||||
if (group.type === 'cube') {
|
||||
if (group.parent === 'root') {
|
||||
index = TreeElements.indexOf(group)
|
||||
if (index === TreeElements.length-1) {
|
||||
index++;
|
||||
}
|
||||
group = 'root'
|
||||
} else {
|
||||
index = group.parent.children.indexOf(group)
|
||||
if (index === group.parent.children.length-1) {
|
||||
index++;
|
||||
}
|
||||
group = group.parent
|
||||
}
|
||||
}
|
||||
}
|
||||
if (group != 'root' && group.type === 'group') {
|
||||
if (group.type === 'group') {
|
||||
var i = 0
|
||||
var level = group;
|
||||
while (i < 50) {
|
||||
@ -312,6 +356,12 @@ class OutlinerElement {
|
||||
}
|
||||
return iterate(this.parent, 0)
|
||||
}
|
||||
get mirror_uv() {
|
||||
return !this.shade;
|
||||
}
|
||||
set mirror_uv(val) {
|
||||
this.shade = !val;
|
||||
}
|
||||
}
|
||||
class Cube extends OutlinerElement {
|
||||
constructor(data, uuid) {
|
||||
@ -336,7 +386,14 @@ class Cube extends OutlinerElement {
|
||||
this.export = true;
|
||||
this.parent = 'root';
|
||||
|
||||
this.faces = {north: new Face(), east: new Face(), south: new Face(), west: new Face(), up: new Face(), down: new Face()}
|
||||
this.faces = {
|
||||
north: new Face('north'),
|
||||
east: new Face('east'),
|
||||
south: new Face('south'),
|
||||
west: new Face('west'),
|
||||
up: new Face('up'),
|
||||
down: new Face('down')
|
||||
}
|
||||
if (data && typeof data === 'object') {
|
||||
this.extend(data)
|
||||
}
|
||||
@ -522,20 +579,7 @@ class Cube extends OutlinerElement {
|
||||
if (object.faces) {
|
||||
for (var face in this.faces) {
|
||||
if (this.faces.hasOwnProperty(face) && object.faces.hasOwnProperty(face)) {
|
||||
if (object.faces[face].texture === null) {
|
||||
this.faces[face].texture = null
|
||||
} else {
|
||||
Merge.string(this.faces[face], object.faces[face], 'texture')
|
||||
}
|
||||
Merge.string(this.faces[face], object.faces[face], 'cullface')
|
||||
Merge.number(this.faces[face], object.faces[face], 'rotation')
|
||||
Merge.number(this.faces[face], object.faces[face], 'tintindex')
|
||||
if (object.faces[face].uv) {
|
||||
Merge.number(this.faces[face].uv, object.faces[face].uv, 0)
|
||||
Merge.number(this.faces[face].uv, object.faces[face].uv, 1)
|
||||
Merge.number(this.faces[face].uv, object.faces[face].uv, 2)
|
||||
Merge.number(this.faces[face].uv, object.faces[face].uv, 3)
|
||||
}
|
||||
this.faces[face].extend(object.faces[face])
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -614,22 +658,22 @@ class Cube extends OutlinerElement {
|
||||
this.faces.north.rotation= rotateUVFace(this.faces.north.rotation, 2)
|
||||
this.faces.down.rotation = rotateUVFace(this.faces.down.rotation, 2)
|
||||
|
||||
var temp = this.faces.north
|
||||
this.faces.north = this.faces.down
|
||||
this.faces.down = this.faces.south
|
||||
this.faces.south = this.faces.up
|
||||
this.faces.up = temp
|
||||
var temp = new Face(true, this.faces.north)
|
||||
this.faces.north.extend(this.faces.down)
|
||||
this.faces.down.extend(this.faces.south)
|
||||
this.faces.south.extend(this.faces.up)
|
||||
this.faces.up.extend(temp)
|
||||
|
||||
} else if (axis === 1) {
|
||||
|
||||
this.faces.up.rotation= rotateUVFace(this.faces.up.rotation, 1)
|
||||
this.faces.down.rotation = rotateUVFace(this.faces.down.rotation, 3)
|
||||
|
||||
var temp = this.faces.north
|
||||
this.faces.north = this.faces.west
|
||||
this.faces.west = this.faces.south
|
||||
this.faces.south = this.faces.east
|
||||
this.faces.east = temp
|
||||
var temp = new Face(true, this.faces.north)
|
||||
this.faces.north.extend(this.faces.west)
|
||||
this.faces.west.extend(this.faces.south)
|
||||
this.faces.south.extend(this.faces.east)
|
||||
this.faces.east.extend(temp)
|
||||
|
||||
} else if (axis === 2) {
|
||||
|
||||
@ -641,11 +685,11 @@ class Cube extends OutlinerElement {
|
||||
this.faces.west.rotation = rotateUVFace(this.faces.west.rotation, 3)
|
||||
this.faces.down.rotation = rotateUVFace(this.faces.down.rotation, 3)
|
||||
|
||||
var temp = this.faces.east
|
||||
this.faces.east = this.faces.down
|
||||
this.faces.down = this.faces.west
|
||||
this.faces.west = this.faces.up
|
||||
this.faces.up = temp
|
||||
var temp = new Face(true, this.faces.east)
|
||||
this.faces.east.extend(this.faces.down)
|
||||
this.faces.down.extend(this.faces.west)
|
||||
this.faces.west.extend(this.faces.up)
|
||||
this.faces.up.extend(temp)
|
||||
}
|
||||
|
||||
|
||||
@ -708,8 +752,8 @@ class Cube extends OutlinerElement {
|
||||
case 2: switchFaces = ['south', 'north']; break;
|
||||
}
|
||||
var x = this.faces[switchFaces[0]]
|
||||
this.faces[switchFaces[0]] = this.faces[switchFaces[1]]
|
||||
this.faces[switchFaces[1]] = x
|
||||
this.faces[switchFaces[0]].extend(this.faces[switchFaces[1]])
|
||||
this.faces[switchFaces[1]].extend(x)
|
||||
|
||||
//UV
|
||||
if (axis === 1) {
|
||||
@ -735,6 +779,58 @@ class Cube extends OutlinerElement {
|
||||
Canvas.adaptObjectFaces(this)
|
||||
Canvas.updateUV(this)
|
||||
}
|
||||
transferOrigin(origin) {
|
||||
if (!this.mesh) return;
|
||||
var q = this.mesh.getWorldQuaternion(new THREE.Quaternion())
|
||||
var shift = new THREE.Vector3(
|
||||
this.origin[0] - origin[0],
|
||||
this.origin[1] - origin[1],
|
||||
this.origin[2] - origin[2],
|
||||
)
|
||||
var dq = new THREE.Vector3().copy(shift)
|
||||
dq.applyQuaternion(q)
|
||||
shift.sub(dq)
|
||||
shift.applyQuaternion(q.inverse())
|
||||
|
||||
this.from[0] += shift.x;
|
||||
this.from[1] += shift.y;
|
||||
this.from[2] += shift.z;
|
||||
this.to[0] += shift.x;
|
||||
this.to[1] += shift.y;
|
||||
this.to[2] += shift.z;
|
||||
|
||||
this.origin = origin.slice();
|
||||
|
||||
Canvas.adaptObjectPosition(this)
|
||||
return this;
|
||||
}
|
||||
getWorldCenter() {
|
||||
var m = this.mesh;
|
||||
var pos = new THREE.Vector3(
|
||||
this.from[0] + this.size(0)/2,
|
||||
this.from[1] + this.size(1)/2,
|
||||
this.from[2] + this.size(2)/2
|
||||
)
|
||||
if (!Blockbench.entity_mode) {
|
||||
|
||||
pos.x -= this.origin[0]
|
||||
pos.y -= this.origin[1]
|
||||
pos.z -= this.origin[2]
|
||||
var r = m.getWorldQuaternion(new THREE.Quaternion())
|
||||
pos.applyQuaternion(r)
|
||||
pos.x += this.origin[0]
|
||||
pos.y += this.origin[1]
|
||||
pos.z += this.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
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
setColor(index) {
|
||||
this.color = index;
|
||||
if (this.visibility) {
|
||||
@ -797,8 +893,8 @@ class Cube extends OutlinerElement {
|
||||
var sides = faces
|
||||
}
|
||||
var id = null
|
||||
if (texture && texture.id !== undefined) {
|
||||
id = '#'+texture.id
|
||||
if (texture) {
|
||||
id = texture.uuid
|
||||
} else if (texture === 'blank') {
|
||||
id = undefined;
|
||||
}
|
||||
@ -888,14 +984,6 @@ class Cube extends OutlinerElement {
|
||||
var sy = scope.faces[face].uv[1]
|
||||
var rot = scope.faces[face].rotation
|
||||
|
||||
//Use Texture resolution
|
||||
/*
|
||||
var tex = getTextureById(scope.faces[face].texture)
|
||||
if (tex && tex.res && tex.res != 16) {
|
||||
size[0] *= 16 / tex.res
|
||||
size[1] *= 16 / tex.res
|
||||
}*/
|
||||
|
||||
//Match To Rotation
|
||||
if (rot === 90 || rot === 270) {
|
||||
size.reverse()
|
||||
@ -1046,6 +1134,7 @@ class Group extends OutlinerElement {
|
||||
this.export = true;
|
||||
this.autouv = 0;
|
||||
this.parent = 'root';
|
||||
this.isOpen = false;
|
||||
|
||||
if (typeof data === 'object') {
|
||||
this.extend(data)
|
||||
@ -1096,6 +1185,7 @@ class Group extends OutlinerElement {
|
||||
})
|
||||
}
|
||||
updateSelection()
|
||||
return this;
|
||||
}
|
||||
selectChildren(event) {
|
||||
var scope = this;
|
||||
@ -1118,6 +1208,7 @@ class Group extends OutlinerElement {
|
||||
s.selectLow()
|
||||
})
|
||||
updateSelection()
|
||||
return this;
|
||||
}
|
||||
selectLow(highlight) {
|
||||
//Only Select
|
||||
@ -1127,6 +1218,7 @@ class Group extends OutlinerElement {
|
||||
this.children.forEach(function(s) {
|
||||
s.selectLow(highlight)
|
||||
})
|
||||
return this;
|
||||
}
|
||||
unselect() {
|
||||
if (this.selected === false) return;
|
||||
@ -1167,6 +1259,7 @@ class Group extends OutlinerElement {
|
||||
Merge.number(this, object, 'autouv')
|
||||
Merge.boolean(this, object, 'export')
|
||||
Merge.boolean(this, object, 'visibility')
|
||||
return this;
|
||||
}
|
||||
openUp() {
|
||||
this.isOpen = true
|
||||
@ -1247,6 +1340,7 @@ class Group extends OutlinerElement {
|
||||
}
|
||||
showContextMenu(event) {
|
||||
this.menu.open(event, this)
|
||||
return this;
|
||||
}
|
||||
setMaterial(material) {
|
||||
var scope = this;
|
||||
@ -1259,6 +1353,7 @@ class Group extends OutlinerElement {
|
||||
}
|
||||
Undo.finishEdit('bone_material')
|
||||
})
|
||||
return this;
|
||||
}
|
||||
sortContent() {
|
||||
Undo.initEdit({outliner: true})
|
||||
@ -1267,22 +1362,26 @@ class Group extends OutlinerElement {
|
||||
return sort_collator.compare(a.name, b.name)
|
||||
});
|
||||
Undo.finishEdit('sort')
|
||||
return this;
|
||||
}
|
||||
duplicate(destination) {
|
||||
function duplicateArray(g1, g2) {
|
||||
var array = g1.children
|
||||
var i = 0;
|
||||
while (i < array.length) {
|
||||
if (array[i].type === 'cube') {
|
||||
if (array[i].type !== 'group') {
|
||||
var dupl = new Cube(array[i])
|
||||
dupl.addTo(g2, false)
|
||||
if (destination !== 'cache') {
|
||||
dupl.init()
|
||||
dupl.init(false)
|
||||
} else {
|
||||
dupl.parent = undefined
|
||||
}
|
||||
} else {
|
||||
var dupl = array[i].getChildlessCopy()
|
||||
if (Blockbench.entity_mode && destination !== 'cache') {
|
||||
dupl.createUniqueName()
|
||||
}
|
||||
duplicateArray(array[i], dupl)
|
||||
dupl.addTo(g2, false)
|
||||
}
|
||||
@ -1335,10 +1434,10 @@ class Group extends OutlinerElement {
|
||||
obj.autouv = this.autouv;
|
||||
}
|
||||
if (this.origin.join('_') !== '8_8_8' || Blockbench.entity_mode) {
|
||||
obj.origin = this.origin
|
||||
obj.origin = this.origin.slice()
|
||||
}
|
||||
if (this.rotation.join('_') !== '0_0_0') {
|
||||
obj.rotation = this.rotation
|
||||
obj.rotation = this.rotation.slice()
|
||||
}
|
||||
if (this.reset) {
|
||||
obj.reset = true
|
||||
@ -1657,13 +1756,12 @@ function loadOutlinerDraggable() {
|
||||
|
||||
} else if ($(ui.draggable).hasClass('texture')) {
|
||||
//Texture
|
||||
var id = $(ui.helper).attr('texid')
|
||||
var sides = ['north', 'east', 'south', 'west', 'up', 'down']
|
||||
var uuid = $(ui.helper).attr('texid')
|
||||
if (target.type === 'group') {
|
||||
target.forEachChild(function(s) {
|
||||
sides.forEach(function(side) {
|
||||
s.faces[side].texture = '#'+id
|
||||
})
|
||||
target.forEachChild(function(cube) {
|
||||
for (var face in cube.faces) {
|
||||
cube.faces[face].texture = uuid
|
||||
}
|
||||
}, 'cube')
|
||||
} else {
|
||||
var targets;
|
||||
@ -1673,10 +1771,10 @@ function loadOutlinerDraggable() {
|
||||
targets = [target]
|
||||
}
|
||||
|
||||
targets.forEach(function(target) {
|
||||
sides.forEach(function(side) {
|
||||
target.faces[side].texture = '#'+id
|
||||
})
|
||||
targets.forEach(function(cube) {
|
||||
for (var face in cube.faces) {
|
||||
cube.faces[face].texture = uuid
|
||||
}
|
||||
})
|
||||
}
|
||||
main_uv.loadData()
|
||||
@ -1718,19 +1816,20 @@ function dropOutlinerObjects(item, target, event) {
|
||||
if (item && item !== target) {
|
||||
if (event.altKey) {
|
||||
if (item.type === 'cube') {
|
||||
var cube = new Cube(item).addTo(target).init()
|
||||
var cube = new Cube(item).addTo(target, false).init(false)
|
||||
selected.push(cube)
|
||||
} else {
|
||||
item.duplicate().addTo(target).select()
|
||||
item.duplicate().addTo(target, false).select()
|
||||
}
|
||||
} else {
|
||||
item.addTo(target)
|
||||
item.addTo(target, false)
|
||||
if (Blockbench.entity_mode) {
|
||||
updatePosRecursive(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
loadOutlinerDraggable()
|
||||
if (event.altKey) {
|
||||
updateSelection()
|
||||
Undo.finishEdit('drag', {cubes: selected, outliner: true, selection: true})
|
||||
@ -1753,10 +1852,9 @@ function addCube() {
|
||||
}
|
||||
|
||||
if (textures.length && Blockbench.entity_mode) {
|
||||
var sides = ['north', 'east', 'south', 'west', 'up', 'down']
|
||||
sides.forEach(function(side) {
|
||||
base_cube.faces[side].texture = '#'+textures[0].id
|
||||
})
|
||||
for (var face in base_cube.faces) {
|
||||
base_cube.faces[face].texture = textures[0].uuid
|
||||
}
|
||||
main_uv.loadData()
|
||||
}
|
||||
if (Blockbench.entity_mode) {
|
||||
@ -1878,6 +1976,11 @@ function stopRenameCubes(save) {
|
||||
}
|
||||
$('.outliner_object input.renaming').attr('disabled', true).removeClass('renaming')
|
||||
$('body').focus()
|
||||
if (window.getSelection) {
|
||||
window.getSelection().removeAllRanges()
|
||||
} else if (document.selection) {
|
||||
document.selection.empty()
|
||||
}
|
||||
Blockbench.removeFlag('renaming')
|
||||
}
|
||||
}
|
||||
@ -1906,9 +2009,31 @@ function toggleCubeProperty(key) {
|
||||
if (key === 'visibility') {
|
||||
Canvas.updateVisibility()
|
||||
}
|
||||
if (key === 'shade' && Blockbench.entity_mode) {
|
||||
Canvas.updateUVs()
|
||||
}
|
||||
Undo.finishEdit('toggle_prop')
|
||||
}
|
||||
|
||||
onVueSetup(function() {
|
||||
outliner = new Vue({
|
||||
el: '#cubes_list',
|
||||
data: {
|
||||
option: {
|
||||
root: {
|
||||
name: 'Model',
|
||||
isParent: true,
|
||||
isOpen: true,
|
||||
selected: false,
|
||||
onOpened: function () {},
|
||||
select: function() {},
|
||||
children: TreeElements
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
BARS.defineActions(function() {
|
||||
new Action({
|
||||
id: 'add_cube',
|
||||
|
@ -384,6 +384,11 @@ function setupInterface() {
|
||||
}
|
||||
})
|
||||
|
||||
var stats_bar_vue = new Vue({
|
||||
el: '#status_bar',
|
||||
data: {Prop}
|
||||
})
|
||||
|
||||
//Clickbinds
|
||||
$('header' ).click( function() { setActivePanel('header' )})
|
||||
$('#preview' ).click(function() { setActivePanel('preview' )})
|
||||
@ -400,6 +405,9 @@ function setupInterface() {
|
||||
if (open_menu && $('.contextMenu').find(event.target).length === 0 && $('.menu_bar_point.opened:hover').length === 0) {
|
||||
open_menu.hide();
|
||||
}
|
||||
if (ActionControl.open && $('#action_selector').find(event.target).length === 0) {
|
||||
ActionControl.hide();
|
||||
}
|
||||
if ($(event.target).is('input.cube_name:not([disabled])') === false) {
|
||||
stopRenameCubes()
|
||||
}
|
||||
@ -743,6 +751,7 @@ var splashScreen = {
|
||||
});
|
||||
}
|
||||
showDialog('welcome_screen')
|
||||
Blockbench.dispatchEvent('show_splash_screen')
|
||||
localStorage.setItem('welcomed_version', appVersion)
|
||||
})
|
||||
},
|
||||
|
166
js/io.js
166
js/io.js
@ -33,6 +33,7 @@ function newProject(entity_mode) {
|
||||
entityMode.leave();
|
||||
}
|
||||
$('#var_placeholder_area').val('')
|
||||
Blockbench.dispatchEvent('new_project')
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@ -70,15 +71,15 @@ function setupDragHandlers() {
|
||||
function(files, event) {
|
||||
var texture_li = $(event.target).parents('li.texture')
|
||||
if (texture_li.length) {
|
||||
var tex = getTextureById(texture_li.attr('texid'))
|
||||
var tex = textures.findInArray('uuid', texture_li.attr('texid'))
|
||||
if (tex) {
|
||||
tex.fromFile(files[0])
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
files.forEach(function(f) {
|
||||
new Texture().fromFile(f).add().fillParticle()
|
||||
})
|
||||
}
|
||||
files.forEach(function(f) {
|
||||
new Texture().fromFile(f).add().fillParticle()
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
@ -162,6 +163,9 @@ function loadBlockModel(model, filepath, add) {
|
||||
if (obj.faces[face].texture === '#missing') {
|
||||
delete base_cube.faces[face].texture;
|
||||
}
|
||||
if (obj.faces[face].tintindex !== undefined) {
|
||||
base_cube.faces[face].tint = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!uv_stated) {
|
||||
@ -247,29 +251,23 @@ function loadBlockModel(model, filepath, add) {
|
||||
}
|
||||
}
|
||||
//Get Rid Of ID overlapping
|
||||
textures.forEach(function(t, i) {
|
||||
if (i >= previous_texture_length) {
|
||||
if (getTexturesById(t.id).length > 1) {
|
||||
var before = t.id
|
||||
t.id = Prop.added_models + '_' + t.id
|
||||
elements.forEach(function(s, si) {
|
||||
if (si >= previous_length) {
|
||||
for (var face in s.faces) {
|
||||
if (s.faces[face].texture === '#'+before) {
|
||||
s.faces[face].texture = '#'+t.id
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
for (var i = previous_texture_length; i < textures.length; i++) {
|
||||
var t = textures[i]
|
||||
var import_id = t.id;
|
||||
if (getTexturesById(t.id).length > 1) {
|
||||
t.id = Prop.added_models + '_' + t.id
|
||||
}
|
||||
})
|
||||
elements.forEach(function(s, si) {
|
||||
for (var face in s.faces) {
|
||||
if (s.faces[face].texture === '#'+import_id) {
|
||||
s.faces[face].texture = t.uuid
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
//Select Last Texture
|
||||
if (textures.length > 0) {
|
||||
textures.forEach(function(s) {
|
||||
s.selected = false;
|
||||
})
|
||||
textures[textures.length-1].selected = true;
|
||||
textures[textures.length-1].select();
|
||||
}
|
||||
}
|
||||
|
||||
@ -336,7 +334,7 @@ function loadJEMModel(model) {
|
||||
name: b.part,
|
||||
origin: b.translate,
|
||||
rotation: b.rotate,
|
||||
shade: !(b.mirrorTexture && b.mirrorTexture.includes('u'))
|
||||
mirror_uv: (b.mirrorTexture && b.mirrorTexture.includes('u'))
|
||||
})
|
||||
group.origin[1] *= -1
|
||||
group.origin[2] *= -1
|
||||
@ -595,7 +593,7 @@ function loadPEModel(data) {
|
||||
group.rotation[ri] *= -1
|
||||
})
|
||||
|
||||
group.shade = !b.mirror
|
||||
group.mirror_uv = b.mirror === true
|
||||
group.reset = b.reset === true
|
||||
|
||||
if (b.cubes) {
|
||||
@ -618,9 +616,9 @@ function loadPEModel(data) {
|
||||
base_cube.inflate = s.inflate
|
||||
}
|
||||
if (s.mirror === undefined) {
|
||||
base_cube.shade = group.shade
|
||||
base_cube.mirror_uv = group.mirror_uv
|
||||
} else {
|
||||
base_cube.shade = !s.mirror
|
||||
base_cube.mirror_uv = s.mirror === true
|
||||
}
|
||||
elements.push(base_cube)
|
||||
base_cube.addTo(group, false)
|
||||
@ -805,20 +803,20 @@ var Extruder = {
|
||||
}
|
||||
draw_y++;
|
||||
}
|
||||
var current_cube = new Cube({name: cube_name+'_'+cube_nr, autouv: 0})
|
||||
|
||||
current_cube.from = [rect.x*scale_i, 0, rect.y*scale_i]
|
||||
current_cube.to = [(rect.x2+1)*scale_i, scale_i, (rect.y2+1)*scale_i]
|
||||
|
||||
//Sides
|
||||
current_cube.faces.up = {uv:[rect.x*scale_i, rect.y*scale_i, (rect.x2+1)*scale_i, (rect.y2+1)*scale_i], texture: texture_index}
|
||||
current_cube.faces.down = {uv:[rect.x*scale_i, (rect.y2+1)*scale_i, (rect.x2+1)*scale_i, rect.y*scale_i], texture: texture_index}
|
||||
|
||||
current_cube.faces.north = {uv:[(rect.x2+1)*scale_i, rect.y*scale_i, rect.x*scale_i, (rect.y+1)*scale_i], texture: texture_index}
|
||||
current_cube.faces.south = {uv:[rect.x*scale_i, rect.y2*scale_i, (rect.x2+1)*scale_i, (rect.y2+1)*scale_i], texture: texture_index}
|
||||
|
||||
current_cube.faces.east = {uv:[rect.x2*scale_i, rect.y*scale_i, (rect.x2+1)*scale_i, (rect.y2+1)*scale_i], texture: texture_index, rotation: 90}
|
||||
current_cube.faces.west = {uv:[rect.x*scale_i, rect.y*scale_i, (rect.x+1)*scale_i, (rect.y2+1)*scale_i], texture: texture_index, rotation: 270}
|
||||
var current_cube = new Cube({
|
||||
name: cube_name+'_'+cube_nr,
|
||||
autouv: 0,
|
||||
from: [rect.x*scale_i, 0, rect.y*scale_i],
|
||||
to: [(rect.x2+1)*scale_i, scale_i, (rect.y2+1)*scale_i],
|
||||
faces: {
|
||||
up: {uv:[rect.x*scale_i, rect.y*scale_i, (rect.x2+1)*scale_i, (rect.y2+1)*scale_i], texture: texture_index},
|
||||
down: {uv:[rect.x*scale_i, (rect.y2+1)*scale_i, (rect.x2+1)*scale_i, rect.y*scale_i], texture: texture_index},
|
||||
north: {uv:[(rect.x2+1)*scale_i, rect.y*scale_i, rect.x*scale_i, (rect.y+1)*scale_i], texture: texture_index},
|
||||
south: {uv:[rect.x*scale_i, rect.y2*scale_i, (rect.x2+1)*scale_i, (rect.y2+1)*scale_i], texture: texture_index},
|
||||
east: {uv:[rect.x2*scale_i, rect.y*scale_i, (rect.x2+1)*scale_i, (rect.y2+1)*scale_i], texture: texture_index, rotation: 90},
|
||||
west: {uv:[rect.x*scale_i, rect.y*scale_i, (rect.x+1)*scale_i, (rect.y2+1)*scale_i], texture: texture_index, rotation: 270}
|
||||
}
|
||||
})
|
||||
|
||||
elements.push(current_cube)
|
||||
selected.push(elements[elements.length-1])
|
||||
@ -847,17 +845,6 @@ var Extruder = {
|
||||
}
|
||||
}
|
||||
//Export
|
||||
class oneLiner {
|
||||
constructor(data) {
|
||||
if (data !== undefined) {
|
||||
for (var key in data) {
|
||||
if (data.hasOwnProperty(key)) {
|
||||
this[key] = data[key]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function buildBlockModel(options) {
|
||||
if (options === undefined) options = {}
|
||||
var clear_elements = []
|
||||
@ -917,31 +904,28 @@ function buildBlockModel(options) {
|
||||
tag.rotation = s.faces[face].rotation
|
||||
}
|
||||
if (s.faces[face].texture) {
|
||||
tag.texture = s.faces[face].texture
|
||||
var tex = s.faces[face].getTexture()
|
||||
if (tex) {
|
||||
tag.texture = '#' + tex.id
|
||||
textures_used.safePush(tex)
|
||||
}
|
||||
element_has_texture = true
|
||||
} else {
|
||||
}
|
||||
if (!tag.texture) {
|
||||
tag.texture = '#missing'
|
||||
}
|
||||
if (s.faces[face].cullface !== undefined) {
|
||||
if (s.faces[face].cullface) {
|
||||
tag.cullface = s.faces[face].cullface
|
||||
}
|
||||
if (s.faces[face].tintindex !== undefined) {
|
||||
tag.tintindex = s.faces[face].tintindex
|
||||
if (s.faces[face].tint) {
|
||||
tag.tintindex = 0
|
||||
}
|
||||
e_faces[face] = tag
|
||||
}
|
||||
}
|
||||
}
|
||||
//Gather Textures
|
||||
if (element_has_texture) {
|
||||
for (var face in s.faces) {
|
||||
if (s.faces.hasOwnProperty(face)) {
|
||||
if (!textures_used.includes(s.faces[face].texture)) {
|
||||
textures_used.push(s.faces[face].texture)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!element_has_texture) {
|
||||
element.color = s.color
|
||||
}
|
||||
element.faces = e_faces
|
||||
@ -992,7 +976,7 @@ function buildBlockModel(options) {
|
||||
var texturesObj = {}
|
||||
var hasUnsavedTextures = false
|
||||
textures.forEach(function(t, i){
|
||||
if (!textures_used.includes('#'+t.id) && !isTexturesOnlyModel) return;
|
||||
if (!textures_used.includes(t) && !isTexturesOnlyModel) return;
|
||||
|
||||
texturesObj[t.id] = t.javaTextureLink(options.backup)
|
||||
if (t.particle) {
|
||||
@ -1038,12 +1022,9 @@ function buildBlockModel(options) {
|
||||
var entries = 0;
|
||||
for (var i in DisplayMode.slots) {
|
||||
var key = DisplayMode.slots[i]
|
||||
if (DisplayMode.slots.hasOwnProperty(i) && display[key]) {
|
||||
var slot = display[key].export()
|
||||
if (slot) {
|
||||
new_display[key] = display[key].export()
|
||||
entries++;
|
||||
}
|
||||
if (DisplayMode.slots.hasOwnProperty(i) && display[key] && display[key].export) {
|
||||
new_display[key] = display[key].export()
|
||||
entries++;
|
||||
}
|
||||
}
|
||||
if (entries) {
|
||||
@ -1081,7 +1062,25 @@ function buildEntityModel(options) {
|
||||
var cube_count = 0;
|
||||
var visible_box = new THREE.Box3()
|
||||
|
||||
getAllOutlinerGroups().forEach(function(g) {
|
||||
var groups = getAllOutlinerGroups()
|
||||
var loose_cubes = [];
|
||||
TreeElements.forEach(obj => {
|
||||
if (obj.type === 'cube') {
|
||||
loose_cubes.push(obj)
|
||||
}
|
||||
})
|
||||
if (loose_cubes.length) {
|
||||
groups.splice(0, 0, {
|
||||
type: 'group',
|
||||
parent: 'root',
|
||||
name: 'unknown_bone',
|
||||
origin: [0, 0, 0],
|
||||
rotation: [0],
|
||||
children: loose_cubes
|
||||
})
|
||||
}
|
||||
|
||||
groups.forEach(function(g) {
|
||||
if (g.type !== 'group') return;
|
||||
//Bone
|
||||
var bone = {}
|
||||
@ -1091,7 +1090,7 @@ function buildEntityModel(options) {
|
||||
}
|
||||
bone.pivot = g.origin.slice()
|
||||
bone.pivot[0] *= -1
|
||||
if (g.rotation.join('_') !== '0_0_0') {
|
||||
if (!g.rotation.allEqual(0)) {
|
||||
bone.rotation = g.rotation.slice()
|
||||
bone.rotation.forEach(function(br, ri) {
|
||||
bone.rotation[ri] *= -1
|
||||
@ -1100,7 +1099,7 @@ function buildEntityModel(options) {
|
||||
if (g.reset) {
|
||||
bone.reset = true
|
||||
}
|
||||
if (!g.shade) {
|
||||
if (g.mirror_uv) {
|
||||
bone.mirror = true
|
||||
}
|
||||
if (g.material) {
|
||||
@ -1121,8 +1120,8 @@ function buildEntityModel(options) {
|
||||
if (s.inflate && typeof s.inflate === 'number') {
|
||||
cube.inflate = s.inflate
|
||||
}
|
||||
if (s.shade === !!bone.mirror) {
|
||||
cube.mirror = !s.shade
|
||||
if (s.mirror_uv === !bone.mirror) {
|
||||
cube.mirror = s.mirror_uv
|
||||
}
|
||||
//Visible Bounds
|
||||
var mesh = s.mesh
|
||||
@ -1212,7 +1211,6 @@ function buildJPMModel(options) {
|
||||
} else {
|
||||
boxes.push(box)
|
||||
}
|
||||
submodels.push(submodel)
|
||||
})
|
||||
if (boxes.length) {
|
||||
jpm.boxes = boxes
|
||||
@ -1250,7 +1248,7 @@ function buildJEMModel(options) {
|
||||
if (g.rotation.join('_') !== '0_0_0') {
|
||||
bone.rotate = g.rotation.slice()
|
||||
}
|
||||
if (g.shade === false) {
|
||||
if (g.mirror_uv) {
|
||||
bone.mirrorTexture = 'u'
|
||||
}
|
||||
//Cubes
|
||||
@ -1282,7 +1280,7 @@ function buildJEMModel(options) {
|
||||
if (s.inflate && typeof s.inflate === 'number') {
|
||||
cube.sizeAdd = s.inflate
|
||||
}
|
||||
if (s.shade === g.shade) {
|
||||
if (s.mirror_uv === g.mirror_uv) {
|
||||
bone.boxes.push(cube)
|
||||
} else {
|
||||
mirrored_boxes.push(cube)
|
||||
@ -1397,7 +1395,7 @@ function buildClassModel(options) {
|
||||
obj.size(1, true),
|
||||
obj.size(2, true),
|
||||
F(obj.inflate),
|
||||
!obj.shade
|
||||
obj.mirror_uv
|
||||
]
|
||||
bone.lines.push(
|
||||
`${id}.cubeList.add(new ModelBox(${ values.join(', ') }));`
|
||||
|
@ -165,7 +165,7 @@ class Keybind {
|
||||
}
|
||||
}
|
||||
|
||||
function setupKeybindings() {
|
||||
onVueSetup(function() {
|
||||
Keybinds.vue = new Vue({
|
||||
el: 'ul#keybindlist',
|
||||
data: {structure: Keybinds.structure},
|
||||
@ -203,14 +203,9 @@ function setupKeybindings() {
|
||||
}
|
||||
category.open = !category.open
|
||||
}
|
||||
/*
|
||||
change
|
||||
reset
|
||||
clear
|
||||
*/
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
$(document).keydown(function(e) {
|
||||
if (Keybinds.recording) return;
|
||||
@ -283,13 +278,16 @@ $(document).keydown(function(e) {
|
||||
|
||||
} else if (open_interface && typeof open_interface == 'object' && open_interface.hide) {
|
||||
if (Keybinds.extra.confirm.keybind.isTriggered(e)) {
|
||||
open_interface.confirm()
|
||||
open_interface.confirm(e)
|
||||
used = true
|
||||
} else if (Keybinds.extra.cancel.keybind.isTriggered(e)) {
|
||||
open_interface.hide()
|
||||
open_interface.hide(e)
|
||||
used = true
|
||||
}
|
||||
}
|
||||
if (ActionControl.open) {
|
||||
used = ActionControl.handleKeys(e) || used
|
||||
}
|
||||
if (used) {
|
||||
e.preventDefault()
|
||||
}
|
||||
|
@ -250,7 +250,7 @@ function previewVariableValue(name, time) {
|
||||
return 1
|
||||
} else if (name === 'false') {
|
||||
return 0
|
||||
} else if (name === 'global.anim_time' || name === 'Params.AnimTime' || name === 'Params.LifeTime' || name === 'global.life_time' ) {
|
||||
} else if (name === 'global.anim_time' || name === 'time' || name === 'query.life_time' ) {
|
||||
return time
|
||||
} else {
|
||||
var inputs = $('#var_placeholder_area').val().split('\n')
|
||||
|
426
js/painter.js
426
js/painter.js
@ -59,12 +59,7 @@ class BBPainter {
|
||||
})
|
||||
} 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)
|
||||
|
||||
var c = Painter.current.canvas = Painter.getCanvas(texture)
|
||||
cb(c)
|
||||
|
||||
texture.updateSource(c.toDataURL())
|
||||
@ -76,7 +71,7 @@ class BBPainter {
|
||||
}
|
||||
startBrushCanvas(data, event) {
|
||||
Painter.current.x = Painter.current.y = 0
|
||||
var texture = getTextureById(data.cube.faces[data.face].texture)
|
||||
var texture = data.cube.faces[data.face].getTexture()
|
||||
if (!texture) {
|
||||
Blockbench.showQuickMessage('message.untextured')
|
||||
}
|
||||
@ -93,7 +88,7 @@ class BBPainter {
|
||||
moveBrushCanvas(force) {
|
||||
var data = Canvas.raycast()
|
||||
if (data) {
|
||||
var texture = getTextureById(data.cube.faces[data.face].texture)
|
||||
var texture = data.cube.faces[data.face].getTexture()
|
||||
if (texture) {
|
||||
var x, y, new_face;
|
||||
var end_x = x = Math.floor( data.intersects[0].uv.x * texture.img.naturalWidth )
|
||||
@ -148,17 +143,25 @@ class BBPainter {
|
||||
Painter.colorPicker(texture, x, y)
|
||||
}
|
||||
}
|
||||
getCanvas(texture) {
|
||||
var c = document.createElement('canvas')
|
||||
var ctx = c.getContext('2d');
|
||||
c.width = texture.res;
|
||||
c.height = texture.img.naturalHeight;
|
||||
ctx.drawImage(texture.img, 0, 0)
|
||||
return c;
|
||||
}
|
||||
colorPicker(texture, x, y) {
|
||||
function getPxColor(image) {
|
||||
var c = image.getPixelColor(x,y)
|
||||
c = tinycolor(Jimp.intToRGBA(c))
|
||||
BarItems.brush_color.set(c)
|
||||
}
|
||||
if (texture.mode == 'bitmap') {
|
||||
Jimp.read(Buffer.from(texture.source.replace('data:image/png;base64,', ''), 'base64')).then(getPxColor)
|
||||
} else {
|
||||
Jimp.read(texture.source).then(getPxColor)
|
||||
}
|
||||
var ctx = Painter.getCanvas(texture).getContext('2d')
|
||||
Painter.scanCanvas(ctx, x, y, 1, 1, (x, y, px) => {
|
||||
var t = tinycolor({
|
||||
r: px[0],
|
||||
g: px[1],
|
||||
b: px[2],
|
||||
a: px[3]/256
|
||||
})
|
||||
BarItems.brush_color.set(t)
|
||||
})
|
||||
}
|
||||
useBrush(texture, x, y, uvTag, no_update) {
|
||||
if ((Painter.currentPixel[0] !== x || Painter.currentPixel[1] !== y)) {
|
||||
@ -185,39 +188,90 @@ class BBPainter {
|
||||
uvTag[3] / 16 * texture.img.naturalHeight
|
||||
]
|
||||
} else {
|
||||
var rect = Painter.editing_area = [0, 0, texture.red, texture.red]
|
||||
var rect = Painter.editing_area = [0, 0, texture.img.naturalWidth, texture.img.naturalHeight]
|
||||
}
|
||||
for (var t = 0; t < 2; t++) {
|
||||
if (rect[t] > rect[t+2]) {
|
||||
[rect[t], rect[t+2]] = [rect[t+2], rect[t]]
|
||||
}
|
||||
rect[t] = Math.floor(rect[t])
|
||||
rect[t+2] = Math.ceil(rect[t+2])
|
||||
}
|
||||
ctx.rect(rect[0], rect[1], rect[2] - rect[0], rect[3] - rect[1])
|
||||
var [w, h] = [rect[2] - rect[0], rect[3] - rect[1]]
|
||||
ctx.rect(rect[0], rect[1], w, h)
|
||||
|
||||
if (tool === 'fill_tool') {
|
||||
|
||||
ctx.fillStyle = BarItems.brush_color.get().toRgbString()
|
||||
ctx.fill()
|
||||
|
||||
var fill_mode = BarItems.fill_mode.get()
|
||||
var cube = selected[0]
|
||||
|
||||
if (cube && fill_mode === 'cube') {
|
||||
for (var face in cube.faces) {
|
||||
var tag = cube.faces[face]
|
||||
if (tag.texture === Painter.current.texture.uuid) {
|
||||
var rect = getRectangle(
|
||||
Math.floor(tag.uv[0] / 16 * texture.img.naturalWidth),
|
||||
Math.floor(tag.uv[1] / 16 * texture.img.naturalHeight),
|
||||
Math.ceil(tag.uv[2] / 16 * texture.img.naturalWidth),
|
||||
Math.ceil(tag.uv[3] / 16 * texture.img.naturalHeight)
|
||||
)
|
||||
ctx.rect(rect.ax, rect.ay, rect.x, rect.y)
|
||||
ctx.fill()
|
||||
}
|
||||
}
|
||||
|
||||
} else if (fill_mode === 'face') {
|
||||
ctx.fill()
|
||||
} else {
|
||||
|
||||
var pxcol = [];
|
||||
var map = {}
|
||||
Painter.scanCanvas(ctx, x, y, 1, 1, (x, y, px) => {
|
||||
px.forEach((val, i) => {
|
||||
pxcol[i] = val
|
||||
})
|
||||
})
|
||||
Painter.scanCanvas(ctx, rect[0], rect[1], w, h, (x, y, px) => {
|
||||
if (pxcol.equals(px)) {
|
||||
if (!map[x]) map[x] = {}
|
||||
map[x][y] = true
|
||||
}
|
||||
})
|
||||
function checkPx(x, y) {
|
||||
if (map[x] && map[x][y]) {
|
||||
map[x][y] = false;
|
||||
|
||||
checkPx(x+1, y)
|
||||
checkPx(x-1, y)
|
||||
checkPx(x, y+1)
|
||||
checkPx(x, y-1)
|
||||
}
|
||||
}
|
||||
checkPx(x, y)
|
||||
Painter.scanCanvas(ctx, rect[0], rect[1], w, h, (x, y, px) => {
|
||||
if (map[x] && map[x][y] === false) {
|
||||
var pxcolor = {
|
||||
r: px[0],
|
||||
g: px[1],
|
||||
b: px[2],
|
||||
a: px[3]/255
|
||||
}
|
||||
var result_color = Painter.combineColors(pxcolor, color, 1);
|
||||
px[0] = result_color.r
|
||||
px[1] = result_color.g
|
||||
px[2] = result_color.b
|
||||
px[3] = result_color.a*255
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
||||
} 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));
|
||||
@ -417,6 +471,7 @@ class BBPainter {
|
||||
lines.push({label: 'dialog.create_texture.folder', node: '<input class="dark_bordered half" type="text" id="bitmap_folder">'})
|
||||
if (elements.length > 0) {
|
||||
lines.push({label: 'dialog.create_texture.template', node: '<input type="checkbox" id="bitmap_doTemplate">'})
|
||||
lines.push({label: 'dialog.create_texture.compress', node: '<input type="checkbox" id="bitmap_compressTemplate">'})
|
||||
}
|
||||
lines.push({widget: Painter.background_color})
|
||||
lines.push({label: 'dialog.create_texture.resolution', node: '<input class="dark_bordered" style="width:72px" type="number" id="bitmap_resolution">'})
|
||||
@ -433,7 +488,11 @@ class BBPainter {
|
||||
}
|
||||
})
|
||||
dialog.show()
|
||||
$('#bitmap_compressTemplate').parent().hide()
|
||||
|
||||
$('.dialog#add_bitmap input#bitmap_doTemplate').click(function() {
|
||||
var checked = $('.dialog#add_bitmap input#bitmap_doTemplate').is(':checked')
|
||||
$('#bitmap_compressTemplate').parent()[ checked ? 'show' : 'hide' ]()
|
||||
if (Painter.background_color.get().toHex8() === 'ffffffff') {
|
||||
Painter.background_color.set('#00000000')
|
||||
}
|
||||
@ -457,7 +516,8 @@ class BBPainter {
|
||||
name: $('.dialog#add_bitmap input#bitmap_name').val(),
|
||||
folder: $('.dialog#add_bitmap input#bitmap_folder').val(),
|
||||
particle: 'auto',
|
||||
entity_template: $('.dialog#add_bitmap input#bitmap_doTemplate').is(':checked')
|
||||
entity_template: $('.dialog#add_bitmap input#bitmap_doTemplate').is(':checked'),
|
||||
compress: $('.dialog#add_bitmap input#bitmap_compressTemplate').is(':checked')
|
||||
})
|
||||
}
|
||||
addBitmap(options, after) {
|
||||
@ -493,16 +553,19 @@ class BBPainter {
|
||||
if (typeof after === 'function') {
|
||||
after(texture)
|
||||
}
|
||||
if (options.entity_template) {
|
||||
Undo.finishEdit('create template', {textures: [texture], bitmap: true, cubes: Blockbench.entity_mode ? elements : selected, uv_only: true})
|
||||
} else {
|
||||
Undo.finishEdit('create blank texture', {textures: [texture], bitmap: true})
|
||||
}
|
||||
return texture.add(false);
|
||||
}
|
||||
if (options.entity_template === true) {
|
||||
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})
|
||||
Undo.initEdit({textures: Blockbench.entity_mode ? textures : [], cubes: Blockbench.entity_mode ? elements : selected, uv_only: true})
|
||||
Painter.generateTemplate(options, makeTexture)
|
||||
} else {
|
||||
Undo.initEdit({textures: []})
|
||||
Painter.generateBlank(options.res, options.res, options.color, makeTexture)
|
||||
Undo.finishEdit({textures: [texture]})
|
||||
}
|
||||
}
|
||||
generateBlank(height, width, color, cb) {
|
||||
@ -515,15 +578,18 @@ class BBPainter {
|
||||
ctx.fillRect(0, 0, width, height)
|
||||
|
||||
cb(canvas.toDataURL())
|
||||
|
||||
}
|
||||
generateTemplate(res, background_color, cb, texture) {
|
||||
generateTemplate(options, cb) {
|
||||
var res = options.res
|
||||
var background_color = options.color
|
||||
var texture = options.texture
|
||||
function cubeTempl(obj) {
|
||||
var min = Blockbench.entity_mode ? 0 : 1
|
||||
this.x = obj.size(0, true) || min
|
||||
this.y = obj.size(1, true) || min
|
||||
this.z = obj.size(2, true) || min
|
||||
this.obj = obj
|
||||
this.template_size = (obj.size(2, true) + obj.size(1, true)) + (obj.size(2, true) + obj.size(0, true))*2
|
||||
|
||||
this.height = this.z + this.y
|
||||
this.width = 2* (this.x + this.z)
|
||||
@ -532,103 +598,143 @@ class BBPainter {
|
||||
|
||||
var res_multiple = res / 16
|
||||
var templates = []
|
||||
var max_x_pos = 0
|
||||
var line_y_pos = 0;
|
||||
var valid_cubes = 0;
|
||||
|
||||
var lines = [[]]
|
||||
var line_length = Math.sqrt(elements.length/2)
|
||||
var o = 0
|
||||
|
||||
var cubes = Blockbench.entity_mode ? elements.slice() : selected.slice()
|
||||
var extend_x = 0;
|
||||
var extend_y = 0;
|
||||
var avg_size = 0;
|
||||
var cubes = Blockbench.entity_mode ? elements.slice() : selected.slice()
|
||||
|
||||
var i = cubes.length-1
|
||||
while (i >= 0) {
|
||||
let obj = cubes[i]
|
||||
if (obj.visibility === false) {
|
||||
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
|
||||
avg_size += obj.template_size
|
||||
if (obj.visibility === true) {
|
||||
templates.push(new cubeTempl(obj))
|
||||
avg_size += templates[templates.length-1].template_size
|
||||
}
|
||||
i--;
|
||||
}
|
||||
avg_size /= cubes.length
|
||||
cubes.sort(function(a,b) {
|
||||
return b.template_size - a.template_size
|
||||
})
|
||||
|
||||
i = 0
|
||||
var ox = 0
|
||||
cubes.forEach(function(obj) {
|
||||
if (ox >= line_length) {
|
||||
o = 0
|
||||
ox = 0
|
||||
i++
|
||||
lines[i] = []
|
||||
}
|
||||
lines[i][o] = obj
|
||||
o++;
|
||||
ox += obj.template_size/avg_size
|
||||
})
|
||||
|
||||
lines.forEach(function(b) {
|
||||
|
||||
//Data
|
||||
var temps = []
|
||||
b.forEach(function(s, si) {
|
||||
if (s.type === 'cube') {
|
||||
temps.push(new cubeTempl(s))
|
||||
valid_cubes++;
|
||||
}
|
||||
})
|
||||
//Defaults
|
||||
//Find the maximum height of the line
|
||||
var max_height = 0
|
||||
temps.forEach(function(t) {
|
||||
max_height = Math.max(max_height, t.height)
|
||||
})
|
||||
var x_pos = 0
|
||||
var y_pos = 0 //Y Position of current area relative to this bone
|
||||
var filled_x_pos = 0;
|
||||
//Algorithm
|
||||
temps.forEach(function(t) {
|
||||
if (y_pos > 0 && (y_pos + t.height) <= max_height) {
|
||||
//same column
|
||||
t.posx = x_pos
|
||||
t.posy = y_pos + line_y_pos
|
||||
filled_x_pos = Math.max(filled_x_pos, x_pos+t.width)
|
||||
y_pos += t.height
|
||||
} else {
|
||||
//new column
|
||||
x_pos = filled_x_pos
|
||||
y_pos = t.height
|
||||
t.posx = x_pos
|
||||
t.posy = line_y_pos
|
||||
filled_x_pos = Math.max(filled_x_pos, x_pos+t.width)
|
||||
}
|
||||
//size of widest bone
|
||||
max_x_pos = Math.max(max_x_pos, filled_x_pos)
|
||||
templates.push(t)
|
||||
})
|
||||
line_y_pos += max_height
|
||||
templates.sort(function(a,b) {
|
||||
return b.template_size - a.template_size;
|
||||
})
|
||||
//Cancel if no cubes
|
||||
if (valid_cubes == 0) {
|
||||
if (templates.length == 0) {
|
||||
Blockbench.showMessage('No valid cubes', 'center')
|
||||
return;
|
||||
}
|
||||
function getNextPower(num, min) {
|
||||
var i = min ? min : 2
|
||||
while (i < num && i < 4000) {
|
||||
i *= 2
|
||||
/*
|
||||
TEMPLATE MENU
|
||||
condensed
|
||||
use old texture
|
||||
*/
|
||||
if (options.compress) {
|
||||
|
||||
var fill_map = {}
|
||||
function occupy(x, y) {
|
||||
if (!fill_map[x]) fill_map[x] = {}
|
||||
fill_map[x][y] = true
|
||||
}
|
||||
return i;
|
||||
function check(x, y) {
|
||||
return fill_map[x] && fill_map[x][y]
|
||||
}
|
||||
function forTemplatePixel(tpl, sx, sy, cb) {
|
||||
for (var x = 0; x < tpl.width; x++) {
|
||||
for (var y = 0; y < tpl.height; y++) {
|
||||
if (y >= tpl.z || (x >= tpl.z && x < (tpl.z + 2*tpl.x))) {
|
||||
if (cb(sx+x, sy+y)) return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function place(tpl, x, y) {
|
||||
var works = true;
|
||||
forTemplatePixel(tpl, x, y, (tx, ty) => {
|
||||
if (check(tx, ty)) {
|
||||
works = false;
|
||||
return true;
|
||||
}
|
||||
})
|
||||
if (works) {
|
||||
forTemplatePixel(tpl, x, y, occupy)
|
||||
tpl.posx = x;
|
||||
tpl.posy = y;
|
||||
extend_x = Math.max(extend_x, x + tpl.width);
|
||||
extend_y = Math.max(extend_y, y + tpl.height);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
templates.forEach(tpl => {
|
||||
var vert = extend_x > extend_y;
|
||||
//Scan for empty spot
|
||||
for (var line = 0; line < 2e3; line++) {
|
||||
for (var x = 0; x < line; x++) {
|
||||
if (place(tpl, x, line)) return;
|
||||
}
|
||||
for (var y = 0; y < line; y++) {
|
||||
if (place(tpl, line, y)) return;
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
//OLD -------------------------------------------
|
||||
var lines = [[]]
|
||||
var line_length = Math.sqrt(elements.length/2)
|
||||
avg_size /= templates.length
|
||||
var o = 0
|
||||
var i = 0
|
||||
var ox = 0
|
||||
templates.forEach(function(tpl) {
|
||||
if (ox >= line_length) {
|
||||
o = ox = 0
|
||||
i++
|
||||
lines[i] = []
|
||||
}
|
||||
lines[i][o] = tpl
|
||||
o++;
|
||||
ox += tpl.template_size/avg_size
|
||||
})
|
||||
|
||||
lines.forEach(function(temps) {
|
||||
|
||||
var x_pos = 0
|
||||
var y_pos = 0 //Y Position of current area relative to this bone
|
||||
var filled_x_pos = 0;
|
||||
var max_height = 0
|
||||
//Find the maximum height of the line
|
||||
temps.forEach(function(t) {
|
||||
max_height = Math.max(max_height, t.height)
|
||||
})
|
||||
//Place
|
||||
temps.forEach(function(t) {
|
||||
if (y_pos > 0 && (y_pos + t.height) <= max_height) {
|
||||
//same column
|
||||
t.posx = x_pos
|
||||
t.posy = y_pos + extend_y
|
||||
filled_x_pos = Math.max(filled_x_pos, x_pos+t.width)
|
||||
y_pos += t.height
|
||||
} else {
|
||||
//new column
|
||||
x_pos = filled_x_pos
|
||||
y_pos = t.height
|
||||
t.posx = x_pos
|
||||
t.posy = extend_y
|
||||
filled_x_pos = Math.max(filled_x_pos, x_pos+t.width)
|
||||
}
|
||||
//size of widest bone
|
||||
extend_x = Math.max(extend_x, filled_x_pos)
|
||||
})
|
||||
extend_y += max_height
|
||||
})
|
||||
}
|
||||
|
||||
//Size
|
||||
var max_size = Math.max(max_x_pos, line_y_pos)
|
||||
max_size = Math.ceil(max_size/16)*16//getNextPower(max_size, 16)
|
||||
//function getNextPower(num, min) {
|
||||
// var i = min ? min : 2
|
||||
// while (i < num && i < 4000) {
|
||||
// i *= 2
|
||||
// }
|
||||
// return i;
|
||||
//}
|
||||
var max_size = Math.max(extend_x, extend_y)
|
||||
max_size = Math.ceil(max_size/16)*16
|
||||
|
||||
if (background_color.getAlpha() != 0) {
|
||||
background_color = background_color.toInteger()
|
||||
@ -664,22 +770,52 @@ class BBPainter {
|
||||
function drawTexture(face, coords) {
|
||||
if (!Blockbench.entity_mode) {
|
||||
if (face.texture === undefined || face.texture === null) return false;
|
||||
texture = getTextureById(face.texture)
|
||||
texture = face.getTexture()
|
||||
}
|
||||
if (!texture || !texture.img) return false;
|
||||
var uv = face.uv;
|
||||
|
||||
ctx.save()
|
||||
var uv = face.uv.slice();
|
||||
|
||||
if (face.direction === 'up') {
|
||||
uv = [uv[2], uv[3], uv[0], uv[1]]
|
||||
} else if (face.direction === 'down') {
|
||||
uv = [uv[2], uv[1], uv[0], uv[3]]
|
||||
}
|
||||
|
||||
var src = getRectangle(uv[0], uv[1], uv[2], uv[3])
|
||||
var flip = [
|
||||
uv[0] > uv[2] ? -1 : 1,
|
||||
uv[1] > uv[3] ? -1 : 1
|
||||
]
|
||||
if (flip[0] + flip[1] < 1) {
|
||||
ctx.scale(flip[0], flip[1])
|
||||
}
|
||||
if (face.rotation) {
|
||||
ctx.rotate(Math.degToRad(face.rotation))
|
||||
let rot = face.rotation
|
||||
|
||||
if (rot <= 180) flip[1] *= -1;
|
||||
if (rot >= 180) flip[0] *= -1;
|
||||
|
||||
while (rot > 0) {
|
||||
[coords.x, coords.y] = [coords.y, coords.x];
|
||||
[coords.w, coords.h] = [coords.h, coords.w];
|
||||
rot -= 90;
|
||||
}
|
||||
}
|
||||
ctx.drawImage(
|
||||
texture.img,
|
||||
src.ax/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
|
||||
coords.x*res_multiple*flip[0],
|
||||
coords.y*res_multiple*flip[1],
|
||||
coords.w*res_multiple*flip[0],
|
||||
coords.h*res_multiple*flip[1]
|
||||
)
|
||||
ctx.restore()
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -693,8 +829,9 @@ class BBPainter {
|
||||
}
|
||||
|
||||
//Drawing
|
||||
|
||||
templates.forEach(function(t) {
|
||||
let obj = t.obj
|
||||
|
||||
for (var face in face_data) {
|
||||
let d = face_data[face]
|
||||
|
||||
@ -704,7 +841,6 @@ class BBPainter {
|
||||
drawTemplateRectangle(d.c1, d.c2, d.place(t))
|
||||
}
|
||||
}
|
||||
let obj = t.obj
|
||||
obj.uv_offset[0] = t.posx
|
||||
obj.uv_offset[1] = t.posy
|
||||
|
||||
@ -719,15 +855,16 @@ class BBPainter {
|
||||
{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
|
||||
|
||||
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;
|
||||
obj.faces[f.face].rotation = 0;
|
||||
})
|
||||
} else {
|
||||
obj.mirror_uv = false
|
||||
}
|
||||
})
|
||||
var dataUrl = canvas.toDataURL()
|
||||
@ -854,6 +991,15 @@ BARS.defineActions(function() {
|
||||
noise: true
|
||||
}
|
||||
})
|
||||
new BarSelect({
|
||||
id: 'fill_mode',
|
||||
condition: () => Toolbox && Toolbox.selected.id === 'fill_tool',
|
||||
options: {
|
||||
face: true,
|
||||
color: true,
|
||||
cube: true
|
||||
}
|
||||
})
|
||||
|
||||
new NumSlider({
|
||||
id: 'slider_brush_size',
|
||||
|
@ -1,14 +1,10 @@
|
||||
/*
|
||||
Plugin Loader for Blockbench
|
||||
By JannisX11
|
||||
*/
|
||||
var onUninstall, onInstall;
|
||||
const Plugins = {
|
||||
apipath: 'https://raw.githubusercontent.com/JannisX11/blockbench-plugins/master/plugins.json',
|
||||
Vue: [], //Vue Object
|
||||
installed: [], //Simple List of Names
|
||||
json: undefined, //Json from website
|
||||
data: [], //Vue Object Data
|
||||
all: [], //Vue Object Data
|
||||
loadingStep: false,
|
||||
updateSearch: function() {
|
||||
Plugins.Vue._data.showAll = !Plugins.Vue._data.showAll
|
||||
@ -16,16 +12,182 @@ const Plugins = {
|
||||
},
|
||||
devReload: function() {
|
||||
var reloads = 0;
|
||||
Plugins.data.forEach(function(pl) {
|
||||
if (pl.fromFile) {
|
||||
pl.reload()
|
||||
for (var i = Plugins.all.length-1; i >= 0; i--) {
|
||||
if (Plugins.all[i].fromFile) {
|
||||
Plugins.all[i].reload()
|
||||
reloads++;
|
||||
}
|
||||
})
|
||||
}
|
||||
Blockbench.showQuickMessage(tl('message.plugin_reload', [reloads]))
|
||||
console.log('Reloaded '+reloads+ ' plugin'+pluralS(reloads))
|
||||
}
|
||||
}
|
||||
|
||||
class Plugin {
|
||||
constructor(id, data) {
|
||||
this.id = id;
|
||||
this.installed = false;
|
||||
this.expanded = false;
|
||||
this.title = '';
|
||||
this.author = '';
|
||||
this.description = '';
|
||||
this.about = '';
|
||||
this.icon = '';
|
||||
this.variant = '';
|
||||
this.min_version = '';
|
||||
if (data) {
|
||||
this.extend(data)
|
||||
}
|
||||
}
|
||||
extend(data) {
|
||||
Merge.boolean(this, data, 'installed')
|
||||
Merge.boolean(this, data, 'expanded')
|
||||
Merge.string(this, data, 'title')
|
||||
Merge.string(this, data, 'author')
|
||||
Merge.string(this, data, 'description')
|
||||
Merge.string(this, data, 'about')
|
||||
Merge.string(this, data, 'icon')
|
||||
Merge.string(this, data, 'variant')
|
||||
Merge.string(this, data, 'min_version')
|
||||
return this;
|
||||
}
|
||||
install(first, cb) {
|
||||
var scope = this;
|
||||
$.getScript(Plugins.path + scope.id + '.js', function() {
|
||||
scope.bindGlobalData(first)
|
||||
if (cb) cb()
|
||||
}).fail(function() {
|
||||
if (isApp) {
|
||||
console.log('Could not find file of plugin "'+scope.id+'". Uninstalling it instead.')
|
||||
scope.uninstall()
|
||||
}
|
||||
})
|
||||
Plugins.installed.safePush(scope.id)
|
||||
scope.installed = true;
|
||||
return scope;
|
||||
}
|
||||
bindGlobalData(first) {
|
||||
var scope = this;
|
||||
if (onUninstall) {
|
||||
scope.onUninstall = onUninstall
|
||||
}
|
||||
if (first && onInstall) {
|
||||
onInstall()
|
||||
}
|
||||
window.onInstall = window.onUninstall = window.plugin_data = undefined
|
||||
return this;
|
||||
}
|
||||
download(first) {
|
||||
var scope = this;
|
||||
if (!isApp) {
|
||||
scope.install(first)
|
||||
return this;
|
||||
}
|
||||
var file = originalFs.createWriteStream(Plugins.path+this.id+'.js')
|
||||
var request = https.get('https://raw.githubusercontent.com/JannisX11/blockbench-plugins/master/plugins/'+this.id+'.js', function(response) {
|
||||
response.pipe(file);
|
||||
response.on('end', function() {
|
||||
setTimeout(function() {
|
||||
scope.install(first)
|
||||
}, 50)
|
||||
})
|
||||
});
|
||||
return this;
|
||||
}
|
||||
loadFromFile(file, hideWarning) {
|
||||
var scope = this;
|
||||
var path = file.path
|
||||
localStorage.setItem('plugin_dev_path', file.path)
|
||||
onInstall = undefined
|
||||
|
||||
if (!hideWarning) {
|
||||
if (isApp) {
|
||||
if (!confirm(tl('message.load_plugin_app'))) return;
|
||||
} else {
|
||||
if (!confirm(tl('message.load_plugin_web'))) return;
|
||||
}
|
||||
}
|
||||
$.getScript(file.path, function() {
|
||||
scope.id = (plugin_data && plugin_data.id)||pathToName(file.path)
|
||||
scope.installed = true
|
||||
scope.fromFile = true
|
||||
scope.path = file.path
|
||||
scope.extend(plugin_data)
|
||||
scope.bindGlobalData(true)
|
||||
Plugins.installed.safePush(scope.path)
|
||||
saveInstalledPlugins()
|
||||
Plugins.all.sort(function(a,b) {
|
||||
return sort_collator.compare(a.title, b.title)
|
||||
});
|
||||
})
|
||||
Plugins.all.safePush(this)
|
||||
return this;
|
||||
}
|
||||
uninstall() {
|
||||
var scope = this;
|
||||
if (isApp && this.fromFile) {
|
||||
if (this.onUninstall) {
|
||||
this.onUninstall()
|
||||
}
|
||||
Plugins.all.remove(this)
|
||||
Plugins.installed.remove(this.path)
|
||||
} else {
|
||||
if (isApp) {
|
||||
var filepath = Plugins.path + scope.id + '.js'
|
||||
if (fs.existsSync(filepath)) {
|
||||
fs.unlink(filepath, (err) => {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
Plugins.installed.remove(scope.id)
|
||||
scope.installed = false
|
||||
if (scope.onUninstall) {
|
||||
scope.onUninstall()
|
||||
}
|
||||
}
|
||||
saveInstalledPlugins()
|
||||
return this;
|
||||
}
|
||||
reload() {
|
||||
if (!isApp) return this;
|
||||
this.uninstall()
|
||||
this.loadFromFile({path: this.path}, true)
|
||||
return this;
|
||||
}
|
||||
isInstallable() {
|
||||
var scope = this;
|
||||
var result =
|
||||
scope.variant === 'both' ||
|
||||
(
|
||||
isApp === (scope.variant === 'desktop') &&
|
||||
isApp !== (scope.variant === 'web')
|
||||
);
|
||||
if (result && scope.min_version) {
|
||||
result = compareVersions(scope.min_version, appVersion) ? 'outdated' : true
|
||||
} else if (result === false) {
|
||||
result = (scope.variant === 'web') ? 'web_only' : 'app_only'
|
||||
}
|
||||
return (result === true) ? true : tl('dialog.plugins.'+result);
|
||||
}
|
||||
toggleInfo(force) {
|
||||
var scope = this;
|
||||
Plugins.all.forEach(function(p) {
|
||||
if (p !== scope && p.expanded) p.expanded = false;
|
||||
})
|
||||
if (force !== undefined) {
|
||||
this.expanded = force === true
|
||||
} else {
|
||||
this.expanded = this.expanded !== true
|
||||
}
|
||||
}
|
||||
get expandicon() {
|
||||
return this.expanded ? 'expand_less' : 'expand_more'
|
||||
}
|
||||
}
|
||||
|
||||
if (isApp) {
|
||||
Plugins.path = app.getPath('userData')+osfs+'plugins'+osfs
|
||||
fs.readdir(Plugins.path, function(err) {
|
||||
@ -33,102 +195,78 @@ if (isApp) {
|
||||
fs.mkdir(Plugins.path, function(a) {})
|
||||
}
|
||||
})
|
||||
} else {
|
||||
Plugins.path = 'https://cdn.jsdelivr.net/gh/JannisX11/blockbench-plugins/plugins/';
|
||||
}
|
||||
$.getJSON(Plugins.apipath, function(data) {
|
||||
Plugins.json = data
|
||||
if (Plugins.loadingStep === true) {
|
||||
loadInstalledPlugins()
|
||||
} else {
|
||||
Plugins.loadingStep = true
|
||||
}
|
||||
loadInstalledPlugins()
|
||||
}).fail(function() {
|
||||
console.log('Could not connect to plugin server')
|
||||
$('#plugin_available_empty').text('Could not connect to plugin server')
|
||||
if (Plugins.loadingStep === true) {
|
||||
loadInstalledPlugins()
|
||||
} else {
|
||||
Plugins.loadingStep = true
|
||||
}
|
||||
loadInstalledPlugins()
|
||||
})
|
||||
|
||||
$(document).ready(function() {
|
||||
if (Plugins.loadingStep === true) {
|
||||
loadInstalledPlugins()
|
||||
} else {
|
||||
Plugins.loadingStep = true
|
||||
}
|
||||
loadInstalledPlugins()
|
||||
})
|
||||
|
||||
function loadInstalledPlugins() {
|
||||
if (!Plugins.loadingStep) {
|
||||
Plugins.loadingStep = true
|
||||
return;
|
||||
}
|
||||
var storage_data = localStorage.getItem('installed_plugins')
|
||||
if (storage_data !== null) {
|
||||
Plugins.installed = JSON.parse(storage_data)
|
||||
}
|
||||
if (Plugins.json !== undefined) {
|
||||
//From Store
|
||||
for (var id in Plugins.json) {
|
||||
var plugin = Plugins.json[id]
|
||||
var obj = {
|
||||
id: id,
|
||||
title: plugin.title,
|
||||
author: plugin.author,
|
||||
description: plugin.description,
|
||||
about: plugin.about,
|
||||
icon: plugin.icon,
|
||||
variant: plugin.variant,
|
||||
min_version: plugin.min_version,
|
||||
installed: Plugins.installed.includes(id),
|
||||
expanded: false
|
||||
var plugin = new Plugin(id, Plugins.json[id])
|
||||
if (Plugins.installed.includes(id)) {
|
||||
plugin.download()
|
||||
}
|
||||
if (obj.installed) {
|
||||
if (isApp) {
|
||||
downloadPlugin(id)
|
||||
} else {
|
||||
loadPlugin(id)
|
||||
}
|
||||
}
|
||||
Plugins.data.push(obj)
|
||||
Plugins.data.sort(function(a,b) {
|
||||
return sort_collator.compare(a.title, b.title)
|
||||
});
|
||||
Plugins.all.push(plugin)
|
||||
}
|
||||
} else if (Plugins.installed.length > 0) {
|
||||
//Only show downloaded plugins in the plugin window
|
||||
Plugins.all.sort(function(a,b) {
|
||||
return sort_collator.compare(a.title, b.title)
|
||||
});
|
||||
} else if (Plugins.installed.length > 0 && isApp) {
|
||||
Plugins.installed.forEach(function(id) {
|
||||
loadPlugin(id, function() {
|
||||
//Plugin Data Comes from the plugin file
|
||||
if (plugin_data === undefined) return;
|
||||
var obj = {
|
||||
id: id,
|
||||
title: plugin_data.title,
|
||||
author: plugin_data.author,
|
||||
description: plugin_data.description,
|
||||
about: plugin_data.about,
|
||||
icon: plugin_data.icon,
|
||||
variant: plugin_data.variant,
|
||||
min_version: plugin_data.min_version,
|
||||
installed: true,
|
||||
expanded: false
|
||||
}
|
||||
Plugins.data.push(obj)
|
||||
Plugins.data.sort(function(a,b) {
|
||||
return sort_collator.compare(a.title, b.title)
|
||||
});
|
||||
})
|
||||
|
||||
if (id.substr(-3) !== '.js') {
|
||||
//downloaded public plugin
|
||||
var plugin = new Plugin(id).install(false, () => {
|
||||
if (typeof plugin_data === 'object') {
|
||||
plugin.extend(plugin_data)
|
||||
Plugins.all.push(plugin)
|
||||
Plugins.all.sort(function(a,b) {
|
||||
return sort_collator.compare(a.title, b.title)
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
if (Plugins.installed.length > 0) {
|
||||
Plugins.installed.forEach(function(id) {
|
||||
|
||||
if (id.substr(-3) === '.js') {
|
||||
//Dev Plugins
|
||||
var plugin = new Plugin().loadFromFile({path: id}, true)
|
||||
}
|
||||
})
|
||||
console.log('Loaded '+Plugins.installed.length+' plugin'+pluralS(Plugins.installed.length))
|
||||
}
|
||||
|
||||
|
||||
Plugins.Vue = new Vue({
|
||||
el: '#plugin_list',
|
||||
data: {
|
||||
showAll: false,
|
||||
items: Plugins.data
|
||||
items: Plugins.all
|
||||
},
|
||||
computed: {
|
||||
installedPlugins() {
|
||||
plugin_search() {
|
||||
var name = $('#plugin_search_bar').val().toUpperCase()
|
||||
return this.items.filter(item => {
|
||||
if (this.showAll !== item.installed) {
|
||||
@ -145,196 +283,14 @@ function loadInstalledPlugins() {
|
||||
return false;
|
||||
})
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
install: function(plugin) {
|
||||
if (isApp) {
|
||||
downloadPlugin(plugin.id)
|
||||
} else {
|
||||
loadPlugin(plugin.id)
|
||||
}
|
||||
},
|
||||
uninstall: function(plugin) {
|
||||
uninstallPlugin(plugin.id)
|
||||
},
|
||||
update: function(plugin) {
|
||||
if (isApp) {
|
||||
downloadPlugin(plugin.id)
|
||||
}
|
||||
},
|
||||
checkIfInstallable: function(plugin) {
|
||||
var result =
|
||||
plugin.variant === 'both' ||
|
||||
(
|
||||
isApp === (plugin.variant === 'desktop') &&
|
||||
isApp !== (plugin.variant === 'web')
|
||||
);
|
||||
if (result && plugin.min_version) {
|
||||
result = compareVersions(plugin.min_version, appVersion) ? 'outdated' : true
|
||||
} else if (result === false) {
|
||||
result = (plugin.variant === 'web') ? 'web_only' : 'app_only'
|
||||
}
|
||||
return (result === true) ? true : tl('dialog.plugins.'+result);
|
||||
},
|
||||
toggleInfo: function(plugin, force) {
|
||||
Plugins.data.forEach(function(p) {
|
||||
if (p !== plugin && p.expanded) p.expanded = false;
|
||||
})
|
||||
plugin.expanded = plugin.expanded !== true
|
||||
if (force !== undefined) {
|
||||
plugin.expanded = force === true
|
||||
}
|
||||
if (plugin.expanded) {
|
||||
plugin.expandicon = 'expand_less'
|
||||
} else {
|
||||
plugin.expandicon = 'expand_more'
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
function saveInstalledPlugins() {
|
||||
localStorage.setItem('installed_plugins', JSON.stringify(Plugins.installed))
|
||||
hideDialog()
|
||||
}
|
||||
function loadPlugin(id, cb, install) {
|
||||
if (isApp === true) {
|
||||
$.getScript(Plugins.path + id + '.js', function(a) {
|
||||
if (onUninstall) {
|
||||
Plugins.data.findInArray('id', id).uninstall = onUninstall
|
||||
onUninstall = undefined
|
||||
}
|
||||
if (install && onInstall) {
|
||||
onInstall()
|
||||
}
|
||||
onInstall = undefined
|
||||
if (cb !== undefined) cb()
|
||||
}).fail(function() {
|
||||
console.log('Could not find file of plugin "'+id+'". Uninstalling it instead.')
|
||||
uninstallPlugin(id)
|
||||
saveInstalledPlugins()
|
||||
})
|
||||
} else {
|
||||
$.getScript('https://raw.githubusercontent.com/JannisX11/blockbench-plugins/master/plugins/'+id+'.js', function() {
|
||||
if (onUninstall) {
|
||||
Plugins.data.findInArray('id', id).uninstall = onUninstall
|
||||
onUninstall = undefined
|
||||
}
|
||||
if (install && onInstall) {
|
||||
onInstall()
|
||||
}
|
||||
onInstall = undefined
|
||||
if (cb) cb()
|
||||
})
|
||||
}
|
||||
if (Plugins.installed.includes(id) === false) {
|
||||
Plugins.installed.push(id)
|
||||
}
|
||||
Plugins.data.findInArray('id', id).installed = true
|
||||
}
|
||||
function loadPluginFromFile(file, hideWarning) {
|
||||
var hideWarning;
|
||||
var content = file.content
|
||||
var path = file.path
|
||||
localStorage.setItem('plugin_dev_path', path)
|
||||
onInstall = undefined
|
||||
|
||||
if (!hideWarning) {
|
||||
if (isApp) {
|
||||
if (!confirm(tl('message.load_plugin_app'))) return;
|
||||
} else {
|
||||
if (!confirm(tl('message.load_plugin_web'))) return;
|
||||
}
|
||||
}
|
||||
try {
|
||||
eval(content)
|
||||
} catch (err) {
|
||||
Blockbench.showQuickMessage('message.invalid_plugin')
|
||||
console.error(err)
|
||||
return;
|
||||
}
|
||||
var obj = {
|
||||
author: 'unknown',
|
||||
icon: 'extension',
|
||||
installed: true,
|
||||
id: 'test',
|
||||
title: 'Plugin',
|
||||
variant: 'both',
|
||||
description: '',
|
||||
about: '',
|
||||
fromFile: true,
|
||||
filePath: path,
|
||||
expanded: false,
|
||||
uninstall: function() {
|
||||
var index = Plugins.data.indexOf(this)
|
||||
if (index >= 0) Plugins.data.splice(index, 1)
|
||||
if (this.uninstallMethod) {
|
||||
this.uninstallMethod()
|
||||
}
|
||||
},
|
||||
reload: function() {
|
||||
if (isApp) {
|
||||
obj.uninstall()
|
||||
fs.readFile(path, 'utf-8', function (err, data) {
|
||||
if (err) {
|
||||
console.log(err)
|
||||
return;
|
||||
}
|
||||
loadPluginFromFile({
|
||||
content: data,
|
||||
path: path
|
||||
}, true)
|
||||
})
|
||||
}
|
||||
},
|
||||
uninstallMethod: false
|
||||
}
|
||||
$.extend(true, obj, plugin_data)
|
||||
obj.uninstallMethod = onUninstall
|
||||
onUninstall = undefined
|
||||
if (onInstall) onInstall()
|
||||
onInstall = undefined
|
||||
Plugins.data.push(obj)
|
||||
Plugins.data.sort(function(a,b) {
|
||||
return sort_collator.compare(a.title, b.title)
|
||||
});
|
||||
}
|
||||
function downloadPlugin(id, is_install) {
|
||||
//$('.uc_btn').attr('disabled', true)
|
||||
|
||||
var file = originalFs.createWriteStream(Plugins.path+id+'.js')
|
||||
var request = https.get('https://raw.githubusercontent.com/JannisX11/blockbench-plugins/master/plugins/'+id+'.js', function(response) {
|
||||
response.pipe(file);
|
||||
response.on('end', function() {
|
||||
setTimeout(function() {
|
||||
loadPlugin(id, undefined, is_install)
|
||||
}, 100)
|
||||
})
|
||||
});
|
||||
}
|
||||
function uninstallPlugin(id) {
|
||||
if (isApp) {
|
||||
var filepath = Plugins.path + id + '.js'
|
||||
if (fs.existsSync(filepath)) {
|
||||
fs.unlink(filepath, (err) => {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
return;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
//File does not exist
|
||||
}
|
||||
}
|
||||
var index = Plugins.installed.indexOf(id)
|
||||
if (index > -1) {
|
||||
Plugins.installed.splice(index, 1)
|
||||
}
|
||||
var data_obj = Plugins.data.findInArray('id', id)
|
||||
data_obj.installed = false
|
||||
if (data_obj.uninstall) {
|
||||
data_obj.uninstall()
|
||||
}
|
||||
function loadPluginFromFile(file) {
|
||||
var plugin = new Plugin().loadFromFile(file, false)
|
||||
}
|
||||
function switchPluginTabs(installed) {
|
||||
$('#plugins .tab').removeClass('open')
|
||||
@ -357,13 +313,22 @@ BARS.defineActions(function() {
|
||||
$('#plugin_list').css('max-height', limitNumber($(window).height()-300, 80, 600)+'px')
|
||||
}
|
||||
})
|
||||
new Action({
|
||||
id: 'reload_plugins',
|
||||
icon: 'sync',
|
||||
category: 'blockbench',
|
||||
keybind: new Keybind({ctrl: true, key: 74}),
|
||||
click: function () {
|
||||
Plugins.devReload()
|
||||
}
|
||||
})
|
||||
new Action({
|
||||
id: 'load_plugin',
|
||||
icon: 'fa-file-code-o',
|
||||
category: 'blockbench',
|
||||
click: function () {
|
||||
Blockbench.import({
|
||||
extensions: ['bbplugin', 'js'],
|
||||
extensions: ['js'],
|
||||
type: 'Blockbench Plugin',
|
||||
startpath: localStorage.getItem('plugin_dev_path')
|
||||
}, function(files) {
|
||||
|
150
js/preview.js
150
js/preview.js
@ -35,7 +35,6 @@ class Preview {
|
||||
this.camOrtho = new THREE.OrthographicCamera(-600, 600, -400, 400, 1, 100)
|
||||
this.camOrtho.backgroundHandle = [{n: false, a: 'x'}, {n: false, a: 'y'}]
|
||||
this.camOrtho.axis = null
|
||||
this.camPers.position.set(-20, 20, -20)
|
||||
this.camPers.preview = this.camOrtho.preview = this;
|
||||
|
||||
//Controls
|
||||
@ -46,6 +45,8 @@ class Preview {
|
||||
this.controls.enableKeys = false;
|
||||
this.controls.zoomSpeed = 1.5
|
||||
|
||||
this.resetCamera(true)
|
||||
|
||||
//Keybinds
|
||||
this.controls.mouseButtons.ZOOM = undefined;
|
||||
|
||||
@ -255,10 +256,13 @@ class Preview {
|
||||
this.controls.updateSceneScale();
|
||||
return this;
|
||||
}
|
||||
resetCamera() {
|
||||
resetCamera(init) {
|
||||
var dis = 24
|
||||
this.controls.target.set(0, -3, 0);
|
||||
this.camPers.position.set(-20, 20, -20)
|
||||
this.setNormalCamera()
|
||||
this.camPers.position.set(-dis, dis*0.8, -dis)
|
||||
if (!init) {
|
||||
this.setNormalCamera()
|
||||
}
|
||||
return this;
|
||||
}
|
||||
getFacingDirection() {
|
||||
@ -303,7 +307,7 @@ class Preview {
|
||||
this.static_rclick = false
|
||||
if (Toolbox.selected.selectCubes && Modes.selected.selectCubes && data.type === 'cube') {
|
||||
if (Toolbox.selected.selectFace) {
|
||||
main_uv.setFace(data.face)
|
||||
main_uv.setFace(data.face, false)
|
||||
}
|
||||
Blockbench.dispatchEvent( 'canvas_select', data )
|
||||
if (Animator.open || (Toolbox.selected.id === 'rotate_tool' && Blockbench.entity_mode)) {
|
||||
@ -441,10 +445,10 @@ class Preview {
|
||||
)
|
||||
selected.length = 0;
|
||||
elements.forEach(function(cube) {
|
||||
|
||||
|
||||
if ((event.shiftKey || event.ctrlKey) && scope.selection.old_selected.indexOf(cube) >= 0) {
|
||||
var isSelected = true
|
||||
} else {
|
||||
} else if (cube.visibility) {
|
||||
var mesh = cube.mesh
|
||||
var from = new THREE.Vector3().copy(mesh.geometry.vertices[6]).applyMatrix4(mesh.matrixWorld)
|
||||
var to = new THREE.Vector3().copy(mesh.geometry.vertices[0]).applyMatrix4(mesh.matrixWorld)
|
||||
@ -711,6 +715,7 @@ class Preview {
|
||||
}
|
||||
return [
|
||||
{icon: getBtn(0, true), name: 'menu.preview.perspective.normal', click: function(preview) {preview.setNormalCamera()}},
|
||||
'camera_reset',
|
||||
{icon: getBtn(0), name: 'direction.top', color: 'y', click: function(preview) {preview.setOrthographicCamera(0)}},
|
||||
{icon: getBtn(1), name: 'direction.bottom', color: 'y', click: function(preview) {preview.setOrthographicCamera(1)}},
|
||||
{icon: getBtn(2), name: 'direction.south', color: 'z', click: function(preview) {preview.setOrthographicCamera(2)}},
|
||||
@ -847,30 +852,42 @@ function initCanvas() {
|
||||
Sun = new THREE.AmbientLight( 0xffffff );
|
||||
Sun.name = 'sun'
|
||||
scene.add(Sun);
|
||||
Sun.intensity = 0.44
|
||||
|
||||
lights = new THREE.Object3D()
|
||||
lights.name = 'lights'
|
||||
|
||||
var light_top = new THREE.DirectionalLight( 0x777777 );
|
||||
var light_top = new THREE.DirectionalLight( /*0x777777*/ );
|
||||
light_top.name = 'light_top'
|
||||
light_top.position.set(8, 100, 8)
|
||||
lights.add(light_top);
|
||||
|
||||
light_top.intensity = 0.66
|
||||
|
||||
var light_west = new THREE.DirectionalLight( 0x222222 );
|
||||
light_west.position.set(-100, 8, 8)
|
||||
lights.add(light_west);
|
||||
|
||||
var light_east = new THREE.DirectionalLight( 0x222222 );
|
||||
light_east.position.set(100, 8, 8)
|
||||
lights.add(light_east);
|
||||
|
||||
var light_north = new THREE.DirectionalLight( 0x444444 );
|
||||
var light_north = new THREE.DirectionalLight( /*0x444444*/ );
|
||||
light_north.name = 'light_north'
|
||||
light_north.position.set(8, 8, -100)
|
||||
lights.add(light_north);
|
||||
|
||||
var light_south = new THREE.DirectionalLight( 0x444444 );
|
||||
var light_south = new THREE.DirectionalLight( /*0x444444*/ );
|
||||
light_south.name = 'light_south'
|
||||
light_south.position.set(8, 8, 100)
|
||||
lights.add(light_south);
|
||||
|
||||
light_north.intensity = light_south.intensity = 0.44
|
||||
|
||||
var light_west = new THREE.DirectionalLight( /*0x222222*/ );
|
||||
light_west.name = 'light_west'
|
||||
light_west.position.set(-100, 8, 8)
|
||||
lights.add(light_west);
|
||||
|
||||
var light_east = new THREE.DirectionalLight( /*0x222222*/ );
|
||||
light_east.name = 'light_east'
|
||||
light_east.position.set(100, 8, 8)
|
||||
lights.add(light_east);
|
||||
|
||||
light_west.intensity = light_east.intensity = 0.22
|
||||
|
||||
setShading()
|
||||
|
||||
quad_previews = {
|
||||
@ -951,14 +968,11 @@ function animate() {
|
||||
function setShading() {
|
||||
scene.remove(lights)
|
||||
display_scene.remove(lights)
|
||||
Sun.intensity = 1
|
||||
Sun.intensity = settings.brightness.value/100;
|
||||
if (settings.shading.value === true) {
|
||||
Sun.intensity = 0.65
|
||||
if (display_mode) {
|
||||
display_scene.add(lights)
|
||||
} else {
|
||||
scene.add(lights)
|
||||
}
|
||||
(display_mode ? display_scene : scene).add(lights)
|
||||
} else {
|
||||
Sun.intensity *= (1/0.6)
|
||||
}
|
||||
}
|
||||
//Helpers
|
||||
@ -1089,13 +1103,6 @@ function centerTransformer(offset) {
|
||||
Transformer.position.z += 8;
|
||||
Transformer.rotation.set(0, 0, 0)
|
||||
Transformer.update()
|
||||
|
||||
//if (!rotate_tool) {
|
||||
// var quat = new THREE.Quaternion()
|
||||
// g_mesh.getWorldQuaternion(quat)
|
||||
// Transformer.rotation.setFromQuaternion(quat, 'ZYX')
|
||||
//} else {
|
||||
//}
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1104,57 +1111,18 @@ function centerTransformer(offset) {
|
||||
Canvas.updateAllBones()
|
||||
}
|
||||
if (!rotate_tool) {
|
||||
var first_obj
|
||||
var center = [0, 0, 0]
|
||||
var i = 0;
|
||||
selected.forEach(function(obj) {
|
||||
var m = obj.mesh
|
||||
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
|
||||
}
|
||||
var first_obj;
|
||||
var center = getSelectionCenter()
|
||||
for (var i = 0; i < selected.length && !first_obj; i++) {
|
||||
if (selected[i].visibility) {
|
||||
first_obj = selected[i];
|
||||
}
|
||||
})
|
||||
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
|
||||
}
|
||||
if (!first_obj || !first_obj.visibility) return;
|
||||
var vec = new THREE.Vector3(center[0], center[1], center[2])
|
||||
|
||||
//Position + Rotation
|
||||
@ -1357,7 +1325,7 @@ class CanvasController {
|
||||
if (texture) {
|
||||
used = false;
|
||||
for (var face in obj.faces) {
|
||||
if (obj.faces[face] && obj.faces[face].texture === '#'+texture.id) {
|
||||
if (obj.faces[face].texture === texture.uuid) {
|
||||
used = true;
|
||||
}
|
||||
}
|
||||
@ -1420,9 +1388,7 @@ class CanvasController {
|
||||
}
|
||||
}
|
||||
arr.forEach(function(obj) {
|
||||
if (obj.visibility == true) {
|
||||
Canvas.adaptObjectPosition(obj)
|
||||
}
|
||||
Canvas.adaptObjectPosition(obj)
|
||||
})
|
||||
if (leave_selection !== true) {
|
||||
updateSelection()
|
||||
@ -1608,22 +1574,22 @@ class CanvasController {
|
||||
}
|
||||
iterate(el, elmesh)
|
||||
}
|
||||
adaptObjectFaces(obj, mesh) {
|
||||
if (!mesh) mesh = obj.mesh
|
||||
adaptObjectFaces(cube, mesh) {
|
||||
if (!mesh) mesh = cube.mesh
|
||||
if (!mesh) return;
|
||||
if (!Prop.wireframe) {
|
||||
var materials = []
|
||||
this.face_order.forEach(function(face) {
|
||||
|
||||
if (obj.faces[face].texture === null) {
|
||||
if (cube.faces[face].texture === null) {
|
||||
materials.push(Canvas.transparentMaterial)
|
||||
|
||||
} else {
|
||||
var tex = getTextureById(obj.faces[face].texture)
|
||||
if (typeof tex === 'object') {
|
||||
var tex = cube.faces[face].getTexture()
|
||||
if (tex && tex.uuid) {
|
||||
materials.push(Canvas.materials[tex.uuid])
|
||||
} else {
|
||||
materials.push(emptyMaterials[obj.color])
|
||||
materials.push(emptyMaterials[cube.color])
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -1717,7 +1683,7 @@ class CanvasController {
|
||||
stretch = 1
|
||||
frame = 0
|
||||
if (obj[face].texture && obj[face].texture !== null) {
|
||||
var tex = getTextureById(obj[face].texture)
|
||||
var tex = obj[face].getTexture()
|
||||
if (typeof tex === 'object' && tex.constructor.name === 'Texture' && tex.frameCount) {
|
||||
stretch = tex.frameCount
|
||||
if (animation === true && tex.currentFrame) {
|
||||
@ -1830,6 +1796,9 @@ BARS.defineActions(function() {
|
||||
click: function () {
|
||||
Prop.wireframe = !Prop.wireframe
|
||||
Canvas.updateAll()
|
||||
if (Modes.id === 'animate') {
|
||||
Animator.preview()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@ -1888,6 +1857,7 @@ BARS.defineActions(function() {
|
||||
id: 'toggle_quad_view',
|
||||
icon: 'widgets',
|
||||
category: 'view',
|
||||
condition: () => (Modes.id === 'edit' || Modes.id === 'paint'),
|
||||
keybind: new Keybind({key: 9}),
|
||||
click: function () {
|
||||
main_preview.toggleFullscreen()
|
||||
@ -1895,8 +1865,8 @@ BARS.defineActions(function() {
|
||||
})
|
||||
new Action({
|
||||
id: 'camera_reset',
|
||||
name: 'direction.top',
|
||||
description: 'direction.top',
|
||||
name: 'menu.preview.perspective.reset',
|
||||
description: 'menu.preview.perspective.reset',
|
||||
icon: 'videocam',
|
||||
category: 'view',
|
||||
keybind: new Keybind({key: 96}),
|
||||
|
@ -16,6 +16,7 @@ function settingSetup() {
|
||||
//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},
|
||||
brightness: {category: 'preview', value: 50, type: 'number'},
|
||||
shading: {category: 'preview', value: true},
|
||||
transparency: {category: 'preview', value: true},
|
||||
texture_fps: {category: 'preview', value: 2, type: 'number'},
|
||||
@ -242,7 +243,7 @@ function saveSettings(force_update) {
|
||||
}
|
||||
}
|
||||
Canvas.outlineMaterial.depthTest = !settings.seethrough_outline.value
|
||||
if (hasSettingChanged('shading')) {
|
||||
if (hasSettingChanged('shading') || hasSettingChanged('brightness')) {
|
||||
setShading()
|
||||
}
|
||||
if (hasSettingChanged('texture_fps')) {
|
||||
@ -265,7 +266,10 @@ function saveProjectSettings() {
|
||||
if (uv_dialog.editors) {
|
||||
uv_dialog.editors.single.setGrid()
|
||||
}
|
||||
entityMode.setResolution()
|
||||
if (entityMode.old_res.x !== Project.texture_width || entityMode.old_res.y !== Project.texture_height) {
|
||||
entityMode.setResolution()
|
||||
Undo.finishEdit('changed resolution')
|
||||
}
|
||||
}
|
||||
hideDialog()
|
||||
}
|
||||
@ -279,3 +283,41 @@ function toggleSetting(setting) {
|
||||
}
|
||||
function toggleWireframe() {
|
||||
}
|
||||
|
||||
onVueSetup(function() {
|
||||
var structure = {}
|
||||
for (var key in settings) {
|
||||
var category = settings[key].category
|
||||
if (!category) category = 'general'
|
||||
|
||||
if (!structure[category]) {
|
||||
structure[category] = {
|
||||
name: tl('settings.category.'+category),
|
||||
open: category === 'general',
|
||||
items: {}
|
||||
}
|
||||
}
|
||||
structure[category].items[key] = settings[key]
|
||||
}
|
||||
var settingslist = new Vue({
|
||||
el: 'ul#settingslist',
|
||||
data: {structure},
|
||||
methods: {
|
||||
saveSettings: function() {
|
||||
localStorage.setItem('settings', JSON.stringify(settings))
|
||||
},
|
||||
toggleCategory: function(category) {
|
||||
if (!category.open) {
|
||||
for (var ct in structure) {
|
||||
structure[ct].open = false
|
||||
}
|
||||
}
|
||||
category.open = !category.open
|
||||
}
|
||||
}
|
||||
})
|
||||
var project_vue = new Vue({
|
||||
el: '#project_settings',
|
||||
data: {Project}
|
||||
})
|
||||
})
|
@ -478,7 +478,7 @@ class Texture {
|
||||
var sides = ['north', 'east', 'south', 'west', 'up', 'down']
|
||||
elements.forEach(function(s) {
|
||||
sides.forEach(function(side) {
|
||||
s.faces[side].texture = '#'+scope.id
|
||||
s.faces[side].texture = scope.uuid
|
||||
})
|
||||
})
|
||||
Canvas.updateAllFaces()
|
||||
@ -537,15 +537,16 @@ class Texture {
|
||||
if (selected.length === 0) return;
|
||||
var scope = this;
|
||||
Undo.initEdit({cubes: selected})
|
||||
if (all || Blockbench.entity_mode) {
|
||||
var sides = ['north', 'east', 'south', 'west', 'up', 'down']
|
||||
} else {
|
||||
var sides = [main_uv.face]
|
||||
}
|
||||
|
||||
selected.forEach(function(obj) {
|
||||
sides.forEach(function(side) {
|
||||
obj.faces[side].texture = '#'+scope.id
|
||||
})
|
||||
for (var face in obj.faces) {
|
||||
if (all || Blockbench.entity_mode || face === main_uv.face) {
|
||||
var f = obj.faces[face]
|
||||
if (all !== 'blank' || (f.texture !== null && !f.getTexture())) {
|
||||
f.texture = scope.uuid
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
Canvas.updateSelectedFaces()
|
||||
main_uv.loadData()
|
||||
@ -713,6 +714,12 @@ class Texture {
|
||||
condition: function() {return !Blockbench.entity_mode && selected.length > 0},
|
||||
click: function(texture) {texture.apply()}
|
||||
},
|
||||
{
|
||||
icon: 'texture',
|
||||
name: 'menu.texture.blank',
|
||||
condition: function() {return !Blockbench.entity_mode && selected.length > 0},
|
||||
click: function(texture) {texture.apply('blank')}
|
||||
},
|
||||
{
|
||||
icon: 'fa-cube',
|
||||
name: 'menu.texture.cube',
|
||||
@ -876,7 +883,7 @@ function loadTextureDraggable() {
|
||||
if ($('canvas.preview:hover').length > 0) {
|
||||
var data = Canvas.getCurrentPreview().raycast()
|
||||
if (data.cube && data.face) {
|
||||
var tex = getTextureById(ui.helper.attr('texid'))
|
||||
var tex = textures.findInArray('uuid', ui.helper.attr('texid'));
|
||||
if (tex) {
|
||||
data.cube.applyTexture(tex, [data.face])
|
||||
}
|
||||
@ -928,7 +935,7 @@ function changeTexturesFolder() {
|
||||
|
||||
}
|
||||
function getTextureById(id) {
|
||||
if (id === undefined) return;
|
||||
if (id === undefined || id === false) return;
|
||||
if (id == null) {
|
||||
return {material: transparentMaterial};
|
||||
}
|
||||
@ -937,10 +944,18 @@ function getTextureById(id) {
|
||||
}
|
||||
function getTexturesById(id) {
|
||||
if (id === undefined) return;
|
||||
id = id.split('#').join('');
|
||||
id = id.replace('#', '');
|
||||
return $.grep(textures, function(e) {return e.id == id});
|
||||
}
|
||||
|
||||
onVueSetup(function() {
|
||||
texturelist = new Vue({
|
||||
el: '#texture_list',
|
||||
data: {textures}
|
||||
})
|
||||
texturelist._data.elements = textures
|
||||
})
|
||||
|
||||
BARS.defineActions(function() {
|
||||
new Action({
|
||||
id: 'import_texture',
|
||||
|
127
js/transform.js
127
js/transform.js
@ -1,71 +1,52 @@
|
||||
//Actions
|
||||
function origin2geometry() {
|
||||
Undo.initEdit({cubes: selected})
|
||||
|
||||
if (Blockbench.entity_mode) {
|
||||
Undo.initEdit({group: selected_group})
|
||||
|
||||
if (!selected_group || selected_group.children.length === 0) return;
|
||||
var position = [0, 0, 0]
|
||||
selected_group.children.forEach(function(obj) {
|
||||
position[0] += obj.from[0] + obj.size(0)/2
|
||||
position[1] += obj.from[1] + obj.size(1)/2
|
||||
position[2] += obj.from[2] + obj.size(2)/2
|
||||
if (obj.type === 'cube') {
|
||||
position[0] += obj.from[0] + obj.size(0)/2
|
||||
position[1] += obj.from[1] + obj.size(1)/2
|
||||
position[2] += obj.from[2] + obj.size(2)/2
|
||||
}
|
||||
})
|
||||
position.forEach(function(p, pi) {
|
||||
position[pi] = p / selected_group.children.length
|
||||
})
|
||||
selected_group.origin = position
|
||||
|
||||
} else if (selected.length > 1) {
|
||||
|
||||
var center = [0, 0, 0]
|
||||
var i = 0;
|
||||
selected.forEach(function(obj) {
|
||||
i = 0;
|
||||
while (i < 3) {
|
||||
center[i] += obj.from[i]
|
||||
center[i] += obj.to[i]
|
||||
i++;
|
||||
}
|
||||
})
|
||||
i = 0;
|
||||
while (i < 3) {
|
||||
center[i] = center[i] / (selected.length * 2)
|
||||
i++;
|
||||
}
|
||||
selected.forEach(function(obj) {
|
||||
obj.origin = center.slice()
|
||||
})
|
||||
|
||||
} else {
|
||||
Undo.initEdit({cubes: selected})
|
||||
|
||||
var obj = selected[0]
|
||||
var element_size = obj.size()
|
||||
var element_center = new THREE.Vector3(
|
||||
(element_size[0] / 2) + obj.from[0],
|
||||
(element_size[1] / 2) + obj.from[1],
|
||||
(element_size[2] / 2) + obj.from[2]
|
||||
)
|
||||
|
||||
element_center.x -= obj.origin[0]
|
||||
element_center.y -= obj.origin[1]
|
||||
element_center.z -= obj.origin[2]
|
||||
|
||||
if (obj.mesh) {
|
||||
element_center.applyEuler(obj.mesh.rotation)
|
||||
}
|
||||
obj.origin[0] += element_center.x
|
||||
obj.origin[1] += element_center.y
|
||||
obj.origin[2] += element_center.z
|
||||
|
||||
obj.to[0] = obj.origin[0] + element_size[0] / 2
|
||||
obj.to[1] = obj.origin[1] + element_size[1] / 2
|
||||
obj.to[2] = obj.origin[2] + element_size[2] / 2
|
||||
|
||||
obj.from[0] = obj.origin[0] - element_size[0] / 2
|
||||
obj.from[1] = obj.origin[1] - element_size[1] / 2
|
||||
obj.from[2] = obj.origin[2] - element_size[2] / 2
|
||||
var center = getSelectionCenter()
|
||||
|
||||
selected.forEach(cube => {
|
||||
cube.transferOrigin(center)
|
||||
})
|
||||
}
|
||||
Canvas.updatePositions()
|
||||
Undo.finishEdit('origin2geometry')
|
||||
Undo.finishEdit('origin to geometry')
|
||||
}
|
||||
function getSelectionCenter() {
|
||||
var center = [0, 0, 0]
|
||||
var i = 0;
|
||||
selected.forEach(cube => {
|
||||
var m = cube.mesh
|
||||
if (cube.visibility && m) {
|
||||
|
||||
var pos = cube.getWorldCenter()
|
||||
center[0] += pos.x
|
||||
center[1] += pos.y
|
||||
center[2] += pos.z
|
||||
}
|
||||
})
|
||||
for (var i = 0; i < 3; i++) {
|
||||
center[i] = center[i] / selected.length
|
||||
}
|
||||
return center;
|
||||
}
|
||||
function isMovementGlobal() {
|
||||
if (selected.length === 0 || (!settings.local_move.value && Toolbox.selected.id !== 'resize_tool')) {
|
||||
@ -356,8 +337,10 @@ function scaleAll(save, size) {
|
||||
}
|
||||
if (clip && Blockbench.entity_mode === false) {
|
||||
$('#scaling_clipping_warning').text('Model clipping: Your model is too large for the canvas')
|
||||
$('#scale_overflow_btn').css('display', 'inline-block')
|
||||
} else {
|
||||
$('#scaling_clipping_warning').text('')
|
||||
$('#scale_overflow_btn').hide()
|
||||
}
|
||||
Canvas.updatePositions()
|
||||
if (save === true) {
|
||||
@ -393,6 +376,26 @@ function cancelScaleAll() {
|
||||
Canvas.updatePositions()
|
||||
hideDialog()
|
||||
}
|
||||
function scaleAllSelectOverflow() {
|
||||
var overflow = [];
|
||||
selected.forEach(function(obj) {
|
||||
var clip = false
|
||||
obj.from.forEach(function(ogn, i) {
|
||||
|
||||
if (obj.from[i] > 32 || obj.from[i] < -16) clip = true
|
||||
if (obj.to[i] > 32 || obj.to[i] < -16) clip = true
|
||||
})
|
||||
if (clip) {
|
||||
overflow.push(obj)
|
||||
}
|
||||
})
|
||||
cancelScaleAll()
|
||||
selected.length = 0;
|
||||
overflow.forEach(cube => {
|
||||
selected.push(cube)
|
||||
})
|
||||
updateSelection();
|
||||
}
|
||||
//Center
|
||||
function centerCubesAll(axis) {
|
||||
centerCubes(0, false)
|
||||
@ -474,19 +477,24 @@ function rotateOnAxis(value, fixed, axis) {
|
||||
var axis_letter = getAxisLetter(axis)
|
||||
var origin = selected[0].origin
|
||||
selected.forEach(function(obj, i) {
|
||||
if (!obj.rotation.equals([0,0,0])) {
|
||||
if (!obj.rotation.allEqual(0)) {
|
||||
origin = obj.origin
|
||||
}
|
||||
})
|
||||
if (origin.allEqual(8)) {
|
||||
origin = getSelectionCenter()
|
||||
origin.forEach((n, ni) => {
|
||||
origin[ni] = Math.round(n*2)/2
|
||||
})
|
||||
}
|
||||
selected.forEach(function(obj, i) {
|
||||
if (obj.rotation.equals([0,0,0])) {
|
||||
if (obj.rotation.allEqual(0)) {
|
||||
obj.origin = origin.slice()
|
||||
}
|
||||
var obj_val = value;
|
||||
if (!fixed) {
|
||||
obj_val += obj.rotation[axis]
|
||||
}
|
||||
|
||||
obj_val = Math.trimDeg(obj_val)
|
||||
if (settings.limited_rotation.value) {
|
||||
//Limit To 1 Axis
|
||||
@ -813,6 +821,7 @@ BARS.defineActions(function() {
|
||||
}, 'group', true)
|
||||
}
|
||||
showDialog('scaling')
|
||||
scaleAll(false, 1)
|
||||
}
|
||||
})
|
||||
new Action({
|
||||
@ -964,6 +973,14 @@ BARS.defineActions(function() {
|
||||
id: 'toggle_shade',
|
||||
icon: 'wb_sunny',
|
||||
category: 'transform',
|
||||
condition: () => !Blockbench.entity_mode,
|
||||
click: function () {toggleCubeProperty('shade')}
|
||||
})
|
||||
new Action({
|
||||
id: 'toggle_mirror_uv',
|
||||
icon: 'icon-mirror_x',
|
||||
category: 'transform',
|
||||
condition: () => Blockbench.entity_mode,
|
||||
click: function () {toggleCubeProperty('shade')}
|
||||
})
|
||||
new Action({
|
||||
|
10
js/undo.js
10
js/undo.js
@ -12,8 +12,10 @@ var Undo = {
|
||||
Undo.current_save = new Undo.save(aspects)
|
||||
},
|
||||
finishEdit: function(action, aspects) {
|
||||
if (!Undo.current_save) return;
|
||||
aspects = aspects || Undo.current_save.aspects
|
||||
//After
|
||||
Blockbench.dispatchEvent('finish_edit', {aspects})
|
||||
var entry = {
|
||||
before: Undo.current_save,
|
||||
post: new Undo.save(aspects),
|
||||
@ -34,6 +36,7 @@ var Undo = {
|
||||
if (!aspects || !aspects.keep_saved) {
|
||||
Prop.project_saved = false;
|
||||
}
|
||||
Blockbench.dispatchEvent('finished_edit', {aspects})
|
||||
},
|
||||
cancelEdit: function() {
|
||||
if (!Undo.current_save) return;
|
||||
@ -50,7 +53,7 @@ var Undo = {
|
||||
var entry = Undo.history[Undo.index]
|
||||
Undo.loadSave(entry.before, entry.post)
|
||||
console.log('Undo: '+entry.action)
|
||||
Blockbench.dispatchEvent('undo', {entry: entry})
|
||||
Blockbench.dispatchEvent('undo', {entry})
|
||||
},
|
||||
redo: function() {
|
||||
if (Undo.history.length <= 0) return;
|
||||
@ -63,7 +66,7 @@ var Undo = {
|
||||
var entry = Undo.history[Undo.index-1]
|
||||
Undo.loadSave(entry.post, entry.before)
|
||||
console.log('Redo: '+entry.action)
|
||||
Blockbench.dispatchEvent('redo', {})
|
||||
Blockbench.dispatchEvent('redo', {entry})
|
||||
},
|
||||
getItemByUUID: function(list, uuid) {
|
||||
if (!list || typeof list !== 'object' || !list.length) {return false;}
|
||||
@ -75,7 +78,6 @@ var Undo = {
|
||||
i++;
|
||||
}
|
||||
return false;
|
||||
|
||||
},
|
||||
save: function(aspects) {
|
||||
var scope = this;
|
||||
@ -168,7 +170,7 @@ var Undo = {
|
||||
var obj = elements.findInArray('uuid', uuid)
|
||||
if (obj) {
|
||||
for (var face in obj.faces) {
|
||||
obj.faces[face] = {uv: []}
|
||||
obj.faces[face].reset()
|
||||
}
|
||||
obj.extend(data)
|
||||
Canvas.adaptObjectPosition(obj)
|
||||
|
27
js/util.js
27
js/util.js
@ -60,6 +60,17 @@ const Condition = function(condition, context) {
|
||||
return !!condition
|
||||
}
|
||||
}
|
||||
class oneLiner {
|
||||
constructor(data) {
|
||||
if (data !== undefined) {
|
||||
for (var key in data) {
|
||||
if (data.hasOwnProperty(key)) {
|
||||
this[key] = data[key]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var cl = console.log
|
||||
var asyncLoop = function(o){
|
||||
var i=-1;
|
||||
@ -81,6 +92,20 @@ function guid() {
|
||||
return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
|
||||
s4() + '-' + s4() + s4() + s4();
|
||||
}
|
||||
function bbuid(l) {
|
||||
l = l || 1
|
||||
let chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
||||
var s = '';
|
||||
while (l > 0) {
|
||||
var n = Math.floor(Math.random()*62)
|
||||
if (n > 9) {
|
||||
n = chars[n-10]
|
||||
}
|
||||
s += n
|
||||
l--;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
Math.radToDeg = function(rad) {
|
||||
return rad / Math.PI * 180
|
||||
}
|
||||
@ -125,6 +150,7 @@ function limitNumber(number, min, max) {
|
||||
if (number < min || isNaN(number)) number = min;
|
||||
return number;
|
||||
}
|
||||
Math.clamp = limitNumber;
|
||||
function getRectangle(a, b, c, d) {
|
||||
var rect = {};
|
||||
if (!b && typeof a === 'object') {
|
||||
@ -203,6 +229,7 @@ Array.prototype.remove = function (item) { {
|
||||
}
|
||||
Array.prototype.empty = function() {
|
||||
this.length = 0;
|
||||
return this;
|
||||
}
|
||||
Array.prototype.findInArray = function(key, value) {
|
||||
for (var i = 0; i < this.length; i++) {
|
||||
|
294
js/uv.js
294
js/uv.js
@ -115,7 +115,10 @@ class UVEditor {
|
||||
Undo.initEdit({cubes: selected})
|
||||
}
|
||||
var onAfter = function() {
|
||||
Undo.finishEdit('dones')
|
||||
Undo.finishEdit('edit UV')
|
||||
if (Blockbench.entity_mode) {
|
||||
scope.displayAllMappingOverlays()
|
||||
}
|
||||
}
|
||||
var getInterval = function(event) {
|
||||
return Blockbench.entity_mode
|
||||
@ -226,16 +229,6 @@ class UVEditor {
|
||||
$(this).find('.uv_mapping_overlay').remove()
|
||||
})
|
||||
|
||||
this.jquery.main.on('mousewheel', function() {
|
||||
if (Blockbench.entity_mode) {
|
||||
scope.displayMappingOverlay()
|
||||
scope.jquery.main.on('mousemove', function() {
|
||||
$(scope.jquery.size).find('.uv_mapping_overlay').remove()
|
||||
scope.jquery.main.off('mousemove')
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
if (toolbar) {
|
||||
this.jquery.bar = $(Toolbars.main_uv.node)
|
||||
this.jquery.main.append(this.jquery.bar)
|
||||
@ -289,6 +282,9 @@ class UVEditor {
|
||||
Undo.finishEdit('uv_change')
|
||||
scope.disableAutoUV()
|
||||
scope.updateDragHandle(ui.position)
|
||||
if (Blockbench.entity_mode) {
|
||||
scope.displayAllMappingOverlays()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@ -309,13 +305,25 @@ class UVEditor {
|
||||
})
|
||||
|
||||
this.jquery.frame.mousedown(function(event) {
|
||||
if (Toolbox.selected.id === 'brush_tool') {
|
||||
if (Toolbox.selected.paintTool) {
|
||||
scope.startBrush(event)
|
||||
}
|
||||
})
|
||||
this.setSize(this.size)
|
||||
return this;
|
||||
}
|
||||
message(msg, vars) {
|
||||
msg = tl(msg, vars)
|
||||
var box = $('<div class="uv_message_box">' + msg + '</div>')
|
||||
this.jquery.frame.append(box)
|
||||
setTimeout(function() {
|
||||
box.fadeOut(200)
|
||||
setTimeout(function() {
|
||||
box.remove()
|
||||
}, 300)
|
||||
}, 1000)
|
||||
}
|
||||
//Brush
|
||||
getBrushCoordinates(event, tex) {
|
||||
var scope = this;
|
||||
var multiplier = (Blockbench.entity_mode && tex) ? tex.res/Project.texture_width : 1
|
||||
@ -332,11 +340,10 @@ class UVEditor {
|
||||
var texture = scope.getTexture()
|
||||
if (texture) {
|
||||
Painter.current.x = Painter.current.y = 0
|
||||
var x = scope.getBrushCoordinates(event, texture).x
|
||||
var y = scope.getBrushCoordinates(event, texture).y
|
||||
Painter.startBrush(texture, x, y, undefined, event)
|
||||
var coords = scope.getBrushCoordinates(event, texture)
|
||||
Painter.startBrush(texture, coords.x, coords.y, undefined, event)
|
||||
}
|
||||
if (event.altKey === false && texture && texture.mode !== 'link') {
|
||||
if (Toolbox.selected.id !== 'color_picker' && texture) {
|
||||
scope.jquery.frame.get(0).addEventListener('mousemove', scope.moveBrush, false );
|
||||
document.addEventListener('mouseup', scope.stopBrush, false );
|
||||
}
|
||||
@ -386,17 +393,6 @@ class UVEditor {
|
||||
document.removeEventListener( 'mouseup', scope.stopBrush, false );
|
||||
Painter.stopBrush()
|
||||
}
|
||||
message(msg, vars) {
|
||||
msg = tl(msg, vars)
|
||||
var box = $('<div class="uv_message_box">' + msg + '</div>')
|
||||
this.jquery.frame.append(box)
|
||||
setTimeout(function() {
|
||||
box.fadeOut(200)
|
||||
setTimeout(function() {
|
||||
box.remove()
|
||||
}, 300)
|
||||
}, 1000)
|
||||
}
|
||||
//Get
|
||||
getPixelSize() {
|
||||
if (Blockbench.entity_mode) {
|
||||
@ -426,7 +422,7 @@ class UVEditor {
|
||||
}
|
||||
}
|
||||
getTexture() {
|
||||
return getTextureById(selected[0].faces[this.face].texture)
|
||||
return selected[0].faces[this.face].getTexture()
|
||||
}
|
||||
forCubes(cb) {
|
||||
var i = 0;
|
||||
@ -437,6 +433,7 @@ class UVEditor {
|
||||
}
|
||||
//Set
|
||||
setSize(size, cancel_load) {
|
||||
var old_size = this.size;
|
||||
this.size = size
|
||||
this.jquery.frame.width(size)
|
||||
if (uv_dialog.editors !== undefined && this === uv_dialog.editors.single) {
|
||||
@ -447,6 +444,9 @@ class UVEditor {
|
||||
this.height = size / (Project.texture_width/Project.texture_height)
|
||||
this.jquery.frame.height(this.height)
|
||||
$('.panel#textures').css('top', 133+(size / (Project.texture_width/Project.texture_height))+'px')
|
||||
if (old_size !== size) {
|
||||
this.displayAllMappingOverlays(true)
|
||||
}
|
||||
} else {
|
||||
this.height = size
|
||||
this.jquery.frame.height(size)
|
||||
@ -489,12 +489,14 @@ class UVEditor {
|
||||
}
|
||||
if (load !== false) this.loadData()
|
||||
}
|
||||
setFace(face) {
|
||||
setFace(face, update) {
|
||||
this.face = face
|
||||
this.loadData()
|
||||
if (this.id === 'main_uv') {
|
||||
$('input#'+face+'_radio').prop("checked", true)
|
||||
}
|
||||
if (update !== false) {
|
||||
this.loadData()
|
||||
}
|
||||
return this;
|
||||
}
|
||||
setFrameColor(black) {
|
||||
@ -542,12 +544,14 @@ class UVEditor {
|
||||
//Set Rotation
|
||||
BarItems.uv_rotation.set(face.rotation||0)
|
||||
|
||||
this.displayTexture(face.texture)
|
||||
this.displayTexture(face)
|
||||
this.displayFrame()//and transform info
|
||||
this.displayTools()
|
||||
this.displaySliders()
|
||||
this.updateDragHandle()
|
||||
|
||||
if (Blockbench.entity_mode) {
|
||||
this.displayAllMappingOverlays()
|
||||
}
|
||||
if (this.id !== 'main_uv') {
|
||||
this.displayTools()
|
||||
}
|
||||
@ -570,12 +574,14 @@ class UVEditor {
|
||||
})
|
||||
|
||||
} else {
|
||||
|
||||
var trim = v => Math.round(v*1000+0.3)/1000;
|
||||
var pixelSize = this.size/16
|
||||
var left = this.jquery.size.position().left / pixelSize
|
||||
var top = this.jquery.size.position().top / pixelSize * (Project.texture_width/Project.texture_height)
|
||||
var left2 = (this.jquery.size.width()) / pixelSize + left
|
||||
var top2 = (this.jquery.size.height()) / pixelSize + top
|
||||
|
||||
var left = trim( this.jquery.size.position().left / pixelSize);
|
||||
var top = trim( this.jquery.size.position().top / pixelSize * (Project.texture_width/Project.texture_height));
|
||||
var left2= Math.clamp(trim( (this.jquery.size.width()) / pixelSize + left), 0, 16);
|
||||
var top2 = Math.clamp(trim( (this.jquery.size.height()) / pixelSize + top), 0, 16);
|
||||
|
||||
var uvTag = this.getUVTag()
|
||||
|
||||
if (uvTag[0] > uvTag[2]) {
|
||||
@ -600,25 +606,21 @@ class UVEditor {
|
||||
main_uv.loadData()
|
||||
}
|
||||
}
|
||||
applyTexture(id) {
|
||||
applyTexture(uuid) {
|
||||
var scope = this;
|
||||
Undo.initEdit({cubes: selected, uv_only: true})
|
||||
this.forCubes(obj => {
|
||||
obj.faces[scope.face].texture = '#'+id
|
||||
obj.faces[scope.face].texture = uuid
|
||||
})
|
||||
this.loadData()
|
||||
Canvas.updateSelectedFaces()
|
||||
Undo.finishEdit('apply_texture')
|
||||
}
|
||||
displayTexture(id) {
|
||||
if (!id || id === null) {
|
||||
displayTexture(face) {
|
||||
var tex = face.getTexture()
|
||||
if (!tex || typeof tex !== 'object' || tex.error) {
|
||||
this.displayEmptyTexture()
|
||||
} else {
|
||||
var tex = getTextureById(id+'')
|
||||
if (tex === undefined || tex.error) {
|
||||
this.displayEmptyTexture()
|
||||
return;
|
||||
}
|
||||
this.setFrameColor(tex.dark_box)
|
||||
var css = 'url("'+tex.source.split('\\').join('\\\\').replace(/ /g, '%20')+'")'
|
||||
this.jquery.frame.css('background-image', css)
|
||||
@ -717,24 +719,40 @@ class UVEditor {
|
||||
this.updateDragHandle()
|
||||
this.displayTransformInfo()
|
||||
}
|
||||
//Overlay
|
||||
displayMappingOverlay() {
|
||||
if (!Blockbench.entity_mode) return this;
|
||||
var scope = this;
|
||||
var sides = this.getMappingOverlay()
|
||||
|
||||
$(scope.jquery.size).find('.uv_mapping_overlay').remove()
|
||||
scope.jquery.size.append(sides)
|
||||
|
||||
return this;
|
||||
}
|
||||
getMappingOverlay(cube, absolute) {
|
||||
var scope = this;
|
||||
var sides = $('<div class="mapping_overlay_cube"></div>')
|
||||
var pixels = scope.getPixelSize()
|
||||
if (!cube) cube = selected[0]
|
||||
function addElement(x, y, width, height, n, color) {
|
||||
if (absolute) {
|
||||
x += cube.uv_offset[0];
|
||||
y += cube.uv_offset[1];
|
||||
}
|
||||
x *= pixels;
|
||||
y *= pixels;
|
||||
width = limitNumber(width *pixels + x, 0, scope.size) - x;
|
||||
height = limitNumber(height*pixels + y, 0, scope.height)- y;
|
||||
|
||||
scope.jquery.size.append('<div class="uv_mapping_overlay" '+
|
||||
'style="left: '+x+'px; top: '+y+'px;'+
|
||||
'height: '+height+'px; width: '+width+'px;'+
|
||||
'background: '+color+';"></div>')
|
||||
sides.append($(`<div class="uv_mapping_overlay"
|
||||
style="left: ${x}px; top: ${y}px;
|
||||
height: ${height}px; width: ${width}px;
|
||||
background: ${color};"></div>`))
|
||||
}
|
||||
var size = selected[0].size(undefined, true)
|
||||
var size = cube.size(undefined, true)
|
||||
|
||||
$(scope.jquery.size).find('.uv_mapping_overlay').remove()
|
||||
sides.attr('size_hash', `${cube.uv_offset[0]}_${cube.uv_offset[1]}_${size[0]}_${size[1]}_${size[2]}`)
|
||||
|
||||
addElement(size[2], 0, size[0], size[2], '#b4d4e1', '#ecf8fd')
|
||||
addElement(size[2]+size[0], 0, size[0], size[2], '#536174', '#6e788c')
|
||||
@ -742,7 +760,32 @@ class UVEditor {
|
||||
addElement(size[2], size[2], size[0], size[1], '#5bbcf4', '#7BD4FF')
|
||||
addElement(size[2]+size[0], size[2], size[2], size[1], '#f48686', '#FFA7A4')
|
||||
addElement(2*size[2]+size[0], size[2], size[0], size[1],'#f8dd72', '#FFF899')
|
||||
|
||||
return sides;
|
||||
}
|
||||
displayAllMappingOverlays(force_reload) {
|
||||
var scope = this;
|
||||
var cycle = bbuid(4)
|
||||
if (this.showing_overlays) {
|
||||
elements.forEach(cube => {
|
||||
var size = cube.size(undefined, true)
|
||||
var hash = `${cube.uv_offset[0]}_${cube.uv_offset[1]}_${size[0]}_${size[1]}_${size[2]}`
|
||||
var c = scope.jquery.frame.find(`.mapping_overlay_cube:not(.${cycle})[size_hash="${hash}"]`).first()
|
||||
if (force_reload || !c.length) {
|
||||
var sides = scope.getMappingOverlay(cube, true)
|
||||
sides.addClass(cycle)
|
||||
scope.jquery.frame.append(sides)
|
||||
} else {
|
||||
c.addClass(cycle)
|
||||
}
|
||||
})
|
||||
$(`.mapping_overlay_cube:not(.${cycle})`).remove()
|
||||
$('.mapping_overlay_cube').removeClass(cycle)
|
||||
} else {
|
||||
$(scope.jquery.frame).find('.mapping_overlay_cube').remove()
|
||||
}
|
||||
}
|
||||
//UI
|
||||
displaySliders() {
|
||||
this.sliders.pos_x.update()
|
||||
this.sliders.pos_y.update()
|
||||
@ -753,7 +796,7 @@ class UVEditor {
|
||||
//Cullface
|
||||
var face = selected[0].faces[this.face]
|
||||
BarItems.cullface.set(face.cullface||'off')
|
||||
BarItems.face_tint.setIcon(face.tintindex !== undefined ? 'check_box' : 'check_box_outline_blank')
|
||||
BarItems.face_tint.setIcon(face.tint ? 'check_box' : 'check_box_outline_blank')
|
||||
}
|
||||
updateDragHandle() {
|
||||
var pos = this.jquery.size.position()
|
||||
@ -914,10 +957,10 @@ class UVEditor {
|
||||
break;
|
||||
case 'east':
|
||||
uv = [
|
||||
16 - obj.from[2],
|
||||
16 - obj.from[1],
|
||||
16 - obj.to[2],
|
||||
16 - obj.to[1],
|
||||
16 - obj.from[2],
|
||||
16 - obj.from[1],
|
||||
];
|
||||
break;
|
||||
case 'up':
|
||||
@ -1024,15 +1067,11 @@ class UVEditor {
|
||||
}
|
||||
switchTint(event) {
|
||||
var scope = this;
|
||||
var val = selected[0].faces[scope.face].tintindex === undefined
|
||||
var val = !selected[0].faces[scope.face].tint
|
||||
|
||||
if (event === true || event === false) val = event
|
||||
this.forCubes(obj => {
|
||||
if (val) {
|
||||
obj.faces[scope.face].tintindex = 0
|
||||
} else {
|
||||
delete obj.faces[scope.face].tintindex
|
||||
}
|
||||
obj.faces[scope.face].tint = val
|
||||
})
|
||||
if (val) {
|
||||
this.message('uv_editor.tint_on')
|
||||
@ -1043,13 +1082,9 @@ class UVEditor {
|
||||
}
|
||||
rotate() {
|
||||
var scope = this;
|
||||
var value = BarItems.uv_rotation.get()
|
||||
var value = parseInt(BarItems.uv_rotation.get())
|
||||
this.forCubes(obj => {
|
||||
if (value == 0) {
|
||||
delete obj.faces[scope.face].rotation
|
||||
} else {
|
||||
obj.faces[scope.face].rotation = parseInt(value)
|
||||
}
|
||||
obj.faces[scope.face].rotation = value
|
||||
Canvas.updateUV(obj)
|
||||
})
|
||||
this.displayTransformInfo()
|
||||
@ -1057,12 +1092,9 @@ class UVEditor {
|
||||
}
|
||||
setRotation(value) {
|
||||
var scope = this;
|
||||
value = parseInt(value)
|
||||
this.forCubes(obj => {
|
||||
if (value == 0) {
|
||||
delete obj.faces[scope.face].rotation
|
||||
} else {
|
||||
obj.faces[scope.face].rotation = parseInt(value)
|
||||
}
|
||||
obj.faces[scope.face].rotation = value
|
||||
Canvas.updateUV(obj)
|
||||
})
|
||||
this.loadData()
|
||||
@ -1105,15 +1137,7 @@ class UVEditor {
|
||||
return;
|
||||
}
|
||||
var tag = selected[0].faces[face]
|
||||
var new_tag = {
|
||||
uv: tag.uv.slice(),
|
||||
face: face
|
||||
}
|
||||
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
|
||||
if (tag.tintindex !== undefined) new_tag.tintindex = tag.tintindex
|
||||
var new_tag = new Face().extend(tag)
|
||||
uv_dialog.clipboard.push(new_tag)
|
||||
}
|
||||
if (event.shiftKey) {
|
||||
@ -1141,15 +1165,7 @@ class UVEditor {
|
||||
function applyFace(tag, face) {
|
||||
if (!face) face = tag.face
|
||||
selected.forEach(function(obj) {
|
||||
var target = obj.faces[face]
|
||||
target.uv = tag.uv.slice()
|
||||
|
||||
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
|
||||
if (tag.tintindex !== undefined || target.texture !== undefined) target.tintindex = tag.tintindex
|
||||
|
||||
obj.faces[face].extend(tag)
|
||||
Canvas.updateUV(obj)
|
||||
})
|
||||
}
|
||||
@ -1194,12 +1210,7 @@ class UVEditor {
|
||||
var scope = this;
|
||||
this.forCubes(obj => {
|
||||
scope.getFaces(event).forEach(function(side) {
|
||||
obj.faces[side].uv = [0, 0, 1, 1]
|
||||
delete obj.faces[side].texture;
|
||||
delete obj.faces[side].rotation;
|
||||
delete obj.faces[side].tintindex;
|
||||
delete obj.faces[side].enabled;
|
||||
delete obj.faces[side].cullface;
|
||||
obj.faces[side].reset()
|
||||
})
|
||||
Canvas.adaptObjectFaces(obj)
|
||||
})
|
||||
@ -1213,6 +1224,9 @@ class UVEditor {
|
||||
}
|
||||
}
|
||||
UVEditor.prototype.menu = new Menu([
|
||||
'copy',
|
||||
'paste',
|
||||
/*
|
||||
{icon: 'content_copy', name: 'menu.uv.copy', click: function(editor) {
|
||||
editor.copy(event)
|
||||
}},
|
||||
@ -1220,28 +1234,16 @@ class UVEditor {
|
||||
Undo.initEdit({cubes: selected, uv_only: true})
|
||||
editor.paste(event)
|
||||
Undo.finishEdit('uv_paste')
|
||||
}},
|
||||
}},*/
|
||||
{icon: 'photo_size_select_large', name: 'menu.uv.mapping', children: function(editor) { return [
|
||||
{icon: editor.reference_face.enabled!==false ? 'check_box' : 'check_box_outline_blank', name: 'menu.uv.mapping.export', click: function(editor) {
|
||||
Undo.initEdit({cubes: selected, uv_only: true})
|
||||
editor.toggleUV(event)
|
||||
Undo.finishEdit('uv_toggle')
|
||||
}},
|
||||
{icon: 'zoom_out_map', name: 'menu.uv.mapping.maximize', click: function(editor) {
|
||||
Undo.initEdit({cubes: selected, uv_only: true})
|
||||
editor.maximize(event)
|
||||
Undo.finishEdit('uv_maximize')
|
||||
}},
|
||||
{icon: 'brightness_auto', name: 'menu.uv.mapping.auto', click: function(editor) {
|
||||
Undo.initEdit({cubes: selected, uv_only: true})
|
||||
editor.setAutoSize(event)
|
||||
Undo.finishEdit('uv_auto')
|
||||
}},
|
||||
{icon: 'brightness_auto', name: 'menu.uv.mapping.rel_auto', click: function(editor) {
|
||||
Undo.initEdit({cubes: selected, uv_only: true})
|
||||
editor.setRelativeAutoSize(event)
|
||||
Undo.finishEdit('uv_auto')
|
||||
}},
|
||||
'uv_maximize',
|
||||
'uv_auto',
|
||||
'uv_rel_auto',
|
||||
{icon: 'rotate_90_degrees_ccw', name: 'menu.uv.mapping.rotation', children: function() {
|
||||
var off = 'radio_button_unchecked'
|
||||
var on = 'radio_button_checked'
|
||||
@ -1275,7 +1277,8 @@ class UVEditor {
|
||||
Undo.initEdit({cubes: selected, uv_only: true})
|
||||
editor.mirrorX(event)
|
||||
Undo.finishEdit('uv_mirror')
|
||||
}},
|
||||
}
|
||||
},
|
||||
{
|
||||
icon: (editor.reference_face.uv[1] > editor.reference_face.uv[3] ? 'check_box' : 'check_box_outline_blank'),
|
||||
name: 'menu.uv.mapping.mirror_y',
|
||||
@ -1283,13 +1286,14 @@ class UVEditor {
|
||||
Undo.initEdit({cubes: selected, uv_only: true})
|
||||
editor.mirrorY(event)
|
||||
Undo.finishEdit('uv_mirror')
|
||||
}},
|
||||
}
|
||||
},
|
||||
]}},
|
||||
{
|
||||
icon: (editor) => (editor.reference_face.tintindex === 0 ? 'check_box' : 'check_box_outline_blank'),
|
||||
icon: (editor) => (editor.reference_face.tint ? 'check_box' : 'check_box_outline_blank'),
|
||||
name: 'menu.uv.tint', click: function(editor) {
|
||||
Undo.initEdit({cubes: selected, uv_only: true})
|
||||
editor.switchTint(selected[0].faces[editor.face].tintindex !== 0)
|
||||
editor.switchTint(selected[0].faces[editor.face].tint)
|
||||
Undo.finishEdit('face_tint')
|
||||
}
|
||||
},
|
||||
@ -1313,7 +1317,7 @@ class UVEditor {
|
||||
arr.push({
|
||||
name: t.name,
|
||||
icon: (t.mode === 'link' ? t.img : t.source),
|
||||
click: function(editor) {editor.applyTexture(t.id)}
|
||||
click: function(editor) {editor.applyTexture(t.uuid)}
|
||||
})
|
||||
})
|
||||
return arr;
|
||||
@ -1552,16 +1556,7 @@ const uv_dialog = {
|
||||
|
||||
function addToClipboard(face) {
|
||||
var tag = selected[0].faces[face]
|
||||
var new_tag = {
|
||||
uv: tag.uv.slice(),
|
||||
face: face
|
||||
}
|
||||
if (tag.texture) 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
|
||||
if (tag.tintindex !== undefined) new_tag.tintindex = tag.tintindex
|
||||
uv_dialog.clipboard.push(new_tag)
|
||||
uv_dialog.clipboard.push(new Face(tag))
|
||||
}
|
||||
if (uv_dialog.hoveredSide) {
|
||||
addToClipboard(uv_dialog.hoveredSide)
|
||||
@ -1583,15 +1578,7 @@ const uv_dialog = {
|
||||
function applyFace(tag, face) {
|
||||
if (!face) face = tag.face
|
||||
selected.forEach(function(obj) {
|
||||
var target = obj.faces[face]
|
||||
target.uv = tag.uv.slice()
|
||||
|
||||
if (tag.texture || target.texture) 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
|
||||
if (tag.tintindex !== undefined || target.texture !== undefined) target.tintindex = tag.tintindex
|
||||
|
||||
obj.faces[face].extend(tag)
|
||||
Canvas.updateUV(obj)
|
||||
})
|
||||
}
|
||||
@ -1646,7 +1633,7 @@ BARS.defineActions(function() {
|
||||
onChange: function(slider) {
|
||||
Undo.initEdit({cubes: selected, uv_only: true})
|
||||
uv_dialog.forSelection('rotate')
|
||||
Undo.finishEdit('uv')
|
||||
Undo.finishEdit('uv rotate')
|
||||
}
|
||||
})
|
||||
new BarSelect({
|
||||
@ -1677,7 +1664,7 @@ BARS.defineActions(function() {
|
||||
click: function (event) {
|
||||
Undo.initEdit({cubes: selected, uv_only: true})
|
||||
uv_dialog.forSelection('maximize', event)
|
||||
Undo.finishEdit('uv')
|
||||
Undo.finishEdit('uv maximize')
|
||||
}
|
||||
})
|
||||
new Action({
|
||||
@ -1688,7 +1675,7 @@ BARS.defineActions(function() {
|
||||
click: function (event) {
|
||||
Undo.initEdit({cubes: selected, uv_only: true})
|
||||
uv_dialog.forSelection('setAutoSize', event)
|
||||
Undo.finishEdit('uv')
|
||||
Undo.finishEdit('auto uv')
|
||||
}
|
||||
})
|
||||
new Action({
|
||||
@ -1699,7 +1686,7 @@ BARS.defineActions(function() {
|
||||
click: function (event) {
|
||||
Undo.initEdit({cubes: selected, uv_only: true})
|
||||
uv_dialog.forSelection('setRelativeAutoSize', event)
|
||||
Undo.finishEdit('uv')
|
||||
Undo.finishEdit('auto uv')
|
||||
}
|
||||
})
|
||||
new Action({
|
||||
@ -1710,7 +1697,7 @@ BARS.defineActions(function() {
|
||||
click: function (event) {
|
||||
Undo.initEdit({cubes: selected, uv_only: true})
|
||||
uv_dialog.forSelection('mirrorX', event)
|
||||
Undo.finishEdit('uv')
|
||||
Undo.finishEdit('mirror uv')
|
||||
}
|
||||
})
|
||||
new Action({
|
||||
@ -1721,7 +1708,7 @@ BARS.defineActions(function() {
|
||||
click: function (event) {
|
||||
Undo.initEdit({cubes: selected, uv_only: true})
|
||||
uv_dialog.forSelection('mirrorY', event)
|
||||
Undo.finishEdit('uv')
|
||||
Undo.finishEdit('mirror uv')
|
||||
}
|
||||
})
|
||||
new Action({
|
||||
@ -1732,7 +1719,7 @@ BARS.defineActions(function() {
|
||||
click: function (event) {
|
||||
Undo.initEdit({cubes: selected, uv_only: true})
|
||||
uv_dialog.forSelection('clear', event)
|
||||
Undo.finishEdit('uv')
|
||||
Undo.finishEdit('remove face')
|
||||
}
|
||||
})
|
||||
new Action({
|
||||
@ -1743,7 +1730,7 @@ BARS.defineActions(function() {
|
||||
click: function (event) {
|
||||
Undo.initEdit({cubes: selected, uv_only: true})
|
||||
uv_dialog.forSelection('reset', event)
|
||||
Undo.finishEdit('uv')
|
||||
Undo.finishEdit('reset uv')
|
||||
}
|
||||
})
|
||||
new Action({
|
||||
@ -1754,7 +1741,7 @@ BARS.defineActions(function() {
|
||||
click: function (e) {
|
||||
Undo.initEdit({cubes: selected, uv_only: true})
|
||||
main_uv.applyAll(e)
|
||||
Undo.finishEdit('uv')
|
||||
Undo.finishEdit('uv apply all')
|
||||
}
|
||||
})
|
||||
new BarSelect({
|
||||
@ -1773,7 +1760,7 @@ BARS.defineActions(function() {
|
||||
onChange: function(sel, event) {
|
||||
Undo.initEdit({cubes: selected, uv_only: true})
|
||||
uv_dialog.forSelection('switchCullface')
|
||||
Undo.finishEdit('uv')
|
||||
Undo.finishEdit('cullface')
|
||||
}
|
||||
})
|
||||
new Action({
|
||||
@ -1784,7 +1771,7 @@ BARS.defineActions(function() {
|
||||
click: function (event) {
|
||||
Undo.initEdit({cubes: selected, uv_only: true})
|
||||
uv_dialog.forSelection('autoCullface', event)
|
||||
Undo.finishEdit('uv')
|
||||
Undo.finishEdit('auto cullface')
|
||||
}
|
||||
})
|
||||
new Action({
|
||||
@ -1794,7 +1781,7 @@ BARS.defineActions(function() {
|
||||
click: function (event) {
|
||||
Undo.initEdit({cubes: selected, uv_only: true})
|
||||
uv_dialog.forSelection('switchTint', event)
|
||||
Undo.finishEdit('uv')
|
||||
Undo.finishEdit('tint')
|
||||
}
|
||||
})
|
||||
new Action({
|
||||
@ -1806,4 +1793,15 @@ BARS.defineActions(function() {
|
||||
showUVShiftDialog()
|
||||
}
|
||||
})
|
||||
new Action({
|
||||
id: 'toggle_uv_overlay',
|
||||
condition: () => Blockbench.entity_mode,
|
||||
icon: 'crop_landscape',//'crop_landscape'
|
||||
category: 'uv',
|
||||
click: function () {
|
||||
main_uv.showing_overlays = !main_uv.showing_overlays
|
||||
BarItems.toggle_uv_overlay.setIcon(main_uv.showing_overlays ? 'view_quilt' : 'crop_landscape')
|
||||
main_uv.displayAllMappingOverlays()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
10
js/web.js
10
js/web.js
@ -22,12 +22,10 @@ function tryLoadPOSTModel() {
|
||||
if ($('#post_textures').text() !== '') {
|
||||
var data = JSON.parse( $('#post_textures').text() )
|
||||
for (var key in data) {
|
||||
if (data.hasOwnProperty(key)) {
|
||||
var tex = getTextureById(key+'');
|
||||
if (tex) {
|
||||
tex.img.src = ''
|
||||
tex.source = 'data:image/png;base64,'+data[key]
|
||||
}
|
||||
var tex = textures.findInArray('id', key+'');
|
||||
if (tex) {
|
||||
tex.img.src = ''
|
||||
tex.source = 'data:image/png;base64,'+data[key]
|
||||
}
|
||||
}
|
||||
textures.forEach(function(tex) {
|
||||
|
23
lang/de.json
23
lang/de.json
@ -561,13 +561,8 @@
|
||||
"menu.preview.quadview": "Vierfachansicht",
|
||||
"menu.preview.fullview": "Vollansicht",
|
||||
"menu.preview.stop_drag": "Hintergrundpositionierung beenden",
|
||||
"menu.uv.copy": "Kopieren",
|
||||
"menu.uv.paste": "Einfügen",
|
||||
"menu.uv.mapping": "UV Mapping",
|
||||
"menu.uv.mapping.export": "Exportieren",
|
||||
"menu.uv.mapping.maximize": "Maximieren",
|
||||
"menu.uv.mapping.auto": "Auto UV",
|
||||
"menu.uv.mapping.rel_auto": "Rel. Auto UV",
|
||||
"menu.uv.mapping.rotation": "Drehung",
|
||||
"menu.uv.mapping.mirror_x": "Spiegeln X",
|
||||
"menu.uv.mapping.mirror_y": "Spiegeln Y",
|
||||
@ -825,5 +820,21 @@
|
||||
"action.open_backup_folder": "Backup-Ordner öffnen",
|
||||
"action.open_backup_folder.desc": "Öffnet den Backup-Ordner von Blockbench",
|
||||
"switches.mirror": "UV Spiegeln",
|
||||
"language_name": "Deutsch"
|
||||
"language_name": "Deutsch",
|
||||
"message.plugin_reload": "%0 lokale Plugins wurden neugeladen",
|
||||
"settings.brightness": "Helligkeit",
|
||||
"settings.brightness.desc": "Helligkeit der Vorschau. Standardwert ist 50",
|
||||
"menu.preview.perspective.reset": "Kamera zurücksetzen",
|
||||
"action.fill_mode": "Füllmodus",
|
||||
"action.fill_mode.desc": "Modus des Farbeimers",
|
||||
"action.fill_mode.face": "Fläche",
|
||||
"action.fill_mode.color": "Farbe",
|
||||
"action.fill_mode.cube": "Element",
|
||||
"action.toggle_mirror_uv": "UV spiegeln",
|
||||
"action.toggle_mirror_uv.desc": "UV Mapping der ausgewählten Elemente auf der X Achse spiegeln.",
|
||||
"action.toggle_uv_overlay": "UV Maske einblenden",
|
||||
"action.toggle_uv_overlay.desc": "Blendet UV Masken für alle Elemente über der Textur ein",
|
||||
"menu.texture.blank": "Auf leere Flächen anwenden",
|
||||
"dialog.scale.select_overflow": "Überstehendes auswählen",
|
||||
"dialog.create_texture.compress": "Template verdichten"
|
||||
}
|
21
lang/en.json
21
lang/en.json
@ -142,6 +142,7 @@
|
||||
"message.invalid_plugin": "Invalid Plugin File, See Console",
|
||||
"message.load_plugin_app": "Do you want to allow this plugin to make changes to your PC? Only load plugins from people you trust.",
|
||||
"message.load_plugin_web": "Do you want to load this plugin? Only load plugins from people you trust.",
|
||||
"message.plugin_reload": "Reloaded %0 local plugins",
|
||||
"message.preset_no_info": "Preset does not contain information for this slot",
|
||||
"message.restart_to_update": "Restart Blockbench to apply changes",
|
||||
"message.save_file": "Saved as %0",
|
||||
@ -201,6 +202,7 @@
|
||||
"dialog.scale.scale": "Scale",
|
||||
"dialog.scale.clipping": "Model clipping: Your model is too large for the canvas",
|
||||
"dialog.scale.confirm": "Scale",
|
||||
"dialog.scale.select_overflow": "Select Overflow",
|
||||
|
||||
"dialog.plugins.title": "Plugins",
|
||||
"dialog.plugins.installed": "Installed",
|
||||
@ -228,6 +230,7 @@
|
||||
"dialog.create_texture.name": "Name",
|
||||
"dialog.create_texture.folder": "Folder",
|
||||
"dialog.create_texture.template": "Template",
|
||||
"dialog.create_texture.compress": "Compress Template",
|
||||
"dialog.create_texture.resolution": "Resolution",
|
||||
|
||||
"dialog.create_gif.title": "Record GIF",
|
||||
@ -325,6 +328,8 @@
|
||||
"settings.display_skin.desc": "Skin used for the display reference player model",
|
||||
"settings.seethrough_outline": "X-Ray Outlines",
|
||||
"settings.seethrough_outline.desc": "Show outlines through objects",
|
||||
"settings.brightness": "Brightness",
|
||||
"settings.brightness.desc": "Brightness of the preview. Default is 50",
|
||||
"settings.shading": "Shading",
|
||||
"settings.shading.desc": "Enable shading",
|
||||
"settings.transparency": "Transparency",
|
||||
@ -441,6 +446,11 @@
|
||||
"action.brush_mode.desc": "Mode of the brush",
|
||||
"action.brush_mode.brush": "Round",
|
||||
"action.brush_mode.noise": "Noise",
|
||||
"action.fill_mode": "Fill Mode",
|
||||
"action.fill_mode.desc": "Mode of the fill tool",
|
||||
"action.fill_mode.face": "Face",
|
||||
"action.fill_mode.color": "Color",
|
||||
"action.fill_mode.cube": "Cube",
|
||||
"action.brush_color": "Color",
|
||||
"action.brush_color.desc": "Color of the brush",
|
||||
"action.slider_brush_size": "Size",
|
||||
@ -614,6 +624,8 @@
|
||||
"action.toggle_autouv.desc": "Toggle the auto UV setting of the selected cubes.",
|
||||
"action.toggle_shade": "Toggle Shading",
|
||||
"action.toggle_shade.desc": "Toggle the shading of the selected cubes.",
|
||||
"action.toggle_mirror_uv": "Mirror UV",
|
||||
"action.toggle_mirror_uv.desc": "Toggle the UV mirroring on the X axis of the selected cubes.",
|
||||
"action.rename": "Rename",
|
||||
"action.rename.desc": "Change the name of the selected cubes.",
|
||||
"action.update_autouv": "Update Auto UV",
|
||||
@ -710,6 +722,8 @@
|
||||
"action.face_tint.desc": "Enables the tint option for the current face",
|
||||
"action.uv_shift": "Shift UV",
|
||||
"action.uv_shift.desc": "Shift all UV regions by a fixed amount or mathematical expression",
|
||||
"action.toggle_uv_overlay": "Toggle UV Overlay",
|
||||
"action.toggle_uv_overlay.desc": "When enabled, displays all UV mapping overlays above the texture.",
|
||||
|
||||
"action.add_animation": "Add Animation",
|
||||
"action.add_animation.desc": "Create a blank animation",
|
||||
@ -768,6 +782,7 @@
|
||||
"menu.group.resolve": "Resolve",
|
||||
|
||||
"menu.texture.face": "Apply to Face",
|
||||
"menu.texture.blank": "Apply to Untextured Faces",
|
||||
"menu.texture.cube": "Apply to Cubes",
|
||||
"menu.texture.file": "File",
|
||||
"menu.texture.refresh": "Refresh",
|
||||
@ -788,17 +803,13 @@
|
||||
"menu.preview.screenshot": "Screenshot",
|
||||
"menu.preview.perspective": "Perspective",
|
||||
"menu.preview.perspective.normal": "Normal",
|
||||
"menu.preview.perspective.reset": "Reset Camera",
|
||||
"menu.preview.quadview": "Quad View",
|
||||
"menu.preview.fullview": "Full View",
|
||||
"menu.preview.stop_drag": "Stop Background Positioning",
|
||||
|
||||
"menu.uv.copy": "Copy",
|
||||
"menu.uv.paste": "Paste",
|
||||
"menu.uv.mapping": "UV Mapping",
|
||||
"menu.uv.mapping.export": "Export",
|
||||
"menu.uv.mapping.maximize": "Maximize",
|
||||
"menu.uv.mapping.auto": "Auto UV",
|
||||
"menu.uv.mapping.rel_auto": "Rel. Auto UV",
|
||||
"menu.uv.mapping.rotation": "Rotation",
|
||||
"menu.uv.mapping.mirror_x": "Mirror X",
|
||||
"menu.uv.mapping.mirror_y": "Mirror Y",
|
||||
|
25
lang/es.json
25
lang/es.json
@ -561,13 +561,8 @@
|
||||
"menu.preview.quadview": "Vista Cuádruple",
|
||||
"menu.preview.fullview": "Vista Completa",
|
||||
"menu.preview.stop_drag": "Parar la Colocación del Fondo",
|
||||
"menu.uv.copy": "Copiar",
|
||||
"menu.uv.paste": "Pegar",
|
||||
"menu.uv.mapping": "Mapeado del UV",
|
||||
"menu.uv.mapping.export": "Exportar",
|
||||
"menu.uv.mapping.maximize": "Maximizar",
|
||||
"menu.uv.mapping.auto": "Auto UV",
|
||||
"menu.uv.mapping.rel_auto": "Rel. Auto UV",
|
||||
"menu.uv.mapping.rotation": "Rotación",
|
||||
"menu.uv.mapping.mirror_x": "Invertir X",
|
||||
"menu.uv.mapping.mirror_y": "Invertir Y",
|
||||
@ -824,6 +819,22 @@
|
||||
"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",
|
||||
"switches.mirror": "Mirror UV",
|
||||
"language_name": "English"
|
||||
"switches.mirror": "Invertir UV",
|
||||
"language_name": "Inglés",
|
||||
"message.plugin_reload": "Reloaded %0 local plugins",
|
||||
"settings.brightness": "Brightness",
|
||||
"settings.brightness.desc": "Brightness of the preview. Default is 50",
|
||||
"menu.preview.perspective.reset": "Reset Camera",
|
||||
"action.fill_mode": "Fill Mode",
|
||||
"action.fill_mode.desc": "Mode of the fill tool",
|
||||
"action.fill_mode.face": "Face",
|
||||
"action.fill_mode.color": "Color",
|
||||
"action.fill_mode.cube": "Cube",
|
||||
"action.toggle_mirror_uv": "Mirror UV",
|
||||
"action.toggle_mirror_uv.desc": "Toggle the UV mirroring on the X axis of the selected cubes.",
|
||||
"action.toggle_uv_overlay": "Toggle UV Overlay",
|
||||
"action.toggle_uv_overlay.desc": "When enabled, displays all UV mapping overlays above the texture.",
|
||||
"menu.texture.blank": "Apply to Untextured Faces",
|
||||
"dialog.scale.select_overflow": "Select Overflow",
|
||||
"dialog.create_texture.compress": "Compress Template"
|
||||
}
|
23
lang/fr.json
23
lang/fr.json
@ -561,13 +561,8 @@
|
||||
"menu.preview.quadview": "Quadruple vue",
|
||||
"menu.preview.fullview": "Vue complète",
|
||||
"menu.preview.stop_drag": "Arrêter le positionnement en arrière-plan",
|
||||
"menu.uv.copy": "Copier",
|
||||
"menu.uv.paste": "Coller",
|
||||
"menu.uv.mapping": "Cartographie UV",
|
||||
"menu.uv.mapping.export": "Exporter",
|
||||
"menu.uv.mapping.maximize": "Maximiser",
|
||||
"menu.uv.mapping.auto": "UV automatique",
|
||||
"menu.uv.mapping.rel_auto": "Rel. UV automatique",
|
||||
"menu.uv.mapping.rotation": "Rotation",
|
||||
"menu.uv.mapping.mirror_x": "Miroir X",
|
||||
"menu.uv.mapping.mirror_y": "Miroir Y",
|
||||
@ -825,5 +820,21 @@
|
||||
"action.open_backup_folder": "Ouvrir le dossier de sauvegarde",
|
||||
"action.open_backup_folder.desc": "Ouvre le dossier de sauvegarde de Blockbench",
|
||||
"switches.mirror": "Mirror UV",
|
||||
"language_name": "English"
|
||||
"language_name": "English",
|
||||
"message.plugin_reload": "Reloaded %0 local plugins",
|
||||
"settings.brightness": "Brightness",
|
||||
"settings.brightness.desc": "Brightness of the preview. Default is 50",
|
||||
"menu.preview.perspective.reset": "Reset Camera",
|
||||
"action.fill_mode": "Fill Mode",
|
||||
"action.fill_mode.desc": "Mode of the fill tool",
|
||||
"action.fill_mode.face": "Face",
|
||||
"action.fill_mode.color": "Color",
|
||||
"action.fill_mode.cube": "Cube",
|
||||
"action.toggle_mirror_uv": "Mirror UV",
|
||||
"action.toggle_mirror_uv.desc": "Toggle the UV mirroring on the X axis of the selected cubes.",
|
||||
"action.toggle_uv_overlay": "Toggle UV Overlay",
|
||||
"action.toggle_uv_overlay.desc": "When enabled, displays all UV mapping overlays above the texture.",
|
||||
"menu.texture.blank": "Apply to Untextured Faces",
|
||||
"dialog.scale.select_overflow": "Select Overflow",
|
||||
"dialog.create_texture.compress": "Compress Template"
|
||||
}
|
67
lang/ja.json
67
lang/ja.json
@ -5,7 +5,7 @@
|
||||
"dialog.close": "閉じる",
|
||||
"dialog.import": "インポート",
|
||||
"dialog.save": "保存",
|
||||
"dialog.discard": "削除",
|
||||
"dialog.discard": "保存しない",
|
||||
"dialog.dontshowagain": "二度と表示しないようにします",
|
||||
"data.cube": "キューブ",
|
||||
"data.cubes": "キューブ",
|
||||
@ -561,13 +561,8 @@
|
||||
"menu.preview.quadview": "クワッドビュー",
|
||||
"menu.preview.fullview": "全景",
|
||||
"menu.preview.stop_drag": "背景のポジショニングを停止する",
|
||||
"menu.uv.copy": "コピー",
|
||||
"menu.uv.paste": "ペースト",
|
||||
"menu.uv.mapping": "UVマッピング",
|
||||
"menu.uv.mapping.export": "エクスポート",
|
||||
"menu.uv.mapping.maximize": "最大化",
|
||||
"menu.uv.mapping.auto": "自動UV",
|
||||
"menu.uv.mapping.rel_auto": "小.自動UV",
|
||||
"menu.uv.mapping.rotation": "回転",
|
||||
"menu.uv.mapping.mirror_x": "ミラーX",
|
||||
"menu.uv.mapping.mirror_y": "ミラーY",
|
||||
@ -743,15 +738,15 @@
|
||||
"layout.color.wireframe": "ワイヤーフレーム",
|
||||
"layout.color.wireframe.desc": "Wireframe view lines",
|
||||
"action.add_animation": "アニメーションを加える",
|
||||
"action.add_animation.desc": "action.add_animation.desc",
|
||||
"action.add_animation.desc": "Create a blank animation",
|
||||
"action.load_animation_file": "アニメーションをインポートする",
|
||||
"action.load_animation_file.desc": "action.load_animation_file.desc",
|
||||
"action.load_animation_file.desc": "Import an animation file",
|
||||
"action.play_animation": "アニメーションを再生する",
|
||||
"action.play_animation.desc": "action.play_animation.desc",
|
||||
"action.play_animation.desc": "Preview the selected animation",
|
||||
"action.export_animation_file": "アニメーションをエクスポートする",
|
||||
"action.export_animation_file.desc": "action.export_animation_file.desc",
|
||||
"action.export_animation_file.desc": "Export a json file with the current animations",
|
||||
"action.slider_keyframe_time": "タイムコード",
|
||||
"action.slider_keyframe_time.desc": "action.slider_keyframe_time.desc",
|
||||
"action.slider_keyframe_time.desc": "Change the timecode of the selected keyframes",
|
||||
"timeline.rotation": "ローテーション",
|
||||
"timeline.position": "ポジション",
|
||||
"timeline.scale": "スケール",
|
||||
@ -807,23 +802,39 @@
|
||||
"settings.seethrough_outline": "X-Rey アウトライン",
|
||||
"settings.seethrough_outline.desc": "オブジェクトを通してアウトラインを表示する",
|
||||
"mode.edit": "編集",
|
||||
"mode.paint": "ペイント",
|
||||
"mode.display": "ディスプレイ",
|
||||
"mode.paint": "Paint",
|
||||
"mode.display": "Display",
|
||||
"mode.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",
|
||||
"status_bar.recording_gif": "GIFの録音",
|
||||
"status_bar.processing_gif": "GIFの加工処理",
|
||||
"settings.backup_retain": "バックアップ保持期間",
|
||||
"settings.backup_retain.desc": "Blockbenchがバックアップデーターを保持する期間を設定します",
|
||||
"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": "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",
|
||||
"switches.mirror": "Mirror UV",
|
||||
"language_name": "English"
|
||||
"action.rotate_tool.desc": "選択中の要素を回転させることができます",
|
||||
"action.fill_tool": "バケツ",
|
||||
"action.fill_tool.desc": "選択欄を塗りつぶすことができます",
|
||||
"action.eraser": "消しゴム",
|
||||
"action.eraser.desc": "テクスチャの色を消去できます",
|
||||
"action.color_picker": "カラーピッカー",
|
||||
"action.color_picker.desc": "テクスチャの色を選択できます",
|
||||
"action.open_backup_folder": "バックアップフォルダーを開く",
|
||||
"action.open_backup_folder.desc": "Blockbenchのバックアップフォルダーを開きます",
|
||||
"switches.mirror": "ミラーUV",
|
||||
"language_name": "English",
|
||||
"message.plugin_reload": "Reloaded %0 local plugins",
|
||||
"settings.brightness": "Brightness",
|
||||
"settings.brightness.desc": "Brightness of the preview. Default is 50",
|
||||
"menu.preview.perspective.reset": "Reset Camera",
|
||||
"action.fill_mode": "Fill Mode",
|
||||
"action.fill_mode.desc": "Mode of the fill tool",
|
||||
"action.fill_mode.face": "Face",
|
||||
"action.fill_mode.color": "Color",
|
||||
"action.fill_mode.cube": "Cube",
|
||||
"action.toggle_mirror_uv": "Mirror UV",
|
||||
"action.toggle_mirror_uv.desc": "Toggle the UV mirroring on the X axis of the selected cubes.",
|
||||
"action.toggle_uv_overlay": "Toggle UV Overlay",
|
||||
"action.toggle_uv_overlay.desc": "When enabled, displays all UV mapping overlays above the texture.",
|
||||
"menu.texture.blank": "Apply to Untextured Faces",
|
||||
"dialog.scale.select_overflow": "Select Overflow",
|
||||
"dialog.create_texture.compress": "Compress Template"
|
||||
}
|
23
lang/nl.json
23
lang/nl.json
@ -561,13 +561,8 @@
|
||||
"menu.preview.quadview": "Vierdelige Weergave",
|
||||
"menu.preview.fullview": "Volledige Weergave",
|
||||
"menu.preview.stop_drag": "Stop Achtergrong Positionering",
|
||||
"menu.uv.copy": "Kopiëren",
|
||||
"menu.uv.paste": "Plakken",
|
||||
"menu.uv.mapping": "UV Mapping",
|
||||
"menu.uv.mapping.export": "Exporteren",
|
||||
"menu.uv.mapping.maximize": "Maximaliseer",
|
||||
"menu.uv.mapping.auto": "Auto UV",
|
||||
"menu.uv.mapping.rel_auto": "Rel. Auto UV",
|
||||
"menu.uv.mapping.rotation": "Rotatie",
|
||||
"menu.uv.mapping.mirror_x": "Spiegel X",
|
||||
"menu.uv.mapping.mirror_y": "Spiegel Y",
|
||||
@ -825,5 +820,21 @@
|
||||
"action.open_backup_folder": "Open Backup Folder",
|
||||
"action.open_backup_folder.desc": "Opens the Blockbench backup folder",
|
||||
"switches.mirror": "Mirror UV",
|
||||
"language_name": "English"
|
||||
"language_name": "English",
|
||||
"message.plugin_reload": "Reloaded %0 local plugins",
|
||||
"settings.brightness": "Brightness",
|
||||
"settings.brightness.desc": "Brightness of the preview. Default is 50",
|
||||
"menu.preview.perspective.reset": "Reset Camera",
|
||||
"action.fill_mode": "Fill Mode",
|
||||
"action.fill_mode.desc": "Mode of the fill tool",
|
||||
"action.fill_mode.face": "Face",
|
||||
"action.fill_mode.color": "Color",
|
||||
"action.fill_mode.cube": "Cube",
|
||||
"action.toggle_mirror_uv": "Mirror UV",
|
||||
"action.toggle_mirror_uv.desc": "Toggle the UV mirroring on the X axis of the selected cubes.",
|
||||
"action.toggle_uv_overlay": "Toggle UV Overlay",
|
||||
"action.toggle_uv_overlay.desc": "When enabled, displays all UV mapping overlays above the texture.",
|
||||
"menu.texture.blank": "Apply to Untextured Faces",
|
||||
"dialog.scale.select_overflow": "Select Overflow",
|
||||
"dialog.create_texture.compress": "Compress Template"
|
||||
}
|
103
lang/pl.json
103
lang/pl.json
@ -11,7 +11,7 @@
|
||||
"data.cubes": "Kostki",
|
||||
"data.group": "Grupa",
|
||||
"data.texture": "Tekstura",
|
||||
"data.plugin": "Plugin",
|
||||
"data.plugin": "Wtyczka",
|
||||
"data.preview": "Podgląd",
|
||||
"data.toolbar": "Pasek narzędzi",
|
||||
"data.image": "Obraz",
|
||||
@ -561,13 +561,8 @@
|
||||
"menu.preview.quadview": "Widok Quad",
|
||||
"menu.preview.fullview": "Pełny widok",
|
||||
"menu.preview.stop_drag": "Skończ pozycjonowanie tła",
|
||||
"menu.uv.copy": "Kopiuj",
|
||||
"menu.uv.paste": "Wklej",
|
||||
"menu.uv.mapping": "Mapowanie UV",
|
||||
"menu.uv.mapping.export": "Eksport",
|
||||
"menu.uv.mapping.maximize": "Maksymalizuj",
|
||||
"menu.uv.mapping.auto": "Automatyczne UV",
|
||||
"menu.uv.mapping.rel_auto": "Względne automatyczne UV",
|
||||
"menu.uv.mapping.rotation": "Rotacja",
|
||||
"menu.uv.mapping.mirror_x": "Odbicie X",
|
||||
"menu.uv.mapping.mirror_y": "Odbicie Y",
|
||||
@ -784,46 +779,62 @@
|
||||
"action.slider_animation_length": "Długość animacji",
|
||||
"action.slider_animation_length.desc": "Zmień długość zaznaczonej animacji",
|
||||
"menu.group.material": "Ustal materiał",
|
||||
"action.camera_reset": "Reset Camera",
|
||||
"action.camera_reset.desc": "Reset the current preview to the default camera angle",
|
||||
"panel.variable_placeholders": "Variable Placeholders",
|
||||
"panel.variable_placeholders.info": "List the variables you want to preview via name=value",
|
||||
"status_bar.vertex_distance": "Distance: %0",
|
||||
"dialog.create_gif.title": "Record GIF",
|
||||
"dialog.create_gif.length": "Length (Seconds)",
|
||||
"action.camera_reset": "Zresetój Kamerę",
|
||||
"action.camera_reset.desc": "\n Zresetuj bieżący podgląd do domyślnego kąta kamery",
|
||||
"panel.variable_placeholders": "\n Zmienne symbole zastępcze",
|
||||
"panel.variable_placeholders.info": " Wymień zmienne, które chcesz podglądnąć za pomocą nazwy = wartość",
|
||||
"status_bar.vertex_distance": "Odległość: 0%",
|
||||
"dialog.create_gif.title": "Zapisz GIF",
|
||||
"dialog.create_gif.length": "Długość (sekundy)",
|
||||
"dialog.create_gif.fps": "FPS",
|
||||
"dialog.create_gif.compression": "Compression Amount",
|
||||
"dialog.create_gif.play": "Start Animation",
|
||||
"category.animation": "Animation",
|
||||
"action.record_model_gif": "Record GIF",
|
||||
"action.record_model_gif.desc": "Record an animated GIF of the model from the current angle",
|
||||
"display.mirror": "Mirror",
|
||||
"dialog.create_gif.compression": "Ilość kompresji",
|
||||
"dialog.create_gif.play": "Rozpocznij animację",
|
||||
"category.animation": "Animacja",
|
||||
"action.record_model_gif": "Zapisz GIF",
|
||||
"action.record_model_gif.desc": "\n Nagraj animowany GIF modelu z bieżącego kąta",
|
||||
"display.mirror": "Lustro",
|
||||
"data.separator": "Separator",
|
||||
"message.set_background_position.title": "Background Position",
|
||||
"menu.preview.background.set_position": "Set Position",
|
||||
"dialog.toolbar_edit.hidden": "Hidden",
|
||||
"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",
|
||||
"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",
|
||||
"switches.mirror": "Mirror UV",
|
||||
"language_name": "English"
|
||||
"message.set_background_position.title": "Pozycja tła",
|
||||
"menu.preview.background.set_position": "Ustaw pozycję",
|
||||
"dialog.toolbar_edit.hidden": "\n Ukryty",
|
||||
"action.export_class_entity": "Eksportuj byt Java",
|
||||
"action.export_class_entity.desc": "Wyeksportuj model bytu jako klasę Java",
|
||||
"settings.seethrough_outline": "Kontury X-Ray",
|
||||
"settings.seethrough_outline.desc": "Pokaż kontury przez obiekty",
|
||||
"mode.edit": "Edytować",
|
||||
"mode.paint": "Farba",
|
||||
"mode.display": "Ekspozycja",
|
||||
"mode.animate": "Animować",
|
||||
"status_bar.recording_gif": "Nagrywanie GIF",
|
||||
"status_bar.processing_gif": "Przetwarzanie GIF",
|
||||
"settings.backup_retain": "Czas podtrzymania kopii zapasowej",
|
||||
"settings.backup_retain.desc": "Ustaw jak długo Blockbench zachowuje stare kopie zapasowe w dniach",
|
||||
"action.rotate_tool": "Narzędzie oobracania",
|
||||
"action.rotate_tool.desc": "Narzędzie do wybierania i obracania elementów",
|
||||
"action.fill_tool": "Wiaderko farby",
|
||||
"action.fill_tool.desc": "Wiaderko farby zalewa maluje obszar na jeden kolor",
|
||||
"action.eraser": "Gumka",
|
||||
"action.eraser.desc": "Gumka zastępuje teksturę przeżroczystością",
|
||||
"action.color_picker": "Prubnik koloru",
|
||||
"action.color_picker.desc": "Narzędzie do wyboru koloru pikseli na teksturze",
|
||||
"action.open_backup_folder": "Otwórz folder kopii zapasowej",
|
||||
"action.open_backup_folder.desc": "Otwórz folder kopii zapasowej BlockBench",
|
||||
"switches.mirror": "Lustro UV",
|
||||
"language_name": "Polski",
|
||||
"message.plugin_reload": "Reloaded %0 local plugins",
|
||||
"settings.brightness": "Brightness",
|
||||
"settings.brightness.desc": "Brightness of the preview. Default is 50",
|
||||
"menu.preview.perspective.reset": "Reset Camera",
|
||||
"action.fill_mode": "Fill Mode",
|
||||
"action.fill_mode.desc": "Mode of the fill tool",
|
||||
"action.fill_mode.face": "Face",
|
||||
"action.fill_mode.color": "Color",
|
||||
"action.fill_mode.cube": "Cube",
|
||||
"action.toggle_mirror_uv": "Mirror UV",
|
||||
"action.toggle_mirror_uv.desc": "Toggle the UV mirroring on the X axis of the selected cubes.",
|
||||
"action.toggle_uv_overlay": "Toggle UV Overlay",
|
||||
"action.toggle_uv_overlay.desc": "When enabled, displays all UV mapping overlays above the texture.",
|
||||
"menu.texture.blank": "Apply to Untextured Faces",
|
||||
"dialog.scale.select_overflow": "Select Overflow",
|
||||
"dialog.create_texture.compress": "Compress Template"
|
||||
}
|
23
lang/ru.json
23
lang/ru.json
@ -561,13 +561,8 @@
|
||||
"menu.preview.quadview": "Четыре вида",
|
||||
"menu.preview.fullview": "Полный вид",
|
||||
"menu.preview.stop_drag": "Закончить изменение позиции",
|
||||
"menu.uv.copy": "Копировать",
|
||||
"menu.uv.paste": "Вставить",
|
||||
"menu.uv.mapping": "UV-преобразование",
|
||||
"menu.uv.mapping.export": "Экспортировать",
|
||||
"menu.uv.mapping.maximize": "Максимизировать",
|
||||
"menu.uv.mapping.auto": "Авто UV",
|
||||
"menu.uv.mapping.rel_auto": "Относительный авто UV",
|
||||
"menu.uv.mapping.rotation": "Поворот",
|
||||
"menu.uv.mapping.mirror_x": "Отразить ось X",
|
||||
"menu.uv.mapping.mirror_y": "Отразить ось Y",
|
||||
@ -825,5 +820,21 @@
|
||||
"action.open_backup_folder": "Открыть папку автосохранений",
|
||||
"action.open_backup_folder.desc": "Opens the Blockbench backup folder",
|
||||
"switches.mirror": "Mirror UV",
|
||||
"language_name": "English"
|
||||
"language_name": "English",
|
||||
"message.plugin_reload": "Reloaded %0 local plugins",
|
||||
"settings.brightness": "Brightness",
|
||||
"settings.brightness.desc": "Brightness of the preview. Default is 50",
|
||||
"menu.preview.perspective.reset": "Reset Camera",
|
||||
"action.fill_mode": "Fill Mode",
|
||||
"action.fill_mode.desc": "Mode of the fill tool",
|
||||
"action.fill_mode.face": "Face",
|
||||
"action.fill_mode.color": "Color",
|
||||
"action.fill_mode.cube": "Cube",
|
||||
"action.toggle_mirror_uv": "Mirror UV",
|
||||
"action.toggle_mirror_uv.desc": "Toggle the UV mirroring on the X axis of the selected cubes.",
|
||||
"action.toggle_uv_overlay": "Toggle UV Overlay",
|
||||
"action.toggle_uv_overlay.desc": "When enabled, displays all UV mapping overlays above the texture.",
|
||||
"menu.texture.blank": "Apply to Untextured Faces",
|
||||
"dialog.scale.select_overflow": "Select Overflow",
|
||||
"dialog.create_texture.compress": "Compress Template"
|
||||
}
|
23
lang/sv.json
23
lang/sv.json
@ -561,13 +561,8 @@
|
||||
"menu.preview.quadview": "Fyrvy",
|
||||
"menu.preview.fullview": "Fullvy",
|
||||
"menu.preview.stop_drag": "Stoppa bakgrundspositionering",
|
||||
"menu.uv.copy": "Kopiera",
|
||||
"menu.uv.paste": "Klistra in",
|
||||
"menu.uv.mapping": "UV kartläggning",
|
||||
"menu.uv.mapping.export": "Exportera",
|
||||
"menu.uv.mapping.maximize": "Maximera",
|
||||
"menu.uv.mapping.auto": "Auto UV",
|
||||
"menu.uv.mapping.rel_auto": "Rel. Auto UV",
|
||||
"menu.uv.mapping.rotation": "Rotation",
|
||||
"menu.uv.mapping.mirror_x": "Spegla X",
|
||||
"menu.uv.mapping.mirror_y": "Spegla Y",
|
||||
@ -825,5 +820,21 @@
|
||||
"action.open_backup_folder": "Open Backup Folder",
|
||||
"action.open_backup_folder.desc": "Opens the Blockbench backup folder",
|
||||
"switches.mirror": "Mirror UV",
|
||||
"language_name": "English"
|
||||
"language_name": "English",
|
||||
"message.plugin_reload": "Reloaded %0 local plugins",
|
||||
"settings.brightness": "Brightness",
|
||||
"settings.brightness.desc": "Brightness of the preview. Default is 50",
|
||||
"menu.preview.perspective.reset": "Reset Camera",
|
||||
"action.fill_mode": "Fill Mode",
|
||||
"action.fill_mode.desc": "Mode of the fill tool",
|
||||
"action.fill_mode.face": "Face",
|
||||
"action.fill_mode.color": "Color",
|
||||
"action.fill_mode.cube": "Cube",
|
||||
"action.toggle_mirror_uv": "Mirror UV",
|
||||
"action.toggle_mirror_uv.desc": "Toggle the UV mirroring on the X axis of the selected cubes.",
|
||||
"action.toggle_uv_overlay": "Toggle UV Overlay",
|
||||
"action.toggle_uv_overlay.desc": "When enabled, displays all UV mapping overlays above the texture.",
|
||||
"menu.texture.blank": "Apply to Untextured Faces",
|
||||
"dialog.scale.select_overflow": "Select Overflow",
|
||||
"dialog.create_texture.compress": "Compress Template"
|
||||
}
|
33
lang/zh.json
33
lang/zh.json
@ -288,7 +288,7 @@
|
||||
"category.blockbench": "Blockbench",
|
||||
"category.edit": "编辑",
|
||||
"category.transform": "转换",
|
||||
"category.filter": "滤器",
|
||||
"category.filter": "过滤",
|
||||
"category.view": "视图",
|
||||
"category.display": "显示设置",
|
||||
"category.textures": "贴图",
|
||||
@ -514,7 +514,7 @@
|
||||
"action.reload.desc": "重载 Blockbench,这将删除所有未保存的进度",
|
||||
"menu.file": "文件",
|
||||
"menu.edit": "编辑",
|
||||
"menu.transform": "尺寸",
|
||||
"menu.transform": "模型控制",
|
||||
"menu.filter": "插件目录",
|
||||
"menu.display": "物品显示",
|
||||
"menu.view": "视图",
|
||||
@ -561,13 +561,8 @@
|
||||
"menu.preview.quadview": "四视图",
|
||||
"menu.preview.fullview": "大视图",
|
||||
"menu.preview.stop_drag": "停止背景定位",
|
||||
"menu.uv.copy": "复制",
|
||||
"menu.uv.paste": "粘贴",
|
||||
"menu.uv.mapping": "UV贴图射映",
|
||||
"menu.uv.mapping.export": "导出",
|
||||
"menu.uv.mapping.maximize": "最大化",
|
||||
"menu.uv.mapping.auto": "自动UV",
|
||||
"menu.uv.mapping.rel_auto": "自动相对 UV",
|
||||
"menu.uv.mapping.rotation": "旋转",
|
||||
"menu.uv.mapping.mirror_x": "镜像 X 轴",
|
||||
"menu.uv.mapping.mirror_y": "镜像 Y 轴",
|
||||
@ -624,8 +619,8 @@
|
||||
"display.reference.player": "玩家",
|
||||
"display.reference.zombie": "僵尸",
|
||||
"display.reference.armor_stand": "盔甲架",
|
||||
"display.reference.baby_zombie": "幼年僵尸",
|
||||
"display.reference.armor_stand_small": "小盔甲架",
|
||||
"display.reference.baby_zombie": "小僵尸",
|
||||
"display.reference.armor_stand_small": "小形盔甲架",
|
||||
"display.reference.monitor": "普通",
|
||||
"display.reference.bow": "弓",
|
||||
"display.reference.block": "方块",
|
||||
@ -824,6 +819,22 @@
|
||||
"action.color_picker.desc": "用于选择材质纹理上像素颜色的工具",
|
||||
"action.open_backup_folder": "打开备份文件夹",
|
||||
"action.open_backup_folder.desc": "打开Blockbench备份文件夹",
|
||||
"switches.mirror": "Mirror UV",
|
||||
"language_name": "中文"
|
||||
"switches.mirror": "镜像 UV",
|
||||
"language_name": "中文",
|
||||
"message.plugin_reload": "Reloaded %0 local plugins",
|
||||
"settings.brightness": "Brightness",
|
||||
"settings.brightness.desc": "Brightness of the preview. Default is 50",
|
||||
"menu.preview.perspective.reset": "Reset Camera",
|
||||
"action.fill_mode": "Fill Mode",
|
||||
"action.fill_mode.desc": "Mode of the fill tool",
|
||||
"action.fill_mode.face": "Face",
|
||||
"action.fill_mode.color": "Color",
|
||||
"action.fill_mode.cube": "Cube",
|
||||
"action.toggle_mirror_uv": "Mirror UV",
|
||||
"action.toggle_mirror_uv.desc": "Toggle the UV mirroring on the X axis of the selected cubes.",
|
||||
"action.toggle_uv_overlay": "Toggle UV Overlay",
|
||||
"action.toggle_uv_overlay.desc": "When enabled, displays all UV mapping overlays above the texture.",
|
||||
"menu.texture.blank": "Apply to Untextured Faces",
|
||||
"dialog.scale.select_overflow": "Select Overflow",
|
||||
"dialog.create_texture.compress": "Compress Template"
|
||||
}
|
56
main.js
56
main.js
@ -1,11 +1,14 @@
|
||||
const {app, BrowserWindow} = require('electron')
|
||||
const {app, BrowserWindow, Menu} = require('electron')
|
||||
const path = require('path')
|
||||
const url = require('url')
|
||||
|
||||
let win
|
||||
let orig_win;
|
||||
|
||||
function createWindow () {
|
||||
win = new BrowserWindow({
|
||||
function createWindow() {
|
||||
if (!app.requestSingleInstanceLock()) {
|
||||
return;
|
||||
}
|
||||
let win = new BrowserWindow({
|
||||
icon:'icon.ico',
|
||||
show: false,
|
||||
backgroundColor: '#21252b',
|
||||
@ -16,11 +19,43 @@ function createWindow () {
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
if (!orig_win) orig_win = win;
|
||||
var index_path = path.join(__dirname, 'index.html')
|
||||
/*if (__dirname.includes('xampp\\htdocs\\')) {
|
||||
index_path = path.join(__dirname, 'index.php')
|
||||
}*/
|
||||
win.setMenu(null);
|
||||
if (process.platform === 'darwin') {
|
||||
var template = [{
|
||||
label: 'File',
|
||||
submenu: [{
|
||||
label: 'Quit',
|
||||
accelerator: 'CmdOrCtrl+Q',
|
||||
click: function() {
|
||||
app.quit();
|
||||
}
|
||||
}]
|
||||
}, {
|
||||
label: 'Edit',
|
||||
submenu: [{
|
||||
label: 'Cut',
|
||||
accelerator: 'CmdOrCtrl+X',
|
||||
selector: 'cut:'
|
||||
}, {
|
||||
label: 'Copy',
|
||||
accelerator: 'CmdOrCtrl+C',
|
||||
selector: 'copy:'
|
||||
}, {
|
||||
label: 'Paste',
|
||||
accelerator: 'CmdOrCtrl+V',
|
||||
selector: 'paste:'
|
||||
}, {
|
||||
label: 'Select All',
|
||||
accelerator: 'CmdOrCtrl+A',
|
||||
selector: 'selectAll:'
|
||||
}]
|
||||
}]
|
||||
var osxMenu = Menu.buildFromTemplate(template);
|
||||
Menu.setApplicationMenu(osxMenu)
|
||||
} else {
|
||||
win.setMenu(null);
|
||||
}
|
||||
win.maximize()
|
||||
win.show()
|
||||
win.loadURL(url.format({
|
||||
@ -34,6 +69,11 @@ function createWindow () {
|
||||
//win.webContents.openDevTools()
|
||||
}
|
||||
|
||||
app.on('second-instance', function (event, argv, cwd) {
|
||||
process.argv = argv
|
||||
createWindow()
|
||||
})
|
||||
|
||||
app.commandLine.appendSwitch('ignore-gpu-blacklist')
|
||||
|
||||
app.on('ready', createWindow)
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "Blockbench",
|
||||
"description": "Minecraft Block Model Editor",
|
||||
"version": "2.3.2",
|
||||
"version": "2.4.0",
|
||||
"license": "MIT",
|
||||
"author": {
|
||||
"name": "JannisX11",
|
||||
|
Loading…
x
Reference in New Issue
Block a user