Implement mobile split screen view

Improve panel handling
Allow landscape mode on mobile
This commit is contained in:
JannisX11 2022-03-07 14:37:19 +01:00
parent 4c0de4d7f1
commit 26fe5c40b0
18 changed files with 300 additions and 218 deletions

View File

@ -87,12 +87,6 @@
flex: 1 1 auto;
}
@media (max-device-width: 640px) {
dialog {
width: 100% !important;
}
}
dialog p > code {
background-color: var(--color-back);
border: 1px solid var(--color-border);

View File

@ -37,7 +37,8 @@
width: auto;
}
h3.panel_handle > label {
flex: 0 1 auto;
flex: 1 1 auto;
overflow: hidden;
font-size: 1.1em;
text-transform: uppercase;
color: var(--color-subtle_text);
@ -46,6 +47,25 @@
padding: 0px 4px;
cursor: move;
}
h3.panel_handle > label > span {
cursor: inherit;
}
body.is_mobile.is_landscape h3.panel_handle > label > span::before {
content: "\f337";
font-family: 'Font Awesome 6 Free';
font-weight: 900;
display: inline-block;
pointer-events: none;
margin-right: 7px;
}
body.is_mobile:not(.is_landscape) h3.panel_handle > label > span::after {
content: "\f338";
font-family: 'Font Awesome 6 Free';
font-weight: 900;
display: inline-block;
pointer-events: none;
margin-left: 7px;
}
h3.panel_handle > .tool.panel_control {
flex: 0 0 24px;
margin-top: 4px;
@ -55,6 +75,9 @@
h3.panel_handle > .tool.panel_control:hover {
opacity: 1;
}
body.is_touch h3.panel_handle > .tool.panel_control {
flex-basis: 36px;
}
.panel p {
margin-left: 12px;
}

View File

@ -47,21 +47,19 @@
::selection {
background: var(--color-accent);
}
@media (max-device-width: 640px) {
::-webkit-scrollbar {
width: 0;
height: 0;
}
* {
scrollbar-width: none;
}
.mobile_scrollbar {
scrollbar-width: thin;
}
.mobile_scrollbar::-webkit-scrollbar {
width: 12px;
height: 12px;
}
body.is_mobile ::-webkit-scrollbar {
width: 0;
height: 0;
}
body.is_mobile * {
scrollbar-width: none;
}
body.is_mobile .mobile_scrollbar {
scrollbar-width: thin;
}
body.is_mobile .mobile_scrollbar::-webkit-scrollbar {
width: 12px;
height: 12px;
}
/*Assistant Font*/
@font-face {

View File

@ -249,11 +249,10 @@ License: MIT
.sp-cf { *zoom: 1; }
/* Mobile devices, make hue slider bigger so it is easier to slide */
@media (max-device-width: 640px) {
.sp-color { right: 40%; }
.sp-hue { left: 63%; }
.sp-fill { padding-top: 60%; }
}
body.is_touch .sp-color { right: 40%; }
body.is_touch .sp-hue { left: 63%; }
body.is_touch .sp-fill { padding-top: 60%; }
.sp-dragger {
border-radius: 6px;
height: 8px;

View File

@ -291,12 +291,10 @@
}
/*Mobile*/
@media (max-device-width: 640px) {
#page_wrapper {
body.is_mobile #page_wrapper {
border: none;
}
#work_screen {
body.is_mobile #work_screen {
display: grid;
grid-template-rows: auto minmax(200px, 5000px) 26px 36px !important;
grid-template-areas:
@ -307,73 +305,94 @@
grid-template-columns: auto !important;
position: relative;
}
#main_toolbar {
body.is_mobile.is_landscape #work_screen {
grid-template-columns: auto 48px !important;
grid-template-rows: auto minmax(200px, 5000px) 26px !important;
grid-template-areas:
"toolbar panel_selector"
"center panel_selector"
"status_bar panel_selector";
position: relative;
}
body.is_mobile.is_landscape #work_screen #center {
flex-direction: row;
}
body.is_mobile #main_toolbar {
display: block;
}
#main_toolbar > * {
body.is_mobile #main_toolbar > * {
display: block;
}
#main_toolbar > div.tools {
body.is_mobile .toolbar_wrapper.narrow.tools {
position: absolute;
z-index: 2;
bottom: 62px;
bottom: 0px;
right: 0px;
}
#main_toolbar > div.mobile_side {
position: absolute;
z-index: 2;
right: 0px;
margin-top: 30px;
}
#main_toolbar > div.tool_options {
body.is_mobile #main_toolbar > div.tool_options {
background-color: var(--color-back);
}
.preview .preview_menu {
body.is_mobile .preview .preview_menu {
left: 0;
right: unset;
flex-direction: row-reverse;
}
.resizer.vertical {
body.is_mobile .resizer.vertical {
display: none;
}
.sidebar {
body.is_mobile .sidebar {
overflow-y: auto;
}
#left_bar, #right_bar {
width: calc(100% - 40px);
body.is_mobile #left_bar, body.is_mobile #right_bar {
display: none;
}
#panel_selector_bar {
body.is_mobile #panel_selector_bar {
display: flex;
grid-area: panel_selector;
background-color: var(--color-ui);
}
#panel_selector_bar .panel_selector {
body.is_mobile.is_landscape #panel_selector_bar {
flex-direction: column;
background: var(--color-frame);
}
body.is_mobile #panel_selector_bar .panel_selector {
height: 36px;
flex: 36px 1 0;
text-align: center;
cursor: default;
color: var(--color-text);
}
#panel_selector_bar .panel_selector.selected {
body.is_mobile.is_landscape #panel_selector_bar .panel_selector {
display: flex;
justify-content: center;
align-items: center;
}
body.is_mobile #panel_selector_bar .panel_selector.selected {
border-bottom: 3px solid var(--color-accent);
}
.panel_selector:only-child {
body.is_mobile.is_landscape #panel_selector_bar .panel_selector.selected {
border-bottom: none;
border-right: 5px solid var(--color-accent);
padding-left: 5px;
}
body.is_mobile .panel_selector:only-child {
display: none;
}
#panel_selector_bar .panel_selector .icon_wrapper {
body.is_mobile #panel_selector_bar .panel_selector .icon_wrapper {
margin-top: 6px;
}
#mobile_keyboard_menu {
width: 40px;
body.is_mobile #mobile_keyboard_menu {
width: 48px;
text-align: center;
padding: 6px;
position: relative;
color: var(--color-accent);
}
#mobile_keyboard_menu:hover {
body.is_mobile #mobile_keyboard_menu:hover {
color: var(--color-light);
}
#mobile_keyboard_menu.enabled::after {
body.is_mobile #mobile_keyboard_menu.enabled::after {
content: "";
display: block;
position: absolute;
@ -382,24 +401,9 @@
border-radius: 50%;
background-color: var(--color-accent);
bottom: 2px;
right: 15px;
right: 19px;
}
div#mobile_panel_overlay {
position: absolute;
z-index: 12;
top: 0;
left: 0;
right: 40px;
bottom: 0;
overflow-x: hidden;
overflow-y: auto;
background: var(--color-ui);
}
div#mobile_panel_overlay > .panel {
height: 100%;
}
}
/*Menu Bar*/
ul#menu_bar {
@ -432,6 +436,7 @@
height: 30px;
margin-left: auto;
margin-right: 0;
text-align: right;
}
#mode_selector li {
display: inline-block;

View File

@ -420,7 +420,6 @@
v-on:mousedown="mode.select()"
>{{ mode.name }}</li>
</ul>
<div class="toolbar_wrapper narrow mobile_side"></div>
</div>
<div id="left_bar" class="sidebar"></div>

View File

@ -945,7 +945,7 @@ Interface.definePanels(function() {
document.body.append(locator_suggestion_list);
new Panel('keyframe', {
icon: 'timeline',
icon: 'icon-keyframe',
condition: {modes: ['animate']},
default_position: {
slot: 'left_bar',

View File

@ -2,7 +2,8 @@ const LastVersion = localStorage.getItem('last_version') || localStorage.getItem
const Blockbench = {
isWeb: !isApp,
isMobile: !isApp && window.innerWidth <= 640,
isMobile: window.innerWidth <= 960 || window.innerHeight <= 500,
isLandscape: window.innerWidth > window.innerHeight,
isTouch: 'ontouchend' in document,
get isPWA() {
return navigator.standalone || window.matchMedia('(display-mode: standalone)').matches;

View File

@ -68,8 +68,9 @@ class BarItem {
label.innerText = action.keybind || '';
tooltip.append(label);
let description;
if (action.description) {
let description = document.createElement('div');
description = document.createElement('div');
description.className = 'tooltip_description';
description.innerText = action.description;
tooltip.append(description);
@ -77,46 +78,58 @@ class BarItem {
action.node.prepend(tooltip);
action.node.addEventListener('mouseenter', () => {
var tooltip = $(action.node).find('div.tooltip');
if (!tooltip.length) return;
var description = tooltip.find('.tooltip_description');
addEventListeners(action.node, 'mouseenter touchstart', () => {
let j_tooltip = $(tooltip);
let j_description = description && $(description);
if ($(action.node).parent().parent().hasClass('vertical')) {
tooltip.css('margin', '0')
j_tooltip.css('margin', '0')
if ($(action.node).offset().left > window.innerWidth/2) {
tooltip.css('margin-left', (-tooltip.width()-3) + 'px')
j_tooltip.css('margin-left', (-j_tooltip.width()-3) + 'px')
} else {
tooltip.css('margin-left', '34px')
j_tooltip.css('margin-left', '34px')
}
} else {
tooltip.css('margin-left', '0')
var offset = tooltip && tooltip.offset()
offset.right = offset.left + parseInt(tooltip.css('width').replace(/px/, '')) - window.innerWidth
j_tooltip.css('margin-left', '0')
var offset = j_tooltip && j_tooltip.offset()
offset.right = offset.left + parseInt(j_tooltip.css('width').replace(/px/, '')) - window.innerWidth
if (offset.right > 4) {
tooltip.css('margin-left', -offset.right+'px')
j_tooltip.css('margin-left', -offset.right+'px')
}
// description
if (!description.length) return;
if (!j_description) return;
description.css('margin-left', '-5px')
var offset = description.offset()
offset.right = offset.left + parseInt(description.css('width').replace(/px/, '')) - window.innerWidth
j_description.css('margin-left', '-5px')
var offset = j_description.offset()
offset.right = offset.left + parseInt(j_description.css('width').replace(/px/, '')) - window.innerWidth
if (offset.right > 4) {
description.css('margin-left', -offset.right+'px')
j_description.css('margin-left', -offset.right+'px')
}
// height
if ((window.innerHeight - offset.top) < 28) {
tooltip.css('margin-top', -2-tooltip.height()+'px');
description.css('margin-top', '-51px');
j_tooltip.css('margin-top', -2-j_tooltip.height()+'px');
j_description.css('margin-top', '-51px');
}
}
})
action.node.addEventListener('touchstart', () => {
tooltip.style.display = 'none';
let show_tooltip = setTimeout(() => {
tooltip.style.display = 'block';
setTimeout(() => {
tooltip.style.display = 'none';
}, 1200)
}, 500)
let stop = e => {
clearInterval(show_tooltip);
document.removeEventListener('touchend', stop);
};
document.addEventListener('touchend', stop);
})
}
}
getNode(ignore_disconnected) {
@ -2120,18 +2133,6 @@ const BARS = {
Toolbars.vertex_snap.add(BarItems.selection_mode);
})
//Mobile
Toolbars.mobile_side = new Toolbar({
id: 'mobile_side',
children: [
'sidebar_right',
'sidebar_left',
'action_control',
],
vertical: true,
default_place: Blockbench.isMobile
})
Toolbox = Toolbars.tools;
Toolbox.toggleTransforms = function() {
if (Toolbox.selected.id === 'move_tool') {

View File

@ -329,9 +329,10 @@ function getStringWidth(string, size) {
return width;
};
const toggle_sidebar = window.innerWidth < 640;
class DialogSidebar {
constructor(options, dialog) {
this.open = !Blockbench.isMobile;
this.open = !toggle_sidebar;
this.pages = options.pages || {};
this.page = options.page || Object.keys(this.pages)[0];
this.actions = options.actions || {};
@ -354,7 +355,7 @@ class DialogSidebar {
this.page_menu[key] = li;
li.addEventListener('click', event => {
this.setPage(key);
if (Blockbench.isMobile) this.toggle();
if (toggle_sidebar) this.toggle();
})
page_list.append(li);
}

View File

@ -108,6 +108,7 @@ const Interface = {
Resizers: {
left: new ResizeLine('left', {
condition() {
if (Blockbench.isMobile) return false;
if (!Prop.show_left_bar) return false;
for (let p of Interface.data.left_bar) {
if (Interface.Panels[p] && BARS.condition(Interface.Panels[p].condition)) {
@ -138,6 +139,7 @@ const Interface = {
}),
right: new ResizeLine('right', {
condition() {
if (Blockbench.isMobile) return false;
if (!Prop.show_right_bar) return false;
for (let p of Interface.data.right_bar) {
if (Interface.Panels[p] && BARS.condition(Interface.Panels[p].condition)) {
@ -194,7 +196,7 @@ const Interface = {
}),
top: new ResizeLine('top', {
horizontal: true,
condition() {return Interface.getTopPanel()},
condition() {return !Blockbench.isMobile && Interface.getTopPanel()},
get() {
let panel = Interface.getTopPanel();
return panel.folded ? panel.handle.clientHeight : panel.position_data.height;
@ -212,7 +214,7 @@ const Interface = {
}),
bottom: new ResizeLine('bottom', {
horizontal: true,
condition() {return Interface.getBottomPanel()},
condition() {return !Blockbench.isMobile && Interface.getBottomPanel()},
get() {
let panel = Interface.getBottomPanel();
return panel.folded ? panel.handle.clientHeight : panel.position_data.height;
@ -318,6 +320,10 @@ function setupInterface() {
translateUI()
if (Blockbench.isMobile) document.body.classList.add('is_mobile');
if (Blockbench.isLandscape) document.body.classList.add('is_landscape');
if (Blockbench.isTouch) document.body.classList.add('is_touch');
document.getElementById('title_bar_home_button').title = tl('projects.start_screen');
$('#center').toggleClass('checkerboard', settings.preview_checkerboard.value);
@ -342,6 +348,11 @@ function setupInterface() {
}
//$(document).contextmenu()
if (Blockbench.isMobile) {
document.getElementById('preview').append(
document.querySelector('.toolbar_wrapper.narrow.tools')
);
}
//Tooltip Fix
$(document).on('mouseenter', '.tool', function() {
@ -452,6 +463,8 @@ function resizeWindow(event) {
if (!Preview.all || (event && event.target && event.target !== window)) {
return;
}
Blockbench.isLandscape = window.innerWidth > window.innerHeight;
document.body.classList.toggle('is_landscape', Blockbench.isLandscape);
if (Interface.data) {
updateInterfacePanels()
}

View File

@ -8,6 +8,7 @@ class Panel {
this.icon = data.icon;
this.menu = data.menu;
this.condition = data.condition;
this.display_condition = data.display_condition;
this.previous_slot = 'left_bar';
this.growable = data.growable;
@ -26,7 +27,7 @@ class Panel {
if (!this.position_data.float_size) this.position_data.float_size = defaultp.float_size || [300, 300];
if (!this.position_data.height) this.position_data.height = defaultp.height || 300;
this.handle = Interface.createElement('h3', {class: 'panel_handle'}, Interface.createElement('label', {}, this.name));
this.handle = Interface.createElement('h3', {class: 'panel_handle'}, Interface.createElement('label', {}, Interface.createElement('span', {}, this.name)));
this.node = Interface.createElement('div', {class: 'panel', id: `panel_${this.id}`}, this.handle);
if (this.selection_only) this.node.classList.add('selection_only');
@ -64,7 +65,7 @@ class Panel {
if (typeof onmounted == 'function') {
onmounted.call(this);
}
updateInterfacePanels()
//updateInterfacePanels()
})
}
this.vue = this.inside_vue = new Vue(data.component).$mount(component_mount);
@ -138,7 +139,8 @@ class Panel {
this.position_data.float_position[0] = position_before[0] + e2.clientX - e1.clientX;
this.position_data.float_position[1] = position_before[1] + e2.clientY - e1.clientY;
let threshold = -8;
let threshold = -5;
let center_x = this.position_data.float_position[0] + this.position_data.float_size[0]/2;
if (this.position_data.float_position[0] < threshold) {
let panels = [];
Interface.left_bar.childNodes.forEach(child => {
@ -148,7 +150,7 @@ class Panel {
})
let anchor = this.position_data.float_position[1];
anchor += this.node.clientHeight * ((this.position_data.float_position[1] + this.position_data.float_size[1]) / Interface.work_screen.clientHeight);
let index = Math.floor(Math.clamp(anchor / Interface.work_screen.clientHeight, 0, 1) * (panels.length+1));
let index = Math.floor(Math.clamp(anchor / Interface.work_screen.clientHeight, 0, 1) * (panels.length));
this.moveTo('left_bar', Panels[panels[Math.clamp(index, 0, panels.length-1)]], index < panels.length);
} else if (this.position_data.float_position[0] + Math.min(this.position_data.float_size[0], Interface.data.right_bar_width) > document.body.clientWidth - threshold) {
@ -160,13 +162,19 @@ class Panel {
})
let anchor = this.position_data.float_position[1];
anchor += this.node.clientHeight * ((this.position_data.float_position[1] + this.position_data.float_size[1]) / Interface.work_screen.clientHeight);
let index = Math.floor(Math.clamp(anchor / Interface.work_screen.clientHeight, 0, 1) * (panels.length+1));
let index = Math.floor(Math.clamp(anchor / Interface.work_screen.clientHeight, 0, 1) * (panels.length));
this.moveTo('right_bar', Panels[panels[Math.clamp(index, 0, panels.length-1)]], index < panels.length);
} else if (this.position_data.float_position[1] < threshold) {
} else if (
this.position_data.float_position[1] < threshold &&
center_x > Interface.left_bar_width && center_x < (Interface.work_screen.clientWidth - Interface.right_bar_width)
) {
if (this.slot == 'float') this.moveTo('top');
} else if (this.position_data.float_position[1] + Math.min(this.position_data.float_size[1], 200) > Interface.work_screen.clientHeight - threshold) {
} else if (
this.position_data.float_position[1] + Math.min(this.position_data.float_size[1], 200) > Interface.work_screen.clientHeight - threshold &&
center_x > Interface.left_bar_width && center_x < (Interface.work_screen.clientWidth - Interface.right_bar_width)
) {
if (this.slot == 'float') this.moveTo('bottom');
} else if (this.slot != 'float') {
@ -194,20 +202,47 @@ class Panel {
addEventListeners(document, 'mouseup touchend', stop);
})
} else {
let fold_button = Interface.createElement('div', {class: 'tool panel_control panel_folding_button'}, Blockbench.getIconNode('expand_more'))
this.handle.append(fold_button);
fold_button.addEventListener('click', (e) => {
this.fold();
})
} else {
let close_button = Interface.createElement('div', {class: 'tool panel_control'}, Blockbench.getIconNode('clear'))
this.handle.append(close_button);
close_button.addEventListener('click', (e) => {
Interface.PanelSelectorVue.select(null);
})
addEventListeners(this.handle.firstElementChild, 'mousedown touchstart', e1 => {
convertTouchEvent(e1);
let started = false;
let height_before = this.position_data.height;
let max = Blockbench.isLandscape ? window.innerWidth - 50 : Interface.work_screen.clientHeight;
let drag = e2 => {
convertTouchEvent(e2);
let diff = Blockbench.isLandscape ? e1.clientX - e2.clientX : e1.clientY - e2.clientY;
if (!started && Math.abs(diff) > 4) {
started = true;
}
if (!started) return;
this.position_data.height = Math.clamp(height_before + diff, 140, max);
this.update(true);
resizeWindow();
}
let stop = e2 => {
convertTouchEvent(e2);
this.update();
removeEventListeners(document, 'mousemove touchmove', drag);
removeEventListeners(document, 'mouseup touchend', stop);
}
addEventListeners(document, 'mousemove touchmove', drag);
addEventListeners(document, 'mouseup touchend', stop);
})
}
this.node.addEventListener('mousedown', event => {
setActivePanel(this.id);
@ -235,6 +270,9 @@ class Panel {
if (this.onFold) {
this.onFold();
}
if (this.slot == 'top' || this.slot == 'bottom') {
resizeWindow();
}
this.update();
return this;
}
@ -379,7 +417,7 @@ class Panel {
if (show) {
$(this.node).show()
if (this.slot == 'float') {
if (!dragging) {
if (!dragging && work_screen.clientWidth) {
this.position_data.float_position[0] = Math.clamp(this.position_data.float_position[0], 0, work_screen.clientWidth - this.width);
this.position_data.float_position[1] = Math.clamp(this.position_data.float_position[1], 0, work_screen.clientHeight - this.height);
this.position_data.float_size[0] = Math.clamp(this.position_data.float_size[0], 300, work_screen.clientWidth - this.position_data.float_position[0]);
@ -404,8 +442,17 @@ class Panel {
this.width = Interface.data.right_bar_width
}
if (this.slot == 'top' || this.slot == 'bottom') {
this.height = Math.clamp(this.position_data.height, 30, center_screen.clientHeight);
if (this.folded) this.height = this.handle.clientHeight;
if (Blockbench.isMobile && Blockbench.isLandscape) {
this.height = center_screen.clientHeight;
this.width = Math.clamp(this.position_data.height, 30, center_screen.clientWidth);
if (this.folded) this.width = 72;
} else {
this.height = Math.clamp(this.position_data.height, 30, center_screen.clientHeight);
if (this.folded) this.height = this.handle.clientHeight;
this.width = Interface.work_screen.clientWidth - Interface.left_bar_width - Interface.right_bar_width;
}
this.node.style.width = this.width + 'px';
this.node.style.height = this.height + 'px';
}
@ -490,3 +537,84 @@ function setActivePanel(panel) {
function saveSidebarOrder() {
localStorage.setItem('interface_data', JSON.stringify(Interface.data))
}
function setupMobilePanelSelector() {
if (Blockbench.isMobile) {
Interface.PanelSelectorVue = new Vue({
el: '#panel_selector_bar',
data: {
all_panels: Interface.Panels,
selected: null,
modifiers: Pressing.overrides
},
computed: {
},
methods: {
panels() {
let arr = [];
for (var id in this.all_panels) {
let panel = this.all_panels[id];
if (Condition(panel.condition) && Condition(panel.display_condition)) {
arr.push(panel);
}
}
return arr;
},
select(panel) {
this.selected = panel && panel.id;
if (panel) {
panel.moveTo('bottom');
} else {
let other_panel = Interface.getBottomPanel();
if (other_panel) {
$(other_panel.node).detach();
}
resizeWindow();
}
},
openKeyboardMenu(event) {
if (Menu.closed_in_this_click == 'mobile_keyboard') return;
let modifiers = ['ctrl', 'shift', 'alt'];
let menu = new Menu('mobile_keyboard', [
...modifiers.map(key => {
let name = tl(`keys.${key}`);
if (Interface.status_bar.vue.modifier_keys[key].length) {
name += ' (' + tl(Interface.status_bar.vue.modifier_keys[key].last()) + ')';
}
return {
name,
icon: Pressing.overrides[key] ? 'check_box' : 'check_box_outline_blank',
click() {
Pressing.overrides[key] = !Pressing.overrides[key]
}
}
}),
'_',
{icon: 'clear_all', name: 'menu.mobile_keyboard.disable_all', condition: () => {
let {length} = [Pressing.overrides.ctrl, Pressing.overrides.shift, Pressing.overrides.alt].filter(key => key);
return length;
}, click() {
Pressing.overrides.ctrl = false; Pressing.overrides.shift = false; Pressing.overrides.alt = false;
}},
])
menu.open(this.$refs.mobile_keyboard_menu)
},
Condition,
getIconNode: Blockbench.getIconNode
},
template: `
<div id="panel_selector_bar">
<div class="panel_selector" :class="{selected: selected == null}" @click="select(null)">
<div class="icon_wrapper"><i class="material-icons icon">3d_rotation</i></div>
</div>
<div class="panel_selector" :class="{selected: selected == panel.id}" v-for="panel in panels()" v-if="Condition(panel.condition)" @click="select(panel)">
<div class="icon_wrapper" v-html="getIconNode(panel.icon).outerHTML"></div>
</div>
<div id="mobile_keyboard_menu" @click="openKeyboardMenu($event)" ref="mobile_keyboard_menu" :class="{enabled: modifiers.ctrl || modifiers.shift || modifiers.alt}">
<i class="material-icons">keyboard</i>
</div>
</div>`
})
}
}

View File

@ -682,6 +682,7 @@ Interface.definePanels(function() {
new Panel('bone', {
icon: 'fas.fa-bone',
condition: !Blockbench.isMobile && {modes: ['animate']},
display_condition: () => UVEditor.getMappableElements().length,
selection_only: true,
default_position: {
slot: 'right_bar',

View File

@ -1511,6 +1511,7 @@ Interface.definePanels(function() {
new Panel('element', {
icon: 'fas.fa-cube',
condition: !Blockbench.isMobile && {modes: ['edit', 'pose']},
display_condition: () => Outliner.selected.length || Group.selected,
selection_only: true,
default_position: {
slot: 'right_bar',

View File

@ -616,7 +616,7 @@ BARS.defineActions(function() {
BarItems.load_plugin.toElement('#plugins_header_bar');
BarItems.load_plugin_from_url.toElement('#plugins_header_bar');
}
$('#plugin_list').css('max-height', limitNumber(window.innerHeight-300, 80, 600)+'px');
$('#plugin_list').css('max-height', limitNumber(window.innerHeight-226, 80, 800)+'px');
$('dialog#plugins #plugin_search_bar input').trigger('focus')
}
})

View File

@ -1671,6 +1671,7 @@ Interface.definePanels(function() {
icon: 'photo_size_select_large',
selection_only: true,
condition: {modes: ['edit', 'paint']},
display_condition: () => UVEditor.getMappableElements().length,
default_position: {
slot: 'left_bar',
float_position: [300, 0],
@ -1756,8 +1757,11 @@ Interface.definePanels(function() {
if (!this.$refs.viewport) return;
let old_size = this.width;
let size = Math.floor(Math.clamp(UVEditor.panel.width - 10, 64, 1e5));
let sidebar = Panels.uv.slot.includes('_bar');
this.width = size;
this.height = size * Math.clamp(this.project_resolution[1] / this.project_resolution[0], 0.5, 1);
this.height = sidebar
? size * Math.clamp(this.project_resolution[1] / this.project_resolution[0], 0.5, 1)
: Math.clamp(UVEditor.panel.height - UVEditor.panel.handle.clientHeight - 30 - (this.mode == 'uv' ? 30 : 0) - 8, 64, 1e5);
this.$refs.viewport.scrollLeft = Math.round(this.$refs.viewport.scrollLeft * (size / old_size));
this.$refs.viewport.scrollTop = Math.round(this.$refs.viewport.scrollTop * (size / old_size));

View File

@ -50,89 +50,3 @@ window.onbeforeunload = function() {
if (Project.EditSession) Project.EditSession.quit()
}
}
function setupMobilePanelSelector() {
if (Blockbench.isMobile) {
Interface.PanelSelectorVue = new Vue({
el: '#panel_selector_bar',
data: {
all_panels: Interface.Panels,
selected: null,
modifiers: Pressing.overrides
},
computed: {
panels() {
let arr = [];
arr.push({
icon: '3d_rotation',
name: tl('data.preview'),
id: 'preview'
})
for (var id in this.all_panels) {
let panel = this.all_panels[id];
if (Condition(panel.condition)) {
arr.push(panel)
}
}
return arr;
}
},
methods: {
select(panel) {
this.selected = panel && panel.id;
let overlay = $('#mobile_panel_overlay');
$('#left_bar').append(overlay.children());
if (panel instanceof Panel) {
overlay.append(panel.node);
overlay.show();
panel.update();
} else {
overlay.hide();
}
},
openKeyboardMenu(event) {
if (Menu.closed_in_this_click == 'mobile_keyboard') return;
let modifiers = ['ctrl', 'shift', 'alt'];
let menu = new Menu('mobile_keyboard', [
...modifiers.map(key => {
let name = tl(`keys.${key}`);
if (Interface.status_bar.vue.modifier_keys[key].length) {
name += ' (' + tl(Interface.status_bar.vue.modifier_keys[key].last()) + ')';
}
return {
name,
icon: Pressing.overrides[key] ? 'check_box' : 'check_box_outline_blank',
click() {
Pressing.overrides[key] = !Pressing.overrides[key]
}
}
}),
'_',
{icon: 'clear_all', name: 'menu.mobile_keyboard.disable_all', condition: () => {
let {length} = [Pressing.overrides.ctrl, Pressing.overrides.shift, Pressing.overrides.alt].filter(key => key);
return length;
}, click() {
Pressing.overrides.ctrl = false; Pressing.overrides.shift = false; Pressing.overrides.alt = false;
}},
])
menu.open(this.$refs.mobile_keyboard_menu)
},
Condition,
getIconNode: Blockbench.getIconNode
},
template: `
<div id="panel_selector_bar">
<div class="panel_selector" :class="{selected: selected == null}" @click="select(null)">
<div class="icon_wrapper"><i class="material-icons icon">3d_rotation</i></div>
</div>
<div class="panel_selector" :class="{selected: selected == panel.id}" v-for="panel in all_panels" v-if="Condition(panel.condition)" @click="select(panel)">
<div class="icon_wrapper" v-html="getIconNode(panel.icon).outerHTML"></div>
</div>
<div id="mobile_keyboard_menu" @click="openKeyboardMenu($event)" ref="mobile_keyboard_menu" :class="{enabled: modifiers.ctrl || modifiers.shift || modifiers.alt}">
<i class="material-icons">keyboard</i>
</div>
</div>`
})
}
}

View File

@ -25,5 +25,5 @@
"theme_color": "#3e90ff",
"display": "standalone",
"display_override": ["tabbed", "minimal-ui"],
"orientation": "portrait-primary"
"orientation": "any"
}