+ jq_dialog.append(`
${tl('dialog.confirm')}
${tl('dialog.cancel')}
`)
diff --git a/js/interface/interface.js b/js/interface/interface.js
index c583f160..4da1e10e 100644
--- a/js/interface/interface.js
+++ b/js/interface/interface.js
@@ -2,109 +2,7 @@ const StartScreen = {};
var ColorPanel;
//Panels
-class Panel {
- constructor(data) {
- var scope = this;
- this.type = 'panel'
- this.id = data.id || 'new_panel'
- this.menu = data.menu
- this.title = data.title || tl('panel.'+this.id)
- this.condition = data.condition
- this.onResize = data.onResize
- this.node = $('.panel#'+this.id).get(0)// || $('
')[0]
- if (data.toolbars) {
- this.toolbars = data.toolbars
- }
- this.handle = $('
'+this.title+' ').get(0)
- if (!Blockbench.isMobile) {
- $(this.handle).draggable({
- revertDuration: 0,
- cursorAt: { left: 24, top: 24 },
- helper: 'clone',
- revert: true,
- appendTo: 'body',
- zIndex: 19,
- scope: 'panel',
- start: function() {
- Interface.panel = scope;
- },
- stop: function(e, ui) {
- if (!ui) return;
- if (Math.abs(ui.position.top - ui.originalPosition.top) + Math.abs(ui.position.left - ui.originalPosition.left) < 180) return;
- var target = Interface.panel
- if (typeof target === 'string') {
- scope.moveTo(target)
- } else if (target.type === 'panel') {
- var target_pos = $(target.node).offset().top
- var target_height = $(target.node).height()
- var before = ui.position.top < target_pos + target_height / 2
- if (target && target !== scope) {
- scope.moveTo(target, before)
- } else {
- if (e.clientX > window.innerWidth - 200) {
- scope.moveTo('right_bar')
- } else if (e.clientX < 200) {
- scope.moveTo('left_bar')
- }
- }
- }
- saveInterfaceRearrangement()
- updateInterface()
- }
- })
- }
- $(this.node)
- .droppable({
- accept: 'h3',
- scope: 'panel',
- tolerance: 'pointer',
- drop: function(e, ui) {
- Interface.panel = scope;
- }
- })
- .click((event) => {
- setActivePanel(this.id)
- })
- .contextmenu((event) => {
- setActivePanel(this.id)
- })
- .prepend(this.handle)
- }
- moveTo(ref_panel, before) {
- var scope = this
- if (typeof ref_panel === 'string') {
- if (ref_panel === 'left_bar') {
- $('#left_bar').append(scope.node)
- } else {
- $('#right_bar').append(scope.node)
- }
- } else {
- if (before) {
- $(ref_panel.node).before(scope.node)
- } else {
- $(ref_panel.node).after(scope.node)
- }
- }
- if (this.onResize) {
- this.onResize()
- }
- updateInterface()
- }
- update() {
- var show = BARS.condition(this.condition)
- if (show) {
- $(this.node).show()
- if (Interface.data.left_bar.includes(this.id)) {
- this.width = Interface.data.left_bar_width
- } else if (Interface.data.right_bar.includes(this.id)) {
- this.width = Interface.data.right_bar_width
- }
- if (this.onResize) this.onResize()
- } else {
- $(this.node).hide()
- }
- }
-}
+
class ResizeLine {
constructor(data) {
var scope = this;
@@ -168,7 +66,7 @@ class ResizeLine {
}
}
-var Interface = {
+const Interface = {
default_data: {
left_bar_width: 332,
right_bar_width: 314,
@@ -182,11 +80,11 @@ var Interface = {
left: new ResizeLine({
id: 'left',
condition: function() {
- var i = 0;
- Interface.data.left_bar.forEach(p => {
- if (Interface.Panels[p] && BARS.condition(Interface.Panels[p].condition)) {i++;}
- })
- return i;
+ for (let p of Interface.data.left_bar) {
+ if (Interface.Panels[p] && BARS.condition(Interface.Panels[p].condition)) {
+ return true;
+ }
+ }
},
get: function() {return Interface.data.left_bar_width},
set: function(o, diff) {
@@ -204,11 +102,11 @@ var Interface = {
right: new ResizeLine({
id: 'right',
condition: function() {
- var i = 0;
- Interface.data.right_bar.forEach(p => {
- if (Interface.Panels[p] && BARS.condition(Interface.Panels[p].condition)) {i++;}
- })
- return i;
+ for (let p of Interface.data.right_bar) {
+ if (Interface.Panels[p] && BARS.condition(Interface.Panels[p].condition)) {
+ return true;
+ }
+ }
},
get: function() {return Interface.data.right_bar_width},
set: function(o, diff) {
@@ -290,15 +188,6 @@ function setupInterface() {
var old_data = Interface.data
if (interface_data.left_bar) Interface.data.left_bar = interface_data.left_bar;
if (interface_data.right_bar) Interface.data.right_bar = interface_data.right_bar;
- for (key in Interface.Panels) {
- if (!Interface.data.left_bar.includes(key) && !Interface.data.right_bar.includes(key)) {
- if (old_data.left_bar.includes(key)) {
- Interface.data.left_bar.push(key)
- } else {
- Interface.data.right_bar.push(key)
- }
- }
- }
$.extend(true, Interface.data, interface_data)
} catch (err) {}
@@ -311,135 +200,7 @@ function setupInterface() {
$('#center').toggleClass('checkerboard', settings.preview_checkerboard.value);
- $('.sidebar').droppable({
- accept: 'h3',
- scope: 'panel',
- tolerance: 'pointer',
- drop: function(e, ui) {
- Interface.panel = $(this).attr('id');
- }
- })
-
-
- //Panels
- Interface.Panels.uv = new Panel({
- id: 'uv',
- condition: () => Modes.id === 'edit' || Modes.id === 'paint',
- toolbars: {
- bottom: Toolbars.main_uv
- },
- onResize: function() {
- var size = limitNumber($(this.node).width()-10, 64, 1200)
- size = Math.floor(size/16)*16
- main_uv.setSize(size)
- }
- })
- Interface.Panels.textures = new Panel({
- id: 'textures',
- condition: () => Modes.id === 'edit' || Modes.id === 'paint',
- toolbars: {
- head: Toolbars.textures
- },
- menu: new Menu([
- 'import_texture',
- 'create_texture',
- 'reload_textures',
- 'change_textures_folder',
- 'save_textures'
- ])
- })
- Interface.Panels.element = new Panel({
- id: 'element',
- condition: () => Modes.edit,
- toolbars: {
- element_position: Toolbars.element_position,
- element_size: Toolbars.element_size,
- element_origin: Toolbars.element_origin,
- element_rotation: Toolbars.element_rotation,
- }
- })
- Interface.Panels.bone = new Panel({
- id: 'bone',
- condition: () => Modes.animate,
- toolbars: {
- //bone_ik: Toolbars.bone_ik,
- }
- })
- Interface.Panels.outliner = new Panel({
- id: 'outliner',
- condition: () => Modes.id === 'edit' || Modes.id === 'paint' || Modes.id === 'animate',
- toolbars: {
- head: Toolbars.outliner
- },
- onResize: t => {
- getAllOutlinerObjects().forEach(o => o.updateElement())
- },
- menu: new Menu([
- 'add_cube',
- 'add_group',
- '_',
- 'sort_outliner',
- 'select_all',
- 'collapse_groups',
- 'element_colors',
- 'outliner_toggle'
- ])
- })
- Interface.Panels.chat = new Panel({
- id: 'chat',
- condition: function() {return EditSession.active},
- toolbars: {},
- onResize: t => {
- },
- menu: new Menu([
- ])
- })
- Interface.Panels.animations = new Panel({
- id: 'animations',
- condition: () => Animator.open,
- toolbars: {
- head: Toolbars.animations
- }
- })
- Interface.Panels.keyframe = new Panel({
- id: 'keyframe',
- condition: () => Animator.open,
- toolbars: {
- head: Toolbars.keyframe
- }
- })
- Interface.Panels.variable_placeholders = new Panel({
- id: 'variable_placeholders',
- condition: () => Animator.open,
- toolbars: {
- }
- })
- Interface.Panels.display = new Panel({
- id: 'display',
- condition: function() {return display_mode},
- toolbars: {
- head: Toolbars.textures
- }
- })
- Interface.data.left_bar.forEach((id) => {
- if (Interface.Panels[id]) {
- $('#left_bar').append(Interface.Panels[id].node)
- }
- })
- Interface.data.right_bar.forEach((id) => {
- if (Interface.Panels[id]) {
- $('#right_bar').append(Interface.Panels[id].node)
- }
- })
-
-
- Interface.status_bar.menu = new Menu([
- 'project_window',
- 'open_model_folder',
- 'open_backup_folder',
- 'save',
- 'timelapse',
- ])
+ setupPanels()
for (var key in Interface.Resizers) {
var resizer = Interface.Resizers[key]
@@ -531,19 +292,6 @@ function setupInterface() {
})
updateInterface()
}
-function saveInterfaceRearrangement() {
- Interface.data.left_bar.length = 0
- $('#left_bar > .panel').each((i, obj) => {
- let id = $(obj).attr('id');
- Interface.data.left_bar.push(id);
- })
- Interface.data.right_bar.length = 0
- $('#right_bar > .panel').each((i, obj) => {
- let id = $(obj).attr('id');
- Interface.data.right_bar.push(id);
- })
- localStorage.setItem('interface_data', JSON.stringify(Interface.data))
-}
function updateInterface() {
BARS.updateConditions()
@@ -581,7 +329,7 @@ function updateInterfacePanels() {
}
function resizeWindow(event) {
- if (!previews || (event && event.target && event.target !== window)) {
+ if (!Preview.all || (event && event.target && event.target !== window)) {
return;
}
if (Animator.open) {
@@ -591,7 +339,7 @@ function resizeWindow(event) {
if (Interface.data) {
updateInterfacePanels()
}
- previews.forEach(function(prev) {
+ Preview.all.forEach(function(prev) {
if (prev.canvas.isConnected) {
prev.resize()
}
@@ -609,9 +357,6 @@ function resizeWindow(event) {
}
$(window).on('resize orientationchange', resizeWindow)
-function setActivePanel(panel) {
- Prop.active_panel = panel
-}
function setProjectTitle(title) {
if (Format.bone_rig && Project.geometry_name) {
title = Project.geometry_name
@@ -705,6 +450,30 @@ function setSettingsTab(tab) {
//Layout
$('#theme_editor').css('max-height', ($(window).height() - 420) +'px')
+ } else if (tab == 'credits') {
+ // About
+
+ $('#version_tag').text(appVersion)
+ if (isApp) {
+ 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, appVersion)) {
+ $('#version_tag').text(`${appVersion} (${tl('about.version.update_available', [v])})`)
+ } else if (compareVersions(appVersion, v)) {
+ $('#version_tag').text(`${appVersion} (Pre-release)`)
+ } else {
+ $('#version_tag').text(`${appVersion} (${tl('about.version.up_to_date')}😄)`)
+ }
+ },
+ error(err) {
+
+ }
+ })
+ }
}
}
@@ -731,8 +500,12 @@ $(document).keyup(function(event) {
})
//Start Screen
-function addStartScreenSection(data) {
- var obj = $('
')
+function addStartScreenSection(id, data) {
+ if (typeof id == 'object') {
+ data = id;
+ id = '';
+ }
+ var obj = $(`
`)
if (typeof data.graphic === 'object') {
var left = $('
')
obj.append(left)
@@ -802,16 +575,10 @@ function addStartScreenSection(data) {
}
}
-var documentReady = new Promise((resolve, reject) => {
- $(document).ready(function() {
- resolve()
- })
-});
(function() {
var news_call = $.getJSON('https://blockbench.net/api/news/news.json')
- var version_call = $.getJSON('https://raw.githubusercontent.com/JannisX11/blockbench/master/package.json')
Promise.all([news_call, documentReady]).then((data) => {
if (!data || !data[0]) return;
data = data[0];
@@ -845,6 +612,9 @@ var documentReady = new Promise((resolve, reject) => {
]
})
}
+ if (settings.streamer_mode.value) {
+ updateStreamerModeNotification()
+ }
//Electron
@@ -884,49 +654,21 @@ var documentReady = new Promise((resolve, reject) => {
last: true
})
}
- //Donation reminder
- if (Blockbench.startup_count % 20 === 19) {
- addStartScreenSection({
- graphic: {type: 'icon', icon: 'fas.fa-heart'},
- text: [
- {type: 'h1', text: 'Donation'},
- {text: 'Are you enjoying Blockbench? Consider donating to the project. Blockbench is 100% donation funded.'},
- {text: '[Donate](https://blockbench.net/donate)'}
- ],
- last: true
- })
- }
- })
-
- Promise.all([version_call, documentReady]).then((data) => {
- if (data[0] && data[0].version) {
- latest_version = data[0].version;
- if (isApp && compareVersions(latest_version, appVersion)) {
-
- addStartScreenSection({
- color: 'var(--color-back)',
- graphic: {type: 'icon', icon: 'update'},
- text: [
- {type: 'h1', text: tl('message.update_notification.title')},
- {text: tl('message.update_notification.message', [latest_version])},
- {type: 'button', text: tl('message.update_notification.install'), click: (e) => {
- checkForUpdates(true)
- }}
- ]
- })
- }
- }
})
})()
onVueSetup(function() {
+ StateMemory.init('start_screen_list_type', 'string')
StartScreen.vue = new Vue({
el: '#start_screen',
data: {
formats: Formats,
- recent: isApp ? recent_projects : []
+ recent: isApp ? recent_projects : [],
+ list_type: StateMemory.start_screen_list_type || 'list',
+ redact_names: settings.streamer_mode.value,
+ isApp
},
methods: {
getDate(p) {
@@ -950,6 +692,18 @@ onVueSetup(function() {
loadModelFile(files[0]);
})
//readFile(p.path, !event.shiftKey)
+ },
+ getThumbnail(model_path) {
+ let hash = model_path.hashCode().toString().replace(/^-/, '0');
+ let path = PathModule.join(app.getPath('userData'), 'thumbnails', `${hash}.png`);
+ if (!fs.existsSync(path)) return 'none'
+ path = `url('${path.replace(/\\/g, '/')}?${Math.round(Math.random()*255)}')`;
+ return path;
+ },
+ setListType(type) {
+ this.list_type = type;
+ StateMemory.start_screen_list_type = type;
+ StateMemory.save('start_screen_list_type')
}
}
})
diff --git a/js/interface/menu.js b/js/interface/menu.js
index fa225cb9..0fdf30db 100644
--- a/js/interface/menu.js
+++ b/js/interface/menu.js
@@ -181,7 +181,7 @@ class Menu {
} else {
var icon = Blockbench.getIconNode(s.icon, s.color)
}
- entry = $(`
${tl(s.name)} `)
+ entry = $(`
${tl(s.name)} `)
entry.prepend(icon)
if (typeof s.click === 'function') {
entry.click(e => {
@@ -418,11 +418,12 @@ const MenuBar = {
condition: function() {return isApp && recent_projects.length && (!EditSession.active || EditSession.hosting)},
children: function() {
var arr = []
+ let redact = settings.streamer_mode.value;
recent_projects.forEach(function(p) {
arr.push({
- name: p.name,
+ name: redact ? `[${tl('generic.redacted')}]` : p.name,
path: p.path,
- description: p.path,
+ description: redact ? '' : p.path,
icon: p.icon,
click: function(c, event) {
Blockbench.read([p.path], {}, files => {
@@ -434,8 +435,8 @@ const MenuBar = {
return arr
}
},
-
'open_model',
+ '_',
'save_project',
'save_project_as',
'convert_project',
@@ -581,6 +582,7 @@ const MenuBar = {
'preview_checkerboard',
'painting_grid',
'toggle_quad_view',
+ 'focus_on_selection',
{name: 'menu.view.screenshot', id: 'screenshot', icon: 'camera_alt', children: [
'screenshot_model',
'screenshot_app',
@@ -589,6 +591,8 @@ const MenuBar = {
]},
])
new BarMenu('help', [
+ {name: 'menu.help.search_action', description: BarItems.action_control.description, id: 'search_action', icon: 'search', click: ActionControl.select},
+ '_',
{name: 'menu.help.discord', id: 'discord', icon: 'fab.fa-discord', click: () => {
Blockbench.openLink('http://discord.blockbench.net');
}},
@@ -599,9 +603,8 @@ const MenuBar = {
Blockbench.openLink('https://github.com/JannisX11/blockbench/issues');
}},
'_',
- {name: 'menu.help.search_action', description: BarItems.action_control.description, id: 'search_action', icon: 'search', click: ActionControl.select},
+ 'open_backup_folder',
'_',
- 'update_window',
{name: 'menu.help.developer', id: 'developer', icon: 'fas.fa-wrench', children: [
'reload_plugins',
{name: 'menu.help.plugin_documentation', id: 'plugin_documentation', icon: 'fa-book', click: () => {
@@ -627,8 +630,7 @@ const MenuBar = {
Blockbench.openLink('https://blockbench.net/donate/');
}},
{name: 'menu.help.about', id: 'about', icon: 'info', click: () => {
- Settings.open();
- setSettingsTab('credits');
+ Settings.open({tab: 'credits'});
}}
])
MenuBar.update()
diff --git a/js/interface/panels.js b/js/interface/panels.js
new file mode 100644
index 00000000..2150357f
--- /dev/null
+++ b/js/interface/panels.js
@@ -0,0 +1,404 @@
+class Panel {
+ constructor(data) {
+ let scope = this;
+ this.type = 'panel';
+ this.id = data.id || 'new_panel';
+ this.icon = data.icon;
+ this.menu = data.menu;
+ this.name = tl(data.name ? data.name : `panel.${this.id}`);
+ this.selection_only = data.selection_only == true;
+ this.condition = data.condition;
+ this.onResize = data.onResize;
+ if (data.toolbars) {
+ this.toolbars = data.toolbars;
+ } else {
+ this.toolbars = {};
+ }
+ // Vue
+ if (data.component) {
+ data.component.name = 'inside-vue'
+ $(`.sidebar#${data.default_side||'left'}_bar`).append(`
`)
+
+ this.vue = new Vue({
+ components: {
+ 'inside-vue': data.component
+ },
+ template: `
+
${this.name}
+
+ `,
+ mounted() {
+ Vue.nextTick(() => {
+ updateInterfacePanels()
+ })
+ }
+ }).$mount(`#mount-panel-${this.id}`)
+
+ this.inside_vue = this.vue.$refs.inside;
+
+ this.node = $('.panel#'+this.id).get(0)
+ this.handle = $(this.node).find('h3.panel_handle').get(0)
+
+ } else {
+ this.node = $('.panel#'+this.id).get(0)
+ this.handle = $('
'+this.name+' ').get(0)
+ $(this.node).prepend(this.handle)
+ }
+
+
+ if (!Blockbench.isMobile) {
+ $(this.handle).draggable({
+ revertDuration: 0,
+ cursorAt: { left: 24, top: 24 },
+ helper: 'clone',
+ revert: true,
+ appendTo: 'body',
+ zIndex: 19,
+ scope: 'panel',
+ start: function() {
+ Interface.panel = scope;
+ },
+ stop: function(e, ui) {
+ if (!ui) return;
+ if (Math.abs(ui.position.top - ui.originalPosition.top) + Math.abs(ui.position.left - ui.originalPosition.left) < 180) return;
+ let target = Interface.panel
+ if (typeof target === 'string') {
+ scope.moveTo(target)
+ } else if (target.type === 'panel') {
+ let target_pos = $(target.node).offset().top
+ let target_height = $(target.node).height()
+ let before = ui.position.top < target_pos + target_height / 2
+ if (target && target !== scope) {
+ scope.moveTo(target, before)
+ } else {
+ if (e.clientX > window.innerWidth - 200) {
+ scope.moveTo('right_bar')
+ } else if (e.clientX < 200) {
+ scope.moveTo('left_bar')
+ }
+ }
+ }
+ saveInterfaceRearrangement()
+ updateInterface()
+ }
+ })
+ }
+ $(this.node)
+ .droppable({
+ accept: 'h3',
+ scope: 'panel',
+ tolerance: 'pointer',
+ drop: function(e, ui) {
+ Interface.panel = scope;
+ }
+ })
+ .click((event) => {
+ setActivePanel(this.id)
+ })
+ .contextmenu((event) => {
+ setActivePanel(this.id)
+ })
+
+ // Sort
+ if (Blockbench.setup_successful) {
+ if (Interface.data.right_bar.includes(this.id)) {
+ let index = Interface.data.right_bar.indexOf(this.id);
+ if (index == 0) {
+ this.moveTo(Interface.Panels[Interface.data.right_bar[1]], true)
+ } else {
+ this.moveTo(Interface.Panels[Interface.data.right_bar[index-1]], false)
+ }
+ } else if (Interface.data.left_bar.includes(this.id)) {
+ let index = Interface.data.left_bar.indexOf(this.id);
+ if (index == 0) {
+ this.moveTo(Interface.Panels[Interface.data.left_bar[1]], true)
+ } else {
+ this.moveTo(Interface.Panels[Interface.data.left_bar[index-1]], false)
+ }
+ }
+ }
+
+ // Toolbars
+ for (let key in this.toolbars) {
+ let toolbar = this.toolbars[key]
+ if (toolbar instanceof Toolbar) {
+ toolbar.toPlace(toolbar.id)
+ }
+ }
+
+ Interface.Panels[this.id] = this;
+ }
+ moveTo(ref_panel, before) {
+ let scope = this
+ if (typeof ref_panel === 'string') {
+ if (ref_panel === 'left_bar') {
+ $('#left_bar').append(scope.node)
+ } else {
+ $('#right_bar').append(scope.node)
+ }
+ } else {
+ if (before) {
+ $(ref_panel.node).before(scope.node)
+ } else {
+ $(ref_panel.node).after(scope.node)
+ }
+ }
+ if (this.onResize) {
+ this.onResize()
+ }
+ updateInterface()
+ }
+ update() {
+ let show = BARS.condition(this.condition)
+ if (show) {
+ $(this.node).show()
+ if (Interface.data.left_bar.includes(this.id)) {
+ this.width = Interface.data.left_bar_width
+ } else if (Interface.data.right_bar.includes(this.id)) {
+ this.width = Interface.data.right_bar_width
+ }
+ if (this.onResize) this.onResize()
+ } else {
+ $(this.node).hide()
+ }
+ }
+ delete() {
+ delete Interface.Panels[this.id];
+ $(this.node).detach()
+ }
+}
+
+
+function setupPanels() {
+
+ $('.sidebar').droppable({
+ accept: 'h3',
+ scope: 'panel',
+ tolerance: 'pointer',
+ drop: function(e, ui) {
+ Interface.panel = $(this).attr('id');
+ }
+ })
+
+
+ //Panels
+ Interface.Panels.uv = new Panel({
+ id: 'uv',
+ icon: 'photo_size_select_large',
+ condition: {modes: ['edit', 'paint']},
+ toolbars: {
+ bottom: Toolbars.main_uv
+ },
+ onResize: function() {
+ let size = limitNumber($(this.node).width()-10, 64, 1200)
+ size = Math.floor(size/16)*16
+ main_uv.setSize(size)
+ }
+ })
+ Interface.Panels.textures = new Panel({
+ id: 'textures',
+ icon: 'fas.fa-images',
+ condition: {modes: ['edit', 'paint']},
+ toolbars: {
+ head: Toolbars.texturelist
+ },
+ menu: new Menu([
+ 'import_texture',
+ 'create_texture',
+ 'reload_textures',
+ 'change_textures_folder',
+ 'save_textures'
+ ])
+ })
+ Interface.Panels.element = new Panel({
+ id: 'element',
+ icon: 'fas.fa-cube',
+ condition: {modes: ['edit']},
+ selection_only: true,
+ toolbars: {
+ element_position: !Blockbench.isMobile && Toolbars.element_position,
+ element_size: !Blockbench.isMobile && Toolbars.element_size,
+ element_origin: !Blockbench.isMobile && Toolbars.element_origin,
+ element_rotation: !Blockbench.isMobile && Toolbars.element_rotation,
+ }
+ })
+ Interface.Panels.bone = new Panel({
+ id: 'bone',
+ icon: 'fas.fa-bone',
+ condition: {modes: ['animate']},
+ selection_only: true,
+ toolbars: {
+ //bone_ik: Toolbars.bone_ik,
+ },
+ component: {
+ template: `
+
+
${ tl('panel.element.origin') }
+
+
+
+ `
+ }
+ })
+ Interface.Panels.outliner = new Panel({
+ id: 'outliner',
+ icon: 'list_alt',
+ condition: {modes: ['edit', 'paint', 'animate']},
+ toolbars: {
+ head: Toolbars.outliner
+ },
+ onResize: t => {
+ getAllOutlinerObjects().forEach(o => o.updateElement())
+ },
+ menu: new Menu([
+ 'add_cube',
+ 'add_group',
+ '_',
+ 'sort_outliner',
+ 'select_all',
+ 'collapse_groups',
+ 'element_colors',
+ 'outliner_toggle'
+ ])
+ })
+ Interface.Panels.chat = new Panel({
+ id: 'chat',
+ icon: 'chat',
+ condition: {method() {return EditSession.active}},
+ toolbars: {},
+ onResize: t => {
+ },
+ menu: new Menu([
+ 'toggle_chat'
+ ]),
+ component: {
+ data() {return Chat},
+ template: `
+
+
+
+
+ {{ msg.author }}:
+
+ {{ msg.timestamp }}
+
+
+
+
+ send
+
+
+ `
+ }
+ })
+ BarItems.toggle_chat.toElement('#chat_title_bar')
+
+ Interface.Panels.animations = new Panel({
+ id: 'animations',
+ icon: 'movie',
+ condition: {modes: ['animate']},
+ toolbars: {
+ head: Toolbars.animations
+ },
+ component: {
+ name: 'panel-animations',
+ data() { return {
+ animations: Animator.animations
+ }},
+ methods: {
+ sort(event) {
+ let item = Animator.animations.splice(event.oldIndex, 1)[0];
+ Animator.animations.splice(event.newIndex, 0, item);
+ }
+ },
+ template: `
+
+ `
+ }
+ })
+ Interface.Panels.keyframe = new Panel({
+ id: 'keyframe',
+ icon: 'timeline',
+ condition: {modes: ['animate']},
+ toolbars: {
+ head: Toolbars.keyframe
+ }
+ })
+ Interface.Panels.variable_placeholders = new Panel({
+ id: 'variable_placeholders',
+ icon: 'fas.fa-stream',
+ condition: {modes: ['animate']},
+ toolbars: {
+ }
+ })
+ Interface.Panels.display = new Panel({
+ id: 'display',
+ icon: 'tune',
+ condition: {modes: ['display']},
+ toolbars: {
+ head: Toolbars.display
+ }
+ })
+
+
+ Interface.data.left_bar.forEach((id) => {
+ if (Interface.Panels[id]) {
+ $('#left_bar').append(Interface.Panels[id].node)
+ }
+ })
+ Interface.data.right_bar.forEach((id) => {
+ if (Interface.Panels[id]) {
+ $('#right_bar').append(Interface.Panels[id].node)
+ }
+ })
+
+
+ Interface.status_bar.menu = new Menu([
+ 'project_window',
+ 'open_model_folder',
+ 'open_backup_folder',
+ 'save',
+ 'timelapse',
+ ])
+}
+
+
+function setActivePanel(panel) {
+ Prop.active_panel = panel
+}
+
+function saveInterfaceRearrangement() {
+ Interface.data.left_bar.empty();
+ $('#left_bar > .panel').each((i, obj) => {
+ let id = $(obj).attr('id');
+ Interface.data.left_bar.push(id);
+ })
+ Interface.data.right_bar.empty();
+ $('#right_bar > .panel').each((i, obj) => {
+ let id = $(obj).attr('id');
+ Interface.data.right_bar.push(id);
+ })
+ localStorage.setItem('interface_data', JSON.stringify(Interface.data))
+}
diff --git a/js/interface/settings.js b/js/interface/settings.js
index fb33635b..f060e440 100644
--- a/js/interface/settings.js
+++ b/js/interface/settings.js
@@ -79,9 +79,10 @@ const Settings = {
//General
new Setting('language', {value: 'en', type: 'select', options: Language.options});
new Setting('username', {value: '', type: 'text'});
- new Setting('recent_projects', {value: 12, max: 128, min: 0, type: 'number', condition: isApp});
- new Setting('backup_interval', {value: 10, type: 'number', condition: isApp});
- new Setting('backup_retain', {value: 30, type: 'number', condition: isApp});
+ new Setting('streamer_mode', {value: false, onChange() {
+ StartScreen.vue._data.redact_names = settings.streamer_mode.value;
+ updateStreamerModeNotification();
+ }});
//Interface
new Setting('origin_size', {category: 'interface', value: 10, type: 'number'});
@@ -98,7 +99,7 @@ const Settings = {
//Preview
new Setting('brightness', {category: 'preview', value: 50, type: 'number'});
new Setting('shading', {category: 'preview', value: true, onChange() {
- setShading()
+ updateShading()
}});
new Setting('render_sides', {category: 'preview', value: 'auto', type: 'select', options: {
'auto': tl('settings.render_sides.auto'),
@@ -139,9 +140,7 @@ const Settings = {
new Setting('large_grid_size', {category: 'grid', value: 3, type: 'number'});
new Setting('display_grid', {category: 'grid', value: false});
new Setting('painting_grid', {category: 'grid', value: true, onChange() {
- Cube.all.forEach(cube => {
- Canvas.buildGridBox(cube)
- })
+ Canvas.updatePaintingGrid();
}});
//Snapping
@@ -175,11 +174,18 @@ const Settings = {
new Setting('dialog_larger_cubes', {category: 'dialogs', value: true});
new Setting('dialog_rotation_limit', {category: 'dialogs', value: true});
+ //Application
+ new Setting('recent_projects', {category: 'application', value: 12, max: 128, min: 0, type: 'number', condition: isApp});
+ new Setting('backup_interval', {category: 'application', value: 10, type: 'number', condition: isApp});
+ new Setting('backup_retain', {category: 'application', value: 30, type: 'number', condition: isApp});
+ new Setting('automatic_updates', {category: 'application', value: true, condition: isApp});
+
//Export
new Setting('minifiedout', {category: 'export', value: false});
new Setting('export_groups', {category: 'export', value: true});
new Setting('sketchfab_token', {category: 'export', value: '', type: 'password'});
new Setting('credit', {category: 'export', value: 'Made with Blockbench', type: 'text'});
+
},
addCategory(id, data) {
if (!data) data = 0;
@@ -189,14 +195,24 @@ const Settings = {
items: {}
}
},
- open() {
+ open(options = 0) {
for (var sett in settings) {
if (settings.hasOwnProperty(sett)) {
Settings.old[sett] = settings[sett].value
}
}
showDialog('settings')
- setSettingsTab('setting')
+
+ setSettingsTab(options.tab || 'setting');
+
+ if (options.search) {
+ $('dialog#settings div.search_bar input').val(options.search);
+ if (options.tab == 'keybindings') {
+ Keybinds.updateSearch()
+ } else {
+ Settings.updateSearch()
+ }
+ }
},
saveLocalStorages() {
var settings_copy = {}
@@ -231,7 +247,7 @@ const Settings = {
}
Canvas.outlineMaterial.depthTest = !settings.seethrough_outline.value
if (hasSettingChanged('brightness')) {
- setShading()
+ updateShading()
}
for (var id in settings) {
var setting = settings[id];
@@ -286,9 +302,20 @@ const Settings = {
}
Settings.setup()
-window.onunload = function() {
- if (!Blockbench.hasFlag('no_localstorage_saving')) {
- Settings.saveLocalStorages()
+function updateStreamerModeNotification() {
+ $('#start_screen section#streamer_mode').detach()
+
+ if (settings.streamer_mode.value) {
+ addStartScreenSection('streamer_mode', {
+ graphic: {type: 'icon', icon: 'live_tv'},
+ color: 'var(--color-stream)',
+ text_color: 'var(--color-light)',
+ text: [
+ {type: 'h1', text: tl('interface.streamer_mode_on'), click() {
+ Settings.open({search: 'streamer_mode'})
+ }}
+ ]
+ })
}
}
diff --git a/js/io/bbmodel.js b/js/io/formats/bbmodel.js
similarity index 80%
rename from js/io/bbmodel.js
rename to js/io/formats/bbmodel.js
index 5c8f6b98..3804cd89 100644
--- a/js/io/bbmodel.js
+++ b/js/io/formats/bbmodel.js
@@ -1,5 +1,7 @@
(function() {
+let FORMATV = '3.6';
+
var codec = new Codec('project', {
name: 'Blockbench Project',
extension: 'bbmodel',
@@ -22,27 +24,18 @@ var codec = new Codec('project', {
if (!options) options = 0;
var model = {
meta: {
- format_version: '3.2',
+ format_version: FORMATV,
model_format: Format.id,
box_uv: Project.box_uv
- },
- name: Project.name,
+ }
}
- if (Format.bone_rig) {
- model.geo_name = Project.geometry_name
+
+ for (var key in ModelProject.properties) {
+ ModelProject.properties[key].copy(Project, model)
}
- if (Project.parent) {
- model.parent = Project.parent;
- }
- if (Format.id == 'java_block') {
- model.ambientocclusion = Project.ambientocclusion
- model.front_gui_light = Project.front_gui_light;
- }
- if (Format.id == 'bedrock' || Format.id == 'bedrock_legacy') {
- model.visible_box = Project.visible_box
- }
- if (Format.id == 'modded_entity') {
- model.modded_entity_version = Project.modded_entity_version
+
+ if (Project.overrides) {
+ model.overrides = Project.overrides;
}
model.resolution = {
width: Project.texture_width || 16,
@@ -128,7 +121,7 @@ var codec = new Codec('project', {
if (!model.meta.format_version) {
model.meta.format_version = model.meta.format;
}
- if (compareVersions(model.meta.format_version, '3.2')) {
+ if (compareVersions(model.meta.format_version, FORMATV)) {
Blockbench.showMessageBox({
translateKey: 'outdated_client',
icon: 'error',
@@ -143,30 +136,20 @@ var codec = new Codec('project', {
} else {
Formats.java_block.select()
}
- if (model.meta.box_uv !== undefined && Format.optional_box_uv) {
- Project.box_uv = model.meta.box_uv
- }
Blockbench.dispatchEvent('load_project', {model, path});
this.dispatchEvent('parse', {model})
- Project.name = model.name;
- if (model.geo_name) {
- Project.geometry_name = model.geo_name;
- } else if (model.parent) {
- Project.parent = model.parent;
+ if (model.meta.box_uv !== undefined && Format.optional_box_uv) {
+ Project.box_uv = model.meta.box_uv
}
- if (model.ambientocclusion !== undefined) {
- Project.ambientocclusion = !!model.ambientocclusion;
+
+ for (var key in ModelProject.properties) {
+ ModelProject.properties[key].merge(Project, model)
}
- if (model.front_gui_light !== undefined) {
- Project.front_gui_light = !!model.front_gui_light;
- }
- if (model.visible_box) {
- Project.visible_box.splice(0, Infinity, ...model.visible_box)
- }
- if (model.modded_entity_version) {
- Project.modded_entity_version = model.modded_entity_version
+
+ if (model.overrides) {
+ Project.overrides = model.overrides;
}
if (model.resolution !== undefined) {
Project.texture_width = model.resolution.width;
@@ -176,10 +159,10 @@ var codec = new Codec('project', {
if (model.textures) {
model.textures.forEach(tex => {
var tex_copy = new Texture(tex, tex.uuid).add(false);
- if (isApp && tex.path && fs.existsSync(tex.path)) {
- tex_copy.fromPath(tex.path)
- } else {
+ if (tex.source && tex.source.substr(0, 5) == 'data:') {
tex_copy.fromDataURL(tex.source)
+ } else if (isApp && tex.path && fs.existsSync(tex.path)) {
+ tex_copy.fromPath(tex.path)
}
})
}
@@ -196,8 +179,8 @@ var codec = new Codec('project', {
if (texture) {
copy.faces[face].texture = texture.uuid
}
- } else if (textures[0] && copy.faces && copy.faces[face].texture !== null) {
- copy.faces[face].texture = textures[0].uuid
+ } else if (Texture.getDefault() && copy.faces && copy.faces[face].texture !== null) {
+ copy.faces[face].texture = Texture.getDefault().uuid
}
}
copy.init()
@@ -238,6 +221,7 @@ var codec = new Codec('project', {
Undo.history = model.history.slice()
Undo.index = model.history_index;
}
+ this.dispatchEvent('parsed', {model})
Canvas.updateAll()
}
})
diff --git a/js/io/bedrock.js b/js/io/formats/bedrock.js
similarity index 63%
rename from js/io/bedrock.js
rename to js/io/formats/bedrock.js
index a7513875..f7b3aaeb 100644
--- a/js/io/bedrock.js
+++ b/js/io/formats/bedrock.js
@@ -84,23 +84,48 @@ window.BedrockEntityManager = {
new Texture({keep_size: true}).fromPath(valid_textures_list[0]).add()
} else if (valid_textures_list.length > 1) {
- var dialog_list = '';
- valid_textures_list.forEach((path, i) => {
- dialog_list += `
`;
- })
- var dialog = new Dialog({
- title: tl('data.texture'),
- id: 'select_texture',
- lines: [`
`],
- singleButton: true
- }).show()
- $('#import_texture_list li').each((i, el) => {
- $(el).css('background-image', `url("${ valid_textures_list[i].replace(/\\/g, '/') }?${Math.round(Math.random()*1e6)}")`)
- .click(() => {
- dialog.hide();
- new Texture({keep_size: true}).fromPath(valid_textures_list[i]).add()
- });
- })
+ setTimeout(() => {
+ var dialog_list = '';
+ valid_textures_list.forEach((path, i) => {
+ dialog_list += `
`;
+ })
+ let selected_textures = [];
+ var dialog = new Dialog({
+ title: tl('data.texture'),
+ id: 'select_texture',
+ lines: [`
`],
+ buttons: ['dialog.import', 'dialog.select_texture.import_all', 'dialog.cancel'],
+ confirmIndex: 0,
+ cancelIndex: 2,
+ onButton(index) {
+ dialog.hide();
+ if (index == 1) {
+ valid_textures_list.forEach(path => {
+ new Texture({keep_size: true}).fromPath(path).add()
+ })
+ } else if (index == 0) {
+ selected_textures.forEach(i => {
+ new Texture({keep_size: true}).fromPath(valid_textures_list[i]).add()
+ })
+ }
+ }
+ }).show()
+ $('#import_texture_list li').each((i, el) => {
+ $(el).css('background-image', `url("${ valid_textures_list[i].replace(/\\/g, '/') }?${Math.round(Math.random()*1e6)}")`)
+ .click(function() {
+ if (selected_textures.includes(i)) {
+ selected_textures.remove(i)
+ } else {
+ selected_textures.push(i)
+ }
+ $(this).toggleClass('selected')
+ })
+ .dblclick(function() {
+ selected_textures.replace([i])
+ dialog.confirm()
+ })
+ })
+ }, 2)
}
}
@@ -209,10 +234,12 @@ window.BedrockEntityManager = {
function calculateVisibleBox() {
var visible_box = new THREE.Box3()
- Cube.all.forEach(cube => {
- if (cube.export && cube.mesh) {
- visible_box.expandByObject(cube.mesh);
- }
+ Canvas.withoutGizmos(() => {
+ Cube.all.forEach(cube => {
+ if (cube.export && cube.mesh) {
+ visible_box.expandByObject(cube.mesh);
+ }
+ })
})
var offset = new THREE.Vector3(8,8,8);
@@ -249,175 +276,288 @@ function calculateVisibleBox() {
(function() {
-function parseGeometry(data) {
- if (data === undefined) {
- pe_list_data.forEach(function(s) {
- if (s.selected === true) {
- data = s
- }
+// Parse
+
+ function parseCube(s, group) {
+ var base_cube = new Cube({
+ name: s.name || group.name,
+ autouv: 0,
+ color: Group.all.indexOf(group)%8,
+ rotation: s.rotation,
+ origin: s.pivot
})
- if (data == undefined) {
- data = pe_list_data[0]
- }
- }
- codec.dispatchEvent('parse', {model: data.object});
- let {description} = data.object;
-
- Project.geometry_name = (description.identifier && description.identifier.replace(/^geometry\./, '')) || '';
- Project.texture_width = 16;
- Project.texture_height = 16;
-
- if (typeof description.visible_bounds_width == 'number' && typeof description.visible_bounds_height == 'number') {
- Project.visible_box[0] = Math.max(Project.visible_box[0], description.visible_bounds_width);
- Project.visible_box[1] = Math.max(Project.visible_box[1], description.visible_bounds_height);
- if (description.visible_bounds_offset && typeof description.visible_bounds_offset[1] == 'number') {
- Project.visible_box[2] = Math.min(Project.visible_box[2], description.visible_bounds_offset[1]);
- }
- }
-
- if (description.texture_width !== undefined) {
- Project.texture_width = description.texture_width;
- }
- if (description.texture_height !== undefined) {
- Project.texture_height = description.texture_height;
- }
-
- var bones = {}
-
- if (data.object.bones) {
- var included_bones = []
- data.object.bones.forEach(function(b) {
- included_bones.push(b.name)
+ base_cube.rotation.forEach(function(br, axis) {
+ if (axis != 2) base_cube.rotation[axis] *= -1
})
- data.object.bones.forEach(function(b, bi) {
- var group = new Group({
- name: b.name,
- origin: b.pivot,
- rotation: b.rotation,
- material: b.material
- }).init()
- group.createUniqueName();
- bones[b.name] = group
- if (b.pivot) {
- group.origin[0] *= -1
+ base_cube.origin[0] *= -1;
+ if (s.origin) {
+ base_cube.from.V3_set(s.origin)
+ base_cube.from[0] = -(base_cube.from[0] + s.size[0])
+ if (s.size) {
+ base_cube.to[0] = s.size[0] + base_cube.from[0]
+ base_cube.to[1] = s.size[1] + base_cube.from[1]
+ base_cube.to[2] = s.size[2] + base_cube.from[2]
}
- group.rotation.forEach(function(br, axis) {
- if (axis !== 2) group.rotation[axis] *= -1
- })
-
- group.mirror_uv = b.mirror === true
- group.reset = b.reset === true
-
- if (b.cubes) {
- b.cubes.forEach(function(s) {
- var base_cube = new Cube({
- name: s.name || b.name,
- autouv: 0,
- color: bi%8,
- rotation: s.rotation,
- origin: s.pivot
+ }
+ if (s.uv instanceof Array) {
+ base_cube.uv_offset[0] = s.uv[0]
+ base_cube.uv_offset[1] = s.uv[1]
+ Project.box_uv = true;
+ } else if (s.uv) {
+ Project.box_uv = false;
+ for (var key in base_cube.faces) {
+ var face = base_cube.faces[key]
+ if (s.uv[key]) {
+ face.extend({
+ uv: [
+ s.uv[key].uv[0],
+ s.uv[key].uv[1]
+ ]
})
- base_cube.rotation.forEach(function(br, axis) {
- if (axis != 2) base_cube.rotation[axis] *= -1
- })
- base_cube.origin[0] *= -1;
- if (s.origin) {
- base_cube.from.V3_set(s.origin)
- base_cube.from[0] = -(base_cube.from[0] + s.size[0])
- if (s.size) {
- base_cube.to[0] = s.size[0] + base_cube.from[0]
- base_cube.to[1] = s.size[1] + base_cube.from[1]
- base_cube.to[2] = s.size[2] + base_cube.from[2]
- }
- }
- if (s.uv instanceof Array) {
- base_cube.uv_offset[0] = s.uv[0]
- base_cube.uv_offset[1] = s.uv[1]
- Project.box_uv = true;
- } else if (s.uv) {
- Project.box_uv = false;
- for (var key in base_cube.faces) {
- var face = base_cube.faces[key]
- if (s.uv[key]) {
- face.extend({
- uv: [
- s.uv[key].uv[0],
- s.uv[key].uv[1]
- ]
- })
- if (s.uv[key].uv_size) {
- face.uv_size = [
- s.uv[key].uv_size[0],
- s.uv[key].uv_size[1]
- ]
- } else {
- base_cube.autouv = 1;
- base_cube.mapAutoUV();
- }
- if (key == 'up') {
- face.uv = [face.uv[2], face.uv[3], face.uv[0], face.uv[1]]
- }
- if (key == 'down') {
- face.uv = [face.uv[0], face.uv[3], face.uv[2], face.uv[1]]
- }
- } else {
- face.texture = null;
- face.uv = [0, 0, 0, 0]
- }
- }
-
- }
- if (s.inflate && typeof s.inflate === 'number') {
- base_cube.inflate = s.inflate;
- }
- if (s.mirror === undefined) {
- base_cube.mirror_uv = group.mirror_uv;
+ if (s.uv[key].uv_size) {
+ face.uv_size = [
+ s.uv[key].uv_size[0],
+ s.uv[key].uv_size[1]
+ ]
} else {
- base_cube.mirror_uv = s.mirror === true;
+ base_cube.autouv = 1;
+ base_cube.mapAutoUV();
+ }
+ if (key == 'up' || key == 'down') {
+ face.uv = [face.uv[2], face.uv[3], face.uv[0], face.uv[1]]
}
- base_cube.addTo(group).init()
- })
- }
- if (b.locators) {
- for (var key in b.locators) {
- var coords = b.locators[key];
- coords[0] *= -1
- var locator = new Locator({from: coords, name: key}).addTo(group).init();
- }
- }
- if (b.children) {
- b.children.forEach(function(cg) {
- cg.addTo(group);
- })
- }
- var parent_group = 'root';
- if (b.parent) {
- if (bones[b.parent]) {
- parent_group = bones[b.parent]
} else {
- data.object.bones.forEach(function(ib) {
- if (ib.name === b.parent) {
- ib.children && ib.children.length ? ib.children.push(group) : ib.children = [group]
- }
- })
+ face.texture = null;
+ face.uv = [0, 0, 0, 0]
}
}
- group.addTo(parent_group)
+
+ }
+ if (s.inflate && typeof s.inflate === 'number') {
+ base_cube.inflate = s.inflate;
+ }
+ if (s.mirror === undefined) {
+ base_cube.mirror_uv = group.mirror_uv;
+ } else {
+ base_cube.mirror_uv = s.mirror === true;
+ }
+ base_cube.addTo(group).init()
+ }
+ function parseBone(b, bones) {
+ var group = new Group({
+ name: b.name,
+ origin: b.pivot,
+ rotation: b.rotation,
+ material: b.material
+ }).init()
+ group.createUniqueName();
+ bones[b.name] = group
+ if (b.pivot) {
+ group.origin[0] *= -1
+ }
+ group.rotation.forEach(function(br, axis) {
+ if (axis !== 2) group.rotation[axis] *= -1
})
- }
- pe_list_data.length = 0;
- hideDialog()
+
+ group.mirror_uv = b.mirror === true
+ group.reset = b.reset === true
- loadTextureDraggable()
- Canvas.updateAllBones()
- setProjectTitle()
- if (isApp && Project.geometry_name) {
- BedrockEntityManager.initEntity()
+ if (b.cubes) {
+ b.cubes.forEach(function(s) {
+ parseCube(s, group)
+ })
+ }
+ if (b.locators) {
+ for (var key in b.locators) {
+ var coords = b.locators[key];
+ coords[0] *= -1
+ new Locator({from: coords, name: key}).addTo(group).init();
+ }
+ }
+ if (b.children) {
+ b.children.forEach(function(cg) {
+ cg.addTo(group);
+ })
+ }
+ var parent_group = 'root';
+ if (b.parent) {
+ if (bones[b.parent]) {
+ parent_group = bones[b.parent]
+ } else {
+ data.object.bones.forEach(function(ib) {
+ if (ib.name === b.parent) {
+ ib.children && ib.children.length ? ib.children.push(group) : ib.children = [group]
+ }
+ })
+ }
+ }
+ group.addTo(parent_group)
}
- updateSelection()
- EditSession.initNewModel()
-}
+ function parseGeometry(data) {
+ if (data === undefined) {
+ pe_list_data.forEach(function(s) {
+ if (s.selected === true) {
+ data = s
+ }
+ })
+ if (data == undefined) {
+ data = pe_list_data[0]
+ }
+ }
+ codec.dispatchEvent('parse', {model: data.object});
+ let {description} = data.object;
+ Project.geometry_name = (description.identifier && description.identifier.replace(/^geometry\./, '')) || '';
+ Project.texture_width = 16;
+ Project.texture_height = 16;
+
+ if (typeof description.visible_bounds_width == 'number' && typeof description.visible_bounds_height == 'number') {
+ Project.visible_box[0] = Math.max(Project.visible_box[0], description.visible_bounds_width);
+ Project.visible_box[1] = Math.max(Project.visible_box[1], description.visible_bounds_height);
+ if (description.visible_bounds_offset && typeof description.visible_bounds_offset[1] == 'number') {
+ Project.visible_box[2] = Math.min(Project.visible_box[2], description.visible_bounds_offset[1]);
+ }
+ }
+
+ if (description.texture_width !== undefined) {
+ Project.texture_width = description.texture_width;
+ }
+ if (description.texture_height !== undefined) {
+ Project.texture_height = description.texture_height;
+ }
+
+ var bones = {}
+
+ if (data.object.bones) {
+ var included_bones = []
+ data.object.bones.forEach(function(b) {
+ included_bones.push(b.name)
+ })
+ data.object.bones.forEach(function(b) {
+ parseBone(b, bones)
+ })
+ }
+
+ codec.dispatchEvent('parsed', {model: data.object});
+
+ pe_list_data.length = 0;
+ hideDialog()
+
+ loadTextureDraggable()
+ Canvas.updateAllBones()
+ setProjectTitle()
+ if (isApp && Project.geometry_name) {
+ BedrockEntityManager.initEntity()
+ }
+ updateSelection()
+ EditSession.initNewModel()
+ }
+
+// Compile
+
+ function compileCube(obj, bone) {
+ var template = {
+ origin: obj.from.slice(),
+ size: obj.size(),
+ inflate: obj.inflate||undefined,
+ }
+ if (Project.box_uv) {
+ template = new oneLiner(template);
+ }
+ template.origin[0] = -(template.origin[0] + template.size[0])
+
+ if (!obj.rotation.allEqual(0)) {
+ template.pivot = obj.origin.slice();
+ template.pivot[0] *= -1;
+
+ template.rotation = obj.rotation.slice();
+ template.rotation.forEach(function(br, axis) {
+ if (axis != 2) template.rotation[axis] *= -1
+ })
+ }
+
+ if (Project.box_uv) {
+ template.uv = obj.uv_offset;
+ if (obj.mirror_uv === !bone.mirror) {
+ template.mirror = obj.mirror_uv
+ }
+ } else {
+ template.uv = {};
+ for (var key in obj.faces) {
+ var face = obj.faces[key];
+ if (face.texture !== null) {
+ template.uv[key] = new oneLiner({
+ uv: [
+ face.uv[0],
+ face.uv[1],
+ ],
+ uv_size: [
+ face.uv_size[0],
+ face.uv_size[1],
+ ]
+ });
+ if (key == 'up' || key == 'down') {
+ template.uv[key].uv[0] += template.uv[key].uv_size[0];
+ template.uv[key].uv[1] += template.uv[key].uv_size[1];
+ template.uv[key].uv_size[0] *= -1;
+ template.uv[key].uv_size[1] *= -1;
+ }
+ }
+ }
+ }
+ return template;
+ }
+ function compileGroup(g) {
+ if (g.type !== 'group') return;
+ //Bone
+ var bone = {}
+ bone.name = g.name
+ if (g.parent.type === 'group') {
+ bone.parent = g.parent.name
+ }
+ bone.pivot = g.origin.slice()
+ bone.pivot[0] *= -1
+ if (!g.rotation.allEqual(0)) {
+ bone.rotation = g.rotation.slice()
+ bone.rotation[0] *= -1;
+ bone.rotation[1] *= -1;
+ }
+ if (g.reset) {
+ bone.reset = true
+ }
+ if (g.mirror_uv) {
+ bone.mirror = true
+ }
+ if (g.material) {
+ bone.material = g.material
+ }
+ //Cubes
+ var cubes = []
+ var locators = {};
+
+ for (var obj of g.children) {
+ if (obj.export) {
+ if (obj instanceof Cube) {
+
+ let template = compileCube(obj, bone);
+ cubes.push(template);
+
+ } else if (obj instanceof Locator) {
+
+ locators[obj.name] = obj.from.slice();
+ locators[obj.name][0] *= -1;
+ }
+ }
+ }
+
+ if (cubes.length) {
+ bone.cubes = cubes
+ }
+ if (Object.keys(locators).length) {
+ bone.locators = locators
+ }
+ return bone;
+ }
var codec = new Codec('bedrock', {
@@ -457,106 +597,7 @@ var codec = new Codec('bedrock', {
})
}
groups.forEach(function(g) {
- if (g.type !== 'group') return;
- //Bone
- var bone = {}
- bone.name = g.name
- if (g.parent.type === 'group') {
- bone.parent = g.parent.name
- }
- bone.pivot = g.origin.slice()
- bone.pivot[0] *= -1
- if (!g.rotation.allEqual(0)) {
- bone.rotation = g.rotation.slice()
- bone.rotation[0] *= -1;
- bone.rotation[1] *= -1;
- }
- if (g.reset) {
- bone.reset = true
- }
- if (g.mirror_uv) {
- bone.mirror = true
- }
- if (g.material) {
- bone.material = g.material
- }
- //Cubes
- var cubes = []
- var locators = {};
-
- for (var obj of g.children) {
- if (obj.export) {
- if (obj instanceof Cube) {
- var template = {
- origin: obj.from.slice(),
- size: obj.size(),
- inflate: obj.inflate||undefined,
- }
- if (Project.box_uv) {
- template = new oneLiner(template);
- }
- template.origin[0] = -(template.origin[0] + template.size[0])
-
-
- if (!obj.rotation.allEqual(0)) {
- template.pivot = obj.origin.slice();
- template.pivot[0] *= -1;
-
- template.rotation = obj.rotation.slice();
- template.rotation.forEach(function(br, axis) {
- if (axis != 2) template.rotation[axis] *= -1
- })
- }
-
- if (Project.box_uv) {
- template.uv = obj.uv_offset;
- if (obj.mirror_uv === !bone.mirror) {
- template.mirror = obj.mirror_uv
- }
- } else {
- template.uv = {};
- for (var key in obj.faces) {
- var face = obj.faces[key];
- if (face.texture !== null) {
- template.uv[key] = new oneLiner({
- uv: [
- face.uv[0],
- face.uv[1],
- ],
- uv_size: [
- face.uv_size[0],
- face.uv_size[1],
- ]
- });
- if (key == 'up') {
- template.uv[key].uv[0] += template.uv[key].uv_size[0];
- template.uv[key].uv[1] += template.uv[key].uv_size[1];
- template.uv[key].uv_size[0] *= -1;
- template.uv[key].uv_size[1] *= -1;
- }
- if (key == 'down') {
- template.uv[key].uv[1] += template.uv[key].uv_size[1];
- template.uv[key].uv_size[1] *= -1;
- }
- }
- }
- }
- cubes.push(template)
-
- } else if (obj instanceof Locator) {
-
- locators[obj.name] = obj.from.slice();
- locators[obj.name][0] *= -1;
- }
- }
- }
-
- if (cubes.length) {
- bone.cubes = cubes
- }
- if (Object.keys(locators).length) {
- bone.locators = locators
- }
+ let bone = compileGroup(g);
bones.push(bone)
})
@@ -653,15 +694,6 @@ var codec = new Codec('bedrock', {
})
var thumbnail = new Jimp(48, 48, 0x00000000, function(err, image) {
model_entry.object.bones.forEach(function(b) {
- //var rotate_bone = false;
- //if (b.name === 'body' &&
- // (included_bones.includes('leg3') || model_entry.name.includes('chicken') || model_entry.name.includes('ocelot')) &&
- // included_bones.includes('leg4') === false &&
- // !model_entry.name.includes('creeper') &&
- // ( b.rotation === undefined ||b.rotation.join('_') === '0_0_0')
- //) {
- // rotate_bone = true;
- //}
var rotation = b.rotation
if (!rotation || rotation[0] === undefined) {
if (entityMode.hardcodes[model_entry.name] && entityMode.hardcodes[model_entry.name][b.name]) {
@@ -796,6 +828,13 @@ var codec = new Codec('bedrock', {
}
})
+codec.parseCube = parseCube;
+codec.parseBone = parseBone;
+codec.parseGeometry = parseGeometry;
+codec.compileCube = compileCube;
+codec.compileGroup = compileGroup;
+
+
var format = new ModelFormat({
id: 'bedrock',
extension: 'json',
@@ -806,6 +845,7 @@ var format = new ModelFormat({
single_texture: true,
bone_rig: true,
centered_grid: true,
+ animated_textures: true,
animation_mode: true,
locators: true,
codec,
diff --git a/js/io/bedrock_old.js b/js/io/formats/bedrock_old.js
similarity index 96%
rename from js/io/bedrock_old.js
rename to js/io/formats/bedrock_old.js
index a84a3080..9e02ce15 100644
--- a/js/io/bedrock_old.js
+++ b/js/io/formats/bedrock_old.js
@@ -102,6 +102,9 @@ function parseGeometry(data) {
group.addTo(parent_group)
})
}
+
+ codec.dispatchEvent('parsed', {model: data.object});
+
pe_list_data.length = 0;
hideDialog()
@@ -258,15 +261,6 @@ var codec = new Codec('bedrock_old', {
})
new Jimp(48, 48, 0x00000000, function(err, image) {
model_entry.object.bones.forEach(function(b) {
- //var rotate_bone = false;
- //if (b.name === 'body' &&
- // (included_bones.includes('leg3') || model_entry.name.includes('chicken') || model_entry.name.includes('ocelot')) &&
- // included_bones.includes('leg4') === false &&
- // !model_entry.name.includes('creeper') &&
- // ( b.rotation === undefined ||b.rotation.join('_') === '0_0_0')
- //) {
- // rotate_bone = true;
- //}
var rotation = b.rotation
if (!rotation || rotation[0] === undefined) {
if (entityMode.hardcodes[model_entry.name] && entityMode.hardcodes[model_entry.name][b.name]) {
@@ -473,6 +467,7 @@ var format = new ModelFormat({
single_texture: true,
bone_rig: true,
centered_grid: true,
+ animated_textures: true,
animation_mode: true,
locators: true,
codec,
diff --git a/js/io/gltf.js b/js/io/formats/gltf.js
similarity index 100%
rename from js/io/gltf.js
rename to js/io/formats/gltf.js
diff --git a/js/io/java_block.js b/js/io/formats/java_block.js
similarity index 96%
rename from js/io/java_block.js
rename to js/io/formats/java_block.js
index c35264f4..9e621cf2 100644
--- a/js/io/java_block.js
+++ b/js/io/formats/java_block.js
@@ -199,6 +199,9 @@ var codec = new Codec('java_block', {
if (checkExport('front_gui_light', Project.front_gui_light)) {
blockmodel.gui_light = 'front';
}
+ if (checkExport('overrides', Project.overrides)) {
+ blockmodel.overrides = Project.overrides;
+ }
if (checkExport('display', Object.keys(display).length >= 1)) {
var new_display = {}
var entries = 0;
@@ -263,6 +266,10 @@ var codec = new Codec('java_block', {
if (model.display !== undefined) {
DisplayMode.loadJSON(model.display)
}
+ if (model.overrides instanceof Array) {
+ Project.overrides = model.overrides.slice();
+ }
+
var texture_ids = {}
var texture_paths = {}
if (model.textures) {
@@ -398,8 +405,8 @@ var codec = new Codec('java_block', {
from: [0, 0, 7.5],
to: [16, 16, 7.8],
faces: {
- north: {uv: [16,0,0,16], texture: textures[0].uuid || null},
- south: {uv: [0,0,16,16], texture: textures[0].uuid || null},
+ north: {uv: [16,0,0,16], texture: Texture.getDefault().uuid || null},
+ south: {uv: [0,0,16,16], texture: Texture.getDefault().uuid || null},
east: {uv: [0,0,0,0], texture: null},
west: {uv: [0,0,0,0], texture: null},
up: {uv: [0,0,0,0], texture: null},
@@ -429,6 +436,7 @@ var codec = new Codec('java_block', {
if (model.gui_light === 'front') {
Project.front_gui_light = true;
}
+ this.dispatchEvent('parsed', {model});
if (add) {
Undo.finishEdit('add block model')
}
diff --git a/js/io/modded_entity.js b/js/io/formats/modded_entity.js
similarity index 98%
rename from js/io/modded_entity.js
rename to js/io/formats/modded_entity.js
index 199129eb..ef2c870f 100644
--- a/js/io/modded_entity.js
+++ b/js/io/formats/modded_entity.js
@@ -12,7 +12,7 @@ function I(num) {
}
const Templates = {
'1.12': {
- name: '1.12',
+ name: 'Forge 1.12',
flip_y: true,
integer_size: true,
file:
@@ -54,7 +54,7 @@ const Templates = {
},
'1.14': {
- name: '1.14',
+ name: 'Forge 1.14',
flip_y: true,
integer_size: true,
file:
@@ -96,7 +96,7 @@ const Templates = {
},
'1.15': {
- name: '1.15',
+ name: 'Forge 1.15',
flip_y: true,
integer_size: false,
file:
@@ -174,11 +174,12 @@ var codec = new Codec('modded_entity', {
if (cube.parent == 'root') loose_cubes.push(cube)
})
if (loose_cubes.length) {
- all_groups.push(new Group({
+ let group = new Group({
name: 'bb_main',
- children: loose_cubes,
is_catch_bone: true
- }))
+ });
+ all_groups.push(group)
+ group.children.replace(loose_cubes)
}
let model = Templates.get('file');
@@ -302,8 +303,9 @@ var codec = new Codec('modded_entity', {
return group_snippets.join('\n\t\t')
});
- this.dispatchEvent('compile', {model, options});
- return model;
+ let event = {model, options};
+ this.dispatchEvent('compile', event);
+ return event.model;
},
parse(model, path, add) {
this.dispatchEvent('parse', {model});
@@ -612,6 +614,7 @@ var codec = new Codec('modded_entity', {
}
})
Project.geometry_name = geo_name;
+ this.dispatchEvent('parsed', {model});
Canvas.updateAll();
},
fileName() {
diff --git a/js/io/obj.js b/js/io/formats/obj.js
similarity index 98%
rename from js/io/obj.js
rename to js/io/formats/obj.js
index 4dd747c2..b2185372 100644
--- a/js/io/obj.js
+++ b/js/io/formats/obj.js
@@ -19,7 +19,7 @@ function getMtlFace(obj, index) {
} else if (!tex || typeof tex === 'string') {
return 'usemtl none\n'
} else {
- return 'usemtl ' + tex.id + '\n';
+ return 'usemtl m_' + tex.id + '\n';
}
}
@@ -164,7 +164,7 @@ var codec = new Codec('obj', {
for (var key in materials) {
if (materials.hasOwnProperty(key) && materials[key]) {
var tex = materials[key];
- mtlOutput += 'newmtl ' +key+ '\n'
+ mtlOutput += 'newmtl m_' +key+ '\n'
mtlOutput += `map_Kd ${tex.name} \n`;
}
}
@@ -214,7 +214,6 @@ var codec = new Codec('obj', {
type: this.name,
extensions: [this.extension],
name: this.fileName(),
- startpath: this.startPath(),
custom_writer: (a, b) => scope.write(a, b),
})
diff --git a/js/io/optifine_jem.js b/js/io/formats/optifine_jem.js
similarity index 96%
rename from js/io/optifine_jem.js
rename to js/io/formats/optifine_jem.js
index a715a242..f7ea6be1 100644
--- a/js/io/optifine_jem.js
+++ b/js/io/formats/optifine_jem.js
@@ -8,8 +8,8 @@ var codec = new Codec('optifine_entity', {
if (options === undefined) options = {}
var entitymodel = {}
var geo_code = 'geometry.'+Project.geometry_name
- if (textures[0]) {
- entitymodel.texture = textures[0].name
+ if (Texture.getDefault()) {
+ entitymodel.texture = Texture.getDefault().name
}
entitymodel.textureSize = [Project.texture_width, Project.texture_height];
entitymodel.models = []
@@ -127,6 +127,11 @@ var codec = new Codec('optifine_entity', {
})
}
populate(bone, g, 0)
+
+ if (g.cem_animations.length) {
+ bone.animations = g.cem_animations;
+ }
+
entitymodel.models.push(bone)
})
@@ -155,7 +160,8 @@ var codec = new Codec('optifine_entity', {
name: b.part,
origin: b.translate,
rotation: b.rotate,
- mirror_uv: (b.mirrorTexture && b.mirrorTexture.includes('u'))
+ mirror_uv: (b.mirrorTexture && b.mirrorTexture.includes('u')),
+ cem_animations: b.animations
})
group.origin[1] *= -1;
group.origin[2] *= -1;
@@ -238,11 +244,12 @@ var codec = new Codec('optifine_entity', {
})
}
loadOutlinerDraggable()
- Canvas.updateAll()
if (model.texture) {
var path = path.replace(/\\[\w .-]+$/, '\\'+model.texture)
new Texture().fromPath(path).add(false)
}
+ this.dispatchEvent('parsed', {model});
+ Canvas.updateAll()
}
})
diff --git a/js/io/optifine_jpm.js b/js/io/formats/optifine_jpm.js
similarity index 97%
rename from js/io/optifine_jpm.js
rename to js/io/formats/optifine_jpm.js
index e1e572ea..d46a7e1e 100644
--- a/js/io/optifine_jpm.js
+++ b/js/io/formats/optifine_jpm.js
@@ -7,8 +7,8 @@ var part_codec = new Codec('optifine_part', {
compile(options) {
if (options === undefined) options = {}
var jpm = {}
- if (textures[0]) {
- jpm.texture = pathToName(textures[0].name, false)
+ if (Texture.getDefault()) {
+ jpm.texture = pathToName(Texture.getDefault().name, false)
}
jpm.textureSize = [Project.texture_width, Project.texture_height]
@@ -203,6 +203,7 @@ var part_codec = new Codec('optifine_part', {
Undo.finishEdit('add jpm model')
}
addSubmodel(model)
+ this.dispatchEvent('parsed', {model});
Canvas.updateAll()
}
})
diff --git a/js/io/skin.js b/js/io/formats/skin.js
similarity index 98%
rename from js/io/skin.js
rename to js/io/formats/skin.js
index 9612f4bf..53a72be9 100644
--- a/js/io/skin.js
+++ b/js/io/formats/skin.js
@@ -74,13 +74,14 @@ const codec = new Codec('skin_model', {
this.dispatchEvent('compile', {model: entitymodel, options});
return entitymodel
},
- parse(data, resolution, texture_path, pose = true) {
+ parse(data, resolution, texture_path, pose = true, layer_template) {
this.dispatchEvent('parse', {model: data});
Project.geometry_name = data.name;
Project.texture_width = data.texturewidth || 64;
Project.texture_height = data.textureheight || 64;
var bones = {}
+ var template_cubes = {};
if (data.bones) {
var included_bones = []
@@ -129,6 +130,7 @@ const codec = new Codec('skin_model', {
base_cube.mirror_uv = s.mirror === true
}
base_cube.addTo(group).init()
+ template_cubes[Cube.all.indexOf(base_cube)] = s;
})
}
if (b.children) {
@@ -161,7 +163,14 @@ const codec = new Codec('skin_model', {
if (texture_path) {
var texture = new Texture().fromPath(texture_path).add(false);
} else {
- var texture = generateTemplate(Project.texture_width*resolution, Project.texture_height*resolution, data.name, data.eyes)
+ var texture = generateTemplate(
+ Project.texture_width*resolution,
+ Project.texture_height*resolution,
+ template_cubes,
+ data.name,
+ data.eyes,
+ layer_template
+ )
}
texture.load_callback = function() {
Modes.options.paint.select();
@@ -199,7 +208,7 @@ format.new = function() {
}
}
-function generateTemplate(width = 64, height = 64, name = 'name', eyes) {
+function generateTemplate(width = 64, height = 64, cubes, name = 'name', eyes, layer_template) {
var texture = new Texture({
mode: 'bitmap',
@@ -210,8 +219,11 @@ function generateTemplate(width = 64, height = 64, name = 'name', eyes) {
canvas.width = width;
canvas.height = height;
- Cube.all.forEach(cube => {
- TextureGenerator.paintCubeBoxTemplate(cube, texture, canvas, null, !!cube.inflate);
+ Cube.all.forEach((cube, i) => {
+ let template_cube = cubes[i];
+ if (layer_template || !template_cube.layer) {
+ TextureGenerator.paintCubeBoxTemplate(cube, texture, canvas, null, template_cube.layer);
+ }
})
if (eyes) {
var res_multiple = canvas.width/Project.texture_width;
@@ -322,13 +334,14 @@ const skin_dialog = new Dialog({
extensions: ['png'],
filetype: 'PNG',
},
- pose: {type: 'checkbox', label: 'dialog.skin.pose', value: true}
+ pose: {type: 'checkbox', label: 'dialog.skin.pose', value: true},
+ layer_template: {type: 'checkbox', label: 'dialog.skin.layer_template', value: true}
},
draggable: true,
onConfirm(result) {
if (newProject(format)) {
var model = JSON.parse(skin_presets[result.model]);
- codec.parse(model, result.resolution/16, result.texture, result.pose);
+ codec.parse(model, result.resolution/16, result.texture, result.pose, result.layer_template);
}
this.hide();
},
@@ -344,7 +357,7 @@ BARS.defineActions(function() {
new Action('toggle_skin_layer', {
icon: 'layers_clear',
category: 'edit',
- condition: () => Format.id == 'skin',
+ condition: {formats: ['skin']},
click: function () {
var edited = [];
Cube.all.forEach(cube => {
@@ -380,7 +393,7 @@ skin_presets.steve = `{
"pose": [-6, 5, 0],
"cubes": [
{"name": "Head", "origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [0, 0]},
- {"name": "Hat Layer", "visibility": false, "origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [32, 0], "inflate": 0.5}
+ {"name": "Hat Layer", "visibility": false, "origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [32, 0], "inflate": 0.5, "layer": true}
]
},
{
@@ -389,7 +402,7 @@ skin_presets.steve = `{
"pivot": [0, 24, 0],
"cubes": [
{"name": "Body", "origin": [-4, 12, -2], "size": [8, 12, 4], "uv": [16, 16]},
- {"name": "Body Layer", "visibility": false, "origin": [-4, 12, -2], "size": [8, 12, 4], "uv": [16, 32], "inflate": 0.25}
+ {"name": "Body Layer", "visibility": false, "origin": [-4, 12, -2], "size": [8, 12, 4], "uv": [16, 32], "inflate": 0.25, "layer": true}
]
},
{
@@ -399,7 +412,7 @@ skin_presets.steve = `{
"pose": [-10, 0, 0],
"cubes": [
{"name": "Right Arm", "origin": [-8, 12, -2], "size": [4, 12, 4], "uv": [40, 16]},
- {"name": "Right Arm Layer", "visibility": false, "origin": [-8, 12, -2], "size": [4, 12, 4], "uv": [40, 32], "inflate": 0.25}
+ {"name": "Right Arm Layer", "visibility": false, "origin": [-8, 12, -2], "size": [4, 12, 4], "uv": [40, 32], "inflate": 0.25, "layer": true}
]
},
{
@@ -409,7 +422,7 @@ skin_presets.steve = `{
"pose": [12, 0, 0],
"cubes": [
{"name": "Left Arm", "origin": [4, 12, -2], "size": [4, 12, 4], "uv": [32, 48]},
- {"name": "Left Arm Layer", "visibility": false, "origin": [4, 12, -2], "size": [4, 12, 4], "uv": [48, 48], "inflate": 0.25}
+ {"name": "Left Arm Layer", "visibility": false, "origin": [4, 12, -2], "size": [4, 12, 4], "uv": [48, 48], "inflate": 0.25, "layer": true}
]
},
{
@@ -419,7 +432,7 @@ skin_presets.steve = `{
"pose": [11, 0, 2],
"cubes": [
{"name": "Right Leg", "origin": [-3.9, 0, -2], "size": [4, 12, 4], "uv": [0, 16]},
- {"name": "Right Leg Layer", "visibility": false, "origin": [-3.9, 0, -2], "size": [4, 12, 4], "uv": [0, 32], "inflate": 0.25}
+ {"name": "Right Leg Layer", "visibility": false, "origin": [-3.9, 0, -2], "size": [4, 12, 4], "uv": [0, 32], "inflate": 0.25, "layer": true}
]
},
{
@@ -429,7 +442,7 @@ skin_presets.steve = `{
"pose": [-10, 0, -2],
"cubes": [
{"name": "Left Leg", "origin": [-0.1, 0, -2], "size": [4, 12, 4], "uv": [16, 48]},
- {"name": "Left Leg Layer", "visibility": false, "origin": [-0.1, 0, -2], "size": [4, 12, 4], "uv": [0, 48], "inflate": 0.25}
+ {"name": "Left Leg Layer", "visibility": false, "origin": [-0.1, 0, -2], "size": [4, 12, 4], "uv": [0, 48], "inflate": 0.25, "layer": true}
]
}
]
@@ -450,7 +463,7 @@ skin_presets.alex = `{
"pose": [-6, 5, 0],
"cubes": [
{"name": "Head", "origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [0, 0]},
- {"name": "Hat Layer", "visibility": false, "origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [32, 0], "inflate": 0.5}
+ {"name": "Hat Layer", "visibility": false, "origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [32, 0], "inflate": 0.5, "layer": true}
]
},
{
@@ -459,7 +472,7 @@ skin_presets.alex = `{
"pivot": [0, 24, 0],
"cubes": [
{"name": "Body", "origin": [-4, 12, -2], "size": [8, 12, 4], "uv": [16, 16]},
- {"name": "Body Layer", "visibility": false, "origin": [-4, 12, -2], "size": [8, 12, 4], "uv": [16, 32], "inflate": 0.25}
+ {"name": "Body Layer", "visibility": false, "origin": [-4, 12, -2], "size": [8, 12, 4], "uv": [16, 32], "inflate": 0.25, "layer": true}
]
},
{
@@ -469,7 +482,7 @@ skin_presets.alex = `{
"pose": [-10, 0, 0],
"cubes": [
{"name": "Right Arm", "origin": [-7, 12, -2], "size": [3, 12, 4], "uv": [40, 16]},
- {"name": "Right Arm Layer", "visibility": false, "origin": [-7, 12, -2], "size": [3, 12, 4], "uv": [40, 32], "inflate": 0.25}
+ {"name": "Right Arm Layer", "visibility": false, "origin": [-7, 12, -2], "size": [3, 12, 4], "uv": [40, 32], "inflate": 0.25, "layer": true}
]
},
{
@@ -479,7 +492,7 @@ skin_presets.alex = `{
"pose": [12, 0, 0],
"cubes": [
{"name": "Left Arm", "origin": [4, 12, -2], "size": [3, 12, 4], "uv": [32, 48]},
- {"name": "Left Arm Layer", "visibility": false, "origin": [4, 12, -2], "size": [3, 12, 4], "uv": [48, 48], "inflate": 0.25}
+ {"name": "Left Arm Layer", "visibility": false, "origin": [4, 12, -2], "size": [3, 12, 4], "uv": [48, 48], "inflate": 0.25, "layer": true}
]
},
{
@@ -489,7 +502,7 @@ skin_presets.alex = `{
"pose": [11, 0, 2],
"cubes": [
{"name": "Right Leg", "origin": [-3.9, 0, -2], "size": [4, 12, 4], "uv": [0, 16]},
- {"name": "Right Leg Layer", "visibility": false, "origin": [-3.9, 0, -2], "size": [4, 12, 4], "uv": [0, 32], "inflate": 0.25}
+ {"name": "Right Leg Layer", "visibility": false, "origin": [-3.9, 0, -2], "size": [4, 12, 4], "uv": [0, 32], "inflate": 0.25, "layer": true}
]
},
{
@@ -499,7 +512,7 @@ skin_presets.alex = `{
"pose": [-10, 0, -2],
"cubes": [
{"name": "Left Leg", "origin": [-0.1, 0, -2], "size": [4, 12, 4], "uv": [16, 48]},
- {"name": "Left Leg Layer", "visibility": false, "origin": [-0.1, 0, -2], "size": [4, 12, 4], "uv": [0, 48], "inflate": 0.25}
+ {"name": "Left Leg Layer", "visibility": false, "origin": [-0.1, 0, -2], "size": [4, 12, 4], "uv": [0, 48], "inflate": 0.25, "layer": true}
]
}
]
@@ -1804,7 +1817,7 @@ skin_presets.enderman = `{
"pivot": [0, 24, 0],
"cubes": [
{"name": "head", "origin": [-4, 40, -4], "size": [8, 8, 8], "uv": [0, 0], "inflate": -0.5},
- {"name": "head layer", "origin": [-4, 38, -4], "size": [8, 8, 8], "uv": [0, 16], "inflate": -0.5}
+ {"name": "head layer", "origin": [-4, 38, -4], "size": [8, 8, 8], "uv": [0, 16], "inflate": -0.5, "layer": true}
]
},
{
@@ -4002,7 +4015,7 @@ skin_presets.silverfish = `{
"parent": "bodyPart_1",
"pivot": [0, 5, -1.5],
"cubes": [
- {"name": "bodyLayer_2", "origin": [-3, 0, -3], "size": [6, 5, 2], "uv": [20, 18]}
+ {"name": "bodyLayer_2", "origin": [-3, 0, -3], "size": [6, 5, 2], "uv": [20, 18], "layer": true}
]
},
{
@@ -4026,7 +4039,7 @@ skin_presets.silverfish = `{
"parent": "bodyPart_4",
"pivot": [0, 4, 7],
"cubes": [
- {"name": "bodyLayer_1", "origin": [-3, 0, 5.5], "size": [6, 4, 3], "uv": [20, 11]}
+ {"name": "bodyLayer_1", "origin": [-3, 0, 5.5], "size": [6, 4, 3], "uv": [20, 11], "layer": true}
]
},
{
@@ -4050,7 +4063,7 @@ skin_presets.silverfish = `{
"parent": "bodyPart_2",
"pivot": [0, 8, 1],
"cubes": [
- {"name": "bodyLayer_0", "origin": [-5, 0, -0.5], "size": [10, 8, 3], "uv": [20, 0]}
+ {"name": "bodyLayer_0", "origin": [-5, 0, -0.5], "size": [10, 8, 3], "uv": [20, 0], "layer": true}
]
}
]
@@ -4157,10 +4170,10 @@ skin_presets.slime = `{
"name": "outer",
"pivot": [0, 24, 0],
"cubes": [
- {"name": "cube layer", "visibility": false, "origin": [-4, 0, -4], "size": [8, 8, 8], "uv": [0, 0]},
- {"name": "eye0 layer", "visibility": false, "origin": [-3.3, 4, -3.5], "size": [2, 2, 2], "uv": [32, 0]},
- {"name": "eye1 layer", "visibility": false, "origin": [1.3, 4, -3.5], "size": [2, 2, 2], "uv": [32, 4]},
- {"name": "mouth layer", "visibility": false, "origin": [0, 2, -3.5], "size": [1, 1, 1], "uv": [32, 8]}
+ {"name": "cube layer", "visibility": false, "origin": [-4, 0, -4], "size": [8, 8, 8], "uv": [0, 0], "layer": true},
+ {"name": "eye0 layer", "visibility": false, "origin": [-3.3, 4, -3.5], "size": [2, 2, 2], "uv": [32, 0], "layer": true},
+ {"name": "eye1 layer", "visibility": false, "origin": [1.3, 4, -3.5], "size": [2, 2, 2], "uv": [32, 4], "layer": true},
+ {"name": "mouth layer", "visibility": false, "origin": [0, 2, -3.5], "size": [1, 1, 1], "uv": [32, 8], "layer": true}
]
}
]
diff --git a/js/io/io.js b/js/io/io.js
index 4ec35bf4..5227ba21 100644
--- a/js/io/io.js
+++ b/js/io/io.js
@@ -36,7 +36,7 @@ class ModelFormat {
this.canvas_limit = false;
this.rotation_limit = false;
this.uv_rotation = false;
- this.display_mode = false;
+ this.ro_mode = false;
this.animation_mode = false;
this.codec = data.codec;
@@ -77,8 +77,7 @@ class ModelFormat {
} else {
scene.position.set(-8, -8, -8);
}
- var center = Format.centered_grid ? 8 : 0;
- previews.forEach(preview => {
+ Preview.all.forEach(preview => {
if (preview.isOrtho && typeof preview.angle == 'number') {
preview.loadAnglePreset(DefaultCameraPresets[preview.angle+1])
}
@@ -88,6 +87,7 @@ class ModelFormat {
})
updateSelection()
Modes.vue.$forceUpdate()
+ updateShading();
Canvas.updateRenderSides()
return this;
}
@@ -107,19 +107,6 @@ class ModelFormat {
var old_format = Format
this.select(true)
Modes.options.edit.select()
- //Single Texture
- if (Format.single_texture && !old_format.single_texture) {
- if (textures.length > 1) {
- textures.splice(1)
- }
- if (textures.length) {
- var tex = textures[0]
- tex.particle = false
- if (tex.img.naturalWidth !== tex.img.naturalWidth && tex.error) {
- tex.error = false
- }
- }
- }
//Bone Rig
if (!Format.bone_rig && old_format.bone_rig) {
@@ -811,6 +798,7 @@ BARS.defineActions(function() {
optional_box_uv: true,
uv_rotation: true,
animation_mode: true,
+ codec: Codecs.project
})
//Import
diff --git a/js/io/project.js b/js/io/project.js
index b5b88148..017bd315 100644
--- a/js/io/project.js
+++ b/js/io/project.js
@@ -1,86 +1,140 @@
-const Project = {
- name : '',
- parent : '',
- geometry_name : '',
- description : '',
- _box_uv : false,
- get box_uv() {return Project._box_uv},
+class ModelProject {
+ constructor() {
+ for (var key in ModelProject.properties) {
+ ModelProject.properties[key].reset(this);
+ }
+
+ this._box_uv = false;
+ this._texture_width = 16;
+ this._texture_height = 16;
+ }
+ extend() {
+ for (var key in ModelProject.properties) {
+ ModelProject.properties[key].merge(this, object)
+ }
+ }
+ get box_uv() {return Project._box_uv}
set box_uv(v) {
if (Project._box_uv != v) {
Project._box_uv = v;
switchBoxUV(v);
}
- },
- get texture_width() {return Project._texture_width},
- get texture_height() {return Project._texture_height},
+ }
+ get texture_width() {return this._texture_width}
+ get texture_height() {return this._texture_height}
set texture_width(n) {
n = parseInt(n)||16
Vue.nextTick(updateProjectResolution)
- Project._texture_width = n;
- },
+ this._texture_width = n;
+ }
set texture_height(n) {
n = parseInt(n)||16
Vue.nextTick(updateProjectResolution)
- Project._texture_height = n;
- },
- _texture_width : 16,
- _texture_height : 16,
- ambientocclusion: true,
- front_gui_light: false,
- visible_box: [1, 1, 0], /*width, height, y*/
- modded_entity_version: '1.15',
+ this._texture_height = n;
+ }
get optional_box_uv() {
return Format.optional_box_uv;
}
+ reset() {
+ Blockbench.dispatchEvent('reset_project');
+ if (isApp) updateRecentProjectThumbnail()
+ if (Toolbox.selected.id !== 'move_tool') BarItems.move_tool.select();
+
+ Screencam.stopTimelapse();
+
+ Format = 0;
+ Outliner.elements.empty();
+ Outliner.root.purge();
+ Canvas.materials;
+ selected.empty();
+ Group.all.empty();
+ Group.selected = undefined;
+ Cube.all.empty();
+ Cube.selected.empty();
+ Locator.all.empty();
+ Locator.selected.empty();
+ Texture.all.empty();
+ Texture.selected = undefined;
+
+ for (var key in ModelProject.properties) {
+ ModelProject.properties[key].reset(this)
+ }
+ this.texture_width = this.texture_height = 16;
+ this.overrides = null;
+
+ Blockbench.display_settings = display = {};
+ ModelMeta.save_path = ModelMeta.export_path = ModelMeta.animation_path = ModelMeta.name = '';
+ ModelMeta.saved = true;
+ Prop.project_saved = true;
+ Prop.added_models = 0;
+ Canvas.updateAll();
+ Outliner.vue.$forceUpdate();
+ texturelist.$forceUpdate();
+ Undo.history.empty();
+ Undo.index = 0;
+ Undo.current_save = null;
+ Painter.current = {};
+ Animator.animations.purge();
+ Timeline.animators.purge();
+ Animator.selected = undefined;
+ $('#var_placeholder_area').val('');
+ }
}
+new Property(ModelProject, 'string', 'name', {
+ label: 'dialog.project.name'
+});
+new Property(ModelProject, 'string', 'parent', {
+ label: 'dialog.project.parent',
+ condition: {formats: ['java_block']
+}});
+new Property(ModelProject, 'string', 'geometry_name', {
+ label: 'dialog.project.geoname',
+ condition: () => Format.bone_rig
+});
+new Property(ModelProject, 'string', 'modded_entity_version', {
+ label: 'dialog.project.modded_entity_version',
+ default: '1.15',
+ condition: {formats: ['modded_entity']},
+ options() {
+ let options = {}
+ for (var key in Codecs.modded_entity.templates) {
+ if (Codecs.modded_entity.templates[key] instanceof Function == false) {
+ options[key] = Codecs.modded_entity.templates[key].name;
+ }
+ }
+ return options;
+ }
+});
+new Property(ModelProject, 'boolean', 'ambientocclusion', {
+ label: 'dialog.project.ao',
+ default: true,
+ condition: {formats: ['java_block']}
+});
+new Property(ModelProject, 'boolean', 'front_gui_light', {
+ exposed: false,
+ condition: () => Format.display_mode});
+new Property(ModelProject, 'vector', 'visible_box', {
+ exposed: false,
+ default: [1, 1, 0]
+});
+new Property(ModelProject, 'boolean', 'layered_textures', {
+ label: 'dialog.project.layered_textures',
+ condition() {return Format.single_texture}
+});
+
+
+const Project = new ModelProject();
//New
function resetProject() {
- Blockbench.dispatchEvent('reset_project');
- if (Toolbox.selected.id !== 'move_tool') BarItems.move_tool.select();
- Format = 0;
- elements.length = 0;
- Outliner.root.purge();
- Canvas.materials.length = 0;
- textures.length = 0;
- selected.length = 0;
-
- Screencam.stopTimelapse();
-
- Group.all.empty();
- Group.selected = undefined;
- Cube.all.empty();
- Cube.selected.empty();
- Locator.all.empty();
- Locator.selected.empty();
-
- Blockbench.display_settings = display = {};
- Project.name = Project.parent = Project.geometry_name = Project.description = '';
- Project.texture_width = Project.texture_height = 16;
- Project.ambientocclusion = true;
- Project.front_gui_light = false;
- Project.modded_entity_version = '1.15';
- Project.visible_box.splice(0, Infinity, ...[1, 1, 0])
- ModelMeta.save_path = ModelMeta.export_path = ModelMeta.animation_path = ModelMeta.name = '';
- ModelMeta.saved = true;
- Prop.project_saved = true;
- Prop.added_models = 0;
- Canvas.updateAll();
- Outliner.vue.$forceUpdate();
- texturelist.$forceUpdate();
- Undo.history.length = 0;
- Undo.index = 0;
- Undo.current_save = null;
- Painter.current = {};
- Animator.animations.purge();
- Timeline.animators.purge();
- Animator.selected = undefined;
- $('#var_placeholder_area').val('');
+ Project.reset()
}
function newProject(format, force) {
if (force || showSaveDialog()) {
- resetProject();
+ if (Format) {
+ Project.reset();
+ }
Modes.options.edit.select();
if (format instanceof ModelFormat) {
format.select();
@@ -101,39 +155,46 @@ BARS.defineActions(function() {
condition: () => Format,
click: function () {
- let modded_entity_options = {}
- for (var key in Codecs.modded_entity.templates) {
- if (Codecs.modded_entity.templates[key] instanceof Function == false) {
- modded_entity_options[key] = Codecs.modded_entity.templates[key].name;
+ let form = {
+ format: {type: 'info', label: 'data.format', text: Format.name||'unknown'}
+ }
+
+ for (var key in ModelProject.properties) {
+ let property = ModelProject.properties[key];
+ if (property.exposed == false || !Condition(property.condition)) continue;
+
+ let entry = form[property.name] = {
+ label: property.label,
+ value: Project[property.name],
+ type: property.type
+ }
+ if (property.type == 'boolean') entry.type = 'checkbox';
+ if (property.type == 'string') entry.type = 'text';
+ if (property.options) {
+ entry.options = typeof property.options == 'function' ? property.options() : property.options;
+ entry.type = 'select';
}
}
+
+ form.box_uv = {label: 'dialog.project.box_uv', type: 'checkbox', value: Project.box_uv, condition: Format.optional_box_uv};
+ form.texture_width = {
+ label: 'dialog.project.width',
+ type: 'number',
+ value: Project.texture_width,
+ min: 1
+ };
+ form.texture_height = {
+ label: 'dialog.project.height',
+ type: 'number',
+ value: Project.texture_height,
+ min: 1
+ };
+
var dialog = new Dialog({
id: 'project',
title: 'dialog.project.title',
- width: 540,
- form: {
- format: {type: 'info', label: 'data.format', text: Format.name||'unknown'},
- name: {label: 'dialog.project.name', value: Project.name},
-
- parent: {label: 'dialog.project.parent', value: Project.parent, condition: !Format.bone_rig, list: ['paro', 'foo', 'bar']},
- geometry_name: {label: 'dialog.project.geoname', value: Project.geometry_name, condition: Format.bone_rig},
- modded_entity_version: {label: 'dialog.project.modded_entity_version', type: 'select', default: Project.modded_entity_version, options: modded_entity_options, condition: Format.id == 'modded_entity'},
- ambientocclusion: {label: 'dialog.project.ao', type: 'checkbox', value: Project.ambientocclusion, condition: Format.id == 'java_block'},
-
- box_uv: {label: 'dialog.project.box_uv', type: 'checkbox', value: Project.box_uv, condition: Format.optional_box_uv},
- texture_width: {
- label: 'dialog.project.width',
- type: 'number',
- value: Project.texture_width,
- min: 1
- },
- texture_height: {
- label: 'dialog.project.height',
- type: 'number',
- value: Project.texture_height,
- min: 1
- },
- },
+ width: 500,
+ form,
onConfirm: function(formResult) {
var save;
if (Project.box_uv != formResult.box_uv ||
@@ -165,11 +226,20 @@ BARS.defineActions(function() {
updateSelection()
}
- Project.name = formResult.name;
- Project.parent = formResult.parent;
- Project.geometry_name = formResult.geometry_name;
- Project.ambientocclusion = formResult.ambientocclusion;
- if (formResult.modded_entity_version) Project.modded_entity_version = formResult.modded_entity_version;
+ if (Format.single_texture) {
+ if (Project.layered_textures !== formResult.layered_textures && Texture.all.length >= 2) {
+ Project.layered_textures = formResult.layered_textures;
+ Texture.all.forEach((tex, i) => {
+ tex.visible = i < 3
+ })
+ texturelist.$forceUpdate()
+ Canvas.updateLayeredTextures();
+ }
+ }
+
+ for (var key in ModelProject.properties) {
+ ModelProject.properties[key].merge(Project, formResult);
+ }
if (save) {
Undo.finishEdit('change global UV')
diff --git a/js/modes.js b/js/modes.js
index 3bac4162..12d27f09 100644
--- a/js/modes.js
+++ b/js/modes.js
@@ -81,6 +81,7 @@ BARS.defineActions(function() {
center_windows: ['start_screen'],
hide_toolbars: true,
onSelect: function () {
+ if (Format && isApp) updateRecentProjectThumbnail()
},
onUnselect: function () {
}
diff --git a/js/outliner/cube.js b/js/outliner/cube.js
index df20714e..59b723ee 100644
--- a/js/outliner/cube.js
+++ b/js/outliner/cube.js
@@ -1,7 +1,8 @@
class Face {
- constructor(direction, data) {
+ constructor(direction, data, cube) {
this.direction = direction || 'north';
+ this.cube = cube;
this.reset()
this.uv = [0, 0, canvasGridSize(), canvasGridSize()]
if (data) {
@@ -49,8 +50,8 @@ class Face {
return this;
}
getTexture() {
- if (Format.single_texture && Project.box_uv && this.texture !== null) {
- return textures[0];
+ if (Format.single_texture && this.texture !== null) {
+ return Texture.getDefault();
}
if (typeof this.texture === 'string') {
return textures.findInArray('uuid', this.texture)
@@ -94,7 +95,6 @@ class Cube extends NonGroup {
constructor(data, uuid) {
super(data, uuid)
let size = canvasGridSize();
- this.name = 'cube';
this.from = [0, 0, 0];
this.to = [size, size, size];
this.shade = true;
@@ -111,20 +111,27 @@ class Cube extends NonGroup {
this.autouv = 0
this.parent = 'root';
+ for (var key in Cube.properties) {
+ Cube.properties[key].reset(this);
+ }
+
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')
+ north: new Face('north', null, this),
+ east: new Face('east', null, this),
+ south: new Face('south', null, this),
+ west: new Face('west', null, this),
+ up: new Face('up', null, this),
+ down: new Face('down', null, this)
}
if (data && typeof data === 'object') {
this.extend(data)
}
}
extend(object) {
- Merge.string(this, object, 'name')
+ for (var key in Cube.properties) {
+ Cube.properties[key].merge(this, object)
+ }
+
this.sanitizeName();
Merge.boolean(this, object, 'shade')
Merge.boolean(this, object, 'mirror_uv')
@@ -198,10 +205,10 @@ class Cube extends NonGroup {
}
init() {
super.init();
- if (Format.single_texture && textures[0]) {
+ if (Format.single_texture && Texture.getDefault()) {
for (var face in this.faces) {
if (this.faces[face].texture !== null) {
- this.faces[face].texture = textures[0].uuid
+ this.faces[face].texture = Texture.getDefault().uuid
}
}
}
@@ -284,14 +291,18 @@ class Cube extends NonGroup {
delete copy.parent;
return copy;
}
- getSaveCopy(meta) {
- var el = {
- name: this.name,
- from: this.from,
- to: this.to,
- autouv: this.autouv,
- color: this.color
+ getSaveCopy() {
+ var el = {}
+
+ for (var key in Cube.properties) {
+ Cube.properties[key].copy(this, el)
}
+
+ el.from = this.from;
+ el.to = this.to;
+ el.autouv = this.autouv;
+ el.color = this.color;
+
el.locked = this.locked;
if (!this.visibility) el.visibility = false;
if (!this.export) el.export = false;
@@ -792,6 +803,9 @@ class Cube extends NonGroup {
Cube.selected = [];
Cube.all = [];
+ new Property(Cube, 'string', 'name', {default: 'cube'})
+
+
BARS.defineActions(function() {
new Action({
@@ -811,7 +825,7 @@ BARS.defineActions(function() {
if (textures.length && Format.single_texture) {
for (var face in base_cube.faces) {
- base_cube.faces[face].texture = textures[0].uuid
+ base_cube.faces[face].texture = Texture.getDefault().uuid
}
main_uv.loadData()
}
diff --git a/js/outliner/group.js b/js/outliner/group.js
index 99cb3b0e..f4cd72d3 100644
--- a/js/outliner/group.js
+++ b/js/outliner/group.js
@@ -1,14 +1,14 @@
class Group extends OutlinerElement {
- constructor(data) {
- super()
+ constructor(data, uuid) {
+ super(uuid)
+
+ for (var key in Group.properties) {
+ Group.properties[key].reset(this);
+ }
+
this.name = Format.bone_rig ? 'bone' : 'group'
this.children = []
- this.origin = [0, 0, 0];
- if (!Format.centered_grid) {
- this.origin.V3_set(8, 8, 8);
- }
- this.rotation = [0, 0, 0];
this.reset = false;
this.shade = true;
this.selected = false;
@@ -28,11 +28,15 @@ class Group extends OutlinerElement {
}
}
extend(object) {
+ for (var key in Group.properties) {
+ Group.properties[key].merge(this, object)
+ }
Merge.string(this, object, 'name')
this.sanitizeName();
Merge.boolean(this, object, 'shade')
Merge.boolean(this, object, 'mirror_uv')
Merge.boolean(this, object, 'reset')
+ /*
if (object.origin) {
Merge.number(this.origin, object.origin, 0)
Merge.number(this.origin, object.origin, 1)
@@ -42,7 +46,7 @@ class Group extends OutlinerElement {
Merge.number(this.rotation, object.rotation, 0)
Merge.number(this.rotation, object.rotation, 1)
Merge.number(this.rotation, object.rotation, 2)
- }
+ }*/
Merge.number(this, object, 'autouv')
Merge.boolean(this, object, 'export')
Merge.boolean(this, object, 'locked')
@@ -213,11 +217,11 @@ class Group extends OutlinerElement {
}
}
resolve() {
- var scope = this;
- var array = this.children.slice().reverse();
+ var array = this.children.slice();
+ var index = this.getParentArray().indexOf(this)
- array.forEach(function(s, i) {
- s.addTo(scope.parent)
+ array.forEach((s, i) => {
+ s.addTo(this.parent, index)
})
TickUpdates.outliner = true;
this.remove(false);
@@ -277,7 +281,7 @@ class Group extends OutlinerElement {
}
duplicate() {
var copied_groups = [];
- var copy = this.getChildlessCopy()
+ var copy = this.getChildlessCopy(false)
delete copy.parent;
copied_groups.push(copy)
copy.sortInBefore(this, 1).init()
@@ -293,16 +297,18 @@ class Group extends OutlinerElement {
return copy;
}
getSaveCopy() {
- var scope = this;
- var base_group = this.getChildlessCopy();
+ var base_group = this.getChildlessCopy(true);
for (var child of this.children) {
base_group.children.push(child.getSaveCopy());
}
delete base_group.parent;
return base_group;
}
- getChildlessCopy() {
- var base_group = new Group();
+ getChildlessCopy(keep_uuid) {
+ var base_group = new Group({name: this.name}, keep_uuid ? this.uuid : null);
+ for (var key in Group.properties) {
+ Group.properties[key].copy(this, base_group)
+ }
base_group.name = this.name;
base_group.origin.V3_set(this.origin);
base_group.rotation.V3_set(this.rotation);
@@ -318,6 +324,9 @@ class Group extends OutlinerElement {
var obj = {
name: this.name
}
+ for (var key in Group.properties) {
+ Group.properties[key].copy(this, obj)
+ }
if (this.shade == false) {
obj.shade = false
}
@@ -329,10 +338,9 @@ class Group extends OutlinerElement {
obj.visibility = this.visibility;
obj.autouv = this.autouv;
}
- obj.origin = this.origin.slice()
- if (!this.rotation.allEqual(0)) {
- obj.rotation = this.rotation.slice()
+ if (this.rotation.allEqual(0)) {
+ delete obj.rotation;
}
if (this.reset) {
obj.reset = true
@@ -415,6 +423,13 @@ class Group extends OutlinerElement {
Group.selected;
Group.all = [];
+ new Property(Group, 'vector', 'origin', {default() {
+ return Format.centered_grid ? [0, 0, 0] : [8, 8, 8]
+ }});
+ new Property(Group, 'vector', 'rotation');
+ new Property(Group, 'array', 'cem_animations', {condition: () => Format.id == 'optifine_entity'});
+
+
function getCurrentGroup() {
if (Group.selected) {
return Group.selected
diff --git a/js/outliner/locator.js b/js/outliner/locator.js
index 7125d689..57f27202 100644
--- a/js/outliner/locator.js
+++ b/js/outliner/locator.js
@@ -2,19 +2,22 @@
class Locator extends NonGroup {
constructor(data, uuid) {
super(data, uuid);
- this.from = new Array().V3_set(0, 0, 0);
- this.name = 'locator';
+
+ for (var key in Locator.properties) {
+ Locator.properties[key].reset(this);
+ }
if (data) {
this.extend(data);
}
}
extend(object) {
- Merge.string(this, object, 'name');
+ for (var key in Locator.properties) {
+ Locator.properties[key].merge(this, object)
+ }
this.sanitizeName();
Merge.boolean(this, object, 'locked')
Merge.boolean(this, object, 'export');
- Merge.arrayVector(this, object, 'from');
return this;
}
getUndoCopy() {
@@ -25,14 +28,14 @@ class Locator extends NonGroup {
return copy;
}
getSaveCopy() {
- var el = {
- name: this.name,
- export: this.export ? undefined : false,
- locked: this.locked,
- from: this.from,
- uuid: this.uuid,
- type: 'locator'
- };
+ let el = {};
+ for (var key in Locator.properties) {
+ Locator.properties[key].copy(this, el)
+ }
+ el.export = this.export ? undefined : false;
+ el.locked = this.locked;
+ el.uuid = this.uuid;
+ el.type = 'locator';
return el;
}
init() {
@@ -81,6 +84,9 @@ class Locator extends NonGroup {
])
Locator.selected = [];
Locator.all = [];
+
+ new Property(Locator, 'string', 'name', {default: 'locator'})
+ new Property(Locator, 'vector', 'from')
BARS.defineActions(function() {
new Action('add_locator', {
diff --git a/js/outliner/outliner.js b/js/outliner/outliner.js
index 4543aab0..682ebdd1 100644
--- a/js/outliner/outliner.js
+++ b/js/outliner/outliner.js
@@ -139,10 +139,7 @@ class OutlinerElement {
TickUpdates.outliner = true;
return this;
}
- addTo(group) {
- //Remove
- var index = -1;
-
+ addTo(group, index = -1) {
//Resolve Group Argument
if (group === undefined) {
group = 'root'
@@ -639,7 +636,7 @@ function parseGroups(array, importGroup, startIndex) {
}
}
} else {
- var obj = new Group(array[i])
+ var obj = new Group(array[i], array[i].uuid)
obj.parent = addGroup
obj.isOpen = !!array[i].isOpen
if (array[i].uuid) {
diff --git a/js/preview/canvas.js b/js/preview/canvas.js
index 0b3b94f3..628e4890 100644
--- a/js/preview/canvas.js
+++ b/js/preview/canvas.js
@@ -73,7 +73,7 @@ const Canvas = {
},
getCurrentPreview() {
if (quad_previews.current) return quad_previews.current;
- var canvas = $('canvas.preview:hover').get(0)
+ var canvas = $('.preview:hover').get(0)
if (canvas) return canvas.preview
},
withoutGizmos(cb) {
@@ -87,10 +87,14 @@ const Canvas = {
edit(rot_origin)
edit(Vertexsnap.vertexes)
Cube.selected.forEach(function(obj) {
- var m = obj.mesh
- if (m && m.outline) {
- edit(m.outline)
- }
+ var m = obj.mesh;
+ if (!m) return;
+ if (m.outline) edit(m.outline);
+ })
+ Cube.all.forEach(function(obj) {
+ var m = obj.mesh;
+ if (!m) return;
+ if (m.grid_box) edit(m.grid_box);
})
}
editVis(obj => {
@@ -189,7 +193,7 @@ const Canvas = {
if (texture) {
used = false;
for (var face in obj.faces) {
- if (obj.faces[face].texture === texture.uuid) {
+ if (obj.faces[face].getTexture() == texture) {
used = true;
}
}
@@ -234,6 +238,9 @@ const Canvas = {
mat.side = side
}
})
+ if (Project.layered_textures && Canvas.layered_material) {
+ Canvas.layered_material.side = side;
+ }
emptyMaterials.forEach(function(mat) {
mat.side = side
})
@@ -495,13 +502,44 @@ const Canvas = {
}
iterate(el, elmesh)
},
- getLayeredMaterial() {
+ getLayeredMaterial(layers) {
+ if (Canvas.layered_material && !layers) return Canvas.layered_material;
+ // https://codepen.io/Fyrestar/pen/YmpXYr
var vertShader = `
+ uniform bool SHADE;
+
varying vec2 vUv;
+ varying float light;
+ varying float lift;
+
+ float AMBIENT = 0.5;
+ float XFAC = -0.15;
+ float ZFAC = 0.05;
void main()
{
- vUv = uv;
+
+ if (SHADE) {
+
+ vec3 N = vec3( modelMatrix * vec4(normal, 0.0) );
+
+
+ float yLight = (1.0+N.y) * 0.5;
+ light = yLight * (1.0-AMBIENT) + N.x*N.x * XFAC + N.z*N.z * ZFAC + AMBIENT;
+
+ } else {
+
+ light = 1.0;
+
+ }
+
+ if (color.b == 1.25) {
+ lift = 0.1;
+ } else {
+ lift = 0.0;
+ }
+
+ vUv = uv;
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
gl_Position = projectionMatrix * mvPosition;
}`
@@ -510,47 +548,70 @@ const Canvas = {
precision highp float;
#endif
- uniform sampler2D tOne;
- uniform sampler2D tSec;
+ uniform sampler2D t0;
+ uniform sampler2D t1;
+ uniform sampler2D t2;
+
+ uniform bool SHADE;
varying vec2 vUv;
+ varying float light;
+ varying float lift;
void main(void)
{
- vec3 c;
- vec4 Ca = texture2D(tOne, vUv);
- vec4 Cb = texture2D(tSec, vUv);
- c = Ca.rgb * Ca.a + Cb.rgb * Cb.a * (1.0 - Ca.a); // blending equation
- gl_FragColor= vec4(c, 1.0);
+ vec4 Ca = texture2D(t0, vUv);
+ vec4 Cb = texture2D(t1, vUv);
+ vec4 Cc = texture2D(t2, vUv);
+
+ vec3 ctemp = Ca.rgb * Ca.a + Cb.rgb * Cb.a * (1.0 - Ca.a);
+ vec4 ctemp4 = vec4(ctemp, Ca.a + (1.0 - Ca.a) * Cb.a);
+
+ vec3 c = ctemp4.rgb + Cc.rgb * Cc.a * (1.0 - ctemp4.a);
+ gl_FragColor= vec4(lift + c * light, ctemp4.a + (1.0 - ctemp4.a) * Cc.a);
+
+ if (gl_FragColor.a < 0.05) discard;
}`
var uniforms = {
- tOne: { type: "t", value: textures[1].getMaterial().map },
- tSec: { type: "t", value: textures[0].getMaterial().map }
+ SHADE: {type: 'bool', value: settings.shading.value},
+ t0: {type: 't', value: null},
+ t1: {type: 't', value: null},
+ t2: {type: 't', value: null}
};
+ let i = 0;
+ if (layers instanceof Array == false) layers = Texture.all;
+ layers.forEachReverse(texture => {
+ if (texture.visible && i < 3) {
+ uniforms[`t${i}`].value = texture.getMaterial().map;
+ i++;
+ }
+ })
var material_shh = new THREE.ShaderMaterial({
uniforms: uniforms,
vertexShader: vertShader,
- fragmentShader: fragShader
+ fragmentShader: fragShader,
+ side: Canvas.getRenderSide(),
+ vertexColors: THREE.FaceColors,
+ transparent: true
});
+ Canvas.layered_material = material_shh;
return material_shh;
- /*
- todo:
- Issues:
- Painting is one pixel delayed
- Painting doesn't occur on selected texture
- needs setting
- needs to work with 0-3+ textures
- */
+ },
+ updateLayeredTextures() {
+ delete Canvas.layered_material;
+ if (Format.single_texture && Texture.all.length >= 2) {
+ Canvas.updateAllFaces();
+ }
},
adaptObjectFaces(cube, mesh) {
if (!mesh) mesh = cube.mesh
if (!mesh) return;
if (Prop.wireframe) {
mesh.material = Canvas.wireframeMaterial
- /*} else if (settings.layered_textures.value && Format && Format.id.includes('bedrock')) {
- mesh.material = Canvas.getLayeredMaterial();*/
+ } else if (Format.single_texture && Project.layered_textures && Texture.all.length >= 2) {
+ mesh.material = Canvas.getLayeredMaterial();
} else {
var materials = []
@@ -571,7 +632,7 @@ const Canvas = {
mesh.material = materials
}
},
- updateUV(obj, animation) {
+ updateUV(obj, animation = true) {
if (Prop.wireframe === true) return;
var mesh = obj.mesh
if (mesh === undefined) return;
@@ -848,7 +909,8 @@ const Canvas = {
var height = end[1]-start[1];
var step = Math.abs( height / uv_size[1] );
uv_offset[1] *= step;
- if (texture) step *= Project.texture_height / texture.height;
+ let tex_height = texture.frameCount ? (texture.height / texture.frameCount) : texture.height;
+ if (texture) step *= Project.texture_height / tex_height;
if (step < epsilon) step = epsilon;
for (var line = start[1] - uv_offset[1]; line <= end[1]; line += step) {
@@ -875,5 +937,41 @@ const Canvas = {
lines.no_export = true;
return lines;
+ },
+ updatePaintingGrid() {
+ Cube.all.forEach(cube => {
+ Canvas.buildGridBox(cube)
+ })
+ },
+
+ getModelSize() {
+ var visible_box = new THREE.Box3()
+ Canvas.withoutGizmos(() => {
+ Cube.all.forEach(cube => {
+ if (cube.export && cube.mesh) {
+ visible_box.expandByObject(cube.mesh);
+ }
+ })
+ })
+
+ var offset = new THREE.Vector3(8,8,8);
+ visible_box.max.add(offset);
+ visible_box.min.add(offset);
+
+ // Width
+ var radius = Math.max(
+ visible_box.max.x,
+ visible_box.max.z,
+ -visible_box.min.x,
+ -visible_box.min.z
+ )
+ if (Math.abs(radius) === Infinity) {
+ radius = 0
+ }
+ let width = radius*2
+ let height = Math.abs(visible_box.max.y - visible_box.min.y)
+ if (height === Infinity) height = 0;
+
+ return [width, height]
}
}
diff --git a/js/preview/preview.js b/js/preview/preview.js
index 6527b835..8148ebf7 100644
--- a/js/preview/preview.js
+++ b/js/preview/preview.js
@@ -1,4 +1,5 @@
-var scene, main_preview, previews,
+var scene,
+ main_preview, MediaPreview,
Sun, lights,
emptyMaterials,
outlines,
@@ -114,9 +115,20 @@ class Preview {
//Node
this.canvas = document.createElement('canvas')
this.canvas.preview = this;
- this.canvas.className = 'preview';
this.height = 0;
this.width = 0;
+ this.node = document.createElement('div')
+ this.node.className = 'preview';
+ this.node.appendChild(this.canvas);
+ let menu = $(``)[0]
+ menu.onclick = (event) => {
+ this.menu.open(menu, this)
+ }
+ BarItem.prototype.addLabel(false, {
+ name: tl('data.preview'),
+ node: menu
+ })
+ this.node.appendChild(menu)
//Cameras
this.isOrtho = false
this.angle = null;
@@ -228,21 +240,23 @@ class Preview {
}
scope.loadBackground()
})
-
- previews.push(this)
+ Preview.all.push(this);
}
//Render
- resize() {
- if (!this.canvas.isConnected) return;
- this.height = this.canvas.parentElement.clientHeight;
- this.width = this.canvas.parentElement.clientWidth;
+ resize(width, height) {
+ if (this.canvas.isConnected && this !== MediaPreview) {
+ this.height = this.node.parentElement.clientHeight;
+ this.width = this.node.parentElement.clientWidth;
+ } else if (height && width) {
+ this.height = height;
+ this.width = width;
+ } else {
+ return this;
+ }
if (this.isOrtho === false) {
this.camPers.aspect = this.width / this.height
this.camPers.updateProjectionMatrix();
- if (Transformer) {
- Transformer.update()
- }
} else {
this.camOrtho.right = this.width / 80
this.camOrtho.left = this.camOrtho.right*-1
@@ -251,8 +265,14 @@ class Preview {
this.camOrtho.updateProjectionMatrix();
}
this.renderer.setSize(this.width, this.height);
- this.renderer.setPixelRatio(window.devicePixelRatio);
- this.updateBackground()
+
+ if (this.canvas.isConnected) {
+ this.renderer.setPixelRatio(window.devicePixelRatio);
+ this.updateBackground()
+ if (Transformer) {
+ Transformer.update()
+ }
+ }
return this;
}
raycast(event) {
@@ -322,7 +342,6 @@ class Preview {
}
}
render() {
- if (this.canvas.isConnected === false) return;
this.controls.update()
this.renderer.render(
display_mode
@@ -346,10 +365,6 @@ class Preview {
this.camera.zoom = 0.5;
this.camOrtho.updateProjectionMatrix()
}
- if (Transformer && Transformer.camera !== this.camera) {
- Transformer.camera = this.camera;
- Transformer.update();
- }
this.setLockedAngle()
this.controls.updateSceneScale();
return this;
@@ -365,36 +380,29 @@ class Preview {
this.angle = angle
this.controls.enableRotate = false;
- var dist = 64
switch (angle) {
case 0:
this.camOrtho.axis = 'y'
- //this.camOrtho.position.set(0,dist,0)
this.camOrtho.backgroundHandle = [{n: false, a: 'x'}, {n: false, a: 'z'}]
break;
case 1:
this.camOrtho.axis = 'y'
- //this.camOrtho.position.set(0,-dist,0)
this.camOrtho.backgroundHandle = [{n: false, a: 'x'}, {n: true, a: 'z'}]
break;
case 2:
this.camOrtho.axis = 'z'
- //this.camOrtho.position.set(0,0,dist)
this.camOrtho.backgroundHandle = [{n: false, a: 'x'}, {n: true, a: 'y'}]
break;
case 3:
this.camOrtho.axis = 'z'
- //this.camOrtho.position.set(0,0,-dist)
this.camOrtho.backgroundHandle = [{n: true, a: 'x'}, {n: true, a: 'y'}]
break;
case 4:
this.camOrtho.axis = 'x'
- //this.camOrtho.position.set(dist,0,0)
this.camOrtho.backgroundHandle = [{n: true, a: 'z'}, {n: true, a: 'y'}]
break;
case 5:
this.camOrtho.axis = 'x'
- //this.camOrtho.position.set(-dist,0,0)
this.camOrtho.backgroundHandle = [{n: false, a: 'z'}, {n: true, a: 'y'}]
break;
}
@@ -602,6 +610,8 @@ class Preview {
return scope.raycaster.ray.origin
}
occupyTransformer(event) {
+ if (this == MediaPreview || Transformer.dragging) return this;
+
Transformer.camera = this.isOrtho ? this.camOrtho : this.camPers
Transformer.orbit_controls = this.controls
Transformer.setCanvas(this.canvas)
@@ -655,7 +665,7 @@ class Preview {
};
if (!Modes.edit) return;
- $(this.canvas).parent().append(this.selection.box)
+ $(this.node).append(this.selection.box)
this.selection.activated = settings.canvas_unselect.value;
this.selection.old_selected = selected.slice();
@@ -880,10 +890,18 @@ class Preview {
Canvas.withoutGizmos(function() {
scope.render()
- var dataUrl = scope.canvas.toDataURL()
if (options.crop == false && !options.width && !options.height) {
+ var dataUrl = scope.canvas.toDataURL()
Screencam.returnScreenshot(dataUrl, cb)
+ return;
+ }
+
+ if (options.crop !== false && !(display_mode && display_slot === 'gui') && !options.width && !options.height) {
+ let frame = new CanvasFrame(scope.canvas);
+ frame.autoCrop()
+ Screencam.returnScreenshot(frame.canvas.toDataURL(), cb)
+ return;
}
dataUrl = dataUrl.replace('data:image/png;base64,','')
@@ -922,10 +940,10 @@ class Preview {
$('#preview').empty()
var wrapper = $('
')
- wrapper.append(this.canvas)
+ wrapper.append(this.node)
$('#preview').append(wrapper)
- previews.forEach(function(prev) {
+ Preview.all.forEach(function(prev) {
if (prev.canvas.isConnected) {
prev.resize()
}
@@ -992,6 +1010,7 @@ class Preview {
]
}},
'_',
+ 'focus_on_selection',
{icon: 'add_a_photo', name: 'menu.preview.save_angle', condition(preview) {return !preview.movingBackground && !Modes.display}, click(preview) {
preview.newAnglePreset()
}},
@@ -1041,25 +1060,27 @@ class Preview {
}}
])
+Preview.all = [];
+
function openQuadView() {
quad_previews.enabled = true;
$('#preview').empty()
var wrapper1 = $('
')
- wrapper1.append(quad_previews.one.canvas)
+ wrapper1.append(quad_previews.one.node)
$('#preview').append(wrapper1)
var wrapper2 = $('
')
- wrapper2.append(quad_previews.two.canvas)
+ wrapper2.append(quad_previews.two.node)
$('#preview').append(wrapper2)
var wrapper3 = $('
')
- wrapper3.append(quad_previews.three.canvas)
+ wrapper3.append(quad_previews.three.node)
$('#preview').append(wrapper3)
var wrapper4 = $('
')
- wrapper4.append(quad_previews.four.canvas)
+ wrapper4.append(quad_previews.four.node)
$('#preview').append(wrapper4)
updateInterface()
@@ -1309,8 +1330,6 @@ const Screencam = {
//Init/Update
function initCanvas() {
-
- previews = []
//Objects
scene = new THREE.Scene();
@@ -1383,6 +1402,8 @@ function initCanvas() {
}
active_scene = canvas_scenes.normal
+ MediaPreview = new Preview({id: 'media'})
+
main_preview = new Preview({id: 'main'}).fullscreen()
//TransformControls
@@ -1400,45 +1421,45 @@ function initCanvas() {
lights = new THREE.Object3D()
lights.name = 'lights'
- var light_top = new THREE.DirectionalLight();
- light_top.name = 'light_top'
- light_top.position.set(8, 100, 8)
- lights.add(light_top);
+ lights.top = new THREE.DirectionalLight();
+ lights.top.name = 'light_top'
+ lights.top.position.set(0, 100, 0)
+ lights.add(lights.top);
- light_top.intensity = 0.45
+ lights.top.intensity = 0.41
- var light_bottom = new THREE.DirectionalLight();
- light_bottom.name = 'light_bottom'
- light_bottom.position.set(8, 100, 8)
- lights.add(light_bottom);
+ lights.bottom = new THREE.DirectionalLight();
+ lights.bottom.name = 'light_bottom'
+ lights.bottom.position.set(0, -100, 0)
+ lights.add(lights.bottom);
- light_bottom.intensity = 0.11
+ lights.bottom.intensity = -0.02
- var light_north = new THREE.DirectionalLight();
- light_north.name = 'light_north'
- light_north.position.set(8, 8, -100)
- lights.add(light_north);
+ lights.north = new THREE.DirectionalLight();
+ lights.north.name = 'light_north'
+ lights.north.position.set(0, 0, -100)
+ lights.add(lights.north);
- var light_south = new THREE.DirectionalLight();
- light_south.name = 'light_south'
- light_south.position.set(8, 8, 100)
- lights.add(light_south);
+ lights.south = new THREE.DirectionalLight();
+ lights.south.name = 'light_south'
+ lights.south.position.set(0, 0, 100)
+ lights.add(lights.south);
- light_north.intensity = light_south.intensity = 0.33
+ lights.north.intensity = lights.south.intensity = 0.3
- var light_west = new THREE.DirectionalLight();
- light_west.name = 'light_west'
- light_west.position.set(-100, 8, 8)
- lights.add(light_west);
+ lights.west = new THREE.DirectionalLight();
+ lights.west.name = 'light_west'
+ lights.west.position.set(-100, 0, 0)
+ lights.add(lights.west);
- var light_east = new THREE.DirectionalLight();
- light_east.name = 'light_east'
- light_east.position.set(100, 8, 8)
- lights.add(light_east);
+ lights.east = new THREE.DirectionalLight();
+ lights.east.name = 'light_east'
+ lights.east.position.set(100, 0, 0)
+ lights.add(lights.east);
- light_west.intensity = light_east.intensity = 0.22
+ lights.west.intensity = lights.east.intensity = 0.1
- setShading()
+ updateShading()
quad_previews = {
one: new Preview({id: 'one'}).loadAnglePreset(DefaultCameraPresets[1]),
@@ -1508,8 +1529,10 @@ function initCanvas() {
function animate() {
TickUpdates.Run()
requestAnimationFrame( animate );
- previews.forEach(function(prev) {
- prev.render()
+ Preview.all.forEach(function(prev) {
+ if (prev.canvas.isConnected) {
+ prev.render()
+ }
})
framespersecond++;
if (display_mode === true && ground_animation === true && !Transformer.hoverAxis) {
@@ -1517,14 +1540,16 @@ function animate() {
}
}
-function setShading() {
+function updateShading() {
+ Canvas.updateLayeredTextures();
scene.remove(lights)
display_scene.remove(lights)
- Sun.intensity = settings.brightness.value/100;
+ Sun.intensity = settings.brightness.value/50;
if (settings.shading.value === true) {
- (display_mode ? display_scene : scene).add(lights)
- } else {
- Sun.intensity *= (1/0.6)
+ Sun.intensity *= 0.5;
+ let parent = display_mode ? display_scene : scene;
+ parent.add(lights);
+ lights.position.copy(parent.position).multiplyScalar(-1);
}
}
function updateCubeHighlights(hover_cube, force_off) {
@@ -1533,8 +1558,13 @@ function updateCubeHighlights(hover_cube, force_off) {
var mesh = cube.mesh;
mesh.geometry.faces.forEach(face => {
var b_before = face.color.b;
- if (Settings.get('highlight_cubes') && (hover_cube == cube || cube.selected) && Modes.edit && !force_off) {
- face.color.setRGB(1.3, 1.32, 1.34);
+ if (
+ Settings.get('highlight_cubes') &&
+ ((hover_cube == cube && !Transformer.dragging) || cube.selected) &&
+ Modes.edit &&
+ !force_off
+ ) {
+ face.color.setRGB(1.25, 1.28, 1.3);
} else {
face.color.setRGB(1, 1, 1);
}
@@ -1674,7 +1704,7 @@ function buildGrid() {
Canvas.side_grids.x.visible = !Modes.display;
Canvas.side_grids.x.rotation.z = Math.PI/2;
Canvas.side_grids.x.position.y = Format.centered_grid ? 8 : 0;
- Canvas.side_grids.z.position.y = -512
+ Canvas.side_grids.z.position.z = 0
Canvas.side_grids.x.children.forEach(el => {
el.layers.set(1)
});
@@ -1685,7 +1715,7 @@ function buildGrid() {
Canvas.side_grids.z.rotation.z = Math.PI/2;
Canvas.side_grids.z.rotation.y = Math.PI/2
Canvas.side_grids.z.position.y = Format.centered_grid ? 8 : 0;
- Canvas.side_grids.z.position.z = -512
+ Canvas.side_grids.z.position.z = 0
Canvas.side_grids.z.children.forEach(el => {
el.layers.set(3)
});
@@ -1820,6 +1850,17 @@ BARS.defineActions(function() {
main_preview.toggleFullscreen()
}
})
+ new Action('focus_on_selection', {
+ icon: 'center_focus_weak',
+ category: 'view',
+ condition: () => !Modes.display,
+ keybind: new Keybind({key: 191}),
+ click: function () {
+ let center = getSelectionCenter();
+ if (!Format.centered_grid) center.V3_subtract(8, 8, 8)
+ quad_previews.current.controls.target.fromArray(center);
+ }
+ })
new Action('toggle_camera_projection', {
icon: 'switch_video',
diff --git a/js/preview/transformer.js b/js/preview/transformer.js
index f4165942..8e4aeb99 100644
--- a/js/preview/transformer.js
+++ b/js/preview/transformer.js
@@ -579,7 +579,7 @@
this.children[2].children[0].children[6].renderOrder -= 9
this.children[2].scale.set(0.8, 0.8, 0.8)
-
+ /*
function updateLayers(obj) {
if (obj.name.includes('X')) {
obj.layers.set(4)
@@ -593,6 +593,7 @@
}
this.children[0].children[0].children.forEach(updateLayers)
this.children[1].children[0].children.forEach(updateLayers)
+ */
//Vars
var changeEvent = { type: "change" };
@@ -605,44 +606,16 @@
var point = new THREE.Vector3();
var offset = new THREE.Vector3();
-
- var rotation = new THREE.Vector3();
- var offsetRotation = new THREE.Vector3();
var scale = 1;
-
- var lookAtMatrix = new THREE.Matrix4();
var eye = new THREE.Vector3();
var tempMatrix = new THREE.Matrix4();
- var tempVector = new THREE.Vector3();
- var tempQuaternion = new THREE.Quaternion();
- var unitX = new THREE.Vector3( 1, 0, 0 );
- var unitY = new THREE.Vector3( 0, 1, 0 );
- var unitZ = new THREE.Vector3( 0, 0, 1 );
-
- var quaternionXYZ = new THREE.Quaternion();
- var quaternionX = new THREE.Quaternion();
- var quaternionY = new THREE.Quaternion();
- var quaternionZ = new THREE.Quaternion();
- var quaternionE = new THREE.Quaternion();
-
- var oldRotationMatrix = new THREE.Vector4()
- var oldRotationArray = []
- var parentRotationArray = []
- var oldScale = 0;
- var oldScaleTranslation = 0;
- var positionSnapOffset = new THREE.Vector3()
var originalValue = null;
var previousValue = 0;
- var tempScale = 1;
-
- var parentRotationMatrix = new THREE.Matrix4();
var worldPosition = new THREE.Vector3();
var worldRotation = new THREE.Euler();
- var worldRotationMatrix = new THREE.Matrix4();
var camPosition = new THREE.Vector3();
- var camRotation = new THREE.Euler();
this.attach = function ( object ) {
@@ -738,7 +711,7 @@
if (scope.elements.length == 0) return;
if (object) {
- worldRotation.setFromRotationMatrix( tempMatrix.extractRotation( object.matrixWorld ) );
+ if (!this.dragging) worldRotation.setFromRotationMatrix( tempMatrix.extractRotation( object.matrixWorld ) );
if (Toolbox.selected.transformerMode === 'rotate') {
_gizmo[ _mode ].update( worldRotation, eye );
this.rotation.set(0, 0, 0);
@@ -777,14 +750,6 @@
this.canvas.removeEventListener( "mousemove", onPointerHover );
this.canvas.removeEventListener( "touchmove", onPointerHover );
- this.canvas.removeEventListener( "mousemove", onPointerMove );
- this.canvas.removeEventListener( "touchmove", onPointerMove );
-
- this.canvas.removeEventListener( "mouseup", onPointerUp );
- this.canvas.removeEventListener( "mouseout", onPointerUp );
- this.canvas.removeEventListener( "touchend", onPointerUp );
- this.canvas.removeEventListener( "touchcancel", onPointerUp );
- this.canvas.removeEventListener( "touchleave", onPointerUp );
}
this.canvas = canvas;
this.canvas.addEventListener( "mousedown", onPointerDown, false );
@@ -792,15 +757,8 @@
this.canvas.addEventListener( "mousemove", onPointerHover, false );
this.canvas.addEventListener( "touchmove", onPointerHover, {passive: true} );
+
- this.canvas.addEventListener( "mousemove", onPointerMove, false );
- this.canvas.addEventListener( "touchmove", onPointerMove, {passive: true} );
-
- this.canvas.addEventListener( "mouseup", onPointerUp, false );
- this.canvas.addEventListener( "mouseout", onPointerUp, false );
- this.canvas.addEventListener( "touchend", onPointerUp, {passive: true} );
- this.canvas.addEventListener( "touchcancel", onPointerUp, {passive: true} );
- this.canvas.addEventListener( "touchleave", onPointerUp, {passive: true} );
}
this.setCanvas(domElement)
this.simulateMouseDown = function(e) {
@@ -837,7 +795,9 @@
this.getTransformSpace = function() {
if (!selected.length) return;
- let input_space = BarItems.transform_space.get()
+ let input_space = Toolbox.selected == BarItems.rotate_tool ? BarItems.rotation_space.get() : BarItems.transform_space.get()
+
+ if (Toolbox.selected == BarItems.rotate_tool && Format.rotation_limit) return 2;
if (input_space == 'local' && selected[0].rotatable && Toolbox.selected.id !== 'pivot_tool') {
let is_local = true;
@@ -913,11 +873,11 @@
let space = Transformer.getTransformSpace();
//Rotation
- if (Toolbox.selected.id === 'rotate_tool') {
- Transformer.rotation_ref = rotation_object.mesh.parent;
-
- } else if (space === 2 || Toolbox.selected.id == 'resize_tool') {
+ if (space === 2 || Toolbox.selected.id == 'resize_tool') {
Transformer.rotation_ref = selected[0] && selected[0].mesh;
+ if (Toolbox.selected.id == 'rotate_tool' && Group.selected) {
+ Transformer.rotation_ref = Group.selected.mesh;
+ }
} else if (space instanceof Group) {
Transformer.rotation_ref = space.mesh;
@@ -990,17 +950,17 @@
var pointer = event.changedTouches ? event.changedTouches[ 0 ] : event;
var intersect = intersectObjects( pointer, _gizmo[ _mode ].pickers.children );
- if (intersect) {
- //scope.dragging = true
- }
+
if (_dragging === true) return;
scope.hoverAxis = null;
if ( intersect ) {
scope.hoverAxis = intersect.object.name;
+ /*
if (scope.camera.axis && (scope.hoverAxis.toLowerCase() === scope.camera.axis) === (_mode !== 'rotate')) {
scope.hoverAxis = null;
}
+ */
event.preventDefault();
}
if ( scope.axis !== scope.hoverAxis ) {
@@ -1010,6 +970,8 @@
}
}
function onPointerDown( event ) {
+
+ document.addEventListener( "mouseup", onPointerUp, false );
if ( scope.elements.length === 0 || _dragging === true || ( event.button !== undefined && event.button !== 0 ) ) return;
var pointer = event.changedTouches ? event.changedTouches[ 0 ] : event;
@@ -1018,17 +980,21 @@
var intersect = intersectObjects( pointer, _gizmo[ _mode ].pickers.children );
if ( intersect ) {
scope.dragging = true
+ document.addEventListener( "touchend", onPointerUp, {passive: true} );
+ document.addEventListener( "touchcancel", onPointerUp, {passive: true} );
+ document.addEventListener( "touchleave", onPointerUp, {passive: true} );
+
+ document.addEventListener( "mousemove", onPointerMove, false );
+ document.addEventListener( "touchmove", onPointerMove, {passive: true} );
Transformer.getWorldPosition(worldPosition)
- if (scope.camera.axis && (scope.hoverAxis && scope.hoverAxis.toLowerCase() === scope.camera.axis) === (_mode !== 'rotate')) return;
+ //if (scope.camera.axis && (scope.hoverAxis && scope.hoverAxis.toLowerCase() === scope.camera.axis) === (_mode !== 'rotate')) return;
event.preventDefault();
event.stopPropagation();
scope.dispatchEvent( mouseDownEvent );
scope.axis = intersect.object.name;
scope.update();
- tempScale = 1
- oldScaleTranslation = 0;
eye.copy( camPosition ).sub( worldPosition ).normalize();
_gizmo[ _mode ].setActivePlane( scope.axis, eye );
var planeIntersect = intersectObjects( pointer, [ _gizmo[ _mode ].activePlane ] );
@@ -1510,9 +1476,16 @@
scope.dispatchEvent( objectChangeEvent );
}
function onPointerUp( event ) {
- event.preventDefault(); // Prevent MouseEvent on mobile
+ //event.preventDefault(); // Prevent MouseEvent on mobile
+ document.removeEventListener( "mouseup", onPointerUp );
scope.dragging = false
+ document.removeEventListener( "mousemove", onPointerMove );
+ document.removeEventListener( "touchmove", onPointerMove );
+ document.removeEventListener( "touchend", onPointerUp );
+ document.removeEventListener( "touchcancel", onPointerUp );
+ document.removeEventListener( "touchleave", onPointerUp );
+
if ( event.button !== undefined && event.button !== 0 && event.button !== 2 ) return;
if ( _dragging && scope.axis !== null ) {
diff --git a/js/property.js b/js/property.js
new file mode 100644
index 00000000..a804af6d
--- /dev/null
+++ b/js/property.js
@@ -0,0 +1,87 @@
+class Property {
+ constructor(target_class, type = 'boolean', name, options = 0) {
+ if (!target_class.properties) {
+ target_class.properties = {};
+ }
+ target_class.properties[name] = this;
+
+ this.class = target_class;
+ this.name = name;
+ this.type = type;
+
+ if (options.default) {
+ this.default = options.default;
+ } else {
+ switch (this.type) {
+ case 'string': this.default = ''; break;
+ case 'number': this.default = 0; break;
+ case 'boolean': this.default = false; break;
+ case 'array': this.default = []; break;
+ case 'vector': this.default = [0, 0, 0]; break;
+ case 'vector2': this.default = [0, 0]; break;
+ }
+ }
+ switch (this.type) {
+ case 'string': this.isString = true; break;
+ case 'number': this.isNumber = true; break;
+ case 'boolean': this.isBoolean = true; break;
+ case 'array': this.isArray = true; break;
+ case 'vector': this.isVector = true; break;
+ case 'vector2': this.isVector2 = true; break;
+ }
+
+ if (typeof options.merge == 'function') this.merge = options.merge;
+ if (typeof options.reset == 'function') this.reset = options.reset;
+ if (options.condition) this.condition = options.condition;
+ if (options.exposed == false) this.exposed = false;
+ if (options.label) this.label = options.label;
+ if (options.options) this.options = options.options;
+ }
+ merge(instance, data) {
+ if (data[this.name] == undefined || !Condition(this.condition)) return;
+
+ if (this.isString) {
+ Merge.string(instance, data, this.name)
+ }
+ else if (this.isNumber) {
+ Merge.number(instance, data, this.name)
+ }
+ else if (this.isBoolean) {
+ Merge.boolean(instance, data, this.name)
+ }
+ else if (this.isArray || this.isVector || this.isVector2) {
+ if (data[this.name] instanceof Array) {
+ if (instance[this.name] instanceof Array == false) {
+ instance[this.name] = [];
+ }
+ instance[this.name].replace(data[this.name]);
+ }
+ }
+ }
+ copy(instance, target) {
+ if (!Condition(this.condition)) return;
+
+ if (this.isArray || this.isVector || this.isVector2) {
+ if (instance[this.name] instanceof Array) {
+ target[this.name] = instance[this.name].slice();
+ }
+ } else {
+ target[this.name] = instance[this.name];
+ }
+ }
+ reset(instance) {
+ if (typeof this.default == 'function') {
+ var dft = this.default(instance);
+ } else {
+ var dft = this.default;
+ }
+ if (this.isArray || this.isVector || this.isVector2) {
+ if (instance[this.name] instanceof Array == false) {
+ instance[this.name] = [];
+ }
+ instance[this.name].replace(dft);
+ } else {
+ instance[this.name] = dft;
+ }
+ }
+}
diff --git a/js/texturing/color.js b/js/texturing/color.js
index a868b4d8..c8168e3b 100644
--- a/js/texturing/color.js
+++ b/js/texturing/color.js
@@ -47,6 +47,7 @@ function colorDistance(color1, color2) {
onVueSetup(() => {
ColorPanel = Interface.Panels.color = new Panel({
id: 'color',
+ icon: 'palette',
condition: () => Modes.id === 'paint',
toolbars: {
picker: Toolbars.color_picker,
diff --git a/js/texturing/painter.js b/js/texturing/painter.js
index 596872d1..9991159c 100644
--- a/js/texturing/painter.js
+++ b/js/texturing/painter.js
@@ -288,7 +288,7 @@ const Painter = {
let tool = Toolbox.selected.id;
ctx.clip()
- if (event.touches && event.touches[0] && event.touches[0].force) {
+ if (event.touches && event.touches[0] && event.touches[0].touchType == 'stylus' && event.touches[0].force) {
// Stylus
var touch = event.touches[0];
@@ -361,7 +361,7 @@ const Painter = {
for (var face in cube.faces) {
var tag = cube.faces[face]
ctx.beginPath();
- if (tag.texture === Painter.current.texture.uuid) {
+ if (tag.getTexture() === texture) {
var face_rect = getRectangle(
Math.floor(tag.uv[0] * uvFactorX),
Math.floor(tag.uv[1] * uvFactorY),
diff --git a/js/texturing/texture_generator.js b/js/texturing/texture_generator.js
index 0fd9c5a6..a7c037d7 100644
--- a/js/texturing/texture_generator.js
+++ b/js/texturing/texture_generator.js
@@ -16,6 +16,7 @@ const TextureGenerator = {
var dialog = new Dialog({
id: 'add_bitmap',
title: tl('action.create_texture'),
+ width: 412,
form: {
name: {label: 'generic.name', value: 'texture'},
folder: {label: 'dialog.create_texture.folder'},
@@ -28,6 +29,7 @@ const TextureGenerator = {
var dialog2 = new Dialog({
id: 'texture_template',
title: tl('dialog.create_texture.template'),
+ width: 412,
form: {
compress: {label: 'dialog.create_texture.compress', type: 'checkbox', value: true, condition: Project.box_uv},
power: {label: 'dialog.create_texture.power', type: 'checkbox', value: true},
@@ -81,7 +83,7 @@ const TextureGenerator = {
options.color = new tinycolor().toRgb()
}
if (Format.single_texture) {
- options.texture = textures[0]
+ options.texture = Texture.getDefault()
}
var texture = new Texture({
mode: 'bitmap',
@@ -514,7 +516,7 @@ const TextureGenerator = {
face_list.push(this);
}
- var cube_array = Format.single_texture ? Cube.all : Cube.selected;
+ var cube_array = (Format.single_texture ? Cube.all : Cube.selected).filter(cube => cube.visibility);
cube_array.forEach(cube => {
var fi = 0;
for (var face_key in cube.faces) {
@@ -640,7 +642,7 @@ const TextureGenerator = {
if (face.texture === undefined || face.texture === null) return false;
texture = face.getTexture()
} else {
- texture = textures[0];
+ texture = Texture.getDefault();
}
if (!texture || !texture.img) return false;
diff --git a/js/texturing/textures.js b/js/texturing/textures.js
index a1450b6a..4b9b4877 100644
--- a/js/texturing/textures.js
+++ b/js/texturing/textures.js
@@ -4,17 +4,15 @@ class Texture {
constructor(data, uuid) {
var scope = this;
//Info
- this.id = '';
- this.name = 'texture'
- this.folder = '';
- this.namespace = '';
- this.path = ''
- this.particle = false
+ for (var key in Texture.properties) {
+ Texture.properties[key].reset(this);
+ }
//meta
this.source = ''
this.selected = false
this.show_icon = true
this.error = 0;
+ this.visible = true;
//Data
this.img = 0;
this.width = 0;
@@ -62,7 +60,7 @@ class Texture {
vertexColors: THREE.FaceColors,
map: tex,
transparent: true,
- alphaTest: 0.2
+ alphaTest: 0.05
});
mat.name = this.name;
Canvas.materials[this.uuid] = mat;
@@ -145,7 +143,7 @@ class Texture {
}
}
get frameCount() {
- if (this.ratio !== 1 && this.ratio !== (Project.texture_width / Project.texture_height) && 1/this.ratio % 1 === 0) {
+ if (Format.animated_textures && this.ratio !== 1 && this.ratio !== (Project.texture_width / Project.texture_height) && 1/this.ratio % 1 === 0) {
return 1/this.ratio
}
}
@@ -162,32 +160,27 @@ class Texture {
}
}
getUndoCopy(bitmap) {
- var copy = {
- path: this.path,
- name: this.name,
- folder: this.folder,
- namespace: this.namespace,
- id: this.id,
- particle: this.particle,
- selected: this.selected,
- mode: this.mode,
- saved: this.saved,
- uuid: this.uuid,
- old_width: this.old_width,
- old_height: this.old_height
+ var copy = {}
+ for (var key in Texture.properties) {
+ Texture.properties[key].copy(this, copy)
}
+ copy.visible = this.visible;
+ copy.selected = this.selected;
+ copy.mode = this.mode;
+ copy.saved = this.saved;
+ copy.uuid = this.uuid;
+ copy.old_width = this.old_width;
+ copy.old_height = this.old_height;
if (bitmap || this.mode === 'bitmap') {
copy.source = this.source
}
return copy
}
extend(data) {
- Merge.string(this, data, 'path')
- Merge.string(this, data, 'name')
- Merge.string(this, data, 'folder')
- Merge.string(this, data, 'namespace')
- Merge.string(this, data, 'id')
- Merge.boolean(this, data, 'particle')
+ for (var key in Texture.properties) {
+ Texture.properties[key].merge(this, data)
+ }
+ Merge.boolean(this, data, 'visible')
Merge.string(this, data, 'mode', mode => (mode === 'bitmap' || mode === 'link'))
Merge.boolean(this, data, 'saved')
Merge.boolean(this, data, 'keep_size')
@@ -370,23 +363,12 @@ class Texture {
}
updateMaterial() {
var scope = this;
- var img = new Image()
- try {
- img.src = scope.source
- } catch(err) {
- }
+
Canvas.materials[scope.uuid].name = this.name;
- img.onload = function() {
- Canvas.materials[scope.uuid].map.dispose()
- var tex = new THREE.Texture(img)
- img.tex = tex;
- img.tex.magFilter = THREE.NearestFilter
- img.tex.minFilter = THREE.NearestFilter
- img.tex.name = scope.name;
- img.tex.needsUpdate = true;
+ Canvas.materials[scope.uuid].map.name = scope.name;
+ Canvas.materials[scope.uuid].map.image.src = scope.source;
+ Canvas.materials[scope.uuid].map.needsUpdate = true;
- Canvas.materials[scope.uuid].map = tex
- }
return this;
}
reopen(force) {
@@ -505,8 +487,14 @@ class Texture {
Prop.active_panel = 'textures'
}
this.selected = true
- textures.selected = this
- this.scrollTo()
+ Texture.selected = this;
+ this.scrollTo();
+ if (Project.layered_textures) {
+ Canvas.updatePaintingGrid()
+ } else if (Format.single_texture) {
+ Canvas.updateAllFaces()
+ TickUpdates.selection = true;
+ }
return this;
}
add(undo) {
@@ -526,22 +514,10 @@ class Texture {
loadTextureDraggable()
if (Format.single_texture && Cube.all.length) {
- Cube.all.forEach(function(s) {
- uv_dialog.allFaces.forEach(function(side) {
- if (s.faces[side].texture !== null) {
- s.faces[side].texture = scope.uuid;
- }
- })
- })
Canvas.updateAllFaces()
if (selected.length) {
main_uv.loadData()
}
- textures.forEach(function (t, i) {
- if (t !== scope) {
- textures.splice(i, 1)
- }
- })
}
TickUpdates.selection = true;
@@ -555,7 +531,9 @@ class Texture {
Undo.initEdit({textures: [this]})
}
this.stopWatcher()
- if (textures.selected == this) textures.selected = false;
+ if (Texture.selected == this) {
+ Texture.selected = undefined;
+ }
textures.splice(textures.indexOf(this), 1)
if (!no_update) {
Canvas.updateAllFaces()
@@ -568,6 +546,23 @@ class Texture {
Undo.finishEdit('remove_textures', {textures: []})
}
}
+ toggleVisibility() {
+ if (!Project.layered_textures) {
+ this.visible = true;
+ return this;
+ }
+ this.visible = !this.visible;
+ let c = 0;
+ Texture.all.forEach(tex => {
+ if (tex.visible) {
+ c++;
+ if (c >= 3 && tex !== this) {
+ tex.visible = false;
+ }
+ }
+ })
+ Canvas.updateLayeredTextures();
+ }
//Use
enableParticle() {
textures.forEach(function(s) {
@@ -669,7 +664,7 @@ class Texture {
lines: [
`
-
${path}
+
${settings.streamer_mode.value ? `[${tl('generic.redacted')}]` : path}
`
],
form: {
@@ -998,6 +993,29 @@ class Texture {
}
])
Texture.all = textures;
+ Texture.getDefault = function() {
+ if (Texture.selected && Texture.all.includes(Texture.selected)) {
+ return Texture.selected;
+ } else if (Texture.selected) {
+ Texture.selected = undefined;
+ }
+ if (Project.layered_textures && Texture.all.length > 1) {
+ var i = 0;
+ for (var i = Texture.all.length-1; i >= 0; i--) {
+ if (Texture.all[i].visible) {
+ return Texture.all[i]
+ }
+ }
+ }
+ return Texture.all[0]
+ }
+ new Property(Texture, 'string', 'path')
+ new Property(Texture, 'string', 'name')
+ new Property(Texture, 'string', 'folder')
+ new Property(Texture, 'string', 'namespace')
+ new Property(Texture, 'string', 'id')
+ new Property(Texture, 'boolean', 'particle')
+
function saveTextures() {
textures.forEach(function(t) {
@@ -1024,30 +1042,64 @@ function loadTextureDraggable() {
return t.find('.texture_icon_wrapper').clone().addClass('texture_drag_helper').attr('texid', t.attr('texid'))
},
drag: function(event, ui) {
+
$('.outliner_node[order]').attr('order', null)
- var tar = $('#cubes_list li .drag_hover.outliner_node').deepest()
- var element = Outliner.root.findRecursive('uuid', tar.attr('id'))
- if (element) {
- tar.attr('order', '0')
+ $('.texture[order]').attr('order', null)
+ if ($('#cubes_list.drag_hover').length === 0 && $('#cubes_list li .drag_hover.outliner_node').length) {
+ var tar = $('#cubes_list li .drag_hover.outliner_node').last()
+ var element = Outliner.root.findRecursive('uuid', tar.attr('id'))
+ if (element) {
+ tar.attr('order', '0')
+ }
+ } else if ($('#texture_list li:hover').length) {
+ let node = $('#texture_list > .texture:hover')
+ if (node.length) {
+ var target_tex = Texture.all.findInArray('uuid', node.attr('texid'));
+ index = Texture.all.indexOf(target_tex);
+ let offset = event.clientY - node[0].offsetTop;
+ if (offset > 24) {
+ node.attr('order', '1')
+ } else {
+ node.attr('order', '-1')
+ }
+ }
}
},
stop: function(event, ui) {
setTimeout(function() {
- if ($('canvas.preview:hover').length > 0) {
+ $('.texture[order]').attr('order', null)
+ var tex = textures.findInArray('uuid', ui.helper.attr('texid'));
+ if (!tex) return;
+ if ($('.preview:hover').length > 0) {
var data = Canvas.raycast(event)
if (data.cube && data.face) {
- var tex = textures.findInArray('uuid', ui.helper.attr('texid'));
var cubes_list = data.cube.selected ? Cube.selected : [data.cube];
- Undo.initEdit({elements: cubes_list})
- if (tex) {
+ if (tex && cubes_list) {
+ Undo.initEdit({elements: cubes_list})
cubes_list.forEach(cube => {
if (cube instanceof Cube) {
cube.applyTexture(tex, data.shiftKey || [data.face])
}
})
+ Undo.finishEdit('apply texture')
}
- Undo.finishEdit('apply texture')
}
+ } else if ($('#texture_list:hover').length > 0) {
+ let index = Texture.all.length-1
+ let node = $('#texture_list > .texture:hover')
+ if (node.length) {
+ var target_tex = Texture.all.findInArray('uuid', node.attr('texid'));
+ index = Texture.all.indexOf(target_tex);
+ let own_index = Texture.all.indexOf(tex)
+ if (own_index == index) return;
+ if (own_index < index) index--;
+ if (event.clientY - node[0].offsetTop > 24) index++;
+ }
+ Undo.initEdit({texture_order: true})
+ Texture.all.remove(tex)
+ Texture.all.splice(index, 0, tex)
+ Canvas.updateLayeredTextures()
+ Undo.finishEdit('reorder textures')
}
}, 10)
}
@@ -1059,7 +1111,8 @@ function unselectTextures() {
textures.forEach(function(s) {
s.selected = false;
})
- textures.selected = false
+ Texture.selected = undefined;
+ Canvas.updateLayeredTextures()
}
function getTexturesById(id) {
if (id === undefined) return;
@@ -1089,6 +1142,17 @@ Clipbench.pasteTextures = function() {
}
}
+Object.defineProperty(textures, selected, {
+ get() {
+ console.warn('textures.selected is deprecated. Please use Texture.selected instead.')
+ return Texture.selected;
+ },
+ set(tex) {
+ console.warn('textures.selected is deprecated. Please use Texture.selected instead.')
+ Texture.selected = tex;
+ }
+})
+
TextureAnimator = {
isPlaying: false,
interval: false,
@@ -1166,7 +1230,9 @@ TextureAnimator = {
onVueSetup(function() {
texturelist = new Vue({
el: '#texture_list',
- data: {textures}
+ data: {
+ textures: Texture.all
+ }
})
texturelist._data.elements = textures
})
@@ -1260,12 +1326,13 @@ BARS.defineActions(function() {
icon: 'play_arrow',
category: 'textures',
condition: function() {
+ if (!Format.animated_textures) return false;
var i = 0;
var show = false;
while (i < textures.length) {
if (textures[i].frameCount > 1) {
show = true;
- i = textures.length
+ break;
}
i++;
}
diff --git a/js/texturing/uv.js b/js/texturing/uv.js
index 1a869eb9..a40bf3c3 100644
--- a/js/texturing/uv.js
+++ b/js/texturing/uv.js
@@ -278,9 +278,11 @@ class UVEditor {
})
this.jquery.viewport.on('mousewheel', function(e) {
let event = e.originalEvent;
- event.stopPropagation()
if (event.ctrlOrCmd) {
+
+ event.stopPropagation()
+
var n = (event.deltaY < 0) ? 0.1 : -0.1;
n *= scope.zoom
var number = limitNumber(scope.zoom + n, 1, scope.max_zoom)
@@ -365,19 +367,18 @@ class UVEditor {
convertTouchEvent(event);
var multiplier = (Project.box_uv && tex) ? tex.width/Project.texture_width : 1
var pixel_size = scope.inner_width / tex.width
+ var result = {};
if (Toolbox.selected.id === 'copy_paste_tool') {
- return {
- x: Math.round(event.offsetX/pixel_size*1),
- y: Math.round(event.offsetY/pixel_size*1)
- }
+ result.x = Math.round(event.offsetX/pixel_size*1);
+ result.y = Math.round(event.offsetY/pixel_size*1);
} else {
let offset = BarItems.slider_brush_size.get()%2 == 0 && Toolbox.selected.brushTool ? 0.5 : 0;
- return {
- x: Math.floor(event.offsetX/pixel_size*1 + offset),
- y: Math.floor(event.offsetY/pixel_size*1 + offset)
- }
+ result.x = Math.floor(event.offsetX/pixel_size*1 + offset);
+ result.y = Math.floor(event.offsetY/pixel_size*1 + offset);
}
+ if (tex.frameCount) result.y += (tex.height / tex.frameCount) * tex.currentFrame;
+ return result;
}
startPaintTool(event) {
var scope = this;
@@ -666,7 +667,7 @@ class UVEditor {
}
}
getTexture() {
- if (Format.single_texture) return textures[0];
+ if (Format.single_texture) return Texture.getDefault();
return Cube.selected[0].faces[this.face].getTexture();
}
//Set
@@ -736,9 +737,9 @@ class UVEditor {
}
if (this.zoom > 1) {
- this.jquery.viewport.css('overflow', 'scroll scroll')
+ this.jquery.viewport.addClass('zoomed').css('overflow', 'scroll scroll')
} else {
- this.jquery.viewport.css('overflow', 'hidden')
+ this.jquery.viewport.removeClass('zoomed').css('overflow', 'hidden')
}
}
setFace(face, update = true) {
@@ -754,9 +755,9 @@ class UVEditor {
setToMainSlot() {
var scope = this;
$('.panel#uv').append(this.jquery.main)
- this.jquery.main.on('mousewheel', function(e) {
+ $('.panel#uv').on('mousewheel', function(e) {
- if (!Project.box_uv && !e.ctrlOrCmd) {
+ if (!Project.box_uv && !e.ctrlOrCmd && $('#uv_panel_sides:hover, #uv_viewport:not(.zoomed):hover').length) {
var faceIDs = {'north': 0, 'south': 1, 'west': 2, 'east': 3, 'up': 4, 'down': 5}
var id = faceIDs[scope.face]
event.deltaY > 0 ? id++ : id--;
@@ -903,7 +904,7 @@ class UVEditor {
if (!face && Cube.selected.length) {
var face = Cube.selected[0].faces[this.face];
}
- var tex = face ? face.getTexture() : textures[0];
+ var tex = face ? face.getTexture() : Texture.getDefault();
if (!tex || typeof tex !== 'object' || (tex.error && tex.error != 2)) {
this.img.src = '';
this.img.style.display = 'none';
@@ -2057,7 +2058,7 @@ BARS.defineActions(function() {
new BarSelect('uv_grid', {
category: 'uv',
condition: () => !Project.box_uv && Cube.selected.length,
- width: 60,
+ min_width: 68,
value: 'auto',
options: {
'auto': 'Pixel',
diff --git a/js/transform.js b/js/transform.js
index 9bf32cb7..4172d91b 100644
--- a/js/transform.js
+++ b/js/transform.js
@@ -41,10 +41,11 @@ function origin2geometry() {
Canvas.updatePositions()
Undo.finishEdit('origin to geometry')
}
-function getSelectionCenter() {
+function getSelectionCenter(all = false) {
var center = [0, 0, 0]
var i = 0;
- selected.forEach(obj => {
+ let items = (selected.length == 0 || all) ? elements : selected;
+ items.forEach(obj => {
if (obj.getWorldCenter) {
var pos = obj.getWorldCenter();
center[0] += pos.x
@@ -52,13 +53,13 @@ function getSelectionCenter() {
center[2] += pos.z
}
})
- for (var i = 0; i < 3; i++) {
- center[i] = center[i] / selected.length
+ if (items.length) {
+ for (var i = 0; i < 3; i++) {
+ center[i] = center[i] / items.length
+ }
}
if (!Format.centered_grid) {
- center[0] += 8;
- center[1] += 8;
- center[2] += 8;
+ center.V3_add(8, 8, 8)
}
return center;
}
@@ -645,26 +646,68 @@ function getRotationInterval(event) {
} else if (event.shiftKey && event.ctrlOrCmd) {
return 0.25;
} else if (event.shiftKey) {
- return 45;
+ return 22.5;
} else if (event.ctrlOrCmd) {
return 1;
} else {
- return 5;
+ return 2.5;
}
}
function getRotationObject() {
if (Format.bone_rig && Group.selected) return Group.selected;
if (Format.rotate_cubes && Cube.selected.length) return Cube.selected;
}
-function rotateOnAxis(modify, axis) {
+function rotateOnAxis(modify, axis, slider) {
+ var things;
+ if (Format.bone_rig && Group.selected) {
+ things = [Group.selected]
+ } else if (Format.rotate_cubes && Cube.selected.length) {
+ things = Cube.selected;
+ }
+ if (!things) return;
+ /*
if (Format.bone_rig && Group.selected) {
if (!Group.selected) return;
- var value = modify(Group.selected.rotation[axis]);
- Group.selected.rotation[axis] = Math.trimDeg(value)
- Canvas.updateAllBones()
- return
+ let obj = Group.selected.mesh
+
+ if (typeof space == 'object') {
+ let normal = axis == 0 ? THREE.NormalX : (axis == 1 ? THREE.NormalY : THREE.NormalZ)
+ let rotWorldMatrix = new THREE.Matrix4();
+ rotWorldMatrix.makeRotationAxis(normal, Math.degToRad(modify(0)))
+ rotWorldMatrix.multiply(obj.matrix)
+ obj.matrix.copy(rotWorldMatrix)
+ obj.setRotationFromMatrix(rotWorldMatrix)
+ let e = obj.rotation;
+ Group.selected.rotation[0] = Math.radToDeg(e.x);
+ Group.selected.rotation[1] = Math.radToDeg(e.y);
+ Group.selected.rotation[2] = Math.radToDeg(e.z);
+ Canvas.updateAllBones()
+
+ } else if (space == 0) {
+ let normal = axis == 0 ? THREE.NormalX : (axis == 1 ? THREE.NormalY : THREE.NormalZ)
+ let rotWorldMatrix = new THREE.Matrix4();
+ rotWorldMatrix.makeRotationAxis(normal, Math.degToRad(modify(0)))
+ rotWorldMatrix.multiply(obj.matrixWorld)
+
+ let inverse = new THREE.Matrix4().getInverse(obj.parent.matrixWorld)
+ rotWorldMatrix.premultiply(inverse)
+
+ obj.matrix.copy(rotWorldMatrix)
+ obj.setRotationFromMatrix(rotWorldMatrix)
+ let e = obj.rotation;
+ Group.selected.rotation[0] = Math.radToDeg(e.x);
+ Group.selected.rotation[1] = Math.radToDeg(e.y);
+ Group.selected.rotation[2] = Math.radToDeg(e.z);
+ Canvas.updateAllBones()
+
+ } else {
+ var value = modify(Group.selected.rotation[axis]);
+ Group.selected.rotation[axis] = Math.trimDeg(value)
+ Canvas.updateAllBones()
+ }
+ return;
}
- if (!Format.rotate_cubes) return;
+ */
//Warning
if (Format.rotation_limit && settings.dialog_rotation_limit.value) {
var i = 0;
@@ -692,19 +735,13 @@ function rotateOnAxis(modify, axis) {
}
}
var axis_letter = getAxisLetter(axis)
- var origin = Cube.selected[0].origin
- Cube.selected.forEach(function(obj, i) {
+ var origin =things[0].origin
+ things.forEach(function(obj, i) {
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
- })
- }*/
Cube.selected.forEach(function(obj, i) {
if (obj.rotation.allEqual(0)) {
obj.origin.V3_set(origin)
@@ -729,13 +766,77 @@ function rotateOnAxis(modify, axis) {
obj.rotation[axis] = obj_val
obj.rotation_axis = axis_letter
})
+ */
+ let space = Transformer.getTransformSpace()
+ things.forEach(obj => {
+ let mesh = obj.mesh;
+ if (obj instanceof Cube) {
+ if (obj.rotation.allEqual(0)) {
+ obj.origin.V3_set(origin)
+ }
+ }
+
+ if (slider || space == 2) {
+ var obj_val = modify(obj.rotation[axis]);
+ obj_val = Math.trimDeg(obj_val)
+ if (Format.rotation_limit) {
+ //Limit To 1 Axis
+ obj.rotation[(axis+1)%3] = 0
+ obj.rotation[(axis+2)%3] = 0
+ //Limit Angle
+ obj_val = Math.round(obj_val/22.5)*22.5
+ if (obj_val > 45 || obj_val < -45) {
+
+ let f = obj_val > 45
+ obj.roll(axis, f!=(axis==1) ? 1 : 3)
+ obj_val = f ? -22.5 : 22.5;
+ }
+ }
+ obj.rotation[axis] = obj_val
+ if (obj instanceof Cube) {
+ obj.rotation_axis = axis_letter
+ }
+
+ } else if (space instanceof Group) {
+ let normal = axis == 0 ? THREE.NormalX : (axis == 1 ? THREE.NormalY : THREE.NormalZ)
+ let rotWorldMatrix = new THREE.Matrix4();
+ rotWorldMatrix.makeRotationAxis(normal, Math.degToRad(modify(0)))
+ rotWorldMatrix.multiply(mesh.matrix)
+ mesh.matrix.copy(rotWorldMatrix)
+ mesh.setRotationFromMatrix(rotWorldMatrix)
+ let e = mesh.rotation;
+ obj.rotation[0] = Math.radToDeg(e.x);
+ obj.rotation[1] = Math.radToDeg(e.y);
+ obj.rotation[2] = Math.radToDeg(e.z);
+
+ } else if (space == 0) {
+ let normal = axis == 0 ? THREE.NormalX : (axis == 1 ? THREE.NormalY : THREE.NormalZ)
+ let rotWorldMatrix = new THREE.Matrix4();
+ rotWorldMatrix.makeRotationAxis(normal, Math.degToRad(modify(0)))
+ rotWorldMatrix.multiply(mesh.matrixWorld)
+
+ let inverse = new THREE.Matrix4().getInverse(mesh.parent.matrixWorld)
+ rotWorldMatrix.premultiply(inverse)
+
+ mesh.matrix.copy(rotWorldMatrix)
+ mesh.setRotationFromMatrix(rotWorldMatrix)
+ let e = mesh.rotation;
+ obj.rotation[0] = Math.radToDeg(e.x);
+ obj.rotation[1] = Math.radToDeg(e.y);
+ obj.rotation[2] = Math.radToDeg(e.z);
+
+ }
+ if (obj instanceof Group) {
+ Canvas.updateAllBones()
+ }
+ })
}
BARS.defineActions(function() {
new BarSelect('transform_space', {
- condition: () => Modes.edit,
+ condition: {modes: ['edit'], tools: ['move_tool', 'pivot_tool']},
category: 'transform',
options: {
global: true,
@@ -746,6 +847,19 @@ BARS.defineActions(function() {
updateSelection();
}
})
+ new BarSelect('rotation_space', {
+ condition: {modes: ['edit'], tools: ['rotate_tool']},
+ category: 'transform',
+ value: 'local',
+ options: {
+ global: 'action.transform_space.global',
+ bone: {condition: () => Format.bone_rig, name: true, name: 'action.transform_space.bone'},
+ local: 'action.transform_space.local'
+ },
+ onChange() {
+ updateSelection();
+ }
+ })
let grid_locked_interval = function(event) {
event = event||0;
return canvasGridSize(event.shiftKey, event.ctrlOrCmd);
@@ -951,7 +1065,7 @@ BARS.defineActions(function() {
}
},
change: function(modify) {
- rotateOnAxis(modify, 0)
+ rotateOnAxis(modify, 0, true)
Canvas.updatePositions()
},
onBefore: function() {
@@ -977,7 +1091,7 @@ BARS.defineActions(function() {
}
},
change: function(modify) {
- rotateOnAxis(modify, 1)
+ rotateOnAxis(modify, 1, true)
Canvas.updatePositions()
},
onBefore: function() {
@@ -1003,7 +1117,7 @@ BARS.defineActions(function() {
}
},
change: function(modify) {
- rotateOnAxis(modify, 2)
+ rotateOnAxis(modify, 2, true)
Canvas.updatePositions()
},
onBefore: function() {
diff --git a/js/undo.js b/js/undo.js
index c57da474..527aac5c 100644
--- a/js/undo.js
+++ b/js/undo.js
@@ -17,9 +17,6 @@ var Undo = {
}
- This still causes issues, for example with different texture selections
*/
- if (aspects.textures && aspects.textures.length == 0 && Format.single_texture && textures.length == 1) {
- aspects.textures[0] = textures[0];
- }
Undo.current_save = new Undo.save(aspects)
return Undo.current_save;
},
@@ -155,15 +152,21 @@ var Undo = {
}
if (aspects.group) {
- this.group = aspects.group.getChildlessCopy()
- this.group.uuid = aspects.group.uuid
+ this.group = aspects.group.getChildlessCopy(true)
}
if (aspects.textures) {
this.textures = {}
- aspects.textures.forEach(function(t) {
+ aspects.textures.forEach(t => {
var tex = t.getUndoCopy(aspects.bitmap)
- scope.textures[t.uuid] = tex
+ this.textures[t.uuid] = tex
+ })
+ }
+
+ if (aspects.texture_order && Texture.all.length) {
+ this.texture_order = [];
+ Texture.all.forEach(tex => {
+ this.texture_order.push(tex.uuid);
})
}
@@ -321,14 +324,25 @@ var Undo = {
}
for (var uuid in reference.textures) {
if (!save.textures[uuid]) {
- var tex = Undo.getItemByUUID(textures, uuid)
+ var tex = Undo.getItemByUUID(Texture.all, uuid)
if (tex) {
- textures.splice(textures.indexOf(tex), 1)
+ Texture.all.splice(Texture.all.indexOf(tex), 1)
+ }
+ if (Texture.selected == tex) {
+ Texture.selected = textures.selected = undefined;
}
}
}
Canvas.updateAllFaces()
}
+
+ if (save.texture_order) {
+ Texture.all.sort((a, b) => {
+ return save.texture_order.indexOf(a.uuid) - save.texture_order.indexOf(b.uuid);
+ })
+ Canvas.updateLayeredTextures()
+ }
+
if (save.settings) {
for (var key in save.settings) {
settings[key].value = save.settings[key]
diff --git a/js/util.js b/js/util.js
index 16241e32..25b47fe7 100644
--- a/js/util.js
+++ b/js/util.js
@@ -29,7 +29,7 @@ const Condition = function(condition, context) {
} else if (typeof condition === 'object') {
if (condition.modes instanceof Array && condition.modes.includes(Modes.id) === false) return false;
if (condition.formats instanceof Array && Format && condition.formats.includes(Format.id) === false) return false;
- if (condition.tools instanceof Array && condition.tools.includes(Toolbox.selected.id) === false) return false;
+ if (condition.tools instanceof Array && window.Toolbox && condition.tools.includes(Toolbox.selected.id) === false) return false;
if (condition.method instanceof Function) {
return condition.method(context);
@@ -572,6 +572,17 @@ function pathToExtension(path) {
if (!matches || !matches.length) return '';
return matches[0].replace('.', '').toLowerCase()
}
+Object.defineProperty(String.prototype, 'hashCode', {
+ value() {
+ var hash = 0, i, chr;
+ for (i = 0; i < this.length; i++) {
+ chr = this.charCodeAt(i);
+ hash = ((hash << 5) - hash) + chr;
+ hash |= 0;
+ }
+ return hash;
+ }
+});
//Color
tinycolor.prototype.toInt = function() {
diff --git a/js/web.js b/js/web.js
index 6985d738..88bbc3f6 100644
--- a/js/web.js
+++ b/js/web.js
@@ -1,6 +1,6 @@
(function() {
$.getScript("lib/file_saver.js");
- $.getScript('https://rawgit.com/nodeca/pako/master/dist/pako.js', function() {
+ $.getScript('https://rawgit.com/nodeca/pako/master/dist/pako.min.js', function() {
window.zlib = pako
})
})()
@@ -47,6 +47,7 @@ window.onbeforeunload = function() {
if (Prop.project_saved === false && elements.length > 0) {
return 'Unsaved Changes';
} else {
+ Blockbench.dispatchEvent('before_closing')
EditSession.quit()
}
}
diff --git a/lang/de.json b/lang/de.json
index 8634417b..4b811d6b 100644
--- a/lang/de.json
+++ b/lang/de.json
@@ -47,9 +47,9 @@
"keys.printscreen": "Drucken",
"keys.pause": "Pause",
"message.rotation_limit.title": "Rotationsbegrenzung",
- "message.rotation_limit.message": "Rotationen sind von Minecraft auf nur eine Achse und 22,5 Grad Abstände begrenzt. Das Drehen auf einer weiteren Achse setzt alle anderen Achsen zurück. Konvertiere das Modell in ein freies Modell, wenn du die freie Rotationen benötigst.",
+ "message.rotation_limit.message": "Rotationen sind von Minecraft auf nur eine Achse und 22,5 Grad Schritte begrenzt. Das Drehen auf einer weiteren Achse setzt alle anderen Achsen zurück. Konvertiere das Modell in ein freies Modell, wenn du die freie Rotationen benötigst.",
"message.file_not_found.title": "Datei nicht gefunden",
- "message.file_not_found.message": "Blockbench konnte die angeforderte Datei nicht finden. Überprüfe, ob die Datei lokal gespeichert ist und nicht in einer Cloud. ",
+ "message.file_not_found.message": "Blockbench konnte die angeforderte Datei nicht finden. Überprüfe, ob die Datei lokal gespeichert ist und nicht in einer Cloud.",
"message.screenshot.title": "Bildschirmfoto",
"message.screenshot.message": "Bildschirmfoto aufgezeichnet",
"message.screenshot.clipboard": "Zwischenablage",
@@ -84,7 +84,7 @@
"message.image_editor.title": "Wähle ein Bildbearbeitungsprogramm",
"message.image_editor.file": "Datei auswählen...",
"message.image_editor.exe": "Öffne die Programmdatei eines Bildbearbeitungsprogramms",
- "message.display_skin.title": "Spleierskin",
+ "message.display_skin.title": "Spielerskin",
"message.display_skin.message": "Wähle eine Skindatei von deinem Computer oder gebe einen Spielernamen an",
"message.display_skin.upload": "Skindatei",
"message.display_skin.name": "Spielername",
@@ -105,7 +105,7 @@
"dialog.project.width": "Textur-Breite",
"dialog.project.height": "Textur-Höhe",
"dialog.texture.title": "Textur",
- "dialog.texture.variable": "Alias",
+ "dialog.texture.variable": "Variable",
"dialog.texture.namespace": "Namensraum",
"dialog.texture.folder": "Ordner",
"dialog.extrude.title": "Grafik Extrudieren",
@@ -143,7 +143,7 @@
"dialog.plugins.app_only": "Nur für die Desktopanwendung",
"dialog.plugins.author": "von %0",
"dialog.plugins.show_less": "Weniger anzeigen",
- "dialog.entitylist.title": "Tiermodell öffnen",
+ "dialog.entitylist.title": "Objektmodell öffnen",
"dialog.entitylist.text": "Wähle das Modell, welches du öffnen möchtest",
"dialog.entitylist.bones": "Knochen",
"dialog.entitylist.cubes": "Elemente",
@@ -151,17 +151,13 @@
"dialog.create_texture.template": "Template",
"dialog.create_texture.resolution": "Auflösung",
"dialog.input.title": "Eingabe",
- "dialog.update.title": "Aktualisierungen",
- "dialog.update.refresh": "Neu laden",
- "dialog.update.up_to_date": "Blockbench ist aktuell!",
- "dialog.update.connecting": "Mit Server verbinden",
"dialog.settings.settings": "Einstellungen",
"dialog.settings.keybinds": "Tastenbelegungen",
"dialog.settings.about": "Über",
"layout.color.back": "Dunkler",
"layout.color.back.desc": "Hintergründe und Eingabefelder",
"layout.color.dark": "Dunkel",
- "layout.color.dark.desc": "Huntergrund der Vorschau",
+ "layout.color.dark.desc": "Hintergrund der Vorschau",
"layout.color.ui": "Oberfläche",
"layout.color.ui.desc": "Haupt-Oberflächenfarbe",
"layout.color.bright_ui": "Helle Oberfläche",
@@ -170,7 +166,7 @@
"layout.color.button.desc": "Schaltflächen und Schalter",
"layout.color.selected": "Auswahl",
"layout.color.selected.desc": "Ausgewählte Objekte und Registerkarten",
- "layout.color.border": "Rahmen",
+ "layout.color.border": "Grenze",
"layout.color.border.desc": "Rahmen von Schaltflächen und anderem",
"layout.color.accent": "Akzent",
"layout.color.accent.desc": "Akzentfarbe für Details",
@@ -202,8 +198,6 @@
"settings.category.export": "Export",
"settings.language": "Sprache",
"settings.language.desc": "Sprache der Benutzeroberfläche. Starte Blockbench neu, um die Änderungen wirksam zu machen.",
- "settings.show_actions": "Aktionen anzeigen",
- "settings.show_actions.desc": "Alle Aktionen in der Statusleiste anzeigen",
"settings.backup_interval": "Abstand der Sicherheitskopien",
"settings.backup_interval.desc": "Zeit zwischen den automatischen Sicherheitskopien in Minuten",
"settings.origin_size": "Angelpunkt",
@@ -219,7 +213,7 @@
"settings.base_grid": "Kleines Gitter",
"settings.base_grid.desc": "Kleines Gitter und Achsen anzeigen",
"settings.large_grid": "Großes Gitter",
- "settings.large_grid.desc": "3x3 Blöcke großes Gitter anzeigen",
+ "settings.large_grid.desc": "16x16 Blöcke großes Gitter anzeigen",
"settings.full_grid": "Kompletter großes Gitter",
"settings.full_grid.desc": "Vollständiges, genaues 3x3 Blöcke Gitter anzeigen",
"settings.large_box": "Blockrahmen",
@@ -235,7 +229,7 @@
"settings.paint_side_restrict": "Pinsel auf Seite beschränken",
"settings.paint_side_restrict.desc": "Beschränkt den Pinsel auf das Verändern der Seite, auf die geklickt wurde",
"settings.autouv": "Auto UV",
- "settings.autouv.desc": "Auto UV per Standard aktivieren",
+ "settings.autouv.desc": "Auto UV standardmäßig aktivieren",
"settings.create_rename": "Neue Elemente umbenennen",
"settings.create_rename.desc": "Beim Erstellen von Elementen oder Gruppen das Namensfeld zum Umbenennen auswählen",
"settings.edit_size": "Gitterauflösung",
@@ -326,8 +320,6 @@
"action.settings_window.desc": "Das Blockbench-Einstellungsmenü öffnen",
"action.plugins_window": "Plugins...",
"action.plugins_window.desc": "Öffnet den Pluginstore",
- "action.update_window": "Aktualisierungen...",
- "action.update_window.desc": "Nach Blockbench Aktualisierungen suchen",
"action.reset_keybindings": "Tastenbelegungen zurücksetzen",
"action.reset_keybindings.desc": "Alle Tastenbelegungen auf die Standardwerte zurücksetzen",
"action.reset_layout": "Layout zurücksetzen",
@@ -536,10 +528,6 @@
"message.square_textures": "Texturen müssen quadratisch sein",
"message.unsaved_texture.title": "Ungespeicherte Texturen",
"message.unsaved_texture.message": "Alle ungespeicherten Änderungen an dieser Textur gehen dadurch verloren. Möchtest du fortfahren?",
- "dialog.update.no_connection": "Keine Internetverbindung",
- "dialog.update.latest": "Aktuelle Version",
- "dialog.update.installed": "Installierte Version",
- "dialog.update.update": "Aktualisieren",
"action.vertex_snap_mode.move": "Verschieben",
"action.vertex_snap_mode.scale": "Größe ändern",
"action.open_model_folder": "Modellordner öffnen",
@@ -549,8 +537,6 @@
"menu.texture.particle": "Für Partikel verwenden",
"message.update_notification.title": "Ein Update ist verfügbar",
"message.update_notification.message": "Die neue Blockbench Version \"%0\" ist verfügbar. Möchtest du diese jetzt installieren?",
- "message.update_notification.install": "Installieren",
- "message.update_notification.later": "Später",
"message.untextured": "Diese Fläche hat keine Textur",
"dialog.toolbar_edit.title": "Toolbar Anpassen",
"keybindings.reset": "Zurücksetzen",
@@ -635,7 +621,6 @@
"timeline.rotation": "Drehung",
"timeline.position": "Position",
"timeline.scale": "Größe",
- "menu.timeline.add": "Keyframe hinzufügen",
"menu.keyframe.quaternion": "Quaternion",
"panel.animations": "Animationen",
"panel.keyframe": "Keyframe",
@@ -970,7 +955,6 @@
"action.add_keyframe.desc": "Fügt einen Keyframe hinzu. Halte Umschalt gedrückt, um die Werte zurückzusetzen",
"action.bring_up_all_animations.desc": "Listet alle verwendeten Animatoren in der Timeline auf",
"timeline.timeline": "Anweisungen",
- "menu.palette.load": "Palette laden",
"menu.palette.load.default": "Standard",
"panel.color.picker": "Farbwähler",
"panel.color.palette": "Palette",
@@ -1114,5 +1098,30 @@
"settings.render_sides.desc": "Select which side of a face is rendered",
"settings.render_sides.auto": "Auto",
"settings.render_sides.front": "Outside",
- "settings.render_sides.double": "Inside and Outside"
+ "settings.render_sides.double": "Inside and Outside",
+ "generic.enable": "Enable",
+ "generic.disable": "Disable",
+ "generic.redacted": "Redacted",
+ "dialog.project.layered_textures": "Layered Textures",
+ "dialog.select_texture.import_all": "Import All",
+ "dialog.skin.layer_template": "Layer Texture",
+ "about.version.up_to_date": "Up to date",
+ "about.version.update_available": "Version %0 is available",
+ "settings.category.application": "Application",
+ "settings.streamer_mode": "Streamer Mode",
+ "settings.streamer_mode.desc": "Hides sensitive information like recent models",
+ "settings.automatic_updates": "Automatic Updates",
+ "settings.automatic_updates.desc": "Automatically download new versions and keep Blockbench up-to-date",
+ "action.rotation_space": "Rotation Space",
+ "action.focus_on_selection": "Center View on Selection",
+ "action.focus_on_selection.desc": "Align the camera to face the center of the current selection",
+ "action.jump_to_timeline_start": "Jump to Animation Start",
+ "action.jump_to_timeline_end": "Jump to Animation End",
+ "menu.help.updating": "Updating (%0%)",
+ "menu.help.update_ready": "Relaunch to Update",
+ "menu.help.update_failed": "Update Failed",
+ "menu.animation.loop.once": "Play Once",
+ "menu.animation.loop.hold": "Hold On Last Frame",
+ "menu.animation.loop.loop": "Loop",
+ "interface.streamer_mode_on": "Streamer Mode Enabled"
}
\ No newline at end of file
diff --git a/lang/en.json b/lang/en.json
index 72ba30ef..78ddb296 100644
--- a/lang/en.json
+++ b/lang/en.json
@@ -39,6 +39,9 @@
"generic.name": "Name",
"generic.none": "None",
"generic.unset": "Unset",
+ "generic.enable": "Enable",
+ "generic.disable": "Disable",
+ "generic.redacted": "Redacted",
"dates.today": "Today",
"dates.yesterday": "Yesterday",
@@ -55,8 +58,8 @@
"mode.start.recent": "Recent",
"mode.start.no_recents": "No recently opened models",
- "format.free": "Free Model",
- "format.free.desc": "Model without restrictions for Unity etc.",
+ "format.free": "Generic Model",
+ "format.free.desc": "Model without restrictions for game engines, rendering etc.",
"format.skin": "Skin",
"format.skin.desc": "Edit player and entity skins",
"format.java_block": "Java Block/Item",
@@ -116,7 +119,7 @@
"message.canvas_limit_error.title": "Canvas Limit Error",
"message.canvas_limit_error.message": "The action could not be performed correctly because the format limits the canvas to 48 units. Shift the pivot point to prevent this.",
"message.rotation_limit.title": "Rotation Limits",
- "message.rotation_limit.message": "Rotations are limited by Minecraft to one axis and 22.5 degree increments. Rotating on a different axis will clear all rotations on the other axes. Convert the model to \"Free Model\" if you are modeling for other purposes and need free rotations.",
+ "message.rotation_limit.message": "Rotations are limited by Minecraft to one axis and 22.5 degree increments. Rotating on a different axis will clear all rotations on the other axes. Convert the model to \"Generic Model\" if you are modeling for other purposes and need free rotations.",
"message.file_not_found.title": "File Not Found",
"message.file_not_found.message": "Blockbench could not find the requested file. Make sure it is saved locally and not in a cloud.",
"message.recover_backup.title": "Recover Model",
@@ -165,10 +168,8 @@
"message.square_textures": "Textures have to be square",
"message.unsaved_texture.title": "Unsaved Texture",
"message.unsaved_texture.message": "All unsaved changes to this texture will be lost. Do you want to proceed?",
- "message.update_notification.title": "An Update Is Available",
- "message.update_notification.message": "The new Blockbench version \"%0\" is available. Do you want to install it now?",
- "message.update_notification.install": "Install",
- "message.update_notification.later": "Later",
+ "message.update_notification.title": "Could not Install Update",
+ "message.update_notification.message": "A new Blockbench version is available. Please enable Automatic Updates in the settings in order to update!",
"message.image_editor.title": "Select an image editor",
"message.image_editor.file": "Select File...",
@@ -232,6 +233,7 @@
"dialog.project.openparent": "Open Parent",
"dialog.project.modded_entity_version": "Export Version",
"dialog.project.ao": "Ambient Occlusion",
+ "dialog.project.layered_textures": "Layered Textures",
"dialog.project.box_uv": "Box UV",
"dialog.project.width": "Texture Width",
"dialog.project.height": "Texture Height",
@@ -239,10 +241,13 @@
"dialog.convert_project.title": "Convert Project",
"dialog.convert_project.text": "Are you sure you want to convert this project? You cannot undo this step.",
+ "dialog.select_texture.import_all": "Import All",
+
"dialog.texture.title": "Texture",
"dialog.texture.variable": "Variable",
"dialog.texture.namespace": "Namespace",
"dialog.texture.folder": "Folder",
+
"dialog.resize_texture.fill": "Fill with",
"dialog.resize_texture.fill.transparent": "Transparent",
@@ -334,15 +339,6 @@
"dialog.input.title": "Input",
- "dialog.update.title": "Updates",
- "dialog.update.refresh": "Refresh",
- "dialog.update.up_to_date": "Blockbench is up to date!",
- "dialog.update.connecting": "Connecting to server",
- "dialog.update.no_connection": "No internet connection",
- "dialog.update.latest": "Latest Version",
- "dialog.update.installed": "Installed Version",
- "dialog.update.update": "Update",
-
"dialog.sketchfab_uploader.title": "Upload Sketchfab Model",
"dialog.sketchfab_uploader.token": "API Token",
"dialog.sketchfab_uploader.about_token": "The token is used to connect Blockbench to your Sketchfab account. You can find it on %0",
@@ -365,6 +361,7 @@
"dialog.skin.model": "Model",
"dialog.skin.texture": "Texture (Optional)",
"dialog.skin.pose": "Pose",
+ "dialog.skin.layer_template": "Layer Texture",
"dialog.settings.settings": "Settings",
"dialog.settings.keybinds": "Keybindings",
@@ -413,6 +410,8 @@
"layout.css": "Custom CSS",
"about.version": "Version:",
+ "about.version.up_to_date": "Up to date",
+ "about.version.update_available": "Version %0 is available",
"about.creator": "Creator:",
"about.website": "Website:",
"about.bugtracker": "Bug Tracker:",
@@ -431,19 +430,14 @@
"settings.category.defaults": "Defaults",
"settings.category.dialogs": "Dialogs",
"settings.category.export": "Export",
+ "settings.category.application": "Application",
"settings.language": "Language",
"settings.language.desc": "Interface language. Restart Blockbench to apply changes",
"settings.username": "Username",
"settings.username.desc": "Username for edit sessions",
- "settings.show_actions": "Display Actions",
- "settings.show_actions.desc": "Display every action in the status bar",
- "settings.recent_projects": "Recent Model Cap",
- "settings.recent_projects.desc": "Maximum number of recent models to remember",
- "settings.backup_interval": "Backup Interval",
- "settings.backup_interval.desc": "Interval of the automatic backups in minutes",
- "settings.backup_retain": "Backup Retain Duration",
- "settings.backup_retain.desc": "Set how long Blockbench retains old backups in days",
+ "settings.streamer_mode": "Streamer Mode",
+ "settings.streamer_mode.desc": "Hides sensitive information like recent models",
"settings.origin_size": "Pivot Marker",
"settings.origin_size.desc": "Size of the pivot point marker",
@@ -536,7 +530,7 @@
"settings.minifiedout": "Minified Export",
"settings.minifiedout.desc": "Write JSON file in one line",
"settings.export_groups": "Export Groups",
- "settings.export_groups.desc": "Save groups in blockmodel files",
+ "settings.export_groups.desc": "Save groups in block or item model files",
"settings.credit": "Credit Comment",
"settings.credit.desc": "Add a credit comment to exported files",
"settings.sketchfab_token": "Sketchfab Token",
@@ -544,6 +538,15 @@
"settings.default_path": "Default Path",
"settings.default_path.desc": "Folder from where Blockbench loads default textures",
+ "settings.recent_projects": "Recent Model Cap",
+ "settings.recent_projects.desc": "Maximum number of recent models to remember",
+ "settings.backup_interval": "Backup Interval",
+ "settings.backup_interval.desc": "Interval of the automatic backups in minutes",
+ "settings.backup_retain": "Backup Retain Duration",
+ "settings.backup_retain.desc": "Set how long Blockbench retains old backups in days",
+ "settings.automatic_updates": "Automatic Updates",
+ "settings.automatic_updates.desc": "Automatically download new versions and keep Blockbench up-to-date",
+
"category.navigate": "Navigation",
"category.tools": "Tools",
"category.file": "File",
@@ -659,8 +662,8 @@
"action.add_model.desc": "Add a model from a file to the current model",
"action.extrude_texture": "Extruded Texture",
"action.extrude_texture.desc": "Generate a model by stretching out a texture",
- "action.export_blockmodel": "Export Blockmodel",
- "action.export_blockmodel.desc": "Export a Minecraft block or item model",
+ "action.export_blockmodel": "Export Block/Item Model",
+ "action.export_blockmodel.desc": "Export a Minecraft Java Edition block or item model",
"action.export_asset_archive": "Download Archive",
"action.export_asset_archive.desc": "Download an archive with the model and all textures in it",
"action.export_bedrock": "Export Bedrock Geometry",
@@ -693,8 +696,6 @@
"action.settings_window.desc": "Open the Blockbench settings dialog.",
"action.plugins_window": "Plugins...",
"action.plugins_window.desc": "Open the plugin store window",
- "action.update_window": "Updates...",
- "action.update_window.desc": "Search for Blockbench updates.",
"action.action_control": "Action Control",
"action.action_control.desc": "Search and execute any available action",
"action.edit_session": "Edit Session...",
@@ -784,6 +785,7 @@
"action.transform_space.global": "Global",
"action.transform_space.bone": "Bone",
"action.transform_space.local": "Local",
+ "action.rotation_space": "Rotation Space",
"action.scale": "Scale...",
"action.scale.desc": "Scale the selected cubes",
"action.rotate_cw": "Rotate %0 +90",
@@ -867,6 +869,8 @@
"action.sidebar_right.desc": "Open the interface to edit elements",
"action.load_camera_angle": "Camera Angle: %0",
"action.load_camera_angle.desc": "Load the camera angle '%0'",
+ "action.focus_on_selection": "Center View on Selection",
+ "action.focus_on_selection.desc": "Align the camera to face the center of the current selection",
"action.import_texture": "Import Texture",
"action.import_texture.desc": "Import one or more textures from your file system",
@@ -962,6 +966,8 @@
"action.previous_keyframe.desc": "Jump to the previous keyframe",
"action.next_keyframe": "Next Keyframe",
"action.next_keyframe.desc": "Jump to the next keyframe",
+ "action.jump_to_timeline_start": "Jump to Animation Start",
+ "action.jump_to_timeline_end": "Jump to Animation End",
"action.bring_up_all_animations": "Bring Up All Animators",
"action.bring_up_all_animations.desc": "Brings all modified animators into the timeline",
"action.fold_all_animations": "Fold All Animators",
@@ -1020,6 +1026,9 @@
"menu.help.developer.reset_storage": "Factory Reset",
"menu.help.developer.reset_storage.confirm": "Are you sure you want to reset Blockbench to factory settings? This will delete all custom settings, keybindings and installed plugins.",
"menu.help.developer.cache_reload": "Cache Reload",
+ "menu.help.updating": "Updating (%0%)",
+ "menu.help.update_ready": "Relaunch to Update",
+ "menu.help.update_failed": "Update Failed",
"menu.cube.color": "Marker Color",
"menu.cube.texture": "Texture",
@@ -1080,15 +1089,18 @@
"menu.toolbar.reset": "Reset",
"menu.animation.loop": "Loop",
+ "menu.animation.loop.once": "Play Once",
+ "menu.animation.loop.hold": "Hold On Last Frame",
+ "menu.animation.loop.loop": "Loop",
"menu.animation.override": "Override",
"menu.animation.anim_time_update": "Update Variable",
- "menu.timeline.add": "Add Keyframe",
-
"menu.keyframe.quaternion": "Quaternion",
"web.download_app": "Download App",
+ "interface.streamer_mode_on": "Streamer Mode Enabled",
+
"cube.color.light_blue": "Light Blue",
"cube.color.yellow": "Yellow",
"cube.color.orange": "Orange",
diff --git a/lang/es.json b/lang/es.json
index f4443819..b0af87ee 100644
--- a/lang/es.json
+++ b/lang/es.json
@@ -151,10 +151,6 @@
"dialog.create_texture.template": "Plantilla",
"dialog.create_texture.resolution": "Resolución",
"dialog.input.title": "Entrada",
- "dialog.update.title": "Actualizaciones",
- "dialog.update.refresh": "Reintentar",
- "dialog.update.up_to_date": "¡Blockbench está actualizado!",
- "dialog.update.connecting": "Conectando con el servidor",
"dialog.settings.settings": "Ajustes",
"dialog.settings.keybinds": "Atajos de Teclado",
"dialog.settings.about": "Acerca de",
@@ -202,8 +198,6 @@
"settings.category.export": "Exportar",
"settings.language": "Lenguaje",
"settings.language.desc": "Lenguaje de la interfaz. Reinicia Blockbench para aplicar los cambios.",
- "settings.show_actions": "Mostrar Acciones",
- "settings.show_actions.desc": "Mostrar todas las acciones en la barra de estado",
"settings.backup_interval": "Intervalo de Backup",
"settings.backup_interval.desc": "Intervalo de los backups automáticos en minutos",
"settings.origin_size": "Marcador de Pivote",
@@ -326,8 +320,6 @@
"action.settings_window.desc": "Abre la ventana de ajustes de Blockbench",
"action.plugins_window": "Plugins...",
"action.plugins_window.desc": "Abre la ventana de la tienda de plugins",
- "action.update_window": "Actualizaciones...",
- "action.update_window.desc": "Busca actualizaciones para Blockbench",
"action.reset_keybindings": "Resetear Atajos de Teclado",
"action.reset_keybindings.desc": "Resetea todos los atajos de teclado a los que tiene Blockbench por defecto",
"action.reset_layout": "Resetear Diseño",
@@ -536,10 +528,6 @@
"message.square_textures": "Las texturas tienen que ser cuadradas",
"message.unsaved_texture.title": "Textura sin guardar",
"message.unsaved_texture.message": "Todos los cambios no guardados de esta textura serán perdidos. ¿Quieres continuar?",
- "dialog.update.no_connection": "No hay conexión a Internet",
- "dialog.update.latest": "Última version",
- "dialog.update.installed": "Versión instalada",
- "dialog.update.update": "Actualizar",
"action.vertex_snap_mode.move": "Mover",
"action.vertex_snap_mode.scale": "Reescalar",
"action.open_model_folder": "Abrir la Carpeta del Modelo",
@@ -549,8 +537,6 @@
"menu.texture.particle": "Usar para Partículas",
"message.update_notification.title": "Una Actualización Está Disponible",
"message.update_notification.message": "La nueva versión de Blockbench \"%0\" está disponible. ¿Quieres instalarla ahora?",
- "message.update_notification.install": "Instalar",
- "message.update_notification.later": "Después",
"message.untextured": "La superficie no tiene una textura",
"dialog.toolbar_edit.title": "Personalizar Barra de Herramientas",
"keybindings.reset": "Resetear",
@@ -635,7 +621,6 @@
"timeline.rotation": "Rotación",
"timeline.position": "Posición",
"timeline.scale": "Escala",
- "menu.timeline.add": "Añadir Frame Clave",
"menu.keyframe.quaternion": "Quaternion",
"panel.animations": "Animaciones",
"panel.keyframe": "Frame Clave",
@@ -970,7 +955,6 @@
"action.add_keyframe.desc": "Añade un frame clave automáticamente. Pulsa shift para forzar los valores por defecto",
"action.bring_up_all_animations.desc": "Trae todos los animadores modificados a la timeline",
"timeline.timeline": "Instrucciones",
- "menu.palette.load": "Cargar Paleta",
"menu.palette.load.default": "Por Defecto",
"panel.color.picker": "Seleccionador",
"panel.color.palette": "Paleta",
@@ -1110,9 +1094,34 @@
"switches.lock": "Bloquear",
"camera_angle.isometric_right": "Derecha Isométrica",
"camera_angle.isometric_left": "Izquierda Isométrica",
- "settings.render_sides": "Render Sides",
- "settings.render_sides.desc": "Select which side of a face is rendered",
- "settings.render_sides.auto": "Auto",
- "settings.render_sides.front": "Outside",
- "settings.render_sides.double": "Inside and Outside"
+ "settings.render_sides": "Renderizar Lados",
+ "settings.render_sides.desc": "Seleccionar qué lado de una cara es renderizado",
+ "settings.render_sides.auto": "Automático",
+ "settings.render_sides.front": "Exterior",
+ "settings.render_sides.double": "Interior y Exterior",
+ "generic.enable": "Enable",
+ "generic.disable": "Disable",
+ "generic.redacted": "Redacted",
+ "dialog.project.layered_textures": "Layered Textures",
+ "dialog.select_texture.import_all": "Import All",
+ "dialog.skin.layer_template": "Layer Texture",
+ "about.version.up_to_date": "Up to date",
+ "about.version.update_available": "Version %0 is available",
+ "settings.category.application": "Application",
+ "settings.streamer_mode": "Streamer Mode",
+ "settings.streamer_mode.desc": "Hides sensitive information like recent models",
+ "settings.automatic_updates": "Automatic Updates",
+ "settings.automatic_updates.desc": "Automatically download new versions and keep Blockbench up-to-date",
+ "action.rotation_space": "Rotation Space",
+ "action.focus_on_selection": "Center View on Selection",
+ "action.focus_on_selection.desc": "Align the camera to face the center of the current selection",
+ "action.jump_to_timeline_start": "Jump to Animation Start",
+ "action.jump_to_timeline_end": "Jump to Animation End",
+ "menu.help.updating": "Updating (%0%)",
+ "menu.help.update_ready": "Relaunch to Update",
+ "menu.help.update_failed": "Update Failed",
+ "menu.animation.loop.once": "Play Once",
+ "menu.animation.loop.hold": "Hold On Last Frame",
+ "menu.animation.loop.loop": "Loop",
+ "interface.streamer_mode_on": "Streamer Mode Enabled"
}
\ No newline at end of file
diff --git a/lang/fr.json b/lang/fr.json
index 99cf3ad8..27218dc2 100644
--- a/lang/fr.json
+++ b/lang/fr.json
@@ -151,10 +151,6 @@
"dialog.create_texture.template": "Étalon",
"dialog.create_texture.resolution": "Résolution",
"dialog.input.title": "Entrée",
- "dialog.update.title": "Mises à jour",
- "dialog.update.refresh": "Réessayer",
- "dialog.update.up_to_date": "Blockbench est à jour !",
- "dialog.update.connecting": "Connexion au serveur en cours",
"dialog.settings.settings": "Réglages",
"dialog.settings.keybinds": "Raccourcis clavier",
"dialog.settings.about": "À propos",
@@ -202,8 +198,6 @@
"settings.category.export": "Exporter",
"settings.language": "Langue",
"settings.language.desc": "Langue de l'interface. Redémarrez Blockbench pour appliquer les modifications.",
- "settings.show_actions": "Actions d’affichage",
- "settings.show_actions.desc": "Afficher chaque action dans la barre d’état",
"settings.backup_interval": "Intervalle de sauvegarde",
"settings.backup_interval.desc": "Intervalle des sauvegardes automatiques en minutes",
"settings.origin_size": "Point de pivot",
@@ -326,8 +320,6 @@
"action.settings_window.desc": "Ouvrir la boîte de dialogue des paramètres Blockbench.",
"action.plugins_window": "Plugins…",
"action.plugins_window.desc": "Ouvrir le plugin store",
- "action.update_window": "Mises à jour…",
- "action.update_window.desc": "Rechercher des mises à jour de Blockbench.",
"action.reset_keybindings": "Réinitialiser les raccourcis clavier",
"action.reset_keybindings.desc": "Réinitialiser tous les raccourcis clavier aux valeurs par défaut de Blockbench",
"action.reset_layout": "Réinitialiser la mise en page",
@@ -536,10 +528,6 @@
"message.square_textures": "Les textures doivent être carrées",
"message.unsaved_texture.title": "Texture non sauvegardée",
"message.unsaved_texture.message": "Toute les modification non enregistrée de cette texture sera perdue. Voulez-vous poursuivre ?",
- "dialog.update.no_connection": "Pas de connexion Internet",
- "dialog.update.latest": "Dernière version",
- "dialog.update.installed": "Version installée",
- "dialog.update.update": "Mettre à jour",
"action.vertex_snap_mode.move": "Déplacer",
"action.vertex_snap_mode.scale": "Redimensionner",
"action.open_model_folder": "Ouvrir le dossier du modèle",
@@ -549,8 +537,6 @@
"menu.texture.particle": "Texture des particules",
"message.update_notification.title": "Une mise à jour est disponible",
"message.update_notification.message": "La nouvelle version « %0 » de Blockbench est disponible. Voulez-vous l'installer maintenant ?",
- "message.update_notification.install": "Installer",
- "message.update_notification.later": "Plus tard",
"message.untextured": "Cette surface n'a pas de texture",
"dialog.toolbar_edit.title": "Personnaliser la barre d'outils",
"keybindings.reset": "Réinitialiser",
@@ -635,7 +621,6 @@
"timeline.rotation": "Rotation",
"timeline.position": "Position",
"timeline.scale": "Taille",
- "menu.timeline.add": "Ajouter une image",
"menu.keyframe.quaternion": "Quaternion",
"panel.animations": "Animations",
"panel.keyframe": "Image",
@@ -970,7 +955,6 @@
"action.add_keyframe.desc": "Ajouter une keyframe automatiquement. Utilisez Alt pour forcer les valeurs par défaut.",
"action.bring_up_all_animations.desc": "Met toutes les animations modifiés dans la timeline",
"timeline.timeline": "Instructions",
- "menu.palette.load": "Charger une palette",
"menu.palette.load.default": "Par défaut",
"panel.color.picker": "Sélecteur",
"panel.color.palette": "Palette",
@@ -1114,5 +1098,30 @@
"settings.render_sides.desc": "Select which side of a face is rendered",
"settings.render_sides.auto": "Auto",
"settings.render_sides.front": "Outside",
- "settings.render_sides.double": "Inside and Outside"
+ "settings.render_sides.double": "Inside and Outside",
+ "generic.enable": "Enable",
+ "generic.disable": "Disable",
+ "generic.redacted": "Redacted",
+ "dialog.project.layered_textures": "Layered Textures",
+ "dialog.select_texture.import_all": "Import All",
+ "dialog.skin.layer_template": "Layer Texture",
+ "about.version.up_to_date": "Up to date",
+ "about.version.update_available": "Version %0 is available",
+ "settings.category.application": "Application",
+ "settings.streamer_mode": "Streamer Mode",
+ "settings.streamer_mode.desc": "Hides sensitive information like recent models",
+ "settings.automatic_updates": "Automatic Updates",
+ "settings.automatic_updates.desc": "Automatically download new versions and keep Blockbench up-to-date",
+ "action.rotation_space": "Rotation Space",
+ "action.focus_on_selection": "Center View on Selection",
+ "action.focus_on_selection.desc": "Align the camera to face the center of the current selection",
+ "action.jump_to_timeline_start": "Jump to Animation Start",
+ "action.jump_to_timeline_end": "Jump to Animation End",
+ "menu.help.updating": "Updating (%0%)",
+ "menu.help.update_ready": "Relaunch to Update",
+ "menu.help.update_failed": "Update Failed",
+ "menu.animation.loop.once": "Play Once",
+ "menu.animation.loop.hold": "Hold On Last Frame",
+ "menu.animation.loop.loop": "Loop",
+ "interface.streamer_mode_on": "Streamer Mode Enabled"
}
\ No newline at end of file
diff --git a/lang/it.json b/lang/it.json
index 8cfd2309..90af6c37 100644
--- a/lang/it.json
+++ b/lang/it.json
@@ -151,10 +151,6 @@
"dialog.create_texture.template": "Sagoma",
"dialog.create_texture.resolution": "Risoluzione",
"dialog.input.title": "Input",
- "dialog.update.title": "Aggiornamenti",
- "dialog.update.refresh": "Riprova",
- "dialog.update.up_to_date": "Blockbench è aggiornato!",
- "dialog.update.connecting": "Connesione al server",
"dialog.settings.settings": "Impostazioni",
"dialog.settings.keybinds": "Tasti",
"dialog.settings.about": "Sul Programma",
@@ -202,8 +198,6 @@
"settings.category.export": "Esporta",
"settings.language": "Lingua",
"settings.language.desc": "Lingua Interfaccia. Apri di nuovo Blockbench per applicare modifiche.",
- "settings.show_actions": "Mostra Azioni",
- "settings.show_actions.desc": "Mostrare ogni azione nella barra stato",
"settings.backup_interval": "Intervallo Backup",
"settings.backup_interval.desc": "Intervallo del backup automatico in minuti",
"settings.origin_size": "Origine di Rotazione",
@@ -326,8 +320,6 @@
"action.settings_window.desc": "Apri il dialogo delle impostazioni Blockbench",
"action.plugins_window": "Plugin...",
"action.plugins_window.desc": "Apri la schermata dei plugin",
- "action.update_window": "Aggiornamenti...",
- "action.update_window.desc": "Cerca aggiornamenti Blockbench.",
"action.reset_keybindings": "Ripristina Tasti",
"action.reset_keybindings.desc": "Ripristina tutti i tasti al predefinito di Blockbench",
"action.reset_layout": "Ripristina Layout",
@@ -457,9 +449,9 @@
"menu.texture.save": "Salva",
"menu.texture.properties": "Proprietà",
"menu.preview.background": "Sfondo",
- "menu.preview.background.load": "Caricare",
+ "menu.preview.background.load": "Carica",
"menu.preview.background.position": "Posizione",
- "menu.preview.background.lock": "Blocca Alla Videocamera",
+ "menu.preview.background.lock": "Attacca Alla Videocamera",
"menu.preview.screenshot": "Screenshot",
"menu.preview.perspective": "Prospettiva",
"menu.preview.perspective.normal": "Normale",
@@ -536,10 +528,6 @@
"message.square_textures": "Le texture devono essere quadrate",
"message.unsaved_texture.title": "Texture Non Salvata",
"message.unsaved_texture.message": "Tutte le modifiche non salvate verranno perse. Vuoi procedere?",
- "dialog.update.no_connection": "Nessuna connesione Internet",
- "dialog.update.latest": "Versione più Recente",
- "dialog.update.installed": "Versione Installata",
- "dialog.update.update": "Aggiornamento",
"action.vertex_snap_mode.move": "Muovi",
"action.vertex_snap_mode.scale": "Scala",
"action.open_model_folder": "Apri Cartella Modello",
@@ -549,8 +537,6 @@
"menu.texture.particle": "Usare per Particelle",
"message.update_notification.title": "È Disponibile un Aggiornamento",
"message.update_notification.message": "La versione nuova \"%0\" di Blockbench è disponibile. La vuoi installare adesso?",
- "message.update_notification.install": "Installare",
- "message.update_notification.later": "Più Tardi",
"message.untextured": "Questa superfice non ha una texture",
"dialog.toolbar_edit.title": "Personalizza Toolbar",
"keybindings.reset": "Resetta",
@@ -635,7 +621,6 @@
"timeline.rotation": "Rotazione",
"timeline.position": "Posizione",
"timeline.scale": "Scala",
- "menu.timeline.add": "Aggiungi Fotogramma",
"menu.keyframe.quaternion": "Quaternione",
"panel.animations": "Animazioni",
"panel.keyframe": "Fotogramma",
@@ -720,7 +705,7 @@
"action.action_control": "Controllo Azioni",
"action.action_control.desc": "Cerca ed esegui ogni azione disponibile",
"keybindings.recording": "Registrando Tasti",
- "keybindings.press": "Premi un tasto, una combinazione di tasti o clicca ovunque sullo schermo per registrare una combinzaione tasti",
+ "keybindings.press": "Premi un tasto, una combinazione di tasti o clicca ovunque sullo schermo per registrare una combinzaione tasti.",
"action.pivot_tool": "Strumento Origine",
"action.pivot_tool.desc": "Strumento per modificare l'origine dei cubi e delle ossa",
"action.slider_animation_speed": "Velocità Riproduzione",
@@ -970,7 +955,6 @@
"action.add_keyframe.desc": "Aggiungi un fotogramma automaticamente. Premi shift per forzare valori predefinti",
"action.bring_up_all_animations.desc": "Porta tutti gli animatori modificati nella sequenza temporale",
"timeline.timeline": "Istruzioni",
- "menu.palette.load": "Carica Tavolozza",
"menu.palette.load.default": "Predefinita",
"panel.color.picker": "Picker",
"panel.color.palette": "Tavolozza",
@@ -1007,112 +991,137 @@
"menu.preview.background.clipboard": "Carica dagli Appunti",
"dialog.ignore": "Ignora",
"generic.unset": "Non settato",
- "message.invalid_builtin_parent.title": "Invalid Built-in Parent",
+ "message.invalid_builtin_parent.title": "Genitore Incorporato Invalido",
"message.invalid_builtin_parent.message": "Il collegamento al modello principale non valido '% 0' è stato rimosso per esportare un modello valido.",
"dialog.resize_texture.fill": "Riempire con",
"dialog.resize_texture.fill.transparent": "Trasparente",
"dialog.resize_texture.fill.color": "Colore",
"dialog.resize_texture.fill.repeat": "Ripeti",
"dialog.resize_texture.fill.stretch": "Allunga",
- "dialog.scale.element_pivot": "Element Pivot",
+ "dialog.scale.element_pivot": "Origine dell'Elemento",
"dialog.scale.selection_center": "Centro di Selezione",
"dialog.create_gif.length_mode": "Modalità lunghezza",
"dialog.create_gif.length_mode.seconds": "Secondi",
"dialog.create_gif.length_mode.frames": "Montatura",
"dialog.create_gif.length_mode.animation": "Lunghezza della'animazione",
- "dialog.create_gif.length_mode.turntable": "Turntable Rotation",
- "dialog.save_angle.projection": "Projection",
- "dialog.save_angle.projection.perspective": "Perspective",
- "dialog.save_angle.projection.orthographic": "Orthographic",
- "dialog.sketchfab_uploader.animations": "Animations",
- "dialog.settings.theme": "Theme",
- "settings.category.interface": "Interface",
- "settings.preview_checkerboard": "Preview Checkerboard",
- "settings.preview_checkerboard.desc": "Toggle the checkerboard background behind the preview",
- "settings.uv_checkerboard": "UV Editor Checkerboard",
- "settings.uv_checkerboard.desc": "Toggle the checkerboard background behind the UV editor",
+ "dialog.create_gif.length_mode.turntable": "Velocità Rotazione",
+ "dialog.save_angle.projection": "Proiezione",
+ "dialog.save_angle.projection.perspective": "Prospettiva",
+ "dialog.save_angle.projection.orthographic": "Ortografica",
+ "dialog.sketchfab_uploader.animations": "Animazioni",
+ "dialog.settings.theme": "Tema",
+ "settings.category.interface": "Interfaccia",
+ "settings.preview_checkerboard": "Anteprima Scacchiera",
+ "settings.preview_checkerboard.desc": "Alterna lo sfondo a scacchiera dieto l'anteprima",
+ "settings.uv_checkerboard": "Scacchiera Editore UV",
+ "settings.uv_checkerboard.desc": "Alterna lo sfondo a scacchiera dietro l'editore UV",
"category.paint": "Dipingi",
- "action.fill_mode.color_connected": "Connected Colors",
+ "action.fill_mode.color_connected": "Colori Connessi",
"action.draw_shape_type": "Tipo di forma",
"action.draw_shape_type.rectangle": "Rettangolo",
- "action.draw_shape_type.rectangle_h": "Rectangle (Hollow)",
- "action.draw_shape_type.ellipse": "Eclissi",
- "action.draw_shape_type.ellipse_h": "Ellipse (Hollow)",
+ "action.draw_shape_type.rectangle_h": "Rettangolo (Vuoto)",
+ "action.draw_shape_type.ellipse": "Ellisse",
+ "action.draw_shape_type.ellipse_h": "Ellisse (Vuota)",
"action.draw_shape_type.line": "Linea",
- "action.mirror_painting": "Mirror Painting",
- "action.mirror_painting.description": "Mirror your paint strokes to the other side of the model",
- "action.lock_alpha": "Lock Alpha Channel",
- "action.lock_alpha.description": "Lock the transparency of all pixels",
+ "action.mirror_painting": "Pittura Specchiata",
+ "action.mirror_painting.description": "Specchia il tratto del pennello sull'altro lato del modello",
+ "action.lock_alpha": "Blocca Canale Alfa",
+ "action.lock_alpha.description": "Blocca la trasparenza di tutti i pixel",
"action.draw_shape_tool": "Disegna una forma",
- "action.draw_shape_tool.desc": "Tool to draw simple shapes on textures",
- "action.copy_paste_tool": "Copy Paste Tool",
- "action.copy_paste_tool.desc": "Tool to copy and paste selections of textures",
- "action.export_gltf": "Export As glTF",
- "action.export_gltf.desc": "Export model and animations as glTF file to use in other 3D applications",
- "action.transform_space": "Transform Space",
- "action.transform_space.desc": "Default transform space for elements and bones",
- "action.transform_space.global": "Global",
- "action.transform_space.bone": "Bone",
- "action.transform_space.local": "Local",
- "action.toggle_camera_projection": "Toggle Camera Projection",
- "action.toggle_camera_projection.desc": "Toggle the camera projection between perspective and orthographic",
- "action.load_camera_angle": "Camera Angle: %0",
- "action.load_camera_angle.desc": "Load the camera angle '%0'",
- "action.slider_face_tint": "Tint Index",
- "action.slider_face_tint.desc": "Set the tint index of the current face. -1 means unset.",
- "menu.help.quickstart": "Quickstart Wizard",
- "menu.help.developer": "Developer",
- "menu.help.developer.dev_tools": "Open Dev Tools",
- "menu.help.developer.reset_storage": "Factory Reset",
- "menu.help.developer.reset_storage.confirm": "Are you sure you want to reset Blockbench to factory settings? This will delete all custom settings, keybindings and installed plugins.",
- "menu.help.developer.cache_reload": "Cache Reload",
- "menu.texture.resize": "Resize...",
- "menu.preview.orthographic": "Orthographic",
- "menu.preview.save_angle": "Save Angle...",
- "menu.preview.angle": "Angles",
- "menu.preview.angle.initial": "Initial Angle",
- "menu.preview.angle.load": "Load",
- "menu.preview.maximize": "Maximize",
- "panel.color.both": "Both",
- "uv_editor.copy_selection": "Copy Selection",
- "uv_editor.paste_selection": "Paste Selection",
- "uv_editor.copy_paste_tool.place": "Place",
- "uv_editor.copy_paste_tool.cut": "Cut",
- "uv_editor.copy_paste_tool.mirror_x": "Mirror X",
- "uv_editor.copy_paste_tool.mirror_y": "Mirror Y",
- "uv_editor.copy_paste_tool.rotate": "Rotate 90 Degrees",
- "dialog.project.modded_entity_version": "Export Version",
- "dialog.save_angle.position": "Camera Position",
- "dialog.save_angle.target": "Focal Point",
- "dialog.skin.pose": "Pose",
- "layout.color.frame": "Window Frame",
- "layout.color.frame.desc": "Border and title bar of the window",
- "settings.large_grid_size": "Block Grid Size",
- "settings.large_grid_size.desc": "Size of the block grid",
- "action.load_plugin_from_url": "Load Plugin from URL",
- "action.load_plugin_from_url.desc": "Load a plugin from a server by specifying the URL",
- "action.cube_counter.desc": "Displays the current number of cubes and other statistics",
- "action.unlock_everything": "Unlock All",
- "action.unlock_everything.desc": "Unlock all groups and elements in the outliner.",
- "action.load_palette": "Load Palette",
- "action.load_palette.desc": "Load one of the built-in palette presets",
- "action.toggle_locked": "Toggle Lock",
- "action.toggle_locked.desc": "Toggle whether the selected elements are locked",
- "action.apply_display_preset": "Apply Preset",
- "action.apply_display_preset.desc": "Apply a default or custom display setting preset",
- "action.apply_display_preset.here": "Apply To This Slot",
- "action.apply_display_preset.everywhere": "Apply To All Slots",
- "action.resolve_keyframe_expressions": "Resolve Keyframe",
- "action.resolve_keyframe_expressions.desc": "Resolves the math expressions of the selected keyframes",
- "action.fold_all_animations": "Fold All Animators",
- "action.timeline_focus.used": "In Use",
- "menu.palette.load.empty": "Blank",
- "switches.lock": "Lock",
- "camera_angle.isometric_right": "Isometric Right",
- "camera_angle.isometric_left": "Isometric Left",
- "settings.render_sides": "Render Sides",
- "settings.render_sides.desc": "Select which side of a face is rendered",
+ "action.draw_shape_tool.desc": "Strumento per disegnare figure semplici sulle texture",
+ "action.copy_paste_tool": "Strumento Copia Incolla",
+ "action.copy_paste_tool.desc": "Strumento per copiare e incollare selezioni di texture",
+ "action.export_gltf": "Esporta come glTF",
+ "action.export_gltf.desc": "Esporta il modello e le animzioni come un file glTF per usarlo in altre applicazioni 3D",
+ "action.transform_space": "Spazio Trasformazione",
+ "action.transform_space.desc": "Spazio trasformazione predefinito per tutti gli elementi e ossa",
+ "action.transform_space.global": "Globale",
+ "action.transform_space.bone": "Osso",
+ "action.transform_space.local": "Locale",
+ "action.toggle_camera_projection": "Alterna Proiezione Videocamera",
+ "action.toggle_camera_projection.desc": "Alterna la proezione della videocamera tra prospettiva e ortografica",
+ "action.load_camera_angle": "Angolo Videocamera: %0",
+ "action.load_camera_angle.desc": "Carica l'angolo videocamera '%0'",
+ "action.slider_face_tint": "Indice Tinta",
+ "action.slider_face_tint.desc": "Imposta l'indice tinta della faccia corrente. -1 vuol dire non impostato.",
+ "menu.help.quickstart": "Procedura Guidata D'inizio",
+ "menu.help.developer": "Sviluppatore",
+ "menu.help.developer.dev_tools": "Apri Dev Tools",
+ "menu.help.developer.reset_storage": "Ripristino Impostazioni",
+ "menu.help.developer.reset_storage.confirm": "Sei sicuro di voler ripristinare Blockbench alle impostazioni di fabbrica? Questo eliminera tutte le impostazioni, tutti i tasti personalizzati e plugin installati.",
+ "menu.help.developer.cache_reload": "Ricarica Cache",
+ "menu.texture.resize": "Ridimensiona...",
+ "menu.preview.orthographic": "Ortografico",
+ "menu.preview.save_angle": "Salva Angolo...",
+ "menu.preview.angle": "Angoli",
+ "menu.preview.angle.initial": "Angolo Iniziale",
+ "menu.preview.angle.load": "Carica",
+ "menu.preview.maximize": "Aumentare al Massimo",
+ "panel.color.both": "Entrambi",
+ "uv_editor.copy_selection": "Copia Selezione",
+ "uv_editor.paste_selection": "Incolla Selezione",
+ "uv_editor.copy_paste_tool.place": "Piazza",
+ "uv_editor.copy_paste_tool.cut": "Taglia",
+ "uv_editor.copy_paste_tool.mirror_x": "Specchia Asse X",
+ "uv_editor.copy_paste_tool.mirror_y": "Specchia Asse Y",
+ "uv_editor.copy_paste_tool.rotate": "Ruota 90 Gradi",
+ "dialog.project.modded_entity_version": "Versione Esporto",
+ "dialog.save_angle.position": "Posizione Videocamera",
+ "dialog.save_angle.target": "Punto Focale",
+ "dialog.skin.pose": "Posa",
+ "layout.color.frame": "Cornice Finestra",
+ "layout.color.frame.desc": "Bordi e panello titolare della finestra",
+ "settings.large_grid_size": "Dimensioni Reticolato Blocco",
+ "settings.large_grid_size.desc": "Dimensioni del reticolato dei blocchi",
+ "action.load_plugin_from_url": "Carica Plugin da URL",
+ "action.load_plugin_from_url.desc": "Carica un plugin da un server specificando un URL",
+ "action.cube_counter.desc": "Mostra il numero corrente dei cubi e altri dati",
+ "action.unlock_everything": "Sblocca Tutti",
+ "action.unlock_everything.desc": "Sblocca tutti i gruppi ed elementi nella lista degli elementi",
+ "action.load_palette": "Carica Tavolozza",
+ "action.load_palette.desc": "Carica una delle tavolozze integrate",
+ "action.toggle_locked": "Alterna Blocco",
+ "action.toggle_locked.desc": "Alterna lo stato di blocco degli elementi selezionati",
+ "action.apply_display_preset": "Applica Preset",
+ "action.apply_display_preset.desc": "Applica un preset impostazioni display predefinito oppure un preset personalizzato",
+ "action.apply_display_preset.here": "Applica a Questo Slot",
+ "action.apply_display_preset.everywhere": "Applica a Tutti gli Slot",
+ "action.resolve_keyframe_expressions": "Risolvi Fotogrammi",
+ "action.resolve_keyframe_expressions.desc": "Risolve le espressioni matematiche dei fotogrammi selezionati",
+ "action.fold_all_animations": "Chiudi Animazioni",
+ "action.timeline_focus.used": "In Uso",
+ "menu.palette.load.empty": "Vuoto",
+ "switches.lock": "Blocca",
+ "camera_angle.isometric_right": "Isometrico Destro",
+ "camera_angle.isometric_left": "Isometrico Sinistro",
+ "settings.render_sides": "Lati Rendering",
+ "settings.render_sides.desc": "Seleziona il lato di una faccia che viene mostrato",
"settings.render_sides.auto": "Auto",
- "settings.render_sides.front": "Outside",
- "settings.render_sides.double": "Inside and Outside"
+ "settings.render_sides.front": "Fuori",
+ "settings.render_sides.double": "Dentro e Fuori",
+ "generic.enable": "Enable",
+ "generic.disable": "Disable",
+ "generic.redacted": "Redacted",
+ "dialog.project.layered_textures": "Layered Textures",
+ "dialog.select_texture.import_all": "Import All",
+ "dialog.skin.layer_template": "Layer Texture",
+ "about.version.up_to_date": "Up to date",
+ "about.version.update_available": "Version %0 is available",
+ "settings.category.application": "Application",
+ "settings.streamer_mode": "Streamer Mode",
+ "settings.streamer_mode.desc": "Hides sensitive information like recent models",
+ "settings.automatic_updates": "Automatic Updates",
+ "settings.automatic_updates.desc": "Automatically download new versions and keep Blockbench up-to-date",
+ "action.rotation_space": "Rotation Space",
+ "action.focus_on_selection": "Center View on Selection",
+ "action.focus_on_selection.desc": "Align the camera to face the center of the current selection",
+ "action.jump_to_timeline_start": "Jump to Animation Start",
+ "action.jump_to_timeline_end": "Jump to Animation End",
+ "menu.help.updating": "Updating (%0%)",
+ "menu.help.update_ready": "Relaunch to Update",
+ "menu.help.update_failed": "Update Failed",
+ "menu.animation.loop.once": "Play Once",
+ "menu.animation.loop.hold": "Hold On Last Frame",
+ "menu.animation.loop.loop": "Loop",
+ "interface.streamer_mode_on": "Streamer Mode Enabled"
}
\ No newline at end of file
diff --git a/lang/ja.json b/lang/ja.json
index b7cac4a9..d5e6883b 100644
--- a/lang/ja.json
+++ b/lang/ja.json
@@ -151,10 +151,6 @@
"dialog.create_texture.template": "テンプレート",
"dialog.create_texture.resolution": "解像度",
"dialog.input.title": "入力",
- "dialog.update.title": "アップデート",
- "dialog.update.refresh": "リトライ",
- "dialog.update.up_to_date": "Blockbenchは最新です!",
- "dialog.update.connecting": "サーバーにつなげる",
"dialog.settings.settings": "設定",
"dialog.settings.keybinds": "キー設定",
"dialog.settings.about": "About",
@@ -202,8 +198,6 @@
"settings.category.export": "エクスポート",
"settings.language": "言語",
"settings.language.desc": "言語を変更します。Blockbenchを再起動して変更を適用します",
- "settings.show_actions": "アクションの表示",
- "settings.show_actions.desc": "ステータスバーにすべてのアクションを表示する",
"settings.backup_interval": "バックアップ間隔",
"settings.backup_interval.desc": "自動バックアップの間隔を設定します-分-",
"settings.origin_size": "回転軸",
@@ -326,8 +320,6 @@
"action.settings_window.desc": "Blockbenchの設定",
"action.plugins_window": "プラグイン…",
"action.plugins_window.desc": "プラグインストアを開く",
- "action.update_window": "アップデート…",
- "action.update_window.desc": "更新の確認",
"action.reset_keybindings": "Reset Keybindings",
"action.reset_keybindings.desc": "すべてのキー設定をデフォルトにリセットする",
"action.reset_layout": "Reset Layout",
@@ -536,10 +528,6 @@
"message.square_textures": "テクスチャは正方形でなければ適用出来ません",
"message.unsaved_texture.title": "保存されてないテクスチャ",
"message.unsaved_texture.message": "テクスチャの変更は保存されず失われます。続行しますか?",
- "dialog.update.no_connection": "インターネットに接続されていません",
- "dialog.update.latest": "最新のバージョン",
- "dialog.update.installed": "インストールされたバージョン",
- "dialog.update.update": "更新する",
"action.vertex_snap_mode.move": "Move",
"action.vertex_snap_mode.scale": "Scale",
"action.open_model_folder": "モデルフォルダを開く",
@@ -549,8 +537,6 @@
"menu.texture.particle": "パーティクル",
"message.update_notification.title": "アップデート",
"message.update_notification.message": "新しいBlockbench\"%0\"が使用可能です。今すぐインストールしますか?",
- "message.update_notification.install": "インストール",
- "message.update_notification.later": "後で",
"message.untextured": "このPCにはテクスチャがありません",
"dialog.toolbar_edit.title": "ツールバーのカスタマイズ",
"keybindings.reset": "リセット",
@@ -635,7 +621,6 @@
"timeline.rotation": "Rotation",
"timeline.position": "Position",
"timeline.scale": "Scale",
- "menu.timeline.add": "Add Keyframe",
"menu.keyframe.quaternion": "Quaternion",
"panel.animations": "Animations",
"panel.keyframe": "Keyframe",
@@ -970,7 +955,6 @@
"action.add_keyframe.desc": "キーフレームを自動的に追加します。 Shiftキーを押してデフォルト値を表示します",
"action.bring_up_all_animations.desc": "変更されたすべてのアニメーターをタイムラインに取り込みます",
"timeline.timeline": "取扱説明書",
- "menu.palette.load": "パレットをロード",
"menu.palette.load.default": "デフォルト",
"panel.color.picker": "Picker",
"panel.color.palette": "Palette",
@@ -1081,38 +1065,63 @@
"uv_editor.copy_paste_tool.mirror_x": "Mirror X",
"uv_editor.copy_paste_tool.mirror_y": "Mirror Y",
"uv_editor.copy_paste_tool.rotate": "Rotate 90°",
- "dialog.project.modded_entity_version": "Export Version",
+ "dialog.project.modded_entity_version": "バージョンをエクスポート",
"dialog.save_angle.position": "カメラポジション",
- "dialog.save_angle.target": "Focal Point",
- "dialog.skin.pose": "Pose",
- "layout.color.frame": "Window Frame",
- "layout.color.frame.desc": "Border and title bar of the window",
- "settings.large_grid_size": "Block Grid Size",
- "settings.large_grid_size.desc": "Size of the block grid",
- "action.load_plugin_from_url": "Load Plugin from URL",
- "action.load_plugin_from_url.desc": "Load a plugin from a server by specifying the URL",
- "action.cube_counter.desc": "Displays the current number of cubes and other statistics",
- "action.unlock_everything": "Unlock All",
- "action.unlock_everything.desc": "Unlock all groups and elements in the outliner.",
+ "dialog.save_angle.target": "焦点",
+ "dialog.skin.pose": "ポーズ",
+ "layout.color.frame": "フレーム",
+ "layout.color.frame.desc": "ボーダーとタイトルバーのフレーム",
+ "settings.large_grid_size": "ブロックグリットサイズ",
+ "settings.large_grid_size.desc": "ブロックグリットのサイズを変更",
+ "action.load_plugin_from_url": "URLからプラグインをロード",
+ "action.load_plugin_from_url.desc": "サーバーからプラグインをロードします",
+ "action.cube_counter.desc": "現在のキューブ数とその他の統計を表示します",
+ "action.unlock_everything": "アンロック",
+ "action.unlock_everything.desc": "アウトライナーの全てのロックを解除します",
"action.load_palette": "パレットをロード",
- "action.load_palette.desc": "Load one of the built-in palette presets",
+ "action.load_palette.desc": "パレットプリセットをロードします",
"action.toggle_locked": "トグルロック",
- "action.toggle_locked.desc": "Toggle whether the selected elements are locked",
- "action.apply_display_preset": "Apply Preset",
- "action.apply_display_preset.desc": "Apply a default or custom display setting preset",
- "action.apply_display_preset.here": "Apply To This Slot",
- "action.apply_display_preset.everywhere": "Apply To All Slots",
+ "action.toggle_locked.desc": "ロックするかどうかを切り替えます",
+ "action.apply_display_preset": "プリセットを適用",
+ "action.apply_display_preset.desc": "カスタムの表示設定プリセットを適用します",
+ "action.apply_display_preset.here": "スロットに適応",
+ "action.apply_display_preset.everywhere": "全てのスロットに適応します",
"action.resolve_keyframe_expressions": "Resolve Keyframe",
"action.resolve_keyframe_expressions.desc": "Resolves the math expressions of the selected keyframes",
- "action.fold_all_animations": "Fold All Animators",
+ "action.fold_all_animations": "すべてのアニメーターを折りたたむ",
"action.timeline_focus.used": "使用する",
"menu.palette.load.empty": "空白",
"switches.lock": "ロック",
- "camera_angle.isometric_right": "Isometric Right",
- "camera_angle.isometric_left": "Isometric Left",
- "settings.render_sides": "Render Sides",
- "settings.render_sides.desc": "Select which side of a face is rendered",
- "settings.render_sides.auto": "Auto",
- "settings.render_sides.front": "Outside",
- "settings.render_sides.double": "Inside and Outside"
+ "camera_angle.isometric_right": "同尺-右",
+ "camera_angle.isometric_left": "同尺-左",
+ "settings.render_sides": "レンダリング",
+ "settings.render_sides.desc": "面をレンダリングします",
+ "settings.render_sides.auto": "オート",
+ "settings.render_sides.front": "アウトサイド",
+ "settings.render_sides.double": "両面",
+ "generic.enable": "Enable",
+ "generic.disable": "Disable",
+ "generic.redacted": "Redacted",
+ "dialog.project.layered_textures": "Layered Textures",
+ "dialog.select_texture.import_all": "Import All",
+ "dialog.skin.layer_template": "Layer Texture",
+ "about.version.up_to_date": "Up to date",
+ "about.version.update_available": "Version %0 is available",
+ "settings.category.application": "Application",
+ "settings.streamer_mode": "Streamer Mode",
+ "settings.streamer_mode.desc": "Hides sensitive information like recent models",
+ "settings.automatic_updates": "Automatic Updates",
+ "settings.automatic_updates.desc": "Automatically download new versions and keep Blockbench up-to-date",
+ "action.rotation_space": "Rotation Space",
+ "action.focus_on_selection": "Center View on Selection",
+ "action.focus_on_selection.desc": "Align the camera to face the center of the current selection",
+ "action.jump_to_timeline_start": "Jump to Animation Start",
+ "action.jump_to_timeline_end": "Jump to Animation End",
+ "menu.help.updating": "Updating (%0%)",
+ "menu.help.update_ready": "Relaunch to Update",
+ "menu.help.update_failed": "Update Failed",
+ "menu.animation.loop.once": "Play Once",
+ "menu.animation.loop.hold": "Hold On Last Frame",
+ "menu.animation.loop.loop": "Loop",
+ "interface.streamer_mode_on": "Streamer Mode Enabled"
}
\ No newline at end of file
diff --git a/lang/ko.json b/lang/ko.json
index 451da82c..3a84d9a8 100644
--- a/lang/ko.json
+++ b/lang/ko.json
@@ -99,7 +99,7 @@
"dialog.project.title": "프로젝트",
"dialog.project.name": "파일 이름",
"dialog.project.parent": "부모 모델",
- "dialog.project.geoname": "몹 지오메트리 이름",
+ "dialog.project.geoname": "모델 식별자",
"dialog.project.openparent": "부모 모델 열기",
"dialog.project.ao": "동적 그림자",
"dialog.project.width": "텍스쳐 가로 크기",
@@ -151,10 +151,6 @@
"dialog.create_texture.template": "템플릿",
"dialog.create_texture.resolution": "텍스쳐 해상도",
"dialog.input.title": "입력",
- "dialog.update.title": "업데이트",
- "dialog.update.refresh": "재시도",
- "dialog.update.up_to_date": "Blockbench를 업데이트하여야 합니다!",
- "dialog.update.connecting": "서버 연결 중",
"dialog.settings.settings": "설정",
"dialog.settings.keybinds": "키 설정",
"dialog.settings.about": "정보",
@@ -202,8 +198,6 @@
"settings.category.export": "내보내기 설정",
"settings.language": "언어",
"settings.language.desc": "언어. 변경 사항을 적용하려면 Blockbench 재시작 필요",
- "settings.show_actions": "액션 표시",
- "settings.show_actions.desc": "상태 표시 줄에 있는 모든 행동 표시",
"settings.backup_interval": "백업 주기",
"settings.backup_interval.desc": "분당 자동 백업 주기입니다.",
"settings.origin_size": "중점 표시",
@@ -218,10 +212,10 @@
"settings.texture_fps.desc": "에니메이션 텍스쳐의 초당 프레임",
"settings.base_grid": "작은 격자",
"settings.base_grid.desc": "작은 격자를 표시합니다",
- "settings.large_grid": "중간 격자",
- "settings.large_grid.desc": "1블록 단위의 중간 격자를 표시합니다",
- "settings.full_grid": "큰 격자",
- "settings.full_grid.desc": "3x3 크기의 큰 격자를 표기합니다",
+ "settings.large_grid": "블록 격자",
+ "settings.large_grid.desc": "16x16 크기의 블록 격자를 표시합니다.",
+ "settings.full_grid": "정확한 블록 격자",
+ "settings.full_grid.desc": "픽셀의 정확한 블록 격자를 표시합니다.",
"settings.large_box": "중간 박스",
"settings.large_box.desc": "3x3 경계 표시",
"settings.display_grid": "보기 모드",
@@ -326,8 +320,6 @@
"action.settings_window.desc": "Blockbench 설정 대화 상자 열기",
"action.plugins_window": "플러그인",
"action.plugins_window.desc": "플러그인 스토어 메뉴를 엽니다.",
- "action.update_window": "업데이트...",
- "action.update_window.desc": "Blockbench 업데이트 검색",
"action.reset_keybindings": "조작키 초기화",
"action.reset_keybindings.desc": "설정한 모든 단축키를 기본값으로 되돌립니다.",
"action.reset_layout": "레이아웃 초기화",
@@ -373,7 +365,7 @@
"action.scale": "크기 조정...",
"action.scale.desc": "선택된 큐브 크기",
"action.center_all": "모두 중앙으로",
- "action.center_all.desc": "선택된 큐브를 중앙으로",
+ "action.center_all.desc": "선택된 큐브를 중앙으로 합니다.",
"action.toggle_visibility": "보이기 전환",
"action.toggle_visibility.desc": "선택된 큐브 보이기 전환",
"action.toggle_export": "내보내기 전환",
@@ -385,7 +377,7 @@
"action.rename": "이름 바꾸기",
"action.rename.desc": "선택된 큐브 이름 바꾸기",
"action.add_display_preset": "새 사전 설정",
- "action.add_display_preset.desc": "디스플레이 설정의 새 사전 설정을 추가합니다.",
+ "action.add_display_preset.desc": "새로운 사전 표기 설정을 추가합니다.",
"action.fullscreen": "전체 화면",
"action.fullscreen.desc": "전체화면 켜기/끄기",
"action.zoom_in": "확대",
@@ -536,10 +528,6 @@
"message.square_textures": "텍스쳐는 정사각형이어야 합니다",
"message.unsaved_texture.title": "저장되지 않은 텍스쳐",
"message.unsaved_texture.message": "이 텍스쳐에 대한 변경 사항은 전부 지워질 것입니다. 계속하시겠습니까?",
- "dialog.update.no_connection": "인터넷 연결 없음",
- "dialog.update.latest": "최신 버전",
- "dialog.update.installed": "설치된 버전",
- "dialog.update.update": "업데이트",
"action.vertex_snap_mode.move": "이동",
"action.vertex_snap_mode.scale": "크기",
"action.open_model_folder": "모델 폴더 열기",
@@ -549,13 +537,11 @@
"menu.texture.particle": "파티클로 사용",
"message.update_notification.title": "업데이트가 가능합니다.",
"message.update_notification.message": "Blockbench의 새로운 버전 \"%0\"을 사용할 수 있습니다. 지금 설치하시겠습니까?",
- "message.update_notification.install": "설치",
- "message.update_notification.later": "나중에",
"message.untextured": "이 표면은 텍스쳐가 없습니다",
"dialog.toolbar_edit.title": "툴바 사용자 설정",
"keybindings.reset": "초기화",
"keybindings.clear": "없음",
- "action.cube_counter": "현재 큐브 수 및 기타 통계량 표시",
+ "action.cube_counter": "큐브 개수 세기",
"action.uv_rotation": "UV 회전",
"action.uv_rotation.desc": "UV 표면의 각도",
"action.uv_grid": "UV 그리드",
@@ -635,7 +621,6 @@
"timeline.rotation": "회전",
"timeline.position": "위치",
"timeline.scale": "크기",
- "menu.timeline.add": "키프레임 추가",
"menu.keyframe.quaternion": "쿼터니언",
"panel.animations": "애니메이션",
"panel.keyframe": "키프레임",
@@ -708,7 +693,7 @@
"menu.preview.perspective.reset": "카메라 초기화",
"action.fill_mode": "채우기 모드",
"action.fill_mode.face": "면",
- "action.fill_mode.color": "색상",
+ "action.fill_mode.color": "색깔",
"action.fill_mode.cube": "큐브",
"action.toggle_mirror_uv": "UV 반전",
"action.toggle_mirror_uv.desc": "선택한 큐브의 X축에서 UV 미러링 토글",
@@ -938,92 +923,91 @@
"layout.css": "커스텀 CSS",
"settings.category.paint": "칠하기",
"settings.deactivate_size_limit": "크기 제한 비활성화",
- "settings.deactivate_size_limit.desc": "Deactivate the size limit for specific model formats. WARNING: This can cause invalid models.",
+ "settings.deactivate_size_limit.desc": "특정 모델의 크기 제한을 제거합니다. ( 경고 : 이 설정은 오류를 발생시킬 수 있습니다! )",
"settings.brush_opacity_modifier": "불투명 브러쉬 수정",
- "settings.brush_opacity_modifier.desc": "Modify the brush opacity when using a stylus",
+ "settings.brush_opacity_modifier.desc": "스타일러스펜을 사용할 때 브러쉬 투명도를 설정합니다.",
"settings.brush_size_modifier": "브러쉬 크기 조정",
- "settings.brush_size_modifier.desc": "Modify the brush size when using a stylus",
+ "settings.brush_size_modifier.desc": "스타일러스펜을 사용할 때 브러쉬 크기를 설정합니다. ",
"settings.brush_modifier.pressure": "압력",
"settings.brush_modifier.tilt": "기울기",
"category.color": "색상",
"action.import_theme": "테마 불러오기",
"action.export_theme": "테마 내보내기",
- "action.export_theme.desc": "Create a theme file based on the current settings",
+ "action.export_theme.desc": "현재 설정을 백업 파일로 생성합니다",
"action.reset_theme": "테마 초기화",
- "action.reset_theme.desc": "Reset to the default Blockbench theme",
+ "action.reset_theme.desc": "설정 초기화",
"action.slider_color_h": "합성 색",
- "action.slider_color_s": "Saturation",
+ "action.slider_color_s": "채도",
"action.slider_color_v": "값",
"action.add_to_palette": "색상 견본에 추가",
- "action.add_to_palette.desc": "Add the selected color to the color palette",
+ "action.add_to_palette.desc": "선택된 색깔을 팔레트에 추가합니다.",
"action.import_palette": "색상 견본 불러오기",
"action.import_palette.desc": ".bbpalette 색상 견본 파일 불러오기",
"action.export_palette": "색상 견본 내보내기",
"action.export_palette.desc": ".bbpalette 파일로 색상 견본 내보내기",
"action.generate_palette": "색상 견본 생성",
"action.generate_palette.desc": "텍스쳐로부터 색상 견본 생성",
- "action.sort_palette": "Sort Palette",
- "action.sort_palette.desc": "Sort all colors on the palette by color and brightness",
+ "action.sort_palette": "팔레트 정렬",
+ "action.sort_palette.desc": "팔레트의 모든 색깔을 색깔과 밝기로 정렬",
"action.timelapse": "타임랩스",
- "action.timelapse.desc": "Record a timelapse of your modeling process",
+ "action.timelapse.desc": "모델 제작의 진행 등의 모든 행동들을 기록합니다.",
"action.add_keyframe": "키프레임 추가",
- "action.add_keyframe.desc": "Automatically add a keyframe. Press shift to force default values",
- "action.bring_up_all_animations.desc": "Brings all modified animators into the timeline",
- "timeline.timeline": "Instructions",
- "menu.palette.load": "색상 견본 불러오기",
+ "action.add_keyframe.desc": "자동으로 키 프레임을 추가합니다. 쉬프트를 눌러 강제로 기본 값으로 합니다.",
+ "action.bring_up_all_animations.desc": "설정된 모든 애니메이션들을 타임라인으로 불러옵니다.",
+ "timeline.timeline": "지시",
"menu.palette.load.default": "기본값",
"panel.color.picker": "색 고르기",
"panel.color.palette": "색상 견본",
"generic.import": "불러오기",
"settings.brush_modifier.none": "없음",
"action.export_entity": "베드락 엔티티 내보내기",
- "action.export_entity.desc": "Add the current model as an entity to a mobs.json file",
- "settings.highlight_cubes": "Highlight Cubes",
- "settings.highlight_cubes.desc": "Highlight cubes when you hover over them or select them",
+ "action.export_entity.desc": "현재 제작되어있는 모델을 엔티티 모델 ( mobs.json ) 로 저장합니다.",
+ "settings.highlight_cubes": "큐브 강조하기",
+ "settings.highlight_cubes.desc": "큐브를 마우스로 가리킬 시 혹은 선택할 시 강조하기",
"action.add_marker": "마커 설정",
- "action.add_marker.desc": "Set a timeline marker",
+ "action.add_marker.desc": "타임라인 표시하기",
"timeline.pre_effect_script": "스크립트",
"format.skin": "스킨",
"format.skin.desc": "플레이어, 엔티티 스킨 수정",
- "message.sketchfab.setup_guide": "Want to learn how to set up models in Sketchfab? Read %0",
+ "message.sketchfab.setup_guide": "Sketchfab 에서 3D 모델을 제작하는 방법은 %0 을(를) 참고하세요.",
"dialog.skin.title": "스킨 생성",
- "dialog.skin.model": "스킨",
+ "dialog.skin.model": "스킨 모델",
"dialog.skin.texture": "텍스쳐 (선택 사항)",
"action.toggle_skin_layer": "스킨 레이어 스위치",
- "action.toggle_skin_layer.desc": "Toggle the hat and clothing layer of the skin model",
- "action.gui_light": "GUI Light",
- "action.gui_light.desc": "Select the way the item is lit in the inventory",
+ "action.toggle_skin_layer.desc": "스킨 모델의 모자와 옷 등의 레이어를 활성화 혹은 비활성화합니다.",
+ "action.gui_light": "GUI 밝기",
+ "action.gui_light.desc": "아이템이 인벤토리에서 밝혀지는 방법을 정합니다.",
"action.gui_light.side": "옆면 빛",
"action.gui_light.front": "앞면 빛",
"action.move_keyframe_back": "키 프레임을 뒤로 옮기기",
- "action.move_keyframe_forth": "Move Keyframes Forth",
+ "action.move_keyframe_forth": "키 프레임을 앞으로 이동",
"menu.help": "도움",
"menu.help.discord": "디스코드 서버",
"menu.help.report_issue": "버그 신고",
"menu.help.plugin_documentation": "플러그인 API 문서",
- "menu.help.search_action": "Search and Run Action",
+ "menu.help.search_action": "검색 후 실행 동작",
"menu.help.donate": "기부",
"menu.help.about": "더보기",
"menu.preview.background.clipboard": "클립보드에서 불러오기",
"dialog.ignore": "무시",
- "generic.unset": "Unset",
- "message.invalid_builtin_parent.title": "Invalid Built-in Parent",
- "message.invalid_builtin_parent.message": "The link to the invalid parent model '%0' was removed in order to export a valid model.",
+ "generic.unset": "설정 안함",
+ "message.invalid_builtin_parent.title": "잘못된 페런트입니다.",
+ "message.invalid_builtin_parent.message": "잘못된 페런트 '%0' 의 링크가 모델을 저장하기 위하여 삭제되었습니다.",
"dialog.resize_texture.fill": "채우기",
"dialog.resize_texture.fill.transparent": "투명",
"dialog.resize_texture.fill.color": "색상",
- "dialog.resize_texture.fill.repeat": "Repeat",
+ "dialog.resize_texture.fill.repeat": "반복",
"dialog.resize_texture.fill.stretch": "늘리기",
- "dialog.scale.element_pivot": "Element Pivot",
- "dialog.scale.selection_center": "Selection Center",
- "dialog.create_gif.length_mode": "Length Mode",
- "dialog.create_gif.length_mode.seconds": "Seconds",
+ "dialog.scale.element_pivot": "엘리먼트 중심점",
+ "dialog.scale.selection_center": "중심 선택",
+ "dialog.create_gif.length_mode": "길이 설정",
+ "dialog.create_gif.length_mode.seconds": "초",
"dialog.create_gif.length_mode.frames": "프레임",
- "dialog.create_gif.length_mode.animation": "Animation Length",
- "dialog.create_gif.length_mode.turntable": "Turntable Rotation",
- "dialog.save_angle.projection": "Projection",
- "dialog.save_angle.projection.perspective": "Perspective",
- "dialog.save_angle.projection.orthographic": "Orthographic",
+ "dialog.create_gif.length_mode.animation": "애니메이션 길이",
+ "dialog.create_gif.length_mode.turntable": "회전가능한 회선",
+ "dialog.save_angle.projection": "빛 관통",
+ "dialog.save_angle.projection.perspective": "원근법",
+ "dialog.save_angle.projection.orthographic": "직교",
"dialog.sketchfab_uploader.animations": "애니메이션",
"dialog.settings.theme": "테마",
"settings.category.interface": "인터페이스",
@@ -1081,38 +1065,63 @@
"uv_editor.copy_paste_tool.mirror_x": "X축으로 좌우반전",
"uv_editor.copy_paste_tool.mirror_y": "Y축으로 좌우반전",
"uv_editor.copy_paste_tool.rotate": "90도 회전",
- "dialog.project.modded_entity_version": "Export Version",
- "dialog.save_angle.position": "Camera Position",
- "dialog.save_angle.target": "Focal Point",
- "dialog.skin.pose": "Pose",
- "layout.color.frame": "Window Frame",
- "layout.color.frame.desc": "Border and title bar of the window",
- "settings.large_grid_size": "Block Grid Size",
- "settings.large_grid_size.desc": "Size of the block grid",
- "action.load_plugin_from_url": "Load Plugin from URL",
- "action.load_plugin_from_url.desc": "Load a plugin from a server by specifying the URL",
- "action.cube_counter.desc": "Displays the current number of cubes and other statistics",
- "action.unlock_everything": "Unlock All",
- "action.unlock_everything.desc": "Unlock all groups and elements in the outliner.",
- "action.load_palette": "Load Palette",
- "action.load_palette.desc": "Load one of the built-in palette presets",
- "action.toggle_locked": "Toggle Lock",
- "action.toggle_locked.desc": "Toggle whether the selected elements are locked",
- "action.apply_display_preset": "Apply Preset",
- "action.apply_display_preset.desc": "Apply a default or custom display setting preset",
- "action.apply_display_preset.here": "Apply To This Slot",
- "action.apply_display_preset.everywhere": "Apply To All Slots",
- "action.resolve_keyframe_expressions": "Resolve Keyframe",
- "action.resolve_keyframe_expressions.desc": "Resolves the math expressions of the selected keyframes",
- "action.fold_all_animations": "Fold All Animators",
- "action.timeline_focus.used": "In Use",
- "menu.palette.load.empty": "Blank",
- "switches.lock": "Lock",
- "camera_angle.isometric_right": "Isometric Right",
- "camera_angle.isometric_left": "Isometric Left",
- "settings.render_sides": "Render Sides",
- "settings.render_sides.desc": "Select which side of a face is rendered",
- "settings.render_sides.auto": "Auto",
- "settings.render_sides.front": "Outside",
- "settings.render_sides.double": "Inside and Outside"
+ "dialog.project.modded_entity_version": "저장될 버전",
+ "dialog.save_angle.position": "카메라 위치",
+ "dialog.save_angle.target": "초점",
+ "dialog.skin.pose": "포즈",
+ "layout.color.frame": "프레임",
+ "layout.color.frame.desc": "경계와 제목",
+ "settings.large_grid_size": "블록 격자 크기",
+ "settings.large_grid_size.desc": "블록 격자의 크기",
+ "action.load_plugin_from_url": "URL로부터 플러그인을 불러옵니다.",
+ "action.load_plugin_from_url.desc": "지정된 URL의 서버로부터 플러그인을 불러옵니다.",
+ "action.cube_counter.desc": "현재 큐브 개수와 다른 정보를 표시합니다.",
+ "action.unlock_everything": "모두 잠금 해제",
+ "action.unlock_everything.desc": "바깥쪽의 엘리먼트 잠금 해제",
+ "action.load_palette": "팔레트 불러오기",
+ "action.load_palette.desc": "사전에 설정된 팔레트 설정 불러오기",
+ "action.toggle_locked": "잠금 여부 설정",
+ "action.toggle_locked.desc": "설정된 ",
+ "action.apply_display_preset": "기본 설정 적용하기",
+ "action.apply_display_preset.desc": "기본 설정 혹은 커스텀 설정 적용하기",
+ "action.apply_display_preset.here": "해당 슬릇에 적용하기",
+ "action.apply_display_preset.everywhere": "모든 슬릇에 적용하기",
+ "action.resolve_keyframe_expressions": "키 프레임 재설정하기",
+ "action.resolve_keyframe_expressions.desc": "설정된 키 프레임의 수학 값 재설정하기",
+ "action.fold_all_animations": "모든 애니메이션 접기",
+ "action.timeline_focus.used": "사용됨",
+ "menu.palette.load.empty": "공백",
+ "switches.lock": "잠금",
+ "camera_angle.isometric_right": "우측 치수",
+ "camera_angle.isometric_left": "좌측으로 회전",
+ "settings.render_sides": "렌더 ",
+ "settings.render_sides.desc": "어느 면이 렌더될지 선택",
+ "settings.render_sides.auto": "자동",
+ "settings.render_sides.front": "바깥",
+ "settings.render_sides.double": "안쪽과 바깥",
+ "generic.enable": "Enable",
+ "generic.disable": "Disable",
+ "generic.redacted": "Redacted",
+ "dialog.project.layered_textures": "Layered Textures",
+ "dialog.select_texture.import_all": "Import All",
+ "dialog.skin.layer_template": "Layer Texture",
+ "about.version.up_to_date": "Up to date",
+ "about.version.update_available": "Version %0 is available",
+ "settings.category.application": "Application",
+ "settings.streamer_mode": "Streamer Mode",
+ "settings.streamer_mode.desc": "Hides sensitive information like recent models",
+ "settings.automatic_updates": "Automatic Updates",
+ "settings.automatic_updates.desc": "Automatically download new versions and keep Blockbench up-to-date",
+ "action.rotation_space": "Rotation Space",
+ "action.focus_on_selection": "Center View on Selection",
+ "action.focus_on_selection.desc": "Align the camera to face the center of the current selection",
+ "action.jump_to_timeline_start": "Jump to Animation Start",
+ "action.jump_to_timeline_end": "Jump to Animation End",
+ "menu.help.updating": "Updating (%0%)",
+ "menu.help.update_ready": "Relaunch to Update",
+ "menu.help.update_failed": "Update Failed",
+ "menu.animation.loop.once": "Play Once",
+ "menu.animation.loop.hold": "Hold On Last Frame",
+ "menu.animation.loop.loop": "Loop",
+ "interface.streamer_mode_on": "Streamer Mode Enabled"
}
\ No newline at end of file
diff --git a/lang/nl.json b/lang/nl.json
index aed2e8de..73a81444 100644
--- a/lang/nl.json
+++ b/lang/nl.json
@@ -151,10 +151,6 @@
"dialog.create_texture.template": "Sjabloon",
"dialog.create_texture.resolution": "Resolutie",
"dialog.input.title": "Invoer",
- "dialog.update.title": "Updates",
- "dialog.update.refresh": "Opnieuw proberen",
- "dialog.update.up_to_date": "Blockbench is up-to-date",
- "dialog.update.connecting": "Verbinden met de server",
"dialog.settings.settings": "Instellingen",
"dialog.settings.keybinds": "Sneltoetsen",
"dialog.settings.about": "Over",
@@ -202,8 +198,6 @@
"settings.category.export": "Exporteren",
"settings.language": "Taal",
"settings.language.desc": "Interface taal. Herstart Blockbench om wijzigingen aan te brengen",
- "settings.show_actions": "Toon Acties",
- "settings.show_actions.desc": "Toon alle acties in de status balk",
"settings.backup_interval": "Backup Frequentie",
"settings.backup_interval.desc": "Frequentie van de automatische backups in minuten",
"settings.origin_size": "Draaipunt Markeerder",
@@ -326,8 +320,6 @@
"action.settings_window.desc": "Open het Blockbench instellingen venster",
"action.plugins_window": "Plugins...",
"action.plugins_window.desc": "Open het plugin venster",
- "action.update_window": "Updates...",
- "action.update_window.desc": "Zoek voor Blockbench updates.",
"action.reset_keybindings": "Herstel Sneltoetsen",
"action.reset_keybindings.desc": "Herstel alle sneltoetsen naar Blockbench's standaard",
"action.reset_layout": "Herstel Lay-out",
@@ -536,10 +528,6 @@
"message.square_textures": "Texturen moeten vierkant zijn",
"message.unsaved_texture.title": "Niet Opgeslagen Textuur",
"message.unsaved_texture.message": "Alle niet opgeslagen veranderingen van deze textuur zullen verloren gaan. Wil je doorgaan?",
- "dialog.update.no_connection": "Geen internet connectie",
- "dialog.update.latest": "Laatste Versie",
- "dialog.update.installed": "Geïnstalleerde Versie",
- "dialog.update.update": "Update",
"action.vertex_snap_mode.move": "Beweeg",
"action.vertex_snap_mode.scale": "Schaal",
"action.open_model_folder": "Open Model Map",
@@ -549,8 +537,6 @@
"menu.texture.particle": "Gebruik voor Deeltjes",
"message.update_notification.title": "Er is een update van Blockbench beschikbaar.",
"message.update_notification.message": "Blockbench versie %0 is uit. Wil je deze nu installeren?",
- "message.update_notification.install": "Installeren",
- "message.update_notification.later": "Later",
"message.untextured": "Dit oppervlak heeft geen texture.",
"dialog.toolbar_edit.title": "Aangepast Gereedschap",
"keybindings.reset": "Reset",
@@ -635,7 +621,6 @@
"timeline.rotation": "Rotatie",
"timeline.position": "Positie",
"timeline.scale": "Vergroot/Verklein",
- "menu.timeline.add": "Voeg KeyframeToe",
"menu.keyframe.quaternion": "Quaternion",
"panel.animations": "Animaties",
"panel.keyframe": "Keyframe",
@@ -970,7 +955,6 @@
"action.add_keyframe.desc": "Voeg Automatisch een keyframe toe. Druk op shift om standaard waarden te forceren",
"action.bring_up_all_animations.desc": "Brengt alle gemodificeerde animatoren in de tijdlijn",
"timeline.timeline": "Instructies",
- "menu.palette.load": "Laad Palet",
"menu.palette.load.default": "Standaard",
"panel.color.picker": "Pipet",
"panel.color.palette": "Palet",
@@ -1071,7 +1055,7 @@
"menu.preview.save_angle": "Save Angle...",
"menu.preview.angle": "Angles",
"menu.preview.angle.initial": "Initial Angle",
- "menu.preview.angle.load": "Load",
+ "menu.preview.angle.load": "Laad",
"menu.preview.maximize": "Maximize",
"panel.color.both": "Both",
"uv_editor.copy_selection": "Copy Selection",
@@ -1080,22 +1064,22 @@
"uv_editor.copy_paste_tool.cut": "Cut",
"uv_editor.copy_paste_tool.mirror_x": "Mirror X",
"uv_editor.copy_paste_tool.mirror_y": "Mirror Y",
- "uv_editor.copy_paste_tool.rotate": "Rotate 90 Degrees",
- "dialog.project.modded_entity_version": "Export Version",
- "dialog.save_angle.position": "Camera Position",
+ "uv_editor.copy_paste_tool.rotate": "Draai 90 graden",
+ "dialog.project.modded_entity_version": "Exporteer versie",
+ "dialog.save_angle.position": "Camera positie",
"dialog.save_angle.target": "Focal Point",
"dialog.skin.pose": "Pose",
"layout.color.frame": "Window Frame",
"layout.color.frame.desc": "Border and title bar of the window",
- "settings.large_grid_size": "Block Grid Size",
+ "settings.large_grid_size": "Blok rastergrootte",
"settings.large_grid_size.desc": "Size of the block grid",
- "action.load_plugin_from_url": "Load Plugin from URL",
- "action.load_plugin_from_url.desc": "Load a plugin from a server by specifying the URL",
+ "action.load_plugin_from_url": "Laad een plugin via een URL",
+ "action.load_plugin_from_url.desc": "Laad een plugin van een server door de URL op te geven",
"action.cube_counter.desc": "Displays the current number of cubes and other statistics",
"action.unlock_everything": "Unlock All",
"action.unlock_everything.desc": "Unlock all groups and elements in the outliner.",
- "action.load_palette": "Load Palette",
- "action.load_palette.desc": "Load one of the built-in palette presets",
+ "action.load_palette": "Palet laden",
+ "action.load_palette.desc": "Laad een van de ingebouwde paletvoorinstellingen",
"action.toggle_locked": "Toggle Lock",
"action.toggle_locked.desc": "Toggle whether the selected elements are locked",
"action.apply_display_preset": "Apply Preset",
@@ -1105,7 +1089,7 @@
"action.resolve_keyframe_expressions": "Resolve Keyframe",
"action.resolve_keyframe_expressions.desc": "Resolves the math expressions of the selected keyframes",
"action.fold_all_animations": "Fold All Animators",
- "action.timeline_focus.used": "In Use",
+ "action.timeline_focus.used": "In gebruik",
"menu.palette.load.empty": "Blank",
"switches.lock": "Lock",
"camera_angle.isometric_right": "Isometric Right",
@@ -1114,5 +1098,30 @@
"settings.render_sides.desc": "Select which side of a face is rendered",
"settings.render_sides.auto": "Auto",
"settings.render_sides.front": "Outside",
- "settings.render_sides.double": "Inside and Outside"
+ "settings.render_sides.double": "Inside and Outside",
+ "generic.enable": "Enable",
+ "generic.disable": "Disable",
+ "generic.redacted": "Redacted",
+ "dialog.project.layered_textures": "Layered Textures",
+ "dialog.select_texture.import_all": "Import All",
+ "dialog.skin.layer_template": "Layer Texture",
+ "about.version.up_to_date": "Up to date",
+ "about.version.update_available": "Version %0 is available",
+ "settings.category.application": "Application",
+ "settings.streamer_mode": "Streamer Mode",
+ "settings.streamer_mode.desc": "Hides sensitive information like recent models",
+ "settings.automatic_updates": "Automatic Updates",
+ "settings.automatic_updates.desc": "Automatically download new versions and keep Blockbench up-to-date",
+ "action.rotation_space": "Rotation Space",
+ "action.focus_on_selection": "Center View on Selection",
+ "action.focus_on_selection.desc": "Align the camera to face the center of the current selection",
+ "action.jump_to_timeline_start": "Jump to Animation Start",
+ "action.jump_to_timeline_end": "Jump to Animation End",
+ "menu.help.updating": "Updating (%0%)",
+ "menu.help.update_ready": "Relaunch to Update",
+ "menu.help.update_failed": "Update Failed",
+ "menu.animation.loop.once": "Play Once",
+ "menu.animation.loop.hold": "Hold On Last Frame",
+ "menu.animation.loop.loop": "Loop",
+ "interface.streamer_mode_on": "Streamer Mode Enabled"
}
\ No newline at end of file
diff --git a/lang/pl.json b/lang/pl.json
index 6f3261d1..a3f91cba 100644
--- a/lang/pl.json
+++ b/lang/pl.json
@@ -151,10 +151,6 @@
"dialog.create_texture.template": "Szablon",
"dialog.create_texture.resolution": "Rozdzielczość",
"dialog.input.title": "Wstaw",
- "dialog.update.title": "Aktualizacje",
- "dialog.update.refresh": "Odśwież",
- "dialog.update.up_to_date": "Blockbench jest aktualny!",
- "dialog.update.connecting": "Łączenie z serwerem",
"dialog.settings.settings": "Ustawienia",
"dialog.settings.keybinds": "Klawisze",
"dialog.settings.about": "O programie",
@@ -202,8 +198,6 @@
"settings.category.export": "Eksportuj",
"settings.language": "Język",
"settings.language.desc": "Język interfejsu. Otwórz Blockbench ponownie, żeby zatwierdzić zmiany.",
- "settings.show_actions": "Wyświetlaj akcje",
- "settings.show_actions.desc": "Wyświetlaj każdą akcję w pasku statusu",
"settings.backup_interval": "Interwał kopii zapasowych",
"settings.backup_interval.desc": "Interwał tworzenia automatycznych kopii zapasowych, w minutach",
"settings.origin_size": "Punkt obrotu",
@@ -326,8 +320,6 @@
"action.settings_window.desc": "Otwórz okienko ustawień Blockbench",
"action.plugins_window": "Pluginy...",
"action.plugins_window.desc": "Otwórz okienko sklepu z pluginami",
- "action.update_window": "Aktualizacje...",
- "action.update_window.desc": "Znajdź aktualizacje dla Blockbench",
"action.reset_keybindings": "Resetuj przypisanie klawiszy",
"action.reset_keybindings.desc": "Resetuj wszystkie przypisania klawiszy do domyślnych",
"action.reset_layout": "Resetuj układ",
@@ -536,10 +528,6 @@
"message.square_textures": "Tekstury muszą być kwadratowe",
"message.unsaved_texture.title": "Niezapisana tekstura",
"message.unsaved_texture.message": "Wszystkie niezapisane zmiany tej tekstury zostaną utracone. Chcesz kontynuować?",
- "dialog.update.no_connection": "Brak łączności z internetem",
- "dialog.update.latest": "Najnowsza wersja",
- "dialog.update.installed": "Zainstalowana wersja",
- "dialog.update.update": "Aktualizacja",
"action.vertex_snap_mode.move": "Przesuń",
"action.vertex_snap_mode.scale": "Skaluj",
"action.open_model_folder": "Otwórz folder modelu",
@@ -549,8 +537,6 @@
"menu.texture.particle": "Użyj dla cząstek",
"message.update_notification.title": "Dostępna jest aktualizacja",
"message.update_notification.message": "Nowa wersja Blockbench \"%0\" jest dostępna. Chcesz ją teraz zainstalować?",
- "message.update_notification.install": "Zainstaluj",
- "message.update_notification.later": "Później",
"message.untextured": "Ta powierzchnia nie ma tekstury",
"dialog.toolbar_edit.title": "Dostosuj pasek z narzędziami",
"keybindings.reset": "Resetuj",
@@ -635,7 +621,6 @@
"timeline.rotation": "Rotacja",
"timeline.position": "Pozycja",
"timeline.scale": "Rozmiar",
- "menu.timeline.add": "Dodaj klatkę kluczową",
"menu.keyframe.quaternion": "Kwaternion",
"panel.animations": "Animacje",
"panel.keyframe": "Klatka kluczowa",
@@ -800,8 +785,8 @@
"mode.start": "Start",
"mode.start.new": "New",
"mode.start.recent": "Recent",
- "format.free": "Free Model",
- "format.free.desc": "Model without restrictions for Unity etc.",
+ "format.free": "Generic Model",
+ "format.free.desc": "Model without restrictions for game engines, rendering etc.",
"format.java_block": "Java Blok/Przedmiot",
"format.java_block.desc": "Model bloku na Java Edition. Rozmiar i kąty obrotu są ograniczone.",
"format.bedrock": "Bedrock Model",
@@ -970,7 +955,6 @@
"action.add_keyframe.desc": "Automatycznie dodawaj klatki kluczowe. Naciśnij Shift, aby wymusić podstawowe wartości",
"action.bring_up_all_animations.desc": "Brings all modified animators into the timeline",
"timeline.timeline": "Instrukcje",
- "menu.palette.load": "Wczytaj paletę",
"menu.palette.load.default": "Podstawowa",
"panel.color.picker": "Wybierz kolor",
"panel.color.palette": "Paleta",
@@ -1114,5 +1098,30 @@
"settings.render_sides.desc": "Select which side of a face is rendered",
"settings.render_sides.auto": "Auto",
"settings.render_sides.front": "Outside",
- "settings.render_sides.double": "Inside and Outside"
+ "settings.render_sides.double": "Inside and Outside",
+ "generic.enable": "Enable",
+ "generic.disable": "Disable",
+ "generic.redacted": "Redacted",
+ "dialog.project.layered_textures": "Layered Textures",
+ "dialog.select_texture.import_all": "Import All",
+ "dialog.skin.layer_template": "Layer Texture",
+ "about.version.up_to_date": "Up to date",
+ "about.version.update_available": "Version %0 is available",
+ "settings.category.application": "Application",
+ "settings.streamer_mode": "Streamer Mode",
+ "settings.streamer_mode.desc": "Hides sensitive information like recent models",
+ "settings.automatic_updates": "Automatic Updates",
+ "settings.automatic_updates.desc": "Automatically download new versions and keep Blockbench up-to-date",
+ "action.rotation_space": "Rotation Space",
+ "action.focus_on_selection": "Center View on Selection",
+ "action.focus_on_selection.desc": "Align the camera to face the center of the current selection",
+ "action.jump_to_timeline_start": "Jump to Animation Start",
+ "action.jump_to_timeline_end": "Jump to Animation End",
+ "menu.help.updating": "Updating (%0%)",
+ "menu.help.update_ready": "Relaunch to Update",
+ "menu.help.update_failed": "Update Failed",
+ "menu.animation.loop.once": "Play Once",
+ "menu.animation.loop.hold": "Hold On Last Frame",
+ "menu.animation.loop.loop": "Loop",
+ "interface.streamer_mode_on": "Streamer Mode Enabled"
}
\ No newline at end of file
diff --git a/lang/pt.json b/lang/pt.json
index 8af3e2f1..90a07aa9 100644
--- a/lang/pt.json
+++ b/lang/pt.json
@@ -151,10 +151,6 @@
"dialog.create_texture.template": "Modelo",
"dialog.create_texture.resolution": "Resolução",
"dialog.input.title": "Entrada",
- "dialog.update.title": "Atualizações",
- "dialog.update.refresh": "Tentar de novo",
- "dialog.update.up_to_date": "O Blockbench está atualizado!",
- "dialog.update.connecting": "Conectando-se ao servidor",
"dialog.settings.settings": "Configurações",
"dialog.settings.keybinds": "Atalhos",
"dialog.settings.about": "Sobre",
@@ -202,8 +198,6 @@
"settings.category.export": "Exportação",
"settings.language": "Idioma",
"settings.language.desc": "Idioma da interface. Reinicie o Blockbench para aplicar as alterações",
- "settings.show_actions": "Mostrar ações",
- "settings.show_actions.desc": "Mostrar todas as ações na barra de status",
"settings.backup_interval": "Intervalo de salvamento",
"settings.backup_interval.desc": "Intervalo entre salvamentos automáticos (em minutos)",
"settings.origin_size": "Origem da rotação",
@@ -326,8 +320,6 @@
"action.settings_window.desc": "Abrir a janela de configurações do Blockbench.",
"action.plugins_window": "Extensões...",
"action.plugins_window.desc": "Abrir a janela da loja de extensões",
- "action.update_window": "Atualizações...",
- "action.update_window.desc": "Buscar por atualizações do Blockbench.",
"action.reset_keybindings": "Redefinir atalhos de teclado",
"action.reset_keybindings.desc": "Redefinir todos os atalhos de teclado aos padrões do Blockbench",
"action.reset_layout": "Redefinir aparência",
@@ -536,10 +528,6 @@
"message.square_textures": "Texturas têm que ser quadradas",
"message.unsaved_texture.title": "Textura Não Salva",
"message.unsaved_texture.message": "Todas as alterações não salvas serão perdidas.Você quer continuar?",
- "dialog.update.no_connection": "Sem conexão com a Internet",
- "dialog.update.latest": "Última Versão",
- "dialog.update.installed": "Versão Instalada",
- "dialog.update.update": "Atualização",
"action.vertex_snap_mode.move": "Mover",
"action.vertex_snap_mode.scale": "Redimensionar",
"action.open_model_folder": "Abrir Pasta de Modelos",
@@ -549,8 +537,6 @@
"menu.texture.particle": "Usar para Partículas",
"message.update_notification.title": "Uma Atualização está Disponível",
"message.update_notification.message": "A versão \"%0\" do Blockbench está disponível. Você deseja instalar agora?",
- "message.update_notification.install": "Instalar",
- "message.update_notification.later": "Mais tarde",
"message.untextured": "Esta superfície não tem uma textura",
"dialog.toolbar_edit.title": "Customizar Barra de Ferramentas",
"keybindings.reset": "Redefinir",
@@ -635,7 +621,6 @@
"timeline.rotation": "Rotação",
"timeline.position": "Posição",
"timeline.scale": "Redimensionar",
- "menu.timeline.add": "Adicionar Quadro",
"menu.keyframe.quaternion": "Quaternião",
"panel.animations": "Animações",
"panel.keyframe": "Quadro",
@@ -970,7 +955,6 @@
"action.add_keyframe.desc": "Adicione automaticamente um quadro-chave. Pressione shift para forçar os valores padrão",
"action.bring_up_all_animations.desc": "Traz todos os animadores modificados para a linha do tempo",
"timeline.timeline": "Instruções",
- "menu.palette.load": "Carregar Paleta",
"menu.palette.load.default": "Padrão",
"panel.color.picker": "Seletor",
"panel.color.palette": "Paleta",
@@ -1110,9 +1094,34 @@
"switches.lock": "Travar",
"camera_angle.isometric_right": "Direita isométrica",
"camera_angle.isometric_left": "Esquerda isométrica",
- "settings.render_sides": "Render Sides",
- "settings.render_sides.desc": "Select which side of a face is rendered",
+ "settings.render_sides": "Lados Carregados",
+ "settings.render_sides.desc": "Selecione qual lado de uma face é carregado",
"settings.render_sides.auto": "Auto",
- "settings.render_sides.front": "Outside",
- "settings.render_sides.double": "Inside and Outside"
+ "settings.render_sides.front": "Fora",
+ "settings.render_sides.double": "Dentro e Fora",
+ "generic.enable": "Enable",
+ "generic.disable": "Disable",
+ "generic.redacted": "Redacted",
+ "dialog.project.layered_textures": "Layered Textures",
+ "dialog.select_texture.import_all": "Import All",
+ "dialog.skin.layer_template": "Layer Texture",
+ "about.version.up_to_date": "Up to date",
+ "about.version.update_available": "Version %0 is available",
+ "settings.category.application": "Application",
+ "settings.streamer_mode": "Streamer Mode",
+ "settings.streamer_mode.desc": "Hides sensitive information like recent models",
+ "settings.automatic_updates": "Automatic Updates",
+ "settings.automatic_updates.desc": "Automatically download new versions and keep Blockbench up-to-date",
+ "action.rotation_space": "Rotation Space",
+ "action.focus_on_selection": "Center View on Selection",
+ "action.focus_on_selection.desc": "Align the camera to face the center of the current selection",
+ "action.jump_to_timeline_start": "Jump to Animation Start",
+ "action.jump_to_timeline_end": "Jump to Animation End",
+ "menu.help.updating": "Updating (%0%)",
+ "menu.help.update_ready": "Relaunch to Update",
+ "menu.help.update_failed": "Update Failed",
+ "menu.animation.loop.once": "Play Once",
+ "menu.animation.loop.hold": "Hold On Last Frame",
+ "menu.animation.loop.loop": "Loop",
+ "interface.streamer_mode_on": "Streamer Mode Enabled"
}
\ No newline at end of file
diff --git a/lang/ru.json b/lang/ru.json
index 14fcad95..93580e1c 100644
--- a/lang/ru.json
+++ b/lang/ru.json
@@ -151,10 +151,6 @@
"dialog.create_texture.template": "Шаблон",
"dialog.create_texture.resolution": "Разрешение",
"dialog.input.title": "Ввод",
- "dialog.update.title": "Обновления",
- "dialog.update.refresh": "Перезагрузить",
- "dialog.update.up_to_date": "Blockbench обновлён!",
- "dialog.update.connecting": "Подключение к серверу",
"dialog.settings.settings": "Настройки",
"dialog.settings.keybinds": "Управление",
"dialog.settings.about": "О программе",
@@ -162,9 +158,9 @@
"layout.color.back.desc": "Фон и поля ввода",
"layout.color.dark": "Тьма",
"layout.color.dark.desc": "Фон рабочей области",
- "layout.color.ui": "ИП",
+ "layout.color.ui": "Интерфейс",
"layout.color.ui.desc": "Основной цвет интерфейса",
- "layout.color.bright_ui": "Светлый ИП",
+ "layout.color.bright_ui": "Светлый интерфейс",
"layout.color.bright_ui.desc": "Контекстное меню и подсказки",
"layout.color.button": "Кнопка",
"layout.color.button.desc": "Кнопки и переключатели",
@@ -195,15 +191,13 @@
"settings.category.general": "Основные",
"settings.category.preview": "Предпросмотр",
"settings.category.grid": "Сетка",
- "settings.category.edit": "Изменить",
+ "settings.category.edit": "Редактирование",
"settings.category.snapping": "Привязка к сетке",
"settings.category.defaults": "По умолчанию",
"settings.category.dialogs": "Диалоговые окна",
"settings.category.export": "Экспорт",
"settings.language": "Язык",
"settings.language.desc": "Язык интерфейса. Перезапустите Blockbench, чтобы применить изменения.",
- "settings.show_actions": "Отображение действий",
- "settings.show_actions.desc": "Показывать каждое действие в строке состояния",
"settings.backup_interval": "Интервал автосохранения",
"settings.backup_interval.desc": "Интервал автосохранения в минутах",
"settings.origin_size": "Центр поворота",
@@ -326,8 +320,6 @@
"action.settings_window.desc": "Открыть окно настроек Blockbench",
"action.plugins_window": "Плагины...",
"action.plugins_window.desc": "Открыть окно хранилища плагинов",
- "action.update_window": "Обновления...",
- "action.update_window.desc": "Проверить наличие обновлений Blockbench",
"action.reset_keybindings": "Сбросить управление",
"action.reset_keybindings.desc": "Вернуть все сочетания клавиш к первоначальным",
"action.reset_layout": "Сбросить внешний вид",
@@ -383,7 +375,7 @@
"action.toggle_shade": "Переключить тени",
"action.toggle_shade.desc": "Переключить тени выделенных кубов",
"action.rename": "Переименовать",
- "action.rename.desc": "Переименовать выделенные кубы",
+ "action.rename.desc": "Переименовать всех выделенных кубов",
"action.add_display_preset": "Новый шаблон",
"action.add_display_preset.desc": "Создать шаблон настроек отображения",
"action.fullscreen": "Полный экран",
@@ -412,12 +404,12 @@
"action.save_textures.desc": "Сохранить все несохранённые текстуры",
"action.animated_textures": "Проигрывать анимированные текстуры",
"action.animated_textures.desc": "Проигрывать анимацию текстур",
- "action.origin_to_geometry": "Центр поворота к геометрии",
- "action.origin_to_geometry.desc": "Установить центр поворота в центр геометрии",
+ "action.origin_to_geometry": "Оцентрировать центр поворота",
+ "action.origin_to_geometry.desc": "Установить центр поворота в центр выбора",
"action.rescale_toggle": "Переключить масштабирование",
"action.rescale_toggle.desc": "Масштабировать кубы на основе их поворота",
"action.bone_reset_toggle": "Сбросить кость",
- "action.bone_reset_toggle.desc": "Остановить часть от отображения кубов родительской модели",
+ "action.bone_reset_toggle.desc": "Остановить кость от отображения кубов родительской модели",
"action.reload": "Перезагрузить Blockbench",
"action.reload.desc": "Перезагрузить Blockbench. Это удалит весь несохранённый прогресс.",
"menu.file": "Файл",
@@ -426,7 +418,7 @@
"menu.filter": "Фильтр",
"menu.display": "Отображение",
"menu.view": "Вид",
- "menu.file.new": "Новый",
+ "menu.file.new": "Создать",
"menu.file.recent": "Недавние",
"menu.file.import": "Импортировать",
"menu.file.export": "Экспортировать",
@@ -536,10 +528,6 @@
"message.square_textures": "Текстуры должны быть квадратными",
"message.unsaved_texture.title": "Несохранённая текстура",
"message.unsaved_texture.message": "Все несохранённые изменения к этой текстуре будут потеряны. Вы хотите продолжить?",
- "dialog.update.no_connection": "Отсутствует подключение к Интернету",
- "dialog.update.latest": "Новейшая версия",
- "dialog.update.installed": "Установленная версия",
- "dialog.update.update": "Обновление",
"action.vertex_snap_mode.move": "Перемещение",
"action.vertex_snap_mode.scale": "Масштабирование",
"action.open_model_folder": "Открыть расположение модели",
@@ -549,8 +537,6 @@
"menu.texture.particle": "Использовать для частиц",
"message.update_notification.title": "Доступно обновление",
"message.update_notification.message": "Доступно обновление Blockbench «%0». Хотите установить его?",
- "message.update_notification.install": "Установить",
- "message.update_notification.later": "Позже",
"message.untextured": "Эта поверхность не имеет текстур",
"dialog.toolbar_edit.title": "Настроить панель инструментов",
"keybindings.reset": "Сбросить",
@@ -635,7 +621,6 @@
"timeline.rotation": "Поворот",
"timeline.position": "Позиция",
"timeline.scale": "Масштаб",
- "menu.timeline.add": "Добавить кадр",
"menu.keyframe.quaternion": "Кватернион",
"panel.animations": "Анимации",
"panel.keyframe": "Кадр",
@@ -666,7 +651,7 @@
"panel.variable_placeholders.info": "Перечислите переменные, которые вы хотите просмотреть используя имя=значение",
"status_bar.vertex_distance": "Дистанция: %0",
"dialog.create_gif.title": "Запись GIF",
- "dialog.create_gif.length": "Длительность",
+ "dialog.create_gif.length": "Длина",
"dialog.create_gif.fps": "FPS",
"dialog.create_gif.compression": "Сжатие",
"dialog.create_gif.play": "Воспроизвести анимацию",
@@ -682,8 +667,8 @@
"action.export_class_entity.desc": "Экспортировать модель сущности как класс Java",
"settings.seethrough_outline": "Рентгенные контуры",
"settings.seethrough_outline.desc": "Показывать контуры через объекты",
- "mode.edit": "Изменить",
- "mode.paint": "Красить",
+ "mode.edit": "Редактирование",
+ "mode.paint": "Рисование",
"mode.display": "Предпросмотр",
"mode.animate": "Анимировать",
"status_bar.recording_gif": "Запись GIF",
@@ -708,7 +693,7 @@
"menu.preview.perspective.reset": "Сбросить камеру",
"action.fill_mode": "Режим заполнения",
"action.fill_mode.face": "Грань",
- "action.fill_mode.color": "Цвет",
+ "action.fill_mode.color": "Цвета",
"action.fill_mode.cube": "Куб",
"action.toggle_mirror_uv": "Зеркалить UV",
"action.toggle_mirror_uv.desc": "Переключить зеркальность UV на оси X выделенных кубов",
@@ -760,22 +745,22 @@
"message.recover_backup.message": "Blockbench был закрыт без сохранения. Вы хотите восстановить модель?",
"message.install_plugin": "Установка плагина %0",
"message.invalid_session.title": "Неверный ключ сеанса",
- "message.invalid_session.message": "Сеанс к которому вы пытаетесь подключиться истек или ваш ключ не правильный.",
+ "message.invalid_session.message": "Сеанс, к которому вы пытаетесь подключиться, истёк или введён недействительный токен.",
"dialog.create_texture.power": "Размер второй степени",
"dialog.create_gif.turn": "Скорость поворота камеры",
- "action.edit_session": "Сеанс Редактирования...",
- "action.edit_session.desc": "Присоединиться к сеансу редактирования для коллаборации с другими пользователями",
+ "action.edit_session": "Сеанс редактирования...",
+ "action.edit_session.desc": "Присоединиться к сеансу для совместной работы с другими пользователями",
"action.reset_keyframe": "Сбросить кадр",
"action.reset_keyframe.desc": "Сбросить все значения выбранных кадров",
- "dialog.edit_session.title": "Сеанс Редактирования",
+ "dialog.edit_session.title": "Сеанс редактирования",
"edit_session.username": "Имя пользователя",
- "edit_session.token": "Ключ",
- "edit_session.about": "Сеансы редактирования могут быть использованы для коллаборации по интернету. Создайте сеанс, скопируйте его ключ и отправьте его Вашим друзьям, которые могут воспользоваться им чтобы присоединиться.",
+ "edit_session.token": "Токен",
+ "edit_session.about": "Сеансы редактирования можно использовать для совместной работы над моделями. Создайте сеанс, скопируйте токен и отправьте его друзьям, которые затем смогут присоединиться.",
"edit_session.join": "Присоединиться к сеансу",
"edit_session.create": "Создать сеанс",
"edit_session.quit": "Покинуть сеанс",
- "edit_session.joined": "Пользователь %0 присоединился к сеансу",
- "edit_session.left": "Ползователь %0 покинул сеанс",
+ "edit_session.joined": "%0 присоединяется к сеансу",
+ "edit_session.left": "%0 покидает сеанс",
"edit_session.quit_session": "Покинул текущий сеанс",
"edit_session.status": "Статус",
"edit_session.hosting": "Хост",
@@ -797,17 +782,17 @@
"dates.yesterday": "Вчера",
"dates.this_week": "Этой неделью",
"dates.weeks_ago": "%0 недель назад",
- "mode.start": "Начать",
- "mode.start.new": "Новый",
+ "mode.start": "Стартовый экран",
+ "mode.start.new": "Создать",
"mode.start.recent": "Недавние",
"format.free": "Свободная модель",
- "format.free.desc": "Модель без ограничений для Unity и так далее.",
+ "format.free.desc": "Модель без ограничений для Unity и т. п.",
"format.java_block": "Блок/предмет Java",
- "format.java_block.desc": "Модель для издания Java. Размер и повороты ограничены.",
+ "format.java_block.desc": "Модель для Java Edition. Размер и повороты ограничены.",
"format.bedrock": "Модель Bedrock",
- "format.bedrock.desc": "Модель для издания Bedrock",
+ "format.bedrock.desc": "Модель для Bedrock Edition",
"format.bedrock_old": "Модель Bedrock (старая)",
- "format.bedrock_old.desc": "Модель издания Bedrock для версий старее 1.12",
+ "format.bedrock_old.desc": "Модель Bedrock Edition для версий старее 1.12",
"format.modded_entity": "Сущность для модов",
"format.modded_entity.desc": "Модель сущности для модов. Может быть экспортирована как файл класса .java",
"format.optifine_entity": "Сущность OptiFine",
@@ -828,7 +813,7 @@
"dialog.model_stats.vertices": "Вершины",
"dialog.model_stats.faces": "Грани",
"settings.username": "Имя пользователя",
- "settings.username.desc": "Имя пользователя для сеансов редактирования...",
+ "settings.username.desc": "Имя пользователя в сеансах редактирования",
"settings.painting_grid": "Сетка рисования",
"settings.painting_grid.desc": "Показывать сетку рисования на кубах с текстурой в режиме краски",
"action.slider_brush_min_opacity": "Минимальная непрозрачность",
@@ -838,12 +823,12 @@
"action.close_project": "Закрыть проект",
"action.close_project.desc": "Закрыть текущий проект",
"action.export_bedrock": "Экспортировать геометрию Bedrock",
- "action.export_bedrock.desc": "Экспортировать модель как файл геометрии издания Bedrock",
+ "action.export_bedrock.desc": "Экспортировать модель как файл геометрии Bedrock Edition",
"action.save_project": "Сохранить проект",
"action.save_project.desc": "Сохранить текущую модель как файл проекта",
"action.save_project_as": "Сохранить проект как",
"action.save_project_as.desc": "Сохранить текущую модель как файл проекта в новом месте",
- "action.export_over": "Перезаписать модель",
+ "action.export_over": "Сохранить модель",
"action.export_over.desc": "Сохранить модель, текстуры и анимации перезаписывая файлы",
"action.add_locator": "Добавить локатор",
"action.add_locator.desc": "Добавить новый локатор для контроля позиции частиц, поводков и т.д.",
@@ -861,18 +846,18 @@
"display.reference.crossbow": "Арбалет",
"dialog.settings.search_results": "Результаты поиска",
"settings.animation_snap": "Привязка Анимаций",
- "settings.animation_snap.desc": "Интервал привязки кадров на графике анимаций",
+ "settings.animation_snap.desc": "Интервал привязки кадров на графике анимаций в секунду",
"action.import_optifine_part": "Импортировать часть OptiFine",
"action.import_optifine_part.desc": "Импортировать часть модели сущности OptiFine",
"data.locator": "Локатор",
- "mode.start.no_recents": "Вы еще не открывали моделей",
+ "mode.start.no_recents": "Нет открытых моделей",
"panel.element": "Элемент",
"panel.element.position": "Позиция",
"panel.element.size": "Размер",
"panel.element.origin": "Центральная точка",
"panel.element.rotation": "Поворот",
"message.canvas_limit_error.title": "Ошибка ограничения рабочей области",
- "message.canvas_limit_error.message": "Действие не может быть выполнено правильно, потому что формат ограничивает размеры рабочей области до 48 единиц. Сместите модель, чтобы предотвратить это.",
+ "message.canvas_limit_error.message": "Действие не может быть выполнено правильно, потому что формат ограничивает размеры рабочей области до 48 единиц. Сместите центр поворота, чтобы предотвратить это.",
"data.effect": "Эффект",
"generic.name": "Имя",
"settings.recent_projects": "Недавние модели",
@@ -936,7 +921,7 @@
"layout.color.checkerboard.desc": "Фон рабочей области и редактора UV",
"layout.font.code": "Шрифт кода",
"layout.css": "Пользовательский CSS",
- "settings.category.paint": "Красить",
+ "settings.category.paint": "Рисование",
"settings.deactivate_size_limit": "Выключить лимит размера",
"settings.deactivate_size_limit.desc": "Выключить лимит размера для определенных форматов. ПРЕДУПРЕЖДЕНИЕ: Это может вызвать ошибки с моделями.",
"settings.brush_opacity_modifier": "Модификатор непрозрачности кисти",
@@ -970,7 +955,6 @@
"action.add_keyframe.desc": "Автоматическое добавление ключевого кадра. Нажмите Shift для ввода стандартных значений ",
"action.bring_up_all_animations.desc": "Перенос всех модифицированных анимаций на временную шкалу",
"timeline.timeline": "Инструкции",
- "menu.palette.load": "Загрузка палитры",
"menu.palette.load.default": "Стандарт",
"panel.color.picker": "Подборщик",
"panel.color.palette": "Палитра",
@@ -984,11 +968,11 @@
"action.add_marker.desc": "Установить пометку на шкале времени",
"timeline.pre_effect_script": "Скрипт",
"format.skin": "Скин",
- "format.skin.desc": "Редактировать скины игроков и сущностей",
+ "format.skin.desc": "Редактирование скинов игроков и сущностей",
"message.sketchfab.setup_guide": "Узнать, как настроить модели в Sketchfab: %0",
"dialog.skin.title": "Создать скин",
"dialog.skin.model": "Модель",
- "dialog.skin.texture": "Текстура (по желанию)",
+ "dialog.skin.texture": "Текстура (необязательно)",
"action.toggle_skin_layer": "Переключить слой скина",
"action.toggle_skin_layer.desc": "Переключить слои шляпы и одежды",
"action.gui_light": "Светлый интерфейс",
@@ -998,17 +982,17 @@
"action.move_keyframe_back": "Сдвинуть кадры назад",
"action.move_keyframe_forth": "Сдвинуть кадры вперед",
"menu.help": "Помощь",
- "menu.help.discord": "Сервер Дискорд",
+ "menu.help.discord": "Сервер в Discord",
"menu.help.report_issue": "Сообщить о проблеме",
- "menu.help.plugin_documentation": "Документация API плагинов",
+ "menu.help.plugin_documentation": "Документация Plugin API",
"menu.help.search_action": "Найти и выполнить действие",
"menu.help.donate": "Пожертвовать",
- "menu.help.about": "Инфо",
+ "menu.help.about": "О программе...",
"menu.preview.background.clipboard": "Загрузить из буфера обмена",
"dialog.ignore": "Игнорировать",
"generic.unset": "Не выбрано",
- "message.invalid_builtin_parent.title": "Invalid Built-in Parent",
- "message.invalid_builtin_parent.message": "The link to the invalid parent model '%0' was removed in order to export a valid model.",
+ "message.invalid_builtin_parent.title": "Неверный встроенный родитель",
+ "message.invalid_builtin_parent.message": "Ссылка на неправильную родительскую модель '%0' была удалена для экспорта правильной модели",
"dialog.resize_texture.fill": "Заполнить с помощью",
"dialog.resize_texture.fill.transparent": "Прозрачный",
"dialog.resize_texture.fill.color": "Цвет",
@@ -1020,18 +1004,18 @@
"dialog.create_gif.length_mode.seconds": "Секунды",
"dialog.create_gif.length_mode.frames": "Кадры",
"dialog.create_gif.length_mode.animation": "Длина анимации",
- "dialog.create_gif.length_mode.turntable": "Turntable Rotation",
+ "dialog.create_gif.length_mode.turntable": "Переключаемый поворот",
"dialog.save_angle.projection": "Проэкция",
"dialog.save_angle.projection.perspective": "Перспектива",
"dialog.save_angle.projection.orthographic": "Ортография",
"dialog.sketchfab_uploader.animations": "Анимации",
"dialog.settings.theme": "Тема",
"settings.category.interface": "Интерфейс",
- "settings.preview_checkerboard": "Preview Checkerboard",
- "settings.preview_checkerboard.desc": "Toggle the checkerboard background behind the preview",
- "settings.uv_checkerboard": "UV Editor Checkerboard",
- "settings.uv_checkerboard.desc": "Toggle the checkerboard background behind the UV editor",
- "category.paint": "Текстура",
+ "settings.preview_checkerboard": "Предварительный Просмотр Шахматной Доски",
+ "settings.preview_checkerboard.desc": "Переключить фон шахматной доски за предварительным просмотром",
+ "settings.uv_checkerboard": "шахматная доска UV редактора",
+ "settings.uv_checkerboard.desc": "Переключить фон шахматной доски за UV редактором",
+ "category.paint": "Рисование",
"action.fill_mode.color_connected": "Соединённые цвета",
"action.draw_shape_type": "Тип фигуры",
"action.draw_shape_type.rectangle": "Четырёхугольник",
@@ -1040,7 +1024,7 @@
"action.draw_shape_type.ellipse_h": "Пустой эллипс",
"action.draw_shape_type.line": "Линия",
"action.mirror_painting": "Зеркальное рисование",
- "action.mirror_painting.description": "Mirror your paint strokes to the other side of the model",
+ "action.mirror_painting.description": "Зеркально отразите свои мазки текстуры на другой стороне модели",
"action.lock_alpha": "Заблокировать Альфа Канал",
"action.lock_alpha.description": "Заблокировать прозрачность всех пикселей",
"action.draw_shape_tool": "Нарисовать фигуру",
@@ -1049,28 +1033,28 @@
"action.copy_paste_tool.desc": "Инструмент для копирования/вставки выделенных текстур",
"action.export_gltf": "Экспортировать как glTF",
"action.export_gltf.desc": "Экспортировать модель и анимации как файл типа glTF чтобы использовать в других программах 3D моделирования",
- "action.transform_space": "Transform Space",
- "action.transform_space.desc": "Default transform space for elements and bones",
+ "action.transform_space": "Место для Трансформации",
+ "action.transform_space.desc": "Обычное место для трансформации для элементов и костей",
"action.transform_space.global": "Глобальный",
"action.transform_space.bone": "Кость",
"action.transform_space.local": "Локальный",
"action.toggle_camera_projection": "Включить проекцию камеры",
- "action.toggle_camera_projection.desc": "Toggle the camera projection between perspective and orthographic",
+ "action.toggle_camera_projection.desc": "переключить проекцию камеры между перспективы и ортографией",
"action.load_camera_angle": "Угол камеры: %0",
- "action.load_camera_angle.desc": "Load the camera angle '%0'",
- "action.slider_face_tint": "Tint Index",
- "action.slider_face_tint.desc": "Set the tint index of the current face. -1 means unset.",
+ "action.load_camera_angle.desc": "Загрузить угол камеры '%0'",
+ "action.slider_face_tint": "Индекс оттенка",
+ "action.slider_face_tint.desc": "Поставить индекс оттенка на эту грань. -1 означает непоставлено",
"menu.help.quickstart": "Помощь в начале",
"menu.help.developer": "Фунции разработчика",
"menu.help.developer.dev_tools": "Открыть инструменты разработчика",
- "menu.help.developer.reset_storage": "Factory Reset",
- "menu.help.developer.reset_storage.confirm": "Are you sure you want to reset Blockbench to factory settings? This will delete all custom settings, keybindings and installed plugins.",
- "menu.help.developer.cache_reload": "Cache Reload",
+ "menu.help.developer.reset_storage": "Перезагрузка фабрики",
+ "menu.help.developer.reset_storage.confirm": "Вы уверены, что хотите снести Блокбенч до настроек фабрики. Это удалит все ваши настройки, горячтие клавиши и загруженные плагины.",
+ "menu.help.developer.cache_reload": "Перезагрузить кэш",
"menu.texture.resize": "Изменить размер",
"menu.preview.orthographic": "Ортография",
"menu.preview.save_angle": "Сохранить угол...",
"menu.preview.angle": "Углы",
- "menu.preview.angle.initial": "Initial Angle",
+ "menu.preview.angle.initial": "Инициальный угол",
"menu.preview.angle.load": "Загрузить",
"menu.preview.maximize": "Увеличить до конца",
"panel.color.both": "Оба",
@@ -1081,38 +1065,63 @@
"uv_editor.copy_paste_tool.mirror_x": "Отзеркалеть по X",
"uv_editor.copy_paste_tool.mirror_y": "Отзеркалить по Y",
"uv_editor.copy_paste_tool.rotate": "Повернуть на 90 градусов",
- "dialog.project.modded_entity_version": "Export Version",
+ "dialog.project.modded_entity_version": "Экспортировать версию",
"dialog.save_angle.position": "Позиция камеры",
- "dialog.save_angle.target": "Focal Point",
+ "dialog.save_angle.target": "Точка Фокуса",
"dialog.skin.pose": "Поза",
- "layout.color.frame": "Window Frame",
- "layout.color.frame.desc": "Border and title bar of the window",
+ "layout.color.frame": "Окно",
+ "layout.color.frame.desc": "Рамка и заголовок окна",
"settings.large_grid_size": "Размер сетки блока",
"settings.large_grid_size.desc": "Размер сетки блока",
"action.load_plugin_from_url": "Загрузить плагин через ссылку",
"action.load_plugin_from_url.desc": "Загрузить плагин через сервер, уточняя ссылку",
"action.cube_counter.desc": "Показывает номер кубов и другую статистику",
"action.unlock_everything": "Разблокировать всё",
- "action.unlock_everything.desc": "Unlock all groups and elements in the outliner.",
+ "action.unlock_everything.desc": "Разблокировать все группы и элементы в аутлайнере",
"action.load_palette": "Загрузить палитру",
- "action.load_palette.desc": "Load one of the built-in palette presets",
+ "action.load_palette.desc": "Загрузить одну из встроенных предварительных палитр",
"action.toggle_locked": "Включить блокировку",
- "action.toggle_locked.desc": "Toggle whether the selected elements are locked",
+ "action.toggle_locked.desc": "Переключить будут ли выбранные элементы заблокированы",
"action.apply_display_preset": "Применить предварительный набор",
"action.apply_display_preset.desc": "Применить обычный или свой предварительный набор настроек",
"action.apply_display_preset.here": "Применить к этому слоту",
"action.apply_display_preset.everywhere": "Применить ко всем слотам",
- "action.resolve_keyframe_expressions": "Resolve Keyframe",
- "action.resolve_keyframe_expressions.desc": "Resolves the math expressions of the selected keyframes",
+ "action.resolve_keyframe_expressions": "Вычислить кадры",
+ "action.resolve_keyframe_expressions.desc": "Вычисляет математические примеры выбранных кадров",
"action.fold_all_animations": "Сложить все анимации",
"action.timeline_focus.used": "Используется",
"menu.palette.load.empty": "Чисто",
"switches.lock": "Заблокировать",
"camera_angle.isometric_right": "Изометрическое право",
"camera_angle.isometric_left": "Изометрическое лево",
- "settings.render_sides": "Render Sides",
- "settings.render_sides.desc": "Select which side of a face is rendered",
- "settings.render_sides.auto": "Auto",
- "settings.render_sides.front": "Outside",
- "settings.render_sides.double": "Inside and Outside"
+ "settings.render_sides": "Стороны рендера",
+ "settings.render_sides.desc": "Выбирете какая част ребра будет зарендерена",
+ "settings.render_sides.auto": "Авто",
+ "settings.render_sides.front": "Снаружи",
+ "settings.render_sides.double": "Внутри и снаружи",
+ "generic.enable": "Enable",
+ "generic.disable": "Disable",
+ "generic.redacted": "Redacted",
+ "dialog.project.layered_textures": "Layered Textures",
+ "dialog.select_texture.import_all": "Import All",
+ "dialog.skin.layer_template": "Layer Texture",
+ "about.version.up_to_date": "Up to date",
+ "about.version.update_available": "Version %0 is available",
+ "settings.category.application": "Application",
+ "settings.streamer_mode": "Streamer Mode",
+ "settings.streamer_mode.desc": "Hides sensitive information like recent models",
+ "settings.automatic_updates": "Automatic Updates",
+ "settings.automatic_updates.desc": "Automatically download new versions and keep Blockbench up-to-date",
+ "action.rotation_space": "Rotation Space",
+ "action.focus_on_selection": "Center View on Selection",
+ "action.focus_on_selection.desc": "Align the camera to face the center of the current selection",
+ "action.jump_to_timeline_start": "Jump to Animation Start",
+ "action.jump_to_timeline_end": "Jump to Animation End",
+ "menu.help.updating": "Updating (%0%)",
+ "menu.help.update_ready": "Relaunch to Update",
+ "menu.help.update_failed": "Update Failed",
+ "menu.animation.loop.once": "Play Once",
+ "menu.animation.loop.hold": "Hold On Last Frame",
+ "menu.animation.loop.loop": "Loop",
+ "interface.streamer_mode_on": "Streamer Mode Enabled"
}
\ No newline at end of file
diff --git a/lang/sv.json b/lang/sv.json
index 26ffc443..3ccce0a0 100644
--- a/lang/sv.json
+++ b/lang/sv.json
@@ -151,10 +151,6 @@
"dialog.create_texture.template": "Mall",
"dialog.create_texture.resolution": "Upplösning",
"dialog.input.title": "Inmatning",
- "dialog.update.title": "Uppdateringar",
- "dialog.update.refresh": "Försök igen",
- "dialog.update.up_to_date": "Blockbench är uppdaterad!",
- "dialog.update.connecting": "Ansluter till servern",
"dialog.settings.settings": "Inställningar",
"dialog.settings.keybinds": "Tangentbindningar",
"dialog.settings.about": "Om",
@@ -202,8 +198,6 @@
"settings.category.export": "Exportera",
"settings.language": "Språk",
"settings.language.desc": "Gränssnittsspråk. Starta om Bockbench för att tillämpa ändringar.",
- "settings.show_actions": "Visningsåtgärder",
- "settings.show_actions.desc": "Visa varje åtgärd i statusfältet",
"settings.backup_interval": "Säkerhetskopierings intervall",
"settings.backup_interval.desc": "Intervall av den automatiska säkerhetskopieringen i minuter",
"settings.origin_size": "Rotations ursprung",
@@ -326,8 +320,6 @@
"action.settings_window.desc": "Öppna Blockbenchs inställningsdialogruta.",
"action.plugins_window": "Plugins...",
"action.plugins_window.desc": "Öppna pluginaffärfönstret",
- "action.update_window": "Uppdateringar...",
- "action.update_window.desc": "Sök efter Blockbench uppdateringar.",
"action.reset_keybindings": "Återställ tangentbindningar",
"action.reset_keybindings.desc": "Återställ alla tangentbindningar till Blockbenchs standardtangentbindningar",
"action.reset_layout": "Återställ layout",
@@ -536,10 +528,6 @@
"message.square_textures": "Texturer måste vara fyrkantiga",
"message.unsaved_texture.title": "Osparad textur",
"message.unsaved_texture.message": "Alla osparade ändringar till denna textur kommer att försvinna. Vill du fortsätta?",
- "dialog.update.no_connection": "Ingen internetanslutning",
- "dialog.update.latest": "Senaste version",
- "dialog.update.installed": "Installerad version",
- "dialog.update.update": "Uppdatera",
"action.vertex_snap_mode.move": "Flytta",
"action.vertex_snap_mode.scale": "Skala",
"action.open_model_folder": "Öppna modellmapp",
@@ -549,8 +537,6 @@
"menu.texture.particle": "Använd för partiklar",
"message.update_notification.title": "En uppdatering är tillgänglig ",
"message.update_notification.message": "Den nya Blockbench versionen \"%0\" är tillgänglig. Vill du installera den nu?",
- "message.update_notification.install": "Installera",
- "message.update_notification.later": "Senare",
"message.untextured": "Denna ytan har ingen textur",
"dialog.toolbar_edit.title": "Anpassa verktygsfältet",
"keybindings.reset": "Återställ",
@@ -635,7 +621,6 @@
"timeline.rotation": "Rotation",
"timeline.position": "Position",
"timeline.scale": "Skala",
- "menu.timeline.add": "Lägg till keyframe",
"menu.keyframe.quaternion": "Kvartärperiod",
"panel.animations": "Animationer",
"panel.keyframe": "Keyframe",
@@ -800,8 +785,8 @@
"mode.start": "Start",
"mode.start.new": "Ny",
"mode.start.recent": "Nyligen",
- "format.free": "Free Model",
- "format.free.desc": "Model without restrictions for Unity etc.",
+ "format.free": "Generic Model",
+ "format.free.desc": "Model without restrictions for game engines, rendering etc.",
"format.java_block": "Java Block/Item",
"format.java_block.desc": "Block model for Java Edition. Size and rotations are limited.",
"format.bedrock": "Bedrock Model",
@@ -970,7 +955,6 @@
"action.add_keyframe.desc": "Automatically add a keyframe. Press shift to force default values",
"action.bring_up_all_animations.desc": "Brings all modified animators into the timeline",
"timeline.timeline": "Instruktioner",
- "menu.palette.load": "Load Palette",
"menu.palette.load.default": "Default",
"panel.color.picker": "Picker",
"panel.color.palette": "Palette",
@@ -1114,5 +1098,30 @@
"settings.render_sides.desc": "Select which side of a face is rendered",
"settings.render_sides.auto": "Auto",
"settings.render_sides.front": "Outside",
- "settings.render_sides.double": "Inside and Outside"
+ "settings.render_sides.double": "Inside and Outside",
+ "generic.enable": "Enable",
+ "generic.disable": "Disable",
+ "generic.redacted": "Redacted",
+ "dialog.project.layered_textures": "Layered Textures",
+ "dialog.select_texture.import_all": "Import All",
+ "dialog.skin.layer_template": "Layer Texture",
+ "about.version.up_to_date": "Up to date",
+ "about.version.update_available": "Version %0 is available",
+ "settings.category.application": "Application",
+ "settings.streamer_mode": "Streamer Mode",
+ "settings.streamer_mode.desc": "Hides sensitive information like recent models",
+ "settings.automatic_updates": "Automatic Updates",
+ "settings.automatic_updates.desc": "Automatically download new versions and keep Blockbench up-to-date",
+ "action.rotation_space": "Rotation Space",
+ "action.focus_on_selection": "Center View on Selection",
+ "action.focus_on_selection.desc": "Align the camera to face the center of the current selection",
+ "action.jump_to_timeline_start": "Jump to Animation Start",
+ "action.jump_to_timeline_end": "Jump to Animation End",
+ "menu.help.updating": "Updating (%0%)",
+ "menu.help.update_ready": "Relaunch to Update",
+ "menu.help.update_failed": "Update Failed",
+ "menu.animation.loop.once": "Play Once",
+ "menu.animation.loop.hold": "Hold On Last Frame",
+ "menu.animation.loop.loop": "Loop",
+ "interface.streamer_mode_on": "Streamer Mode Enabled"
}
\ No newline at end of file
diff --git a/lang/zh.json b/lang/zh.json
index d3fada06..82983224 100644
--- a/lang/zh.json
+++ b/lang/zh.json
@@ -151,10 +151,6 @@
"dialog.create_texture.template": "模板",
"dialog.create_texture.resolution": "分辨率",
"dialog.input.title": "输入",
- "dialog.update.title": "更新",
- "dialog.update.refresh": "重试",
- "dialog.update.up_to_date": "Blockbench 已是最新版本!",
- "dialog.update.connecting": "正在连接到服务器",
"dialog.settings.settings": "设置",
"dialog.settings.keybinds": "快捷键",
"dialog.settings.about": "关于",
@@ -202,8 +198,6 @@
"settings.category.export": "导出",
"settings.language": "语言",
"settings.language.desc": "界面语言,重启 Blockbench 以应用更改",
- "settings.show_actions": "显示操作",
- "settings.show_actions.desc": "在状态栏中显示所有操作",
"settings.backup_interval": "自动备份时间间隔",
"settings.backup_interval.desc": "自动备份时间间隔(以分钟为单位)",
"settings.origin_size": "三轴长度",
@@ -326,8 +320,6 @@
"action.settings_window.desc": "打开 Blockbench 设置对话框。",
"action.plugins_window": "插件……",
"action.plugins_window.desc": "打开插件商店页面",
- "action.update_window": "更新……",
- "action.update_window.desc": "检查 Blockbench 更新。",
"action.reset_keybindings": "重置快捷键",
"action.reset_keybindings.desc": "将所有快捷键重置为 Blockbench 默认值",
"action.reset_layout": "重置布局",
@@ -536,10 +528,6 @@
"message.square_textures": "贴图必须是方形的",
"message.unsaved_texture.title": "未保存的贴图",
"message.unsaved_texture.message": "对此贴图的所有未保存更改都将丢失。你想继续吗?",
- "dialog.update.no_connection": "无网络连接",
- "dialog.update.latest": "最新版本",
- "dialog.update.installed": "已安装的版本",
- "dialog.update.update": "更新",
"action.vertex_snap_mode.move": "移动",
"action.vertex_snap_mode.scale": "缩放",
"action.open_model_folder": "打开模型文件夹",
@@ -549,8 +537,6 @@
"menu.texture.particle": "用作粒子贴图",
"message.update_notification.title": "有新的更新",
"message.update_notification.message": "新的 Blockbench 版本“%0”可用。你想现在安装吗?",
- "message.update_notification.install": "安装",
- "message.update_notification.later": "稍后",
"message.untextured": "这个面没有材质纹理",
"dialog.toolbar_edit.title": "自定义工具栏",
"keybindings.reset": "重启",
@@ -635,7 +621,6 @@
"timeline.rotation": "旋转",
"timeline.position": "位置",
"timeline.scale": "缩放",
- "menu.timeline.add": "添加关键帧",
"menu.keyframe.quaternion": "四元数",
"panel.animations": "动画",
"panel.keyframe": "关键帧",
@@ -970,7 +955,6 @@
"action.add_keyframe.desc": "自动添加关键帧,按下 Shift 键强制使用默认值",
"action.bring_up_all_animations.desc": "将所有修改后的动画置入到时间轴内",
"timeline.timeline": "使用说明",
- "menu.palette.load": "加载调色板",
"menu.palette.load.default": "默认",
"panel.color.picker": "选色器",
"panel.color.palette": "调色板",
@@ -1110,9 +1094,34 @@
"switches.lock": "锁",
"camera_angle.isometric_right": "等距右",
"camera_angle.isometric_left": "等距左",
- "settings.render_sides": "Render Sides",
- "settings.render_sides.desc": "Select which side of a face is rendered",
- "settings.render_sides.auto": "Auto",
- "settings.render_sides.front": "Outside",
- "settings.render_sides.double": "Inside and Outside"
+ "settings.render_sides": "渲染边框",
+ "settings.render_sides.desc": "选择要渲染的面",
+ "settings.render_sides.auto": "自动设置",
+ "settings.render_sides.front": "外围",
+ "settings.render_sides.double": "内部与外围",
+ "generic.enable": "Enable",
+ "generic.disable": "Disable",
+ "generic.redacted": "Redacted",
+ "dialog.project.layered_textures": "Layered Textures",
+ "dialog.select_texture.import_all": "Import All",
+ "dialog.skin.layer_template": "Layer Texture",
+ "about.version.up_to_date": "Up to date",
+ "about.version.update_available": "Version %0 is available",
+ "settings.category.application": "Application",
+ "settings.streamer_mode": "Streamer Mode",
+ "settings.streamer_mode.desc": "Hides sensitive information like recent models",
+ "settings.automatic_updates": "Automatic Updates",
+ "settings.automatic_updates.desc": "Automatically download new versions and keep Blockbench up-to-date",
+ "action.rotation_space": "Rotation Space",
+ "action.focus_on_selection": "Center View on Selection",
+ "action.focus_on_selection.desc": "Align the camera to face the center of the current selection",
+ "action.jump_to_timeline_start": "Jump to Animation Start",
+ "action.jump_to_timeline_end": "Jump to Animation End",
+ "menu.help.updating": "Updating (%0%)",
+ "menu.help.update_ready": "Relaunch to Update",
+ "menu.help.update_failed": "Update Failed",
+ "menu.animation.loop.once": "Play Once",
+ "menu.animation.loop.hold": "Hold On Last Frame",
+ "menu.animation.loop.loop": "Loop",
+ "interface.streamer_mode_on": "Streamer Mode Enabled"
}
\ No newline at end of file
diff --git a/lib/CanvasFrame.js b/lib/CanvasFrame.js
new file mode 100644
index 00000000..0a208774
--- /dev/null
+++ b/lib/CanvasFrame.js
@@ -0,0 +1,112 @@
+/*
+ Utility to modify images with a canvas
+*/
+
+class CanvasFrame {
+ constructor(a, b) {
+ if (a && a.nodeName == 'CANVAS') {
+ if (a.getContext('2d')) {
+ this.canvas = a;
+ } else {
+ this.createCanvas(a.width, a.height)
+ this.loadFromImage(a)
+ }
+
+ } else if (a && a.nodeName == 'IMG') {
+ this.createCanvas(a.naturalWidth, a.naturalHeight)
+ this.loadFromImage(a)
+
+ } else if (a && b) {
+ this.createCanvas(a, b)
+ }
+ this.ctx = this.canvas.getContext('2d')
+ }
+ get width() {return this.canvas.width;}
+ get height() {return this.canvas.height;}
+
+ createCanvas(w, h) {
+ this.canvas = document.createElement('canvas');
+ this.canvas.width = w;
+ this.canvas.height = h;
+ this.ctx = this.canvas.getContext('2d')
+ }
+ replace(layer) {
+ this.canvas
+ }
+ async loadFromURL(url) {
+ let img = new Image()
+ img.src = url;
+ await new Promise((resolve, reject) => {
+ img.onload = function() {
+ resolve()
+ }
+ img.onerror = reject;
+ })
+ }
+ loadFromImage(img) {
+ if (img.naturalWidth) {
+ this.canvas.width = img.naturalWidth;
+ this.canvas.height = img.naturalHeight;
+ }
+ this.ctx.drawImage(img, 0, 0)
+ }
+ loadFromCanvas(img) {
+ this.canvas.width = image.naturalWidth;
+ this.canvas.height = image.naturalHeight;
+ this.ctx.drawImage(img, 0, 0)
+ }
+ autoCrop() {
+ // Based on code by remy, licensed under MIT
+ // https://gist.github.com/remy/784508
+
+ let copy = document.createElement('canvas').getContext('2d');
+ let pixels = this.ctx.getImageData(0, 0, this.width, this.height);
+ let i;
+ let bound = {
+ top: null,
+ left: null,
+ right: null,
+ bottom: null
+ };
+ let x, y;
+
+ for (i = 0; i < pixels.data.length; i += 4) {
+ if (pixels.data[i+3] !== 0) {
+ x = (i / 4) % this.width;
+ y = ~~((i / 4) / this.width);
+
+ if (bound.top === null) {
+ bound.top = y;
+ }
+
+ if (bound.left === null) {
+ bound.left = x;
+ } else if (x < bound.left) {
+ bound.left = x;
+ }
+
+ if (bound.right === null) {
+ bound.right = x;
+ } else if (bound.right < x) {
+ bound.right = x;
+ }
+
+ if (bound.bottom === null) {
+ bound.bottom = y;
+ } else if (bound.bottom < y) {
+ bound.bottom = y;
+ }
+ }
+ }
+
+ var trimHeight = bound.bottom - bound.top,
+ trimWidth = bound.right - bound.left,
+ trimmed = this.ctx.getImageData(bound.left, bound.top, trimWidth, trimHeight);
+
+ copy.canvas.width = trimWidth;
+ copy.canvas.height = trimHeight;
+ copy.putImageData(trimmed, 0, 0);
+ this.canvas = copy.canvas;
+ this.ctx = copy;
+ }
+}
\ No newline at end of file
diff --git a/main.js b/main.js
index c4b64b15..5242154a 100644
--- a/main.js
+++ b/main.js
@@ -1,6 +1,8 @@
-const {app, BrowserWindow, Menu} = require('electron')
+const {app, BrowserWindow, Menu, ipcMain} = require('electron')
const path = require('path')
const url = require('url')
+const { autoUpdater } = require('electron-updater');
+const { arch, platform } = require('os');
let orig_win;
@@ -26,35 +28,71 @@ function createWindow(second_instance) {
if (!orig_win) orig_win = win;
var index_path = path.join(__dirname, 'index.html')
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:'
- }]
- }]
+
+ let template = [
+ {
+ "label": "Blockbench",
+ "submenu": [
+ {
+ "role": "hide"
+ },
+ {
+ "role": "hideothers"
+ },
+ {
+ "role": "unhide"
+ },
+ {
+ "type": "separator"
+ },
+ {
+ "label": "Quit",
+ "accelerator": "Command+Q"
+ }
+ ]
+ },
+ {
+ "label": "Edit",
+ "submenu": [
+ {
+ "role": "cut"
+ },
+ {
+ "role": "copy"
+ },
+ {
+ "role": "paste"
+ },
+ {
+ "role": "selectall"
+ }
+ ]
+ },
+ {
+ "label": "Window",
+ "role": "window",
+ "submenu": [
+ {
+ "label": "Toggle Full Screen",
+ "accelerator": "Ctrl+Command+F"
+ },
+ {
+ "role": "minimize"
+ },
+ {
+ "role": "close"
+ },
+ {
+ "type": "separator"
+ },
+ {
+ "role": "front"
+ }
+ ]
+ }
+ ]
+
+
var osxMenu = Menu.buildFromTemplate(template);
Menu.setApplicationMenu(osxMenu)
} else {
@@ -84,8 +122,39 @@ app.on('second-instance', function (event, argv, cwd) {
})
app.commandLine.appendSwitch('ignore-gpu-blacklist')
+app.commandLine.appendSwitch('enable-accelerated-video')
-app.on('ready', createWindow)
+
+
+app.on('ready', () => {
+
+ createWindow()
+
+ autoUpdater.autoInstallOnAppQuit = true;
+ autoUpdater.autoDownload = false;
+
+ autoUpdater.on('update-available', (a) => {
+ console.log('update-available', a)
+ ipcMain.on('allow-auto-update', () => {
+ autoUpdater.downloadUpdate()
+ })
+ orig_win.webContents.send('update-available');
+ })
+ autoUpdater.on('update-downloaded', (a) => {
+ console.log('update-downloaded', a)
+ orig_win.webContents.send('update-downloaded', a)
+ })
+ autoUpdater.on('error', (a) => {
+ console.log('update-error', a)
+ orig_win.webContents.send('update-error', a)
+ })
+ autoUpdater.on('download-progress', (a) => {
+ console.log('update-progress', a)
+ orig_win.webContents.send('update-progress', a)
+ })
+
+ autoUpdater.checkForUpdates()
+})
app.on('window-all-closed', () => {
app.quit()
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 00000000..62c6d64f
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,1630 @@
+{
+ "name": "Blockbench",
+ "version": "3.6.0",
+ "lockfileVersion": 1,
+ "requires": true,
+ "dependencies": {
+ "7zip-bin": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/7zip-bin/-/7zip-bin-5.0.3.tgz",
+ "integrity": "sha512-GLyWIFBbGvpKPGo55JyRZAo4lVbnBiD52cKlw/0Vt+wnmKvWJkpZvsjVoaIolyBXDeAQKSicRtqFNPem9w0WYA==",
+ "dev": true
+ },
+ "@develar/schema-utils": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.1.0.tgz",
+ "integrity": "sha512-qjCqB4ctMig9Gz5bd6lkdFr3bO6arOdQqptdBSpF1ZpCnjofieCciEzkoS9ujY9cMGyllYSCSmBJ3x9OKHXzoA==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.1.0",
+ "ajv-keywords": "^3.1.0"
+ }
+ },
+ "@sindresorhus/is": {
+ "version": "0.14.0",
+ "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz",
+ "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==",
+ "dev": true
+ },
+ "@szmarczak/http-timer": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz",
+ "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==",
+ "dev": true,
+ "requires": {
+ "defer-to-connect": "^1.0.1"
+ }
+ },
+ "@types/debug": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.5.tgz",
+ "integrity": "sha512-Q1y515GcOdTHgagaVFhHnIFQ38ygs/kmxdNpvpou+raI9UO3YZcHDngBSYKQklcKlvA7iuQlmIKbzvmxcOE9CQ==",
+ "dev": true
+ },
+ "@types/node": {
+ "version": "14.0.19",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.19.tgz",
+ "integrity": "sha512-yf3BP/NIXF37BjrK5klu//asUWitOEoUP5xE1mhSUjazotwJ/eJDgEmMQNlOeWOVv72j24QQ+3bqXHE++CFGag=="
+ },
+ "@types/semver": {
+ "version": "7.3.1",
+ "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.1.tgz",
+ "integrity": "sha512-ooD/FJ8EuwlDKOI6D9HWxgIgJjMg2cuziXm/42npDC8y4NjxplBUn9loewZiBNCt44450lHAU0OSb51/UqXeag==",
+ "requires": {
+ "@types/node": "*"
+ }
+ },
+ "ajv": {
+ "version": "6.12.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz",
+ "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==",
+ "dev": true,
+ "requires": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "ajv-keywords": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz",
+ "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==",
+ "dev": true
+ },
+ "ansi-align": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz",
+ "integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==",
+ "dev": true,
+ "requires": {
+ "string-width": "^3.0.0"
+ }
+ },
+ "ansi-regex": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^1.9.0"
+ }
+ },
+ "app-builder-bin": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-3.4.3.tgz",
+ "integrity": "sha512-qMhayIwi3juerQEVJMQ76trObEbfQT0nhUdxZz9a26/3NLT3pE6awmQ8S1cEnrGugaaM5gYqR8OElcDezfmEsg==",
+ "dev": true
+ },
+ "app-builder-lib": {
+ "version": "21.2.0",
+ "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-21.2.0.tgz",
+ "integrity": "sha512-aOX/nv77/Bti6NymJDg7p9T067xD8m1ipIEJR7B4Mm1GsJWpMm9PZdXtCRiMNRjHtQS5KIljT0g17781y6qn5A==",
+ "dev": true,
+ "requires": {
+ "7zip-bin": "~5.0.3",
+ "@develar/schema-utils": "~2.1.0",
+ "async-exit-hook": "^2.0.1",
+ "bluebird-lst": "^1.0.9",
+ "builder-util": "21.2.0",
+ "builder-util-runtime": "8.3.0",
+ "chromium-pickle-js": "^0.2.0",
+ "debug": "^4.1.1",
+ "ejs": "^2.6.2",
+ "electron-publish": "21.2.0",
+ "fs-extra": "^8.1.0",
+ "hosted-git-info": "^2.7.1",
+ "is-ci": "^2.0.0",
+ "isbinaryfile": "^4.0.2",
+ "js-yaml": "^3.13.1",
+ "lazy-val": "^1.0.4",
+ "minimatch": "^3.0.4",
+ "normalize-package-data": "^2.5.0",
+ "read-config-file": "5.0.0",
+ "sanitize-filename": "^1.6.2",
+ "semver": "^6.3.0",
+ "temp-file": "^3.3.4"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
+ }
+ },
+ "argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "requires": {
+ "sprintf-js": "~1.0.2"
+ },
+ "dependencies": {
+ "sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
+ }
+ }
+ },
+ "async-exit-hook": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz",
+ "integrity": "sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==",
+ "dev": true
+ },
+ "at-least-node": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
+ "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg=="
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
+ "dev": true
+ },
+ "bluebird": {
+ "version": "3.7.2",
+ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
+ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==",
+ "dev": true
+ },
+ "bluebird-lst": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/bluebird-lst/-/bluebird-lst-1.0.9.tgz",
+ "integrity": "sha512-7B1Rtx82hjnSD4PGLAjVWeYH3tHAcVUmChh85a3lltKQm6FresXh9ErQo6oAv6CqxttczC3/kEg8SY5NluPuUw==",
+ "dev": true,
+ "requires": {
+ "bluebird": "^3.5.5"
+ }
+ },
+ "boxen": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/boxen/-/boxen-3.2.0.tgz",
+ "integrity": "sha512-cU4J/+NodM3IHdSL2yN8bqYqnmlBTidDR4RC7nJs61ZmtGz8VZzM3HLQX0zY5mrSmPtR3xWwsq2jOUQqFZN8+A==",
+ "dev": true,
+ "requires": {
+ "ansi-align": "^3.0.0",
+ "camelcase": "^5.3.1",
+ "chalk": "^2.4.2",
+ "cli-boxes": "^2.2.0",
+ "string-width": "^3.0.0",
+ "term-size": "^1.2.0",
+ "type-fest": "^0.3.0",
+ "widest-line": "^2.0.0"
+ },
+ "dependencies": {
+ "type-fest": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz",
+ "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==",
+ "dev": true
+ }
+ }
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "buffer-from": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
+ "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
+ "dev": true
+ },
+ "builder-util": {
+ "version": "21.2.0",
+ "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-21.2.0.tgz",
+ "integrity": "sha512-Nd6CUb6YgDY8EXAXEIegx+1kzKqyFQ5ZM5BoYkeunAlwz/zDJoH1UCyULjoS5wQe5czNClFQy07zz2bzYD0Z4A==",
+ "dev": true,
+ "requires": {
+ "7zip-bin": "~5.0.3",
+ "@types/debug": "^4.1.4",
+ "app-builder-bin": "3.4.3",
+ "bluebird-lst": "^1.0.9",
+ "builder-util-runtime": "8.3.0",
+ "chalk": "^2.4.2",
+ "debug": "^4.1.1",
+ "fs-extra": "^8.1.0",
+ "is-ci": "^2.0.0",
+ "js-yaml": "^3.13.1",
+ "source-map-support": "^0.5.13",
+ "stat-mode": "^0.3.0",
+ "temp-file": "^3.3.4"
+ }
+ },
+ "builder-util-runtime": {
+ "version": "8.3.0",
+ "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-8.3.0.tgz",
+ "integrity": "sha512-CSOdsYqf4RXIHh1HANPbrZHlZ9JQJXSuDDloblZPcWQVN62inyYoTQuSmY3KrgefME2Sv3Kn2MxHvbGQHRf8Iw==",
+ "dev": true,
+ "requires": {
+ "debug": "^4.1.1",
+ "sax": "^1.2.4"
+ }
+ },
+ "cacheable-request": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz",
+ "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==",
+ "dev": true,
+ "requires": {
+ "clone-response": "^1.0.2",
+ "get-stream": "^5.1.0",
+ "http-cache-semantics": "^4.0.0",
+ "keyv": "^3.0.0",
+ "lowercase-keys": "^2.0.0",
+ "normalize-url": "^4.1.0",
+ "responselike": "^1.0.2"
+ },
+ "dependencies": {
+ "get-stream": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz",
+ "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==",
+ "dev": true,
+ "requires": {
+ "pump": "^3.0.0"
+ }
+ },
+ "lowercase-keys": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
+ "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==",
+ "dev": true
+ }
+ }
+ },
+ "camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "dev": true
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "dependencies": {
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "dev": true
+ }
+ }
+ },
+ "chromium-pickle-js": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz",
+ "integrity": "sha1-BKEGZywYsIWrd02YPfo+oTjyIgU=",
+ "dev": true
+ },
+ "ci-info": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
+ "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==",
+ "dev": true
+ },
+ "cli-boxes": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.0.tgz",
+ "integrity": "sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w==",
+ "dev": true
+ },
+ "cliui": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
+ "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
+ "dev": true,
+ "requires": {
+ "string-width": "^3.1.0",
+ "strip-ansi": "^5.2.0",
+ "wrap-ansi": "^5.1.0"
+ }
+ },
+ "clone-response": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz",
+ "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=",
+ "dev": true,
+ "requires": {
+ "mimic-response": "^1.0.0"
+ }
+ },
+ "color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
+ "color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+ "dev": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+ "dev": true
+ },
+ "configstore": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/configstore/-/configstore-4.0.0.tgz",
+ "integrity": "sha512-CmquAXFBocrzaSM8mtGPMM/HiWmyIpr4CcJl/rgY2uCObZ/S7cKU0silxslqJejl+t/T9HS8E0PUNQD81JGUEQ==",
+ "dev": true,
+ "requires": {
+ "dot-prop": "^4.1.0",
+ "graceful-fs": "^4.1.2",
+ "make-dir": "^1.0.0",
+ "unique-string": "^1.0.0",
+ "write-file-atomic": "^2.0.0",
+ "xdg-basedir": "^3.0.0"
+ }
+ },
+ "cross-spawn": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
+ "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^4.0.1",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ }
+ },
+ "crypto-random-string": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz",
+ "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=",
+ "dev": true
+ },
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
+ "dev": true
+ },
+ "decompress-response": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz",
+ "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=",
+ "dev": true,
+ "requires": {
+ "mimic-response": "^1.0.0"
+ }
+ },
+ "deep-extend": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
+ "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
+ "dev": true
+ },
+ "defer-to-connect": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz",
+ "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==",
+ "dev": true
+ },
+ "dmg-builder": {
+ "version": "21.2.0",
+ "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-21.2.0.tgz",
+ "integrity": "sha512-9cJEclnGy7EyKFCoHDYDf54pub/t92CQapyiUxU0w9Bj2vUvfoDagP1PMiX4XD5rPp96141h9A+QN0OB4VgvQg==",
+ "dev": true,
+ "requires": {
+ "app-builder-lib": "~21.2.0",
+ "bluebird-lst": "^1.0.9",
+ "builder-util": "~21.2.0",
+ "fs-extra": "^8.1.0",
+ "iconv-lite": "^0.5.0",
+ "js-yaml": "^3.13.1",
+ "sanitize-filename": "^1.6.2"
+ }
+ },
+ "dot-prop": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz",
+ "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==",
+ "dev": true,
+ "requires": {
+ "is-obj": "^1.0.0"
+ }
+ },
+ "dotenv": {
+ "version": "8.2.0",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz",
+ "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==",
+ "dev": true
+ },
+ "dotenv-expand": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz",
+ "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==",
+ "dev": true
+ },
+ "duplexer3": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
+ "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=",
+ "dev": true
+ },
+ "ejs": {
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.7.4.tgz",
+ "integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==",
+ "dev": true
+ },
+ "electron-builder": {
+ "version": "21.2.0",
+ "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-21.2.0.tgz",
+ "integrity": "sha512-x8EXrqFbAb2L3N22YlGar3dGh8vwptbB3ovo3OF6K7NTpcsmM2zEoJv7GhFyX73rNzSG2HaWpXwGAtOp2JWiEw==",
+ "dev": true,
+ "requires": {
+ "app-builder-lib": "21.2.0",
+ "bluebird-lst": "^1.0.9",
+ "builder-util": "21.2.0",
+ "builder-util-runtime": "8.3.0",
+ "chalk": "^2.4.2",
+ "dmg-builder": "21.2.0",
+ "fs-extra": "^8.1.0",
+ "is-ci": "^2.0.0",
+ "lazy-val": "^1.0.4",
+ "read-config-file": "5.0.0",
+ "sanitize-filename": "^1.6.2",
+ "update-notifier": "^3.0.1",
+ "yargs": "^13.3.0"
+ }
+ },
+ "electron-notarize": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/electron-notarize/-/electron-notarize-1.0.0.tgz",
+ "integrity": "sha512-dsib1IAquMn0onCrNMJ6gtEIZn/azG8hZMCYOuZIMVMUeRMgBYHK1s5TK9P8xAcrAjh/2aN5WYHzgVSWX314og==",
+ "dev": true,
+ "requires": {
+ "debug": "^4.1.1",
+ "fs-extra": "^9.0.1"
+ },
+ "dependencies": {
+ "fs-extra": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz",
+ "integrity": "sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==",
+ "dev": true,
+ "requires": {
+ "at-least-node": "^1.0.0",
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^1.0.0"
+ }
+ },
+ "jsonfile": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.0.1.tgz",
+ "integrity": "sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.6",
+ "universalify": "^1.0.0"
+ }
+ },
+ "universalify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz",
+ "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==",
+ "dev": true
+ }
+ }
+ },
+ "electron-publish": {
+ "version": "21.2.0",
+ "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-21.2.0.tgz",
+ "integrity": "sha512-mWavuoWJe87iaeKd0I24dNWIaR+0yRzshjNVqGyK019H766fsPWl3caQJnVKFaEyrZRP397v4JZVG0e7s16AxA==",
+ "dev": true,
+ "requires": {
+ "bluebird-lst": "^1.0.9",
+ "builder-util": "~21.2.0",
+ "builder-util-runtime": "8.3.0",
+ "chalk": "^2.4.2",
+ "fs-extra": "^8.1.0",
+ "lazy-val": "^1.0.4",
+ "mime": "^2.4.4"
+ }
+ },
+ "electron-updater": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-4.3.1.tgz",
+ "integrity": "sha512-UDC5AHCgeiHJYDYWZG/rsl1vdAFKqI/Lm7whN57LKAk8EfhTewhcEHzheRcncLgikMcQL8gFo1KeX51tf5a5Wg==",
+ "requires": {
+ "@types/semver": "^7.1.0",
+ "builder-util-runtime": "8.7.0",
+ "fs-extra": "^9.0.0",
+ "js-yaml": "^3.13.1",
+ "lazy-val": "^1.0.4",
+ "lodash.isequal": "^4.5.0",
+ "semver": "^7.1.3"
+ },
+ "dependencies": {
+ "builder-util-runtime": {
+ "version": "8.7.0",
+ "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-8.7.0.tgz",
+ "integrity": "sha512-G1AqqVM2vYTrSFR982c1NNzwXKrGLQjVjaZaWQdn4O6Z3YKjdMDofw88aD9jpyK9ZXkrCxR0tI3Qe9wNbyTlXg==",
+ "requires": {
+ "debug": "^4.1.1",
+ "sax": "^1.2.4"
+ }
+ },
+ "fs-extra": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz",
+ "integrity": "sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==",
+ "requires": {
+ "at-least-node": "^1.0.0",
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^1.0.0"
+ }
+ },
+ "jsonfile": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.0.1.tgz",
+ "integrity": "sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg==",
+ "requires": {
+ "graceful-fs": "^4.1.6",
+ "universalify": "^1.0.0"
+ }
+ },
+ "universalify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz",
+ "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug=="
+ }
+ }
+ },
+ "emoji-regex": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
+ "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
+ "dev": true
+ },
+ "end-of-stream": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
+ "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+ "dev": true,
+ "requires": {
+ "once": "^1.4.0"
+ }
+ },
+ "esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
+ },
+ "execa": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz",
+ "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=",
+ "dev": true,
+ "requires": {
+ "cross-spawn": "^5.0.1",
+ "get-stream": "^3.0.0",
+ "is-stream": "^1.1.0",
+ "npm-run-path": "^2.0.0",
+ "p-finally": "^1.0.0",
+ "signal-exit": "^3.0.0",
+ "strip-eof": "^1.0.0"
+ },
+ "dependencies": {
+ "get-stream": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
+ "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
+ "dev": true
+ }
+ }
+ },
+ "fast-deep-equal": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz",
+ "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==",
+ "dev": true
+ },
+ "fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true
+ },
+ "find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^3.0.0"
+ }
+ },
+ "fs-extra": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
+ "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^4.0.0",
+ "universalify": "^0.1.0"
+ }
+ },
+ "get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "dev": true
+ },
+ "get-stream": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
+ "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
+ "dev": true,
+ "requires": {
+ "pump": "^3.0.0"
+ }
+ },
+ "global-dirs": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz",
+ "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=",
+ "dev": true,
+ "requires": {
+ "ini": "^1.3.4"
+ }
+ },
+ "got": {
+ "version": "9.6.0",
+ "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz",
+ "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==",
+ "dev": true,
+ "requires": {
+ "@sindresorhus/is": "^0.14.0",
+ "@szmarczak/http-timer": "^1.1.2",
+ "cacheable-request": "^6.0.0",
+ "decompress-response": "^3.3.0",
+ "duplexer3": "^0.1.4",
+ "get-stream": "^4.1.0",
+ "lowercase-keys": "^1.0.1",
+ "mimic-response": "^1.0.1",
+ "p-cancelable": "^1.0.0",
+ "to-readable-stream": "^1.0.0",
+ "url-parse-lax": "^3.0.0"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz",
+ "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ=="
+ },
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+ "dev": true
+ },
+ "has-yarn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz",
+ "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==",
+ "dev": true
+ },
+ "hosted-git-info": {
+ "version": "2.8.8",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz",
+ "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==",
+ "dev": true
+ },
+ "http-cache-semantics": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz",
+ "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==",
+ "dev": true
+ },
+ "iconv-lite": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.1.tgz",
+ "integrity": "sha512-ONHr16SQvKZNSqjQT9gy5z24Jw+uqfO02/ngBSBoqChZ+W8qXX7GPRa1RoUnzGADw8K63R1BXUMzarCVQBpY8Q==",
+ "dev": true,
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ },
+ "import-lazy": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz",
+ "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=",
+ "dev": true
+ },
+ "imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
+ "dev": true
+ },
+ "ini": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
+ "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
+ "dev": true
+ },
+ "is-ci": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz",
+ "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==",
+ "dev": true,
+ "requires": {
+ "ci-info": "^2.0.0"
+ }
+ },
+ "is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+ "dev": true
+ },
+ "is-installed-globally": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz",
+ "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=",
+ "dev": true,
+ "requires": {
+ "global-dirs": "^0.1.0",
+ "is-path-inside": "^1.0.0"
+ }
+ },
+ "is-npm": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-3.0.0.tgz",
+ "integrity": "sha512-wsigDr1Kkschp2opC4G3yA6r9EgVA6NjRpWzIi9axXqeIaAATPRJc4uLujXe3Nd9uO8KoDyA4MD6aZSeXTADhA==",
+ "dev": true
+ },
+ "is-obj": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
+ "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=",
+ "dev": true
+ },
+ "is-path-inside": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz",
+ "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=",
+ "dev": true,
+ "requires": {
+ "path-is-inside": "^1.0.1"
+ }
+ },
+ "is-stream": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
+ "dev": true
+ },
+ "is-yarn-global": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz",
+ "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==",
+ "dev": true
+ },
+ "isbinaryfile": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.6.tgz",
+ "integrity": "sha512-ORrEy+SNVqUhrCaal4hA4fBzhggQQ+BaLntyPOdoEiwlKZW9BZiJXjg3RMiruE4tPEI3pyVPpySHQF/dKWperg==",
+ "dev": true
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+ "dev": true
+ },
+ "js-yaml": {
+ "version": "3.13.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
+ "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
+ "requires": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ }
+ },
+ "json-buffer": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz",
+ "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=",
+ "dev": true
+ },
+ "json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "json5": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz",
+ "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==",
+ "dev": true,
+ "requires": {
+ "minimist": "^1.2.5"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
+ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
+ "dev": true
+ }
+ }
+ },
+ "jsonfile": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
+ "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "keyv": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz",
+ "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==",
+ "dev": true,
+ "requires": {
+ "json-buffer": "3.0.0"
+ }
+ },
+ "latest-version": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz",
+ "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==",
+ "dev": true,
+ "requires": {
+ "package-json": "^6.3.0"
+ }
+ },
+ "lazy-val": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.4.tgz",
+ "integrity": "sha512-u93kb2fPbIrfzBuLjZE+w+fJbUUMhNDXxNmMfaqNgpfQf1CO5ZSe2LfsnBqVAk7i/2NF48OSoRj+Xe2VT+lE8Q=="
+ },
+ "locate-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "lodash.isequal": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
+ "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA="
+ },
+ "lowercase-keys": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
+ "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==",
+ "dev": true
+ },
+ "lru-cache": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
+ "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
+ "dev": true,
+ "requires": {
+ "pseudomap": "^1.0.2",
+ "yallist": "^2.1.2"
+ }
+ },
+ "make-dir": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz",
+ "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==",
+ "dev": true,
+ "requires": {
+ "pify": "^3.0.0"
+ }
+ },
+ "mime": {
+ "version": "2.4.4",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz",
+ "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==",
+ "dev": true
+ },
+ "mimic-response": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
+ "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==",
+ "dev": true
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ },
+ "normalize-package-data": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
+ "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+ "dev": true,
+ "requires": {
+ "hosted-git-info": "^2.1.4",
+ "resolve": "^1.10.0",
+ "semver": "2 || 3 || 4 || 5",
+ "validate-npm-package-license": "^3.0.1"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true
+ }
+ }
+ },
+ "normalize-url": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz",
+ "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==",
+ "dev": true
+ },
+ "npm-run-path": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
+ "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
+ "dev": true,
+ "requires": {
+ "path-key": "^2.0.0"
+ }
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "dev": true,
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "p-cancelable": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz",
+ "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==",
+ "dev": true
+ },
+ "p-finally": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
+ "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=",
+ "dev": true
+ },
+ "p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^2.0.0"
+ }
+ },
+ "p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true
+ },
+ "package-json": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz",
+ "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==",
+ "dev": true,
+ "requires": {
+ "got": "^9.6.0",
+ "registry-auth-token": "^4.0.0",
+ "registry-url": "^5.0.0",
+ "semver": "^6.2.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
+ }
+ },
+ "path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
+ "dev": true
+ },
+ "path-is-inside": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz",
+ "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=",
+ "dev": true
+ },
+ "path-key": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+ "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
+ "dev": true
+ },
+ "path-parse": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
+ "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
+ "dev": true
+ },
+ "pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+ "dev": true
+ },
+ "prepend-http": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz",
+ "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=",
+ "dev": true
+ },
+ "pseudomap": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
+ "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=",
+ "dev": true
+ },
+ "pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "punycode": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+ "dev": true
+ },
+ "rc": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
+ "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
+ "dev": true,
+ "requires": {
+ "deep-extend": "^0.6.0",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
+ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
+ "dev": true
+ }
+ }
+ },
+ "read-config-file": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/read-config-file/-/read-config-file-5.0.0.tgz",
+ "integrity": "sha512-jIKUu+C84bfnKxyJ5j30CxCqgXWYjZLXuVE/NYlMEpeni+dhESgAeZOZd0JZbg1xTkMmnCdxksDoarkOyfEsOg==",
+ "dev": true,
+ "requires": {
+ "dotenv": "^8.0.0",
+ "dotenv-expand": "^5.1.0",
+ "fs-extra": "^8.1.0",
+ "js-yaml": "^3.13.1",
+ "json5": "^2.1.0",
+ "lazy-val": "^1.0.4"
+ }
+ },
+ "registry-auth-token": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.1.1.tgz",
+ "integrity": "sha512-9bKS7nTl9+/A1s7tnPeGrUpRcVY+LUh7bfFgzpndALdPfXQBfQV77rQVtqgUV3ti4vc/Ik81Ex8UJDWDQ12zQA==",
+ "dev": true,
+ "requires": {
+ "rc": "^1.2.8"
+ }
+ },
+ "registry-url": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz",
+ "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==",
+ "dev": true,
+ "requires": {
+ "rc": "^1.2.8"
+ }
+ },
+ "require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
+ "dev": true
+ },
+ "require-main-filename": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
+ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
+ "dev": true
+ },
+ "resolve": {
+ "version": "1.16.1",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.16.1.tgz",
+ "integrity": "sha512-rmAglCSqWWMrrBv/XM6sW0NuRFiKViw/W4d9EbC4pt+49H8JwHy+mcGmALTEg504AUDcLTvb1T2q3E9AnmY+ig==",
+ "dev": true,
+ "requires": {
+ "path-parse": "^1.0.6"
+ }
+ },
+ "responselike": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz",
+ "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=",
+ "dev": true,
+ "requires": {
+ "lowercase-keys": "^1.0.0"
+ }
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "dev": true
+ },
+ "sanitize-filename": {
+ "version": "1.6.3",
+ "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz",
+ "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==",
+ "dev": true,
+ "requires": {
+ "truncate-utf8-bytes": "^1.0.0"
+ }
+ },
+ "sax": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
+ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
+ },
+ "semver": {
+ "version": "7.3.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
+ "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ=="
+ },
+ "semver-diff": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz",
+ "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=",
+ "dev": true,
+ "requires": {
+ "semver": "^5.0.3"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true
+ }
+ }
+ },
+ "set-blocking": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
+ "dev": true
+ },
+ "shebang-command": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+ "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+ "dev": true,
+ "requires": {
+ "shebang-regex": "^1.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
+ "dev": true
+ },
+ "signal-exit": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
+ "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "source-map-support": {
+ "version": "0.5.17",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.17.tgz",
+ "integrity": "sha512-bwdKOBZ5L0gFRh4KOxNap/J/MpvX9Yxsq9lFDx65s3o7F/NiHy7JRaGIS8MwW6tZPAq9UXE207Il0cfcb5yu/Q==",
+ "dev": true,
+ "requires": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "spdx-correct": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz",
+ "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==",
+ "dev": true,
+ "requires": {
+ "spdx-expression-parse": "^3.0.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "spdx-exceptions": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz",
+ "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==",
+ "dev": true
+ },
+ "spdx-expression-parse": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz",
+ "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==",
+ "dev": true,
+ "requires": {
+ "spdx-exceptions": "^2.1.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "spdx-license-ids": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz",
+ "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==",
+ "dev": true
+ },
+ "stat-mode": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-0.3.0.tgz",
+ "integrity": "sha512-QjMLR0A3WwFY2aZdV0okfFEJB5TRjkggXZjxP3A1RsWsNHNu3YPv8btmtc6iCFZ0Rul3FE93OYogvhOUClU+ng==",
+ "dev": true
+ },
+ "string-width": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+ "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^7.0.1",
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^5.1.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^4.1.0"
+ }
+ },
+ "strip-eof": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
+ "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=",
+ "dev": true
+ },
+ "strip-json-comments": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+ "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ },
+ "temp-file": {
+ "version": "3.3.7",
+ "resolved": "https://registry.npmjs.org/temp-file/-/temp-file-3.3.7.tgz",
+ "integrity": "sha512-9tBJKt7GZAQt/Rg0QzVWA8Am8c1EFl+CAv04/aBVqlx5oyfQ508sFIABshQ0xbZu6mBrFLWIUXO/bbLYghW70g==",
+ "dev": true,
+ "requires": {
+ "async-exit-hook": "^2.0.1",
+ "fs-extra": "^8.1.0"
+ }
+ },
+ "term-size": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz",
+ "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=",
+ "dev": true,
+ "requires": {
+ "execa": "^0.7.0"
+ }
+ },
+ "to-readable-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz",
+ "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==",
+ "dev": true
+ },
+ "truncate-utf8-bytes": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz",
+ "integrity": "sha1-QFkjkJWS1W94pYGENLC3hInKXys=",
+ "dev": true,
+ "requires": {
+ "utf8-byte-length": "^1.0.1"
+ }
+ },
+ "unique-string": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz",
+ "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=",
+ "dev": true,
+ "requires": {
+ "crypto-random-string": "^1.0.0"
+ }
+ },
+ "universalify": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
+ "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
+ "dev": true
+ },
+ "update-notifier": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-3.0.1.tgz",
+ "integrity": "sha512-grrmrB6Zb8DUiyDIaeRTBCkgISYUgETNe7NglEbVsrLWXeESnlCSP50WfRSj/GmzMPl6Uchj24S/p80nP/ZQrQ==",
+ "dev": true,
+ "requires": {
+ "boxen": "^3.0.0",
+ "chalk": "^2.0.1",
+ "configstore": "^4.0.0",
+ "has-yarn": "^2.1.0",
+ "import-lazy": "^2.1.0",
+ "is-ci": "^2.0.0",
+ "is-installed-globally": "^0.1.0",
+ "is-npm": "^3.0.0",
+ "is-yarn-global": "^0.3.0",
+ "latest-version": "^5.0.0",
+ "semver-diff": "^2.0.0",
+ "xdg-basedir": "^3.0.0"
+ }
+ },
+ "uri-js": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
+ "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
+ "dev": true,
+ "requires": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "url-parse-lax": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz",
+ "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=",
+ "dev": true,
+ "requires": {
+ "prepend-http": "^2.0.0"
+ }
+ },
+ "utf8-byte-length": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz",
+ "integrity": "sha1-9F8VDExm7uloGGUFq5P8u4rWv2E=",
+ "dev": true
+ },
+ "validate-npm-package-license": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+ "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+ "dev": true,
+ "requires": {
+ "spdx-correct": "^3.0.0",
+ "spdx-expression-parse": "^3.0.0"
+ }
+ },
+ "which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ },
+ "which-module": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
+ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
+ "dev": true
+ },
+ "widest-line": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz",
+ "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==",
+ "dev": true,
+ "requires": {
+ "string-width": "^2.1.1"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true
+ },
+ "string-width": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+ "dev": true,
+ "requires": {
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^4.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^3.0.0"
+ }
+ }
+ }
+ },
+ "wrap-ansi": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
+ "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.0",
+ "string-width": "^3.0.0",
+ "strip-ansi": "^5.0.0"
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+ "dev": true
+ },
+ "write-file-atomic": {
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz",
+ "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.11",
+ "imurmurhash": "^0.1.4",
+ "signal-exit": "^3.0.2"
+ }
+ },
+ "xdg-basedir": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz",
+ "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=",
+ "dev": true
+ },
+ "y18n": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
+ "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
+ "dev": true
+ },
+ "yallist": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+ "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
+ "dev": true
+ },
+ "yargs": {
+ "version": "13.3.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz",
+ "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==",
+ "dev": true,
+ "requires": {
+ "cliui": "^5.0.0",
+ "find-up": "^3.0.0",
+ "get-caller-file": "^2.0.1",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^2.0.0",
+ "set-blocking": "^2.0.0",
+ "string-width": "^3.0.0",
+ "which-module": "^2.0.0",
+ "y18n": "^4.0.0",
+ "yargs-parser": "^13.1.2"
+ }
+ },
+ "yargs-parser": {
+ "version": "13.1.2",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz",
+ "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==",
+ "dev": true,
+ "requires": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ }
+ }
+ }
+}
diff --git a/package.json b/package.json
index 1f0c9060..293ebf26 100644
--- a/package.json
+++ b/package.json
@@ -1,8 +1,8 @@
{
"name": "Blockbench",
"description": "Model editing and animation software",
- "version": "3.5.4",
- "license": "MIT",
+ "version": "3.6.0",
+ "license": "GPL-3.0-or-later",
"author": {
"name": "JannisX11",
"email": "info@blockbench.net"
@@ -14,12 +14,20 @@
},
"main": "main.js",
"build": {
+ "afterSign": "scripts/notarize.js",
"appId": "blockbench",
"productName": "Blockbench",
"artifactName": "${productName}_${arch}_${version}.${ext}",
+ "publish": [
+ {
+ "provider": "github"
+ }
+ ],
"mac": {
"category": "macOS.application",
- "target": "dmg"
+ "hardenedRuntime": true,
+ "entitlements": "build/entitlements.mac.plist",
+ "entitlementsInherit": "build/entitlements.mac.plist"
},
"files": [
"assets/",
@@ -39,7 +47,6 @@
],
"dmg": {
"artifactName": "${productName}_${version}.${ext}",
- "backgroundColor": "#282c34",
"window": {
"x": 200,
"y": 100,
@@ -71,17 +78,26 @@
"appImage"
],
"category": "3DGraphics"
- }
+ },
+ "fileAssociations": [
+ {
+ "ext": "bbmodel",
+ "name": "Blockbench Project",
+ "role": "Editor"
+ }
+ ]
},
"scripts": {
"dev": "electron .",
- "dist": "electron-builder --publish=always",
- "win64": "electron-builder -w --ia32 --publish=always",
- "win32": "electron-builder -w --x64 --publish=always",
+ "dist": "electron-builder",
"beta": "electron-builder --windows portable"
},
"devDependencies": {
- "electron": "8.2.1",
- "electron-builder": "^21.2.0"
+ "electron": "8.2.4",
+ "electron-builder": "^21.2.0",
+ "electron-notarize": "^1.0.0"
+ },
+ "dependencies": {
+ "electron-updater": "^4.3.1"
}
}
diff --git a/scripts/notarize.js b/scripts/notarize.js
new file mode 100644
index 00000000..a873565b
--- /dev/null
+++ b/scripts/notarize.js
@@ -0,0 +1,15 @@
+const { notarize } = require('electron-notarize');
+
+exports.default = async function notarizing(context) {
+ const { electronPlatformName, appOutDir } = context;
+ if (electronPlatformName !== 'darwin') return;
+
+ const appName = context.packager.appInfo.productFilename;
+
+ return await notarize({
+ appBundleId: 'net.blockbench.blockbench',
+ appPath: `${appOutDir}/${appName}.app`,
+ appleId: process.env.APPLEID,
+ appleIdPassword: process.env.APPLEIDPASS,
+ });
+};
\ No newline at end of file