blockbench/js/blockbench.js

348 lines
14 KiB
JavaScript
Raw Normal View History

2017-10-26 19:00:52 +02:00
var osfs = '/'
var prev_side = 'north';
var uv_clipboard;
var pe_list_data = []
var open_dialog = false;
2018-10-17 19:50:25 +02:00
var open_interface = false;
2017-10-26 19:00:52 +02:00
var tex_version = 1;
var pe_list;
2019-04-12 18:44:18 +02:00
const Pressing = {
shift: false,
ctrl: false,
alt: false,
overrides: {
shift: false,
ctrl: false,
alt: false,
}
2019-04-12 18:44:18 +02:00
}
2019-07-19 17:31:22 +02:00
var Prop = {
2019-07-17 18:02:07 +02:00
active_panel : 'preview',
file_path : '',
file_name : '',
2019-12-15 20:04:31 +01:00
recording : null,
2019-07-17 18:02:07 +02:00
fps : 0,
progress : 0,
session : false,
connections : 0,
2021-01-09 18:33:42 +01:00
facing : 'north',
show_right_bar : true,
show_left_bar : true,
2018-10-17 19:50:25 +02:00
}
2020-04-25 20:25:07 +02:00
2019-01-09 15:54:35 +01:00
const mouse_pos = {x:0,y:0}
const sort_collator = new Intl.Collator(undefined, {numeric: true, sensitivity: 'base'});
2017-10-26 19:00:52 +02:00
2017-11-16 22:23:41 +01:00
function canvasGridSize(shift, ctrl) {
2018-10-17 19:50:25 +02:00
if (!shift && !ctrl) {
return 16 / Math.clamp(settings.edit_size.value, 1, 512)
2018-10-17 19:50:25 +02:00
} else if (ctrl && shift) {
return 16 / Math.clamp(settings.ctrl_shift_size.value, 1, 4096)
2018-10-17 19:50:25 +02:00
} else if (ctrl) {
return 16 / Math.clamp(settings.ctrl_size.value, 1, 4096)
2018-10-17 19:50:25 +02:00
} else {
return 16 / Math.clamp(settings.shift_size.value, 1, 4096)
2018-10-17 19:50:25 +02:00
}
2017-10-26 19:00:52 +02:00
}
function updateNslideValues() {
2018-10-17 19:50:25 +02:00
2021-01-03 11:14:24 +01:00
if (Outliner.selected.length) {
2018-10-17 19:50:25 +02:00
BarItems.slider_pos_x.update()
BarItems.slider_pos_y.update()
BarItems.slider_pos_z.update()
BarItems.slider_size_x.update()
BarItems.slider_size_y.update()
BarItems.slider_size_z.update()
2019-03-09 22:06:35 +01:00
BarItems.slider_inflate.update()
2020-03-04 20:56:17 +01:00
if (!Project.box_uv) {
BarItems.slider_face_tint.update()
}
2018-10-17 19:50:25 +02:00
}
2021-01-03 11:14:24 +01:00
if (Outliner.selected.length || (Format.bone_rig && Group.selected)) {
2018-10-17 19:50:25 +02:00
BarItems.slider_origin_x.update()
BarItems.slider_origin_y.update()
BarItems.slider_origin_z.update()
BarItems.slider_rotation_x.update()
BarItems.slider_rotation_y.update()
BarItems.slider_rotation_z.update()
2019-07-17 18:02:07 +02:00
if (Format.bone_rig) {
BarItems.bone_reset_toggle.setIcon(Group.selected && Group.selected.reset ? 'check_box' : 'check_box_outline_blank')
2018-10-17 19:50:25 +02:00
} else {
2021-01-03 11:14:24 +01:00
BarItems.rescale_toggle.setIcon(Outliner.selected[0].rescale ? 'check_box' : 'check_box_outline_blank')
2018-10-17 19:50:25 +02:00
}
}
2021-01-31 20:31:45 +01:00
if (Modes.animate && NullObject.selected[0]) {
2020-08-30 15:00:41 +02:00
BarItems.slider_ik_chain_length.update();
2021-01-31 20:31:45 +01:00
BarItems.ik_enabled.setIcon(NullObject.selected[0].ik_enabled ? 'check_box' : 'check_box_outline_blank')
2019-12-15 20:04:31 +01:00
}
2021-01-03 11:14:24 +01:00
if (Texture.all.length) {
BarItems.animated_texture_frame.update();
}
2017-10-26 19:00:52 +02:00
}
//Selections
2020-12-31 15:08:35 +01:00
function updateSelection(options = {}) {
2021-08-07 12:57:27 +02:00
Outliner.elements.forEach(obj => {
2020-04-25 20:25:07 +02:00
if (selected.includes(obj) && !obj.selected && !obj.locked) {
2019-07-17 18:02:07 +02:00
obj.selectLow()
2020-04-25 20:25:07 +02:00
} else if ((!selected.includes(obj) || obj.locked) && obj.selected) {
2019-07-17 18:02:07 +02:00
obj.unselect()
2018-10-17 19:50:25 +02:00
}
if (obj instanceof Mesh) {
if (Project.selected_vertices[obj.uuid]) {
Project.selected_vertices[obj.uuid].forEachReverse(vkey => {
if (vkey in obj.vertices == false) {
Project.selected_vertices[obj.uuid].remove(vkey);
}
})
}
if (Project.selected_vertices[obj.uuid] && (Project.selected_vertices[obj.uuid].length == 0 || !obj.selected)) {
delete Project.selected_vertices[obj.uuid];
}
2021-08-07 12:57:27 +02:00
}
2019-07-17 18:02:07 +02:00
})
2020-04-25 20:25:07 +02:00
if (Group.selected && Group.selected.locked) Group.selected.unselect()
2019-12-15 20:04:31 +01:00
2021-07-29 18:17:26 +02:00
Outliner.elements.forEach(element => {
2021-08-02 22:55:30 +02:00
if (element.preview_controller.updateSelection) {
element.preview_controller.updateSelection(element);
2018-10-17 19:50:25 +02:00
}
})
2021-07-29 18:17:26 +02:00
for (var i = Outliner.selected.length-1; i >= 0; i--) {
if (!selected.includes(Outliner.selected[i])) {
Outliner.selected.splice(i, 1)
2019-07-17 18:02:07 +02:00
}
}
2021-07-29 18:17:26 +02:00
if (Outliner.selected.length) {
2021-01-31 12:51:10 +01:00
document.querySelectorAll('.selection_only').forEach(node => node.style.setProperty('visibility', 'visible'));
2019-02-03 21:09:35 +01:00
} else {
2019-07-19 17:31:22 +02:00
if (Format.bone_rig && Group.selected) {
2021-01-31 12:51:10 +01:00
document.querySelectorAll('.selection_only').forEach(node => node.style.setProperty('visibility', 'hidden'));
document.querySelectorAll('.selection_only#element').forEach(node => node.style.setProperty('visibility', 'visible'));
2019-07-19 17:31:22 +02:00
} else {
2021-01-31 12:51:10 +01:00
document.querySelectorAll('.selection_only').forEach(node => node.style.setProperty('visibility', 'hidden'));
2021-01-31 20:31:45 +01:00
if (Outliner.selected.length) {
2021-01-31 12:51:10 +01:00
document.querySelectorAll('.selection_only#element').forEach(node => node.style.setProperty('visibility', 'visible'));
2019-07-19 17:31:22 +02:00
}
}
2021-01-31 20:31:45 +01:00
if (Group.selected || NullObject.selected[0]) {
document.querySelectorAll('.selection_only#bone').forEach(node => node.style.setProperty('visibility', 'visible'));
}
2020-01-23 18:53:36 +01:00
if (Format.single_texture && Modes.paint) {
2021-01-31 12:51:10 +01:00
document.querySelectorAll('.selection_only#uv').forEach(node => node.style.setProperty('visibility', 'visible'));
2020-01-23 18:53:36 +01:00
}
}
2021-08-17 22:02:23 +02:00
if (Outliner.selected.length || (Format.single_texture && Modes.paint)) {
UVEditor.selected_faces.forEachReverse((fkey, i) => {
if (!UVEditor.getMappableElements().find(el => el.faces[fkey])) {
UVEditor.selected_faces.splice(i, 1);
}
})
2021-08-17 22:02:23 +02:00
UVEditor.loadData()
2019-07-17 18:02:07 +02:00
}
if (Modes.animate) {
2019-12-15 20:04:31 +01:00
updateKeyframeSelection();
2021-02-13 14:32:31 +01:00
if (Timeline.selected_animator && !Timeline.selected_animator.selected) {
Timeline.selected_animator = null;
}
2019-07-17 18:02:07 +02:00
}
2019-12-15 20:04:31 +01:00
BarItems.cube_counter.update();
updateNslideValues();
Interface.status_bar.vue.updateSelectionInfo();
if (settings.highlight_cubes.value || (Mesh.all[0])) updateCubeHighlights();
2021-07-29 18:17:26 +02:00
Canvas.updatePivotMarker();
2019-12-15 20:04:31 +01:00
Transformer.updateSelection();
Transformer.update();
2020-07-16 09:32:59 +02:00
Preview.all.forEach(preview => {
2020-01-23 18:53:36 +01:00
preview.updateAnnotations();
})
2018-11-11 21:19:08 +01:00
2019-12-15 20:04:31 +01:00
BARS.updateConditions();
2019-07-17 18:02:07 +02:00
delete TickUpdates.selection;
2019-12-15 20:04:31 +01:00
Blockbench.dispatchEvent('update_selection');
2017-10-26 19:00:52 +02:00
}
function selectAll() {
2019-12-15 20:04:31 +01:00
if (Modes.animate) {
selectAllKeyframes()
2021-08-19 15:18:01 +02:00
} else if (Prop.active_panel == 'uv') {
UVEditor.selectAll()
} else if (Modes.edit && Mesh.selected.length && Mesh.selected.length === Outliner.selected.length && BarItems.selection_mode.value !== 'object') {
let unselect = Mesh.selected[0].getSelectedVertices().length == Object.keys(Mesh.selected[0].vertices).length;
Mesh.selected.forEach(mesh => {
if (unselect) {
delete Project.selected_vertices[mesh.uuid];
} else {
mesh.getSelectedVertices(true).replace(Object.keys(mesh.vertices));
}
})
updateSelection();
2019-12-15 20:04:31 +01:00
} else if (Modes.edit || Modes.paint) {
2021-01-30 22:30:34 +01:00
if (Outliner.selected.length < Outliner.elements.length) {
if (Outliner.root.length == 1 && !Outliner.root[0].locked) {
Outliner.root[0].select();
} else {
2021-01-30 22:30:34 +01:00
Outliner.elements.forEach(obj => {
obj.selectLow()
})
TickUpdates.selection = true;
}
2019-12-15 20:04:31 +01:00
} else {
unselectAll()
}
2018-10-17 19:50:25 +02:00
}
Blockbench.dispatchEvent('select_all')
2017-10-26 19:00:52 +02:00
}
function unselectAll() {
2021-08-07 12:57:27 +02:00
Project.selected_elements.forEachReverse(obj => obj.unselect())
2019-07-17 18:02:07 +02:00
if (Group.selected) Group.selected.unselect()
Group.all.forEach(function(s) {
2018-10-17 19:50:25 +02:00
s.selected = false
})
2021-08-07 12:57:27 +02:00
for (let key in Project.selected_vertices) {
delete Project.selected_vertices[key];
}
2020-03-04 20:56:17 +01:00
TickUpdates.selection = true;
2017-10-26 19:00:52 +02:00
}
2019-04-07 18:53:33 +02:00
//Backup
setInterval(function() {
2021-07-20 12:07:47 +02:00
if (Project && (Outliner.root.length || Project.textures.length)) {
2019-04-07 18:53:33 +02:00
try {
var model = Codecs.project.compile({compressed: false, backup: true});
2019-04-07 18:53:33 +02:00
localStorage.setItem('backup_model', model)
} catch (err) {
console.log('Unable to create backup. ', err)
}
}
}, 1e3*30)
2017-10-26 19:00:52 +02:00
//Misc
2019-03-09 22:06:35 +01:00
const TickUpdates = {
2019-07-19 17:31:22 +02:00
Run() {
2020-03-04 20:56:17 +01:00
try {
if (TickUpdates.selection) {
delete TickUpdates.selection;
updateSelection()
}
2021-08-17 22:02:23 +02:00
if (TickUpdates.UVEditor) {
delete TickUpdates.UVEditor;
UVEditor.loadData()
2020-03-04 20:56:17 +01:00
}
if (TickUpdates.texture_list) {
delete TickUpdates.texture_list;
loadTextureDraggable();
}
if (TickUpdates.keyframe_selection) {
delete TickUpdates.keyframe_selection;
Vue.nextTick(updateKeyframeSelection)
}
if (TickUpdates.keybind_conflicts) {
delete TickUpdates.keybind_conflicts;
updateKeybindConflicts();
}
} catch (err) {
console.error(err);
2019-04-07 18:53:33 +02:00
}
2018-10-17 19:50:25 +02:00
}
2017-10-26 19:00:52 +02:00
}
2019-03-09 22:06:35 +01:00
2020-07-16 09:32:59 +02:00
const documentReady = new Promise((resolve, reject) => {
$(document).ready(function() {
resolve()
})
});
BARS.defineActions(() => {
new Action('about_window', {
name: tl('dialog.settings.about') + '...',
description: `Blockbench ${Blockbench.version}`,
icon: 'info',
category: 'blockbench',
click: function () {
const data = {
isApp,
version_label: Blockbench.version
};
jQuery.ajax({
url: 'https://api.github.com/repos/JannisX11/blockbench/releases/latest',
cache: false,
type: 'GET',
success(release) {
let v = release.tag_name.replace(/^v/, '');
if (compareVersions(v, Blockbench.version)) {
data.version_label = `${Blockbench.version} (${tl('about.version.update_available', [v])})`;
} else if (compareVersions(Blockbench.version, v)) {
data.version_label = `${Blockbench.version} (Pre-release)`;
} else {
data.version_label = `${Blockbench.version} (${tl('about.version.up_to_date')}😄)`;
}
},
error(err) {}
})
new Dialog({
id: 'about',
title: 'dialog.settings.about',
width: 600,
singleButton: true,
title_menu: new Menu([
'settings_window',
'keybindings_window',
'theme_window',
'about_window',
]),
component: {
data() {return data},
template: `
<div>
2021-08-08 14:51:00 +02:00
<div class="blockbench_logo" id="about_page_title">
<img src="assets/logo_text_white.svg" alt="Blockbench" width="240px">
</div>
<p><b>${tl('about.version')}</b> <span>{{ version_label }}</span></p>
<p><b>${tl('about.creator')}</b> JannisX11</p>
<p><b>${tl('about.website')}</b> <a class="open-in-browser" href="https://blockbench.net">blockbench.net</a></p>
<p><b>${tl('about.repository')}</b> <a class="open-in-browser" href="https://github.com/JannisX11/blockbench">github.com/JannisX11/blockbench</a></p>
<p>${tl('about.vertex_snap')}</p>
<p><b>${tl('about.icons')}</b> <a href="https://material.io/icons/" class="open-in-browser">material.io/icons</a> &amp; <a href="https://fontawesome.com/icons/" class="open-in-browser">fontawesome</a></p>
<p><b>${tl('about.libraries')}</b>
<a class="open-in-browser" href="https://electronjs.org">Electron</a>,
<a class="open-in-browser" href="https://vuejs.org">Vue</a>,
<a class="open-in-browser" href="https://github.com/weibangtuo/vue-tree">Vue Tree</a>,
<a class="open-in-browser" href="https://github.com/sagalbot/vue-sortable">Vue Sortable</a>,
<a class="open-in-browser" href="https://threejs.org">ThreeJS</a>,
<a class="open-in-browser" href="https://github.com/lo-th/fullik">Full IK</a>,
<a class="open-in-browser" href="https://github.com/oliver-moran/jimp">Jimp</a>,
<a class="open-in-browser" href="https://bgrins.github.io/spectrum">Spectrum</a>,
2021-09-02 12:55:34 +02:00
<a class="open-in-browser" href="https://github.com/stijlbreuk/vue-color-picker-wheel">Vue Color Picker Wheel</a>,
<a class="open-in-browser" href="https://github.com/jnordberg/gif.js">gif.js</a>,
<a class="open-in-browser" href="https://stuk.github.io/jszip/">JSZip</a>,
<a class="open-in-browser" href="https://github.com/rotemdan/lzutf8.js">LZ-UTF8</a>,
<a class="open-in-browser" href="https://jquery.com">jQuery</a>,
<a class="open-in-browser" href="https://jqueryui.com">jQuery UI</a>,
<a class="open-in-browser" href="https://github.com/furf/jquery-ui-touch-punch">jQuery UI Touch Punch</a>,
<a class="open-in-browser" href="https://github.com/eligrey/FileSaver.js">FileSaver.js</a>,
<a class="open-in-browser" href="https://peerjs.com">PeerJS</a>,
<a class="open-in-browser" href="https://github.com/markedjs/marked">Marked</a>,
<a class="open-in-browser" href="https://prismjs.com">Prism</a>,
<a class="open-in-browser" href="https://github.com/koca/vue-prism-editor">Vue Prism Editor</a>,
<a class="open-in-browser" href="https://github.com/JannisX11/molangjs">MolangJS</a>,
<a class="open-in-browser" href="https://github.com/JannisX11/wintersky">Wintersky</a>
</p>
</div>`
}
}).show()
}
})
})
2018-10-17 19:50:25 +02:00
const entityMode = {
2020-03-10 22:19:17 +01:00
hardcodes: JSON.parse('{"geometry.chicken":{"body":{"rotation":[90,0,0]}},"geometry.llama":{"chest1":{"rotation":[0,90,0]},"chest2":{"rotation":[0,90,0]},"body":{"rotation":[90,0,0]}},"geometry.cow":{"body":{"rotation":[90,0,0]}},"geometry.sheep.sheared":{"body":{"rotation":[90,0,0]}},"geometry.sheep":{"body":{"rotation":[90,0,0]}},"geometry.phantom":{"body":{"rotation":[0,0,0]},"wing0":{"rotation":[0,0,5.7]},"wingtip0":{"rotation":[0,0,5.7]},"wing1":{"rotation":[0,0,-5.7]},"wingtip1":{"rotation":[0,0,-5.7]},"head":{"rotation":[11.5,0,0]},"tail":{"rotation":[0,0,0]},"tailtip":{"rotation":[0,0,0]}},"geometry.pig":{"body":{"rotation":[90,0,0]}},"geometry.ocelot":{"body":{"rotation":[90,0,0]},"tail1":{"rotation":[90,0,0]},"tail2":{"rotation":[90,0,0]}},"geometry.cat":{"body":{"rotation":[90,0,0]},"tail1":{"rotation":[90,0,0]},"tail2":{"rotation":[90,0,0]}},"geometry.turtle":{"eggbelly":{"rotation":[90,0,0]},"body":{"rotation":[90,0,0]}},"geometry.villager.witch":{"hat2":{"rotation":[-3,0,1.5]},"hat3":{"rotation":[-6,0,3]},"hat4":{"rotation":[-12,0,6]}},"geometry.pufferfish.mid":{"spines_top_front":{"rotation":[45,0,0]},"spines_top_back":{"rotation":[-45,0,0]},"spines_bottom_front":{"rotation":[-45,0,0]},"spines_bottom_back":{"rotation":[45,0,0]},"spines_left_front":{"rotation":[0,45,0]},"spines_left_back":{"rotation":[0,-45,0]},"spines_right_front":{"rotation":[0,-45,0]},"spines_right_back":{"rotation":[0,45,0]}},"geometry.pufferfish.large":{"spines_top_front":{"rotation":[45,0,0]},"spines_top_back":{"rotation":[-45,0,0]},"spines_bottom_front":{"rotation":[-45,0,0]},"spines_bottom_back":{"rotation":[45,0,0]},"spines_left_front":{"rotation":[0,45,0]},"spines_left_back":{"rotation":[0,-45,0]},"spines_right_front":{"rotation":[0,-45,0]},"spines_right_back":{"rotation":[0,45,0]}},"geometry.tropicalfish_a":{"leftFin":{"rotation":[0,-35,0]},"rightFin":{"rotation":[0,35,0]}},"geometry.tropicalfish_b":{"leftFin":{"rotation":[0,-35,0]},"rightFin":{"rotation":[0,35,0]}}}')
2018-10-17 19:50:25 +02:00
}