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.growable = data.growable;
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;
this.folded = false;
if (data.toolbars) {
this.toolbars = data.toolbars;
} else {
this.toolbars = {};
}
// Vue
if (data.component) {
data.component.name = 'inside-vue'
let bar = $(`.sidebar#${data.default_side||'left'}_bar`);
let node = $(`
`);
if (data.insert_before && bar.find(`> .panel#${data.insert_before}`).length) {
node.insertBefore(bar.find(`> .panel#${data.insert_before}`));
} else if (data.insert_after && bar.find(`> .panel#${data.insert_after}`).length) {
node.insertAfter(bar.find(`> .panel#${data.insert_after}`));
} else {
bar.append(node)
}
this.vue = new Vue({
components: {
'inside-vue': data.component
},
template: `
`,
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 = $(`
`).get(0)
$(this.node).prepend(this.handle)
if (!Blockbench.isMobile) {
let fold_button = $(`expand_more
`)[0];
this.handle.append(fold_button);
fold_button.addEventListener('click', (e) => {
this.fold();
})
$(this.handle).draggable({
revertDuration: 0,
cursorAt: { left: 24, top: 24 },
helper: 'clone',
revert: true,
appendTo: 'body',
zIndex: 19,
scope: 'panel',
handle: '> label',
start: function() {
Interface.panel = scope;
},
drag(e, ui) {
$('.panel[order]').attr('order', null)
let target_panel = $('div.panel:hover').get(0);
if (!target_panel) return;
let top = $(target_panel).offset().top;
let height = target_panel.clientHeight;
if (e.clientY > top + height/2) {
$(target_panel).attr('order', 1);
} else {
$(target_panel).attr('order', -1);
}
},
stop: function(e, ui) {
$('.panel[order]').attr('order', null)
if (!ui) return;
if (Math.abs(ui.position.top - ui.originalPosition.top) + Math.abs(ui.position.left - ui.originalPosition.left) < 30) 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.clientHeight;
let before = e.clientY < 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;
}
fold(state = !this.folded) {
this.folded = !!state;
$(this.handle).find('> .panel_folding_button > i').text(state ? 'expand_less' : 'expand_more');
this.node.classList.toggle('folded', state);
}
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.remove()
}
}
function setupPanels() {
$('.sidebar').droppable({
accept: 'h3',
scope: 'panel',
tolerance: 'pointer',
drop: function(e, ui) {
Interface.panel = $(this).attr('id');
}
})
//Panels
Interface.Panels.element = new Panel({
id: 'element',
icon: 'fas.fa-cube',
condition: !Blockbench.isMobile && {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: !Blockbench.isMobile && {modes: ['animate']},
selection_only: true,
toolbars: {
inverse_kinematics: Toolbars.inverse_kinematics,
},
component: {
template: `
${ tl('panel.element.origin') }
${ tl('panel.bone.ik') }
`
}
})
Interface.panel_definers.forEach((definer) => {
if (typeof definer === 'function') {
definer()
}
})
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))
}