<!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/start_screen.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.5.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.ErrorLog = []; window.onerror = (message, file, line) => { window.ErrorLog.push({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/misc.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/vue_components.js"></script> <script src="js/interface/panels.js"></script> <script src="js/interface/interface.js"></script> <script src="js/interface/menu_bar.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/modeling/transform_gizmo.js"></script> <script src="js/modeling/transform.js"></script> <script src="js/modeling/mesh_editing.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/preview/preview_scenes.js"></script> <script src="js/validator.js"></script> <script src="js/predicate_editor.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/generic.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/fbx.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/io/formats/image.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_preset.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 href="https://blockbench.net/downloads"> <span class="tl">web.download_app</span> <i class="material-icons">system_update</i> </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" v-if="showModes()"> <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>