mirror of
https://github.com/JannisX11/blockbench.git
synced 2025-04-06 17:31:09 +08:00
Implement mobile split screen view
Improve panel handling Allow landscape mode on mobile
This commit is contained in:
parent
4c0de4d7f1
commit
26fe5c40b0
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
|
@ -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',
|
||||
|
@ -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;
|
||||
|
@ -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') {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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>`
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -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',
|
||||
|
@ -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',
|
||||
|
@ -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')
|
||||
}
|
||||
})
|
||||
|
@ -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));
|
||||
|
||||
|
86
js/web.js
86
js/web.js
@ -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>`
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -25,5 +25,5 @@
|
||||
"theme_color": "#3e90ff",
|
||||
"display": "standalone",
|
||||
"display_override": ["tabbed", "minimal-ui"],
|
||||
"orientation": "portrait-primary"
|
||||
"orientation": "any"
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user