Redo outliner dragging + sorting

This commit is contained in:
JannisX11 2021-01-30 22:30:34 +01:00
parent 651f42527b
commit 971327c5ff
13 changed files with 198 additions and 103 deletions

View File

@ -151,10 +151,10 @@
.outliner_object:hover {
color: var(--color-light);
}
#cubes_list.drag_hover > .vue-tree {
#cubes_list.drag_hover > li:last-child {
position: relative;
}
#cubes_list.drag_hover > .vue-tree > ul::before {
#cubes_list.drag_hover > li:last-child::after {
content: '';
width: calc(100% - 12px);
height: 2px;
@ -205,9 +205,20 @@
border-bottom-right-radius: 4px;
}
/*Cancel Dragover for main list*/
#cubes_list > div > ul > li.outliner_node.parent_li {
border: none !important;
#outliner_drag_helper {
position: absolute;
width: auto;
min-width: 150px;
height: 28px;
pointer-events: none;
background-color: var(--color-selected);
box-shadow: 0 0.4px 3.5px rgba(0, 0, 0, 0.6);
display: flex;
padding: 2px 15px 2px 8px;
z-index: 18;
}
#outliner_drag_helper > i {
padding: 4px;
}
.outliner_object > input {
width: 0;
@ -253,15 +264,6 @@
.outliner_object i.ec_7 {
color: #BDFFA6; /*lime*/
}
body > .outliner_object {
width: 180px;
padding-left: 0 !important;
background-color: var(--color-selected);
box-shadow: 0 0.4px 3.5px rgba(0, 0, 0, 0.6);
}
body > .outliner_object .outliner_toggle {
display: none;
}
div#outliner_stats {
float: right;
margin-right: 16px;

View File

@ -349,7 +349,7 @@
div#mobile_panel_overlay {
position: absolute;
z-index: 19;
z-index: 12;
top: 0;
left: 0;
right: 40px;
@ -566,7 +566,7 @@
}
@media (max-device-width: 640px) {
#start_screen {
width: calc(100% - 40px);
width: 100%;
}
#start_screen > content {
margin-top: 0px;

View File

@ -159,11 +159,11 @@ function selectAll() {
if (Modes.animate) {
selectAllKeyframes()
} else if (Modes.edit || Modes.paint) {
if (selected.length < elements.length) {
if (Outliner.selected.length < Outliner.elements.length) {
if (Outliner.root.length == 1) {
Outliner.root[0].select();
} else {
elements.forEach(obj => {
Outliner.elements.forEach(obj => {
obj.selectLow()
})
TickUpdates.selection = true;
@ -197,10 +197,6 @@ setInterval(function() {
const TickUpdates = {
Run() {
try {
if (TickUpdates.outliner) {
delete TickUpdates.outliner;
loadOutlinerDraggable()
}
if (TickUpdates.selection) {
delete TickUpdates.selection;
updateSelection()

View File

@ -257,14 +257,9 @@ function setupInterface() {
//Clickbinds
$('header' ).click( function() { setActivePanel('header' )})
$('#preview' ).click(function() { setActivePanel('preview' )})
$('header' ).click(function() { setActivePanel('header' )})
$('#preview').click(function() { setActivePanel('preview' )})
$('ul#cubes_list').click(function(event) {
if (event.target === document.getElementById('cubes_list')) {
unselectAll()
}
})
$('#texture_list').click(function(){
unselectTextures()
})

View File

@ -199,7 +199,6 @@ var codec = new Codec('project', {
copy.init()
})
loadOutlinerDraggable()
}
if (model.outliner) {
if (compareVersions('3.2', model.meta.format_version)) {

View File

@ -250,7 +250,6 @@ var codec = new Codec('optifine_entity', {
readContent(b, group, 0)
})
}
loadOutlinerDraggable()
if (model.texture) {
var path = path.replace(/\\[\w .-]+$/, '\\'+model.texture)
new Texture().fromPath(path).add(false)

View File

@ -222,7 +222,6 @@ class Cube extends NonGroup {
if (!this.mesh || !this.mesh.parent) {
Canvas.addCube(this)
}
TickUpdates.outliner = true;
return this;
}
size(axis, floored) {
@ -851,7 +850,6 @@ BARS.defineActions(function() {
if (Group.selected) Group.selected.unselect()
base_cube.select()
Canvas.updateSelected()
loadOutlinerDraggable()
Undo.finishEdit('add_cube', {outliner: true, elements: selected, selection: true});
Blockbench.dispatchEvent( 'add_cube', {object: base_cube} )

View File

@ -270,7 +270,6 @@ class Group extends OutlinerElement {
}
this.remove(false);
Undo.finishEdit('resolve group')
TickUpdates.outliner = true;
return array;
}
showContextMenu(event) {
@ -338,8 +337,7 @@ class Group extends OutlinerElement {
child.duplicate().addTo(copy)
}
copy.isOpen = true;
Canvas.updatePositions()
TickUpdates.outliner = true;
Canvas.updatePositions();
return copy;
}
getSaveCopy() {
@ -536,7 +534,6 @@ BARS.defineActions(function() {
}
base_group.init().select()
Undo.finishEdit('add_group');
loadOutlinerDraggable()
Vue.nextTick(function() {
updateSelection()
if (settings.create_rename.value) {

View File

@ -43,7 +43,6 @@ class Locator extends NonGroup {
this.addTo(Group.selected)
}
super.init();
TickUpdates.outliner = true;
return this;
}
flip(axis, center) {

View File

@ -43,7 +43,6 @@ class NullObject extends NonGroup {
this.addTo(Group.selected)
}
super.init();
TickUpdates.outliner = true;
return this;
}
flip(axis, center) {

View File

@ -115,13 +115,11 @@ class OutlinerElement {
else {
arr.splice(index+index_mod, 0, this)
}
TickUpdates.outliner = true;
return this;
}
addTo(group, index = -1) {
//Resolve Group Argument
if (group === undefined) {
if (!group) {
group = 'root'
} else if (group !== 'root') {
if (group.type !== 'group') {
@ -153,8 +151,6 @@ class OutlinerElement {
arr.splice(index, 0, this)
}
//Loading
TickUpdates.outliner = true;
return this;
}
removeFromParent() {
@ -415,7 +411,6 @@ class NonGroup extends OutlinerElement {
if (Condition(copy.needsUniqueName)) {
copy.createUniqueName()
}
TickUpdates.outliner = true;
TickUpdates.selection = true;
return copy;
}
@ -646,6 +641,7 @@ function parseGroups(array, importGroup, startIndex) {
}
//Outliner
function loadOutlinerDraggable() {
return;
function getOrder(loc, obj) {
if (!obj) {
return;
@ -659,45 +655,6 @@ function loadOutlinerDraggable() {
return 0;
}
Vue.nextTick(function() {
$('li.outliner_node:not(.ui-droppable) > div.outliner_object').draggable({
delay: 120,
revertDuration: 50,
revert: 'invalid',
appendTo: 'body',
zIndex: 19,
cursorAt: {left: 5},
start(event, ui) {
if (event.target && event.target.parentNode) {
var element = Outliner.root.findRecursive('uuid', event.target.parentNode.id)
if (!element || element.locked) return false;
}
},
helper: function() {
var item = Outliner.root.findRecursive('uuid', $(this).attr('id'))
var helper = $(this).clone()
if (selected.length > 1) {
helper.append('<div class="outliner_drag_number">'+selected.length+'</div>')
}
helper.addClass('')
helper.on('mousewheel', function() {
var delta = event.deltaY * 1 + $('#cubes_list').scrollTop()
$('#cubes_list').animate({scrollTop: delta}, 10);
})
return helper;
},
drag: function(event, ui) {
$('.outliner_node[order]').attr('order', null)
if ($('#cubes_list.drag_hover').length === 0) {
var tar = $('#cubes_list li .drag_hover.outliner_node').last()
var element = Outliner.root.findRecursive('uuid', tar.attr('id'))
if (element) {
var location = event.clientY - tar.offset().top
var order = getOrder(location, element)
tar.attr('order', order)
}
}
}
})
$('li.outliner_node:not(.ui-droppable)').droppable({
greedy: true,
accept: function(s) {
@ -813,7 +770,6 @@ function dropOutlinerObjects(item, target, event, order) {
}
}
})
loadOutlinerDraggable()
if (Format.bone_rig) {
Canvas.updateAllBones()
}
@ -1170,6 +1126,31 @@ Interface.definePanels(function() {
});
Vue.component('vue-tree-item', VueTreeItem);
function eventTargetToNode(target) {
let target_node = target;
let i = 0;
while (target_node && target_node.classList && !target_node.classList.contains('outliner_node')) {
if (i < 4 && target_node) {
target_node = target_node.parentNode;
i++;
} else {
return [];
}
}
return [OutlinerElement.uuids[target_node.id], target_node];
}
function getOrder(loc, obj) {
if (!obj) {
return;
} else if (obj instanceof Group) {
if (loc < 8) return -1;
if (loc > 24) return 1;
} else {
if (loc < 16) return -1;
return 1;
}
return 0;
}
Interface.Panels.outliner = new Panel({
id: 'outliner',
@ -1191,12 +1172,123 @@ Interface.definePanels(function() {
methods: {
openMenu(event) {
Interface.Panels.outliner.menu.show(event)
},
dragNode(e1) {
convertTouchEvent(e1);
let scope = this;
let [item] = eventTargetToNode(e1.target);
if (!item || item.locked) {
function off(e2) {
removeEventListeners(document, 'mouseup touchend', off);
if (e2.target && e2.target.id == 'cubes_list') unselectAll();
}
addEventListeners(document, 'mouseup touchend', off);
return;
};
let active = false;
let helper;
let timeout;
let drop_target, drop_target_node, order;
let last_event = e1;
function move(e2) {
convertTouchEvent(e2);
let offset = [
e2.clientX - e1.clientX,
e2.clientY - e1.clientY,
]
if (!active) {
let distance = Math.sqrt(Math.pow(offset[0], 2) + Math.pow(offset[1], 2))
if (Blockbench.isTouch) {
if (distance > 20 && timeout) {
clearTimeout(timeout);
timeout = null;
} else {
document.getElementById('cubes_list').scrollTop += last_event.clientY - e2.clientY;
}
} else if (distance > 6) {
active = true;
}
} else {
if (e2) e2.preventDefault();
if (!helper) {
helper = document.createElement('div');
helper.id = 'outliner_drag_helper';
let icon = document.createElement('i'); icon.className = item.icon; helper.append(icon);
let span = document.createElement('span'); span.innerText = item.name; helper.append(span);
if (item instanceof Group == false && Outliner.selected.length > 1) {
let counter = document.createElement('div');
counter.classList.add('outliner_drag_number');
counter.textContent = Outliner.selected.length.toString();
helper.append(counter);
}
document.body.append(helper);
}
helper.style.left = `${e2.clientX}px`;
helper.style.top = `${e2.clientY}px`;
// drag
$('.drag_hover').removeClass('drag_hover');
$('.outliner_node[order]').attr('order', null);
let target = document.elementFromPoint(e2.clientX, e2.clientY);
[drop_target, drop_target_node] = eventTargetToNode(target);
if (drop_target) {
var location = e2.clientY - $(drop_target_node).offset().top;
order = getOrder(location, drop_target)
drop_target_node.setAttribute('order', order)
drop_target_node.classList.add('drag_hover');
} else if ($('#cubes_list').is(':hover')) {
$('#cubes_list').addClass('drag_hover');
}
}
last_event = e2;
}
function off(e2) {
if (helper) helper.remove();
removeEventListeners(document, 'mousemove touchmove', move);
removeEventListeners(document, 'mouseup touchend', off);
$('.drag_hover').removeClass('drag_hover');
$('.outliner_node[order]').attr('order', null);
if (Blockbench.isTouch) clearTimeout(timeout);
if (active) {
convertTouchEvent(e2);
let target = document.elementFromPoint(e2.clientX, e2.clientY);
[drop_target] = eventTargetToNode(target);
if (drop_target) {
dropOutlinerObjects(item, drop_target, e2, order);
} else if ($('#cubes_list').is(':hover')) {
dropOutlinerObjects(item, undefined, e2);
}
}
}
if (Blockbench.isTouch) {
timeout = setTimeout(() => {
active = true;
move(e1);
}, 400)
}
addEventListeners(document, 'mousemove touchmove', move, {passive: false});
addEventListeners(document, 'mouseup touchend', off, {passive: false});
}
},
template: `
<div>
<div class="toolbar_wrapper outliner"></div>
<ul id="cubes_list" class="list mobile_scrollbar" @contextmenu.stop.prevent="openMenu($event)">
<ul id="cubes_list"
class="list mobile_scrollbar"
@contextmenu.stop.prevent="openMenu($event)"
@mousedown="dragNode($event)"
@touchstart="dragNode($event)"
>
<vue-tree-item v-for="item in root" :node="item" :show_advanced_toggles="show_advanced_toggles" v-key="item.uuid"></vue-tree-item>
</ul>
</div>
@ -1214,15 +1306,4 @@ Interface.definePanels(function() {
])
})
Outliner.vue = Interface.Panels.outliner.inside_vue;
$('#cubes_list').droppable({
greedy: true,
accept: 'div.outliner_object',
tolerance: 'pointer',
hoverClass: 'drag_hover',
drop: function(event, ui) {
var item = Outliner.root.findRecursive('uuid', $(ui.draggable).parent().attr('id'))
dropOutlinerObjects(item, undefined, event)
}
})
})

View File

@ -1070,14 +1070,17 @@ function loadTextureDraggable() {
},
drag: function(event, ui) {
$('.outliner_node[order]').attr('order', null)
$('.outliner_node[order]').attr('order', null);
$('.drag_hover').removeClass('drag_hover');
$('.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()
if ($('#cubes_list li.outliner_node:hover').length) {
var tar = $('#cubes_list li.outliner_node:hover').last()
tar.addClass('drag_hover').attr('order', '0');
/*
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) {
@ -1094,7 +1097,8 @@ function loadTextureDraggable() {
},
stop: function(event, ui) {
setTimeout(function() {
$('.texture[order]').attr('order', null)
$('.texture[order]').attr('order', null);
$('.outliner_node[order]').attr('order', null);
var tex = textures.findInArray('uuid', ui.helper.attr('texid'));
if (!tex) return;
if ($('.preview:hover').length > 0) {
@ -1127,6 +1131,33 @@ function loadTextureDraggable() {
Texture.all.splice(index, 0, tex)
Canvas.updateLayeredTextures()
Undo.finishEdit('reorder textures')
} else if ($('#cubes_list:hover')) {
var target_node = $('#cubes_list li.outliner_node.drag_hover').last().get(0);
$('.drag_hover').removeClass('drag_hover');
if (!target_node) return;
let uuid = target_node.id;
var target = OutlinerElement.uuids[uuid];
var array = [];
if (target.type === 'group') {
target.forEachChild(function(cube) {
array.push(cube)
}, Cube)
} else {
array = selected.includes(target) ? selected : [target];
}
Undo.initEdit({elements: array, uv_only: true})
array.forEach(function(cube) {
for (var face in cube.faces) {
cube.faces[face].texture = tex.uuid;
}
})
Undo.finishEdit('drop texture')
main_uv.loadData()
Canvas.updateAllFaces()
}
}, 10)
}

View File

@ -252,7 +252,6 @@ var Undo = {
}
}
}
loadOutlinerDraggable()
Canvas.updateVisibility()
}