mirror of
https://github.com/JannisX11/blockbench.git
synced 2025-01-06 12:35:36 +08:00
d1424b7c65
Support icons in dialog sidebar pages Improve menu bar on touch devices Change version label for modded entity to include 1.18
464 lines
20 KiB
HTML
464 lines
20 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<title>Blockbench</title>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<meta name="theme-color" content="#181a1f">
|
|
<meta name="robots" content="noindex">
|
|
<link rel="manifest" href="manifest.webmanifest">
|
|
<link rel="shortcut icon" href="favicon.png" type="image/x-icon" />
|
|
<link rel="apple-touch-icon" href="icon_full.png">
|
|
<link rel="stylesheet" href="css/w3.css">
|
|
<link rel="stylesheet" href="css/jquery-ui.min.css">
|
|
<link rel="stylesheet" href="css/fontawesome.css">
|
|
<link rel="stylesheet" href="css/spectrum.css">
|
|
<link rel="stylesheet" href="css/prism.css">
|
|
<link rel="stylesheet" href="css/setup.css">
|
|
<link rel="stylesheet" href="css/general.css">
|
|
<link rel="stylesheet" href="css/window.css">
|
|
<link rel="stylesheet" href="css/panels.css">
|
|
<link rel="stylesheet" href="css/dialogs.css">
|
|
<style type="text/css" id="theme_css"></style>
|
|
</head>
|
|
<body spellcheck="false">
|
|
<script>
|
|
if (typeof module === 'object') {window.module = module; module = undefined;}//jQuery Fix
|
|
const isApp = typeof require !== 'undefined';
|
|
const appVersion = '4.2.0-beta.0';
|
|
|
|
|
|
if (localStorage.getItem('theme')) {
|
|
try {
|
|
stored_theme = JSON.parse(localStorage.getItem('theme'));
|
|
document.body.style.setProperty('--color-dark', stored_theme.colors.dark);
|
|
} catch (err) {}
|
|
}
|
|
|
|
window.onerror = (message, file, line) => {
|
|
if (typeof Blockbench != 'undefined' && Blockbench.setup_successful) return;
|
|
|
|
let error_element = document.querySelector('#loading_error_detail');
|
|
if (error_element && !error_element.innerText) {
|
|
error_element.innerText = `${message}\nIn .${file.split(location.origin).join('')}:${line}`
|
|
}
|
|
}
|
|
</script>
|
|
<div id="loading_error_message" style="display: none;">
|
|
<div>An error occurred while loading Blockbench</div>
|
|
<div id="loading_error_detail" style="color: var(--color-subtle_text);"></div>
|
|
<button onclick="isApp ? Blockbench.reload() : window.location.reload(true)" class="large" style="margin-right: auto; margin-left: auto;">Reload</button>
|
|
<button onclick="window.close()" class="large" style="margin-right: auto; margin-left: auto;">Quit</button>
|
|
</div>
|
|
<script src="lib/vue.min.js"></script>
|
|
<script src="lib/vue_sortable.js"></script>
|
|
<script src="lib/jquery.js"></script>
|
|
<script src="lib/jquery-ui.min.js"></script>
|
|
<script src="lib/targa.js"></script>
|
|
<script src="lib/jimp.min.js"></script>
|
|
<script src="lib/jszip.min.js"></script>
|
|
<script src="lib/gif.js"></script>
|
|
<script src="lib/FileSaver.js"></script>
|
|
<script src="lib/prism.js"></script>
|
|
<script src="lib/VuePrismEditor.min.js"></script>
|
|
<script src="lib/molang-prism-syntax.js"></script>
|
|
<script src="lib/lzutf8.js"></script>
|
|
<script src="lib/peer.min.js"></script>
|
|
<script src="lib/marked.min.js"></script>
|
|
<script src="lib/spectrum.js"></script>
|
|
<script src="lib/color-picker.min.js"></script>
|
|
<script src="lib/three.min.js"></script>
|
|
<script src="lib/three_custom.js"></script>
|
|
<script src="lib/GLTFExporter.js"></script>
|
|
<script src="lib/CanvasFrame.js"></script>
|
|
<script src="lib/fik.min.js"></script>
|
|
<script src="lib/molang.umd.js"></script>
|
|
<script src="lib/wintersky.umd.js"></script>
|
|
|
|
<script src="js/webpack/bundle.js"></script>
|
|
<script src="js/preview/OrbitControls.js"></script>
|
|
<script src="js/util.js"></script>
|
|
<script src="js/property.js"></script>
|
|
<script src="js/interface/menu.js"></script>
|
|
<script src="js/interface/actions.js"></script>
|
|
<script src="js/interface/themes.js"></script>
|
|
<script src="js/blockbench.js"></script>
|
|
<script src="js/modes.js"></script>
|
|
<script src="js/api.js"></script>
|
|
<script src="js/file_system.js"></script>
|
|
<script src="js/interface/panels.js"></script>
|
|
<script src="js/interface/interface.js"></script>
|
|
<script src="js/interface/start_screen.js"></script>
|
|
<script src="js/interface/keyboard.js"></script>
|
|
<script src="js/interface/settings.js"></script>
|
|
<script src="js/interface/about.js"></script>
|
|
<script src="js/interface/dialog.js"></script>
|
|
<script src="js/interface/action_control.js"></script>
|
|
<script src="js/copy_paste.js"></script>
|
|
<script src="js/undo.js"></script>
|
|
|
|
<script type="text/javascript">
|
|
if (isApp === true) {
|
|
document.write("<script src='js/desktop.js'><\/script>");
|
|
} else {
|
|
document.write("<script src='js/web.js'><\/script>");
|
|
}
|
|
</script>
|
|
|
|
<script src="js/edit_sessions.js"></script>
|
|
<script src="js/outliner/outliner.js"></script>
|
|
<script src="js/outliner/group.js"></script>
|
|
<script src="js/outliner/mesh.js"></script>
|
|
<script src="js/outliner/cube.js"></script>
|
|
<script src="js/outliner/texture_mesh.js"></script>
|
|
<script src="js/outliner/locator.js"></script>
|
|
<script src="js/outliner/null_object.js"></script>
|
|
<script src="js/preview/preview.js"></script>
|
|
<script src="js/preview/screenshot.js"></script>
|
|
<script src="js/preview/canvas.js"></script>
|
|
<script src="js/preview/transformer.js"></script>
|
|
<script src="js/transform.js"></script>
|
|
<script src="js/texturing/textures.js"></script>
|
|
<script src="js/texturing/uv.js"></script>
|
|
<script src="js/texturing/painter.js"></script>
|
|
<script src="js/texturing/texture_generator.js"></script>
|
|
<script src="js/texturing/color.js"></script>
|
|
<script src="js/texturing/edit_texture.js"></script>
|
|
<script src="js/display_mode.js"></script>
|
|
<script src="js/animations/animation.js"></script>
|
|
<script src="js/animations/timeline_animators.js"></script>
|
|
<script src="js/animations/keyframe.js"></script>
|
|
<script src="js/animations/timeline.js"></script>
|
|
<script src="js/plugin_loader.js"></script>
|
|
|
|
<script src="js/io/codec.js"></script>
|
|
<script src="js/io/format.js"></script>
|
|
<script src="js/io/project.js"></script>
|
|
<script src="js/io/io.js"></script>
|
|
<script src="js/io/formats/bbmodel.js"></script>
|
|
<script src="js/io/formats/java_block.js"></script>
|
|
<script src="js/io/formats/bedrock.js"></script>
|
|
<script src="js/io/formats/bedrock_old.js"></script>
|
|
<script src="js/io/formats/obj.js"></script>
|
|
<script src="js/io/formats/gltf.js"></script>
|
|
<script src="js/io/formats/collada.js"></script>
|
|
<script src="js/io/formats/modded_entity.js"></script>
|
|
<script src="js/io/formats/optifine_jem.js"></script>
|
|
<script src="js/io/formats/optifine_jpm.js"></script>
|
|
<script src="js/io/formats/skin.js"></script>
|
|
<script src="js/globals.js"></script>
|
|
|
|
<script>if (window.module) module = window.module;</script>
|
|
|
|
<div style="display: none;"></div>
|
|
|
|
<div id="overlay_message_box" style="display: none;">
|
|
<div>
|
|
<h3><i class="material-icons">keyboard</i><span class="tl">keybindings.recording</span></h3>
|
|
<p class="tl">keybindings.press</p>
|
|
<button class="tl" onclick="Keybinds.recording.stopRecording()">dialog.cancel</button>
|
|
<button class="tl" onclick="Keybinds.recording.clear().stopRecording()">keybindings.clear</button>
|
|
<div id="keybind_input_box" contenteditable="true" style="font-size: 0"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<dialog class="dialog draggable" id="entity_import">
|
|
<div class="dialog_handle">
|
|
<div class="dialog_title tl">dialog.entitylist.title</div>
|
|
</div>
|
|
<div class="dialog_content">
|
|
<div class="dialog_bar narrow tl">dialog.entitylist.text</div>
|
|
<div class="search_bar">
|
|
<input type="text" class="dark_bordered" id="pe_search_bar" oninput="pe_list._data.search_term = $(this).val().toUpperCase()">
|
|
<i class="material-icons" id="plugin_search_bar_icon">search</i>
|
|
</div>
|
|
<ul id="pe_list" class="list">
|
|
<li v-for="item in searched" v-bind:class="{ selected: item.selected }" v-on:click="selectE(item, $event)" v-on:dblclick="open(item)">
|
|
<img class="pe_icon" v-if="item.icon" v-bind:src="item.icon">
|
|
<div class="pe_icon" v-else></div>
|
|
<h4>{{ item.title }} <span>({{ item.name }})</span></h4>
|
|
<p>{{ item.bonecount+' '+tl('dialog.entitylist.bones') }}, {{ item.cubecount+' '+tl('dialog.entitylist.cubes') }}</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="dialog_bar button_bar">
|
|
<button type="button" class="tl confirm_btn" onclick="">dialog.import</button>
|
|
<button type="button" class="cancel_btn tl" onclick="hideDialog();BarItems.close_project.click()">dialog.cancel</button>
|
|
</div>
|
|
<div class="dialog_close_button" onclick="hideDialog();BarItems.close_project.click()"><i class="material-icons">clear</i></div>
|
|
</dialog>
|
|
|
|
<dialog class="dialog draggable" id="image_extruder">
|
|
<div class="dialog_handle">
|
|
<div class="dialog_title tl">dialog.extrude.title</div>
|
|
</div>
|
|
|
|
<div class="dialog_content">
|
|
<div class="dialog_bar">
|
|
<label class="tl">dialog.extrude.mode</label>
|
|
<div class="bar_select f_left">
|
|
<select id="scan_mode" name="scan_mode">
|
|
<option class="tl" id="areas" selected>dialog.extrude.mode.areas</option>
|
|
<option class="tl" id="lines">dialog.extrude.mode.lines</option>
|
|
<option class="tl" id="columns">dialog.extrude.mode.columns</option>
|
|
<option class="tl" id="pixels">dialog.extrude.mode.pixels</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="dialog_bar">
|
|
<label class="tl">dialog.extrude.opacity</label>
|
|
<input class="tool" type="range" id="scan_tolerance" value="255" min="1" max="255">
|
|
<label id="scan_tolerance_label">255</label>
|
|
</div>
|
|
|
|
<canvas height="256" width="256" id="extrusion_canvas"></canvas>
|
|
</div>
|
|
|
|
<div class="dialog_bar button_bar">
|
|
<button type="button" class="confirm_btn tl" onclick="Extruder.startConversion()">Scan and Import</button>
|
|
<button type="button" class="cancel_btn tl" onclick="hideDialog()">dialog.cancel</button>
|
|
</div>
|
|
<div class="dialog_close_button" onclick="hideDialog()"><i class="material-icons">clear</i></div>
|
|
</dialog>
|
|
|
|
<dialog class="dialog draggable" id="scaling">
|
|
<div class="dialog_handle">
|
|
<div class="dialog_title tl">dialog.scale.title</div>
|
|
</div>
|
|
|
|
<div class="dialog_content">
|
|
<label class="tl">dialog.scale.axis</label>
|
|
|
|
<div class="dialog_bar" style="height: 32px;">
|
|
<input type="checkbox" class="toggle_panel" id="model_scale_x_axis" onchange="scaleAll()" checked>
|
|
<label class="toggle_panel" for="model_scale_x_axis">X</label>
|
|
<input type="checkbox" class="toggle_panel" id="model_scale_y_axis" onchange="scaleAll()" checked>
|
|
<label class="toggle_panel" for="model_scale_y_axis">Y</label>
|
|
<input type="checkbox" class="toggle_panel" id="model_scale_z_axis" onchange="scaleAll()" checked>
|
|
<label class="toggle_panel" for="model_scale_z_axis">Z</label>
|
|
</div>
|
|
|
|
<label class="tl">data.origin</label>
|
|
<div class="dialog_bar">
|
|
<label for="scaling_origin_x" class="inline_label tl">X</label>
|
|
<input type="number" id="scaling_origin_x" class="dark_bordered medium_width" oninput="scaleAll()">
|
|
<label for="scaling_origin_y" class="inline_label tl">Y</label>
|
|
<input type="number" id="scaling_origin_y" class="dark_bordered medium_width" oninput="scaleAll()">
|
|
<label for="scaling_origin_z" class="inline_label tl">Z</label>
|
|
<input type="number" id="scaling_origin_z" class="dark_bordered medium_width" oninput="scaleAll()">
|
|
<div class="tool" style="float: none" onclick="setScaleAllPivot('origin')">
|
|
<div class="tooltip tl">dialog.scale.element_pivot</div>
|
|
<i class="material-icons">center_focus_strong</i>
|
|
</div>
|
|
<div class="tool" style="float: none" onclick="setScaleAllPivot('selection')">
|
|
<div class="tooltip tl">dialog.scale.selection_center</div>
|
|
<i class="material-icons">filter_tilt_shift</i>
|
|
</div>
|
|
</div>
|
|
|
|
<label class="tl">dialog.scale.scale</label>
|
|
<div class="dialog_bar" style="height: 32px;">
|
|
<input type="range" id="model_scale_range" value="1" min="0" max="4" step="0.02" oninput="modelScaleSync()">
|
|
<input type="number" class="f_left dark_bordered" id="model_scale_label" min="0" max="4" step="0.02" value="1" oninput="modelScaleSync(true)">
|
|
</div>
|
|
|
|
<div class="dialog_bar narrow" id="scaling_clipping_warning"></div>
|
|
</div>
|
|
|
|
<div class="dialog_bar button_bar">
|
|
<button type="button" onclick="scaleAll(true)" class="confirm_btn tl">dialog.scale.confirm</button>
|
|
<button type="button" class="cancel_btn tl" onclick="cancelScaleAll()">dialog.cancel</button>
|
|
<button type="button" class="minor hidden tl" id="scale_overflow_btn" onclick="scaleAllSelectOverflow()">dialog.scale.select_overflow</button>
|
|
</div>
|
|
<div class="dialog_close_button" onclick="cancelScaleAll()"><i class="material-icons">clear</i></div>
|
|
</dialog>
|
|
|
|
<dialog class="dialog draggable" id="create_preset">
|
|
<div class="dialog_handle">
|
|
<div class="dialog_title tl">dialog.display_presets.title</div>
|
|
</div>
|
|
<div class="dialog_content">
|
|
<div class="dialog_bar tl">dialog.display_preset.message</div>
|
|
<div class="dialog_bar">
|
|
<input type="checkbox" id="thirdperson_righthand_save" checked>
|
|
<label for="thirdperson_righthand_save" class="tl">display.slot.third_right</label>
|
|
</div>
|
|
<div class="dialog_bar">
|
|
<input type="checkbox" id="thirdperson_lefthand_save" checked>
|
|
<label for="thirdperson_lefthand_save" class="tl">display.slot.third_left</label>
|
|
</div>
|
|
<div class="dialog_bar">
|
|
<input type="checkbox" id="firstperson_righthand_save" checked>
|
|
<label for="firstperson_righthand_save" class="tl">display.slot.first_right</label>
|
|
</div>
|
|
<div class="dialog_bar">
|
|
<input type="checkbox" id="firstperson_lefthand_save" checked>
|
|
<label for="firstperson_lefthand_save" class="tl">display.slot.first_left</label>
|
|
</div>
|
|
<div class="dialog_bar">
|
|
<input type="checkbox" id="head_save" checked>
|
|
<label for="head_save" class="tl">display.slot.head</label>
|
|
</div>
|
|
<div class="dialog_bar">
|
|
<input type="checkbox" id="ground_save" checked>
|
|
<label for="ground_save" class="tl">display.slot.ground</label>
|
|
</div>
|
|
<div class="dialog_bar">
|
|
<input type="checkbox" id="fixed_save" checked>
|
|
<label for="fixed_save" class="tl">display.slot.frame</label>
|
|
</div>
|
|
<div class="dialog_bar">
|
|
<input type="checkbox" id="gui_save" checked>
|
|
<label for="gui_save" class="tl">display.slot.gui</label>
|
|
</div>
|
|
<div class="dialog_bar narrow">
|
|
<label class="tl">generic.name</label>
|
|
</div>
|
|
<div class="dialog_bar">
|
|
<input type="text" id="preset_name" class="input_wide" id="new preset">
|
|
</div>
|
|
</div>
|
|
<div class="dialog_bar button_bar">
|
|
<button type="button" class="tl confirm_btn" onclick="DisplayMode.createPreset()">dialog.display_preset.create</button>
|
|
<button type="button" class="tl cancel_btn" onclick="hideDialog()">dialog.cancel</button>
|
|
</div>
|
|
<div class="dialog_close_button" onclick="hideDialog()"><i class="material-icons">clear</i></div>
|
|
</dialog>
|
|
|
|
<dialog class="dialog draggable" id="text_input">
|
|
<div class="dialog_handle">
|
|
<div class="dialog_title tl">dialog.input.title</div>
|
|
</div>
|
|
|
|
<div class="dialog_content">
|
|
<input type="text" id="text_input_field" class="dark_bordered input_wide">
|
|
</div>
|
|
|
|
<div class="dialog_bar button_bar">
|
|
<button type="button" class="confirm_btn tl" onclick="hideDialog()">dialog.confirm</button>
|
|
<button type="button" class="cancel_btn tl" onclick="hideDialog()">dialog.cancel</button>
|
|
</div>
|
|
<div class="dialog_close_button" onclick="hideDialog()"><i class="material-icons">clear</i></div>
|
|
</dialog>
|
|
|
|
<div id="dialog_wrapper"></div>
|
|
|
|
<header>
|
|
<ul id="mac_window_menu" hidden></ul>
|
|
<div id="corner_logo" class="app-drag-region">
|
|
<img class="blockbench_logo" src="assets/logo_text_white.svg" alt="Blockbench" />
|
|
</div>
|
|
<ul id="menu_bar" class="scroll_horizontal"></ul>
|
|
<div id="title_bar_home_button" class="tool" onclick="Interface.tab_bar.openNewTab()"><i class="material-icons">home</i></div>
|
|
<div id="title_bar_undo_controls" hidden>
|
|
<div class="tool" onclick="BarItems.undo.trigger()"><i class="material-icons">undo</i></div>
|
|
<div class="tool" onclick="BarItems.redo.trigger()"><i class="material-icons">redo</i></div>
|
|
</div>
|
|
<div class="app-drag-region" id="header_free_bar"></div>
|
|
<div id="update_menu"></div>
|
|
<ul id="windows_window_menu" hidden>
|
|
<li onclick="currentwindow.minimize()"><i class="material-icons" style="margin-top: 4px;">remove</i></li>
|
|
<li onclick="currentwindow.isMaximized() ? currentwindow.unmaximize() : currentwindow.maximize()"><i class="material-icons">crop_square</i><!--🗖--></li>
|
|
<li class="wwm_r" onclick="currentwindow.close()"><i class="material-icons">clear</i></li>
|
|
</ul>
|
|
<button id="web_download_button" hidden><a class="tl" href="https://blockbench.net/downloads">web.download_app</a></button>
|
|
</header>
|
|
|
|
|
|
<div id="page_wrapper" class="invisible start_screen">
|
|
|
|
<div id="blackout" class="darken"></div>
|
|
|
|
<div id="tab_bar" :class="{drag_mode: drag_target_index !== null}">
|
|
<div id="tab_bar_list">
|
|
<div
|
|
class="project_tab"
|
|
v-for="(project, index) in tabs" :key="project.uuid"
|
|
:class="{
|
|
selected: project.selected,
|
|
new_tab: project.is_new_tab,
|
|
dragging: index == drag_target_index,
|
|
move_back: (drag_position_index !== null && index > drag_target_index && drag_position_index >= index),
|
|
move_forth: (drag_position_index !== null && index < drag_target_index && drag_position_index <= index)
|
|
}"
|
|
:title="project.name || project.geometry_name"
|
|
@dblclick="project.openSettings()"
|
|
@mousedown="mouseDown(project, $event)"
|
|
@mouseup="mouseUp(project, $event)"
|
|
@mouseenter="mouseEnter(project, $event)"
|
|
@mouseleave="mouseLeave(project, $event)"
|
|
>
|
|
<label class="project_tab_session_badge" v-if="project.EditSession"><i class="material-icons">group</i>{{ project.EditSession.client_count }}</label>
|
|
<label>{{ project.getDisplayName() }}</label>
|
|
<div class="project_tab_close_button" :class="{unsaved: !project.saved}" :title="close_tab_label" @click="project.close()">
|
|
<i class="material-icons close_icon">clear</i>
|
|
<i class="material-icons unsaved_icon" v-if="!project.saved">fiber_manual_record</i>
|
|
</div>
|
|
</div>
|
|
<div id="new_tab_button" v-if="!new_tab.visible" @click="openNewTab()" :title="new_tab.name">
|
|
<i class="material-icons">add</i>
|
|
</div>
|
|
</div>
|
|
<div id="search_tab_button" v-if="projects.length > 1" @click="searchTabs()" :title="search_tabs_label">
|
|
<i class="material-icons">search</i>
|
|
</div>
|
|
</div>
|
|
|
|
<dialog id="action_selector"></dialog>
|
|
|
|
<div id="start_screen"></div>
|
|
|
|
<div id="work_screen" hidden>
|
|
|
|
<div id="main_toolbar">
|
|
<div class="toolbar_wrapper narrow tools"></div>
|
|
|
|
<div class="toolbar_wrapper narrow tool_options"></div>
|
|
<ul id="mode_selector">
|
|
<li
|
|
v-for="mode in options"
|
|
v-if="Condition(mode.condition)"
|
|
v-bind:class="{selected: mode.selected}"
|
|
v-on:mousedown="mode.select()"
|
|
>{{ mode.name }}</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div id="left_bar" class="sidebar"></div>
|
|
|
|
<div id="right_bar" class="sidebar"></div>
|
|
|
|
<div id="center">
|
|
<ul id="toast_notification_list">
|
|
</ul>
|
|
|
|
<div id="top_slot"></div>
|
|
<div id="preview">
|
|
</div>
|
|
<div id="bottom_slot"></div>
|
|
|
|
<div id="mobile_panel_overlay" hidden></div>
|
|
</div>
|
|
<div id="status_bar"></div>
|
|
|
|
<div id="panel_selector_bar"></div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<script src="js/boot_loader.js"></script>
|
|
<script>
|
|
if (!Blockbench || !Blockbench.setup_successful) {
|
|
document.getElementById('loading_error_message').style.display = 'block'
|
|
if (window.require) {
|
|
require('electron').remote.getCurrentWindow().webContents.openDevTools()
|
|
}
|
|
} else {
|
|
document.getElementById('loading_error_message').innerHTML = 'No loading errors...'
|
|
}
|
|
</script>
|
|
</body>
|
|
</html> |