mirror of
https://github.com/JannisX11/blockbench.git
synced 2024-11-27 04:21:46 +08:00
Merge branch 'face-selection' into next
This commit is contained in:
commit
d005c7661c
@ -1700,31 +1700,30 @@ const BARS = {
|
||||
icon: 'delete',
|
||||
category: 'edit',
|
||||
keybind: new Keybind({key: 46}),
|
||||
click: function () {
|
||||
click() {
|
||||
let mesh_selection = Project.mesh_selection[Mesh.selected[0].uuid];
|
||||
if (Prop.active_panel == 'textures' && Texture.selected) {
|
||||
Texture.selected.remove()
|
||||
} else if (Prop.active_panel == 'color' && ['palette', 'both'].includes(ColorPanel.vue._data.open_tab)) {
|
||||
if (ColorPanel.vue._data.palette.includes(ColorPanel.vue._data.main_color)) {
|
||||
ColorPanel.vue._data.palette.remove(ColorPanel.vue._data.main_color)
|
||||
}
|
||||
} else if (Modes.edit && Mesh.selected.length && Project.selected_vertices[Mesh.selected[0].uuid] && Project.selected_vertices[Mesh.selected[0].uuid].length < Mesh.selected[0].vertice_list.length) {
|
||||
} else if (Modes.edit && Mesh.selected.length && mesh_selection) {
|
||||
|
||||
Undo.initEdit({elements: Mesh.selected})
|
||||
|
||||
Mesh.selected.forEach(mesh => {
|
||||
let has_selected_faces = false;
|
||||
let selected_vertices = mesh.getSelectedVertices();
|
||||
for (let key in mesh.faces) {
|
||||
has_selected_faces = has_selected_faces || mesh.faces[key].isSelected();
|
||||
}
|
||||
if (BarItems.selection_mode.value == 'face' && has_selected_faces) {
|
||||
for (let key in mesh.faces) {
|
||||
let face = mesh.faces[key];
|
||||
if (face.isSelected()) {
|
||||
delete mesh.faces[key];
|
||||
}
|
||||
}
|
||||
selected_vertices.forEach(vertex_key => {
|
||||
let selected_edges = mesh.getSelectedEdges();
|
||||
let selected_faces = mesh.getSelectedFaces();
|
||||
|
||||
if (BarItems.selection_mode.value == 'face' && selected_faces.length < Object.keys(mesh.faces).length) {
|
||||
let affected_vertices = [];
|
||||
selected_faces.forEach(fkey => {
|
||||
affected_vertices.safePush(...mesh.faces[fkey].vertices);
|
||||
delete mesh.faces[fkey];
|
||||
})
|
||||
affected_vertices.forEach(vertex_key => {
|
||||
let used = false;
|
||||
for (let key in mesh.faces) {
|
||||
let face = mesh.faces[key];
|
||||
@ -1734,31 +1733,35 @@ const BARS = {
|
||||
delete mesh.vertices[vertex_key];
|
||||
}
|
||||
})
|
||||
} else if (BarItems.selection_mode.value == 'edge' && selected_vertices.length) {
|
||||
} else if (BarItems.selection_mode.value == 'edge') {
|
||||
for (let key in mesh.faces) {
|
||||
let face = mesh.faces[key];
|
||||
let sorted_vertices = face.getSortedVertices();
|
||||
let selected_corners = sorted_vertices.filter(vkey => selected_vertices.includes(vkey));
|
||||
if (selected_corners.length >= 2) {
|
||||
let index_diff = (sorted_vertices.indexOf(selected_corners[0]) - sorted_vertices.indexOf(selected_corners[1])) % sorted_vertices.length;
|
||||
if ((sorted_vertices.length < 4 || Math.abs(index_diff) !== 2)) {
|
||||
delete mesh.faces[key];
|
||||
}
|
||||
let has_edge = sorted_vertices.find((vkey_a, i) => {
|
||||
let vkey_b = sorted_vertices[i+1] || sorted_vertices[0];
|
||||
let edge = [vkey_a, vkey_b];
|
||||
return selected_edges.find(edge2 => sameMeshEdge(edge, edge2))
|
||||
})
|
||||
if (has_edge) {
|
||||
delete mesh.faces[key];
|
||||
}
|
||||
}
|
||||
selected_vertices.forEach(vertex_key => {
|
||||
let used = false;
|
||||
for (let key in mesh.faces) {
|
||||
let face = mesh.faces[key];
|
||||
if (face.vertices.includes(vertex_key)) used = true;
|
||||
}
|
||||
if (!used) {
|
||||
delete mesh.vertices[vertex_key];
|
||||
}
|
||||
selected_edges.forEachReverse(edge => {
|
||||
edge.forEach(vkey => {
|
||||
let used = false;
|
||||
for (let key in mesh.faces) {
|
||||
let face = mesh.faces[key];
|
||||
if (face.vertices.includes(vkey)) used = true;
|
||||
}
|
||||
if (!used) {
|
||||
delete mesh.vertices[vkey];
|
||||
selected_vertices.remove(vkey);
|
||||
selected_edges.remove(edge);
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
} else {
|
||||
let selected_vertices = Project.selected_vertices[mesh.uuid];
|
||||
} else if (BarItems.selection_mode.value == 'vertex' && selected_vertices.length < Object.keys(mesh.vertices).length) {
|
||||
selected_vertices.forEach(vertex_key => {
|
||||
delete mesh.vertices[vertex_key];
|
||||
|
||||
@ -1782,6 +1785,9 @@ const BARS = {
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
Mesh.selected.remove(mesh);
|
||||
mesh.remove(false);
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -147,7 +147,7 @@ var codec = new Codec('project', {
|
||||
|
||||
selected_elements: Project.selected_elements.map(e => e.uuid),
|
||||
selected_group: Project.selected_group?.uuid,
|
||||
selected_vertices: JSON.parse(JSON.stringify(Project.selected_vertices)),
|
||||
mesh_selection: JSON.parse(JSON.stringify(Project.mesh_selection)),
|
||||
selected_faces: Project.selected_faces,
|
||||
selected_texture: Project.selected_texture?.uuid,
|
||||
};
|
||||
@ -399,7 +399,7 @@ var codec = new Codec('project', {
|
||||
})
|
||||
Group.selected = (state.selected_group && Group.all.find(g => g.uuid == state.selected_group));
|
||||
for (let key in state.selected_vertices) {
|
||||
Project.selected_vertices[key] = state.selected_vertices[key];
|
||||
Project.mesh_selection[key] = state.mesh_selection[key];
|
||||
}
|
||||
Project.selected_faces.replace(state.selected_faces);
|
||||
(state.selected_texture && Texture.all.find(t => t.uuid == state.selected_texture))?.select();
|
||||
|
@ -48,7 +48,7 @@ class ModelProject {
|
||||
this.groups = [];
|
||||
this.selected_elements = [];
|
||||
this.selected_group = null;
|
||||
this.selected_vertices = {};
|
||||
this.mesh_selection = {};
|
||||
this.selected_faces = [];
|
||||
this.textures = [];
|
||||
this.selected_texture = null;
|
||||
@ -179,10 +179,13 @@ class ModelProject {
|
||||
|
||||
UVEditor.vue.elements = this.selected_elements;
|
||||
UVEditor.vue.all_elements = this.elements;
|
||||
UVEditor.vue.selected_vertices = this.selected_vertices;
|
||||
UVEditor.vue.selected_vertices = {};
|
||||
UVEditor.vue.selected_faces = this.selected_faces;
|
||||
UVEditor.vue.box_uv = this.box_uv;
|
||||
UVEditor.vue.display_uv = this.display_uv;
|
||||
for (let uuid in this.mesh_selection) {
|
||||
UVEditor.vue.selected_vertices[uuid] = this.mesh_selection[uuid].vertices;
|
||||
}
|
||||
|
||||
Interface.Panels.textures.inside_vue.textures = Texture.all;
|
||||
scene.add(this.model_3d);
|
||||
|
30
js/misc.js
30
js/misc.js
@ -102,15 +102,25 @@ function updateSelection(options = {}) {
|
||||
obj.unselect()
|
||||
}
|
||||
if (obj instanceof Mesh) {
|
||||
if (Project.selected_vertices[obj.uuid]) {
|
||||
Project.selected_vertices[obj.uuid].forEachReverse(vkey => {
|
||||
if (Project.mesh_selection[obj.uuid]) {
|
||||
Project.mesh_selection[obj.uuid].vertices.forEachReverse(vkey => {
|
||||
if (vkey in obj.vertices == false) {
|
||||
Project.selected_vertices[obj.uuid].remove(vkey);
|
||||
Project.mesh_selection[obj.uuid].vertices.remove(vkey);
|
||||
}
|
||||
})
|
||||
Project.mesh_selection[obj.uuid].edges.forEachReverse(edge => {
|
||||
if (!obj.vertices[edge[0]] || !obj.vertices[edge[1]]) {
|
||||
Project.mesh_selection[obj.uuid].edges.remove(edge);
|
||||
}
|
||||
})
|
||||
Project.mesh_selection[obj.uuid].faces.forEachReverse(fkey => {
|
||||
if (fkey in obj.faces == false) {
|
||||
Project.mesh_selection[obj.uuid].faces.remove(fkey);
|
||||
}
|
||||
})
|
||||
}
|
||||
if (Project.selected_vertices[obj.uuid] && (Project.selected_vertices[obj.uuid].length == 0 || !obj.selected)) {
|
||||
delete Project.selected_vertices[obj.uuid];
|
||||
if (Project.mesh_selection[obj.uuid] && (Project.mesh_selection[obj.uuid].vertices.length == 0 || !obj.selected)) {
|
||||
delete Project.mesh_selection[obj.uuid];
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -184,13 +194,13 @@ function updateSelection(options = {}) {
|
||||
if (settings.highlight_cubes.value || (Mesh.all[0])) updateCubeHighlights();
|
||||
if (Toolbox.selected.id == 'seam_tool' && Mesh.selected[0]) {
|
||||
let value;
|
||||
let selected_vertices = Mesh.selected[0].getSelectedVertices();
|
||||
let selected_edges = Mesh.selected[0].getSelectedEdges();
|
||||
Mesh.selected[0].forAllFaces((face) => {
|
||||
if (value == '') return;
|
||||
let vertices = face.getSortedVertices();
|
||||
vertices.forEach((vkey_a, i) => {
|
||||
let vkey_b = vertices[i+1] || vertices[0];
|
||||
if (selected_vertices.includes(vkey_a) && selected_vertices.includes(vkey_b)) {
|
||||
if (selected_edges.find(edge => sameMeshEdge(edge, [vkey_a, vkey_b]))) {
|
||||
let seam = Mesh.selected[0].getSeam([vkey_a, vkey_b]) || 'auto';
|
||||
if (value == undefined) {
|
||||
value = seam;
|
||||
@ -223,7 +233,7 @@ function selectAll() {
|
||||
let unselect = Mesh.selected[0].getSelectedVertices().length == Object.keys(Mesh.selected[0].vertices).length;
|
||||
Mesh.selected.forEach(mesh => {
|
||||
if (unselect) {
|
||||
delete Project.selected_vertices[mesh.uuid];
|
||||
delete Project.mesh_selection[mesh.uuid];
|
||||
} else {
|
||||
mesh.getSelectedVertices(true).replace(Object.keys(mesh.vertices));
|
||||
}
|
||||
@ -253,8 +263,8 @@ function unselectAll() {
|
||||
Group.all.forEach(function(s) {
|
||||
s.selected = false
|
||||
})
|
||||
for (let key in Project.selected_vertices) {
|
||||
delete Project.selected_vertices[key];
|
||||
for (let key in Project.mesh_selection) {
|
||||
delete Project.mesh_selection[key];
|
||||
}
|
||||
TickUpdates.selection = true;
|
||||
}
|
||||
|
@ -1,3 +1,7 @@
|
||||
function sameMeshEdge(edge_a, edge_b) {
|
||||
return edge_a.equals(edge_b) || (edge_a[0] == edge_b[1] && edge_a[1] == edge_b[0])
|
||||
}
|
||||
|
||||
BARS.defineActions(function() {
|
||||
let add_mesh_dialog = new Dialog({
|
||||
id: 'add_primitive',
|
||||
@ -319,7 +323,7 @@ BARS.defineActions(function() {
|
||||
onChange({value}) {
|
||||
if (value === 'object') {
|
||||
Mesh.selected.forEach(mesh => {
|
||||
delete Project.selected_vertices[mesh.uuid];
|
||||
delete Project.mesh_selection[mesh.uuid];
|
||||
})
|
||||
} else if (value === 'face') {
|
||||
UVEditor.vue.selected_faces.empty();
|
||||
@ -653,19 +657,16 @@ BARS.defineActions(function() {
|
||||
Undo.initEdit({elements: Mesh.selected, selection: true}, amended);
|
||||
|
||||
Mesh.selected.forEach(mesh => {
|
||||
let original_vertices = Project.selected_vertices[mesh.uuid].slice();
|
||||
let original_vertices = mesh.getSelectedVertices().slice();
|
||||
let new_vertices;
|
||||
let new_face_keys = [];
|
||||
let selected_faces = [];
|
||||
let selected_face_keys = [];
|
||||
let selected_face_keys = mesh.getSelectedFaces();
|
||||
let selected_faces = selected_face_keys.map(fkey => mesh.faces[fkey]);
|
||||
let combined_direction;
|
||||
for (let fkey in mesh.faces) {
|
||||
let face = mesh.faces[fkey];
|
||||
if (face.isSelected()) {
|
||||
selected_faces.push(face);
|
||||
selected_face_keys.push(fkey);
|
||||
}
|
||||
}
|
||||
|
||||
selected_faces.forEach(face => {
|
||||
original_vertices.safePush(...face.vertices);
|
||||
})
|
||||
|
||||
if (original_vertices.length >= 3 && !selected_faces.length) {
|
||||
let [a, b, c] = original_vertices.slice(0, 3).map(vkey => mesh.vertices[vkey].slice());
|
||||
@ -738,7 +739,7 @@ BARS.defineActions(function() {
|
||||
vector.V3_add(direction.map(v => v * extend));
|
||||
return vector;
|
||||
}))
|
||||
Project.selected_vertices[mesh.uuid].replace(new_vertices);
|
||||
Project.mesh_selection[mesh.uuid].vertices.replace(new_vertices);
|
||||
|
||||
// Move Faces
|
||||
selected_faces.forEach(face => {
|
||||
@ -850,7 +851,7 @@ BARS.defineActions(function() {
|
||||
function runEdit(amended, offset = 50) {
|
||||
Undo.initEdit({elements: Mesh.selected, selection: true}, amended);
|
||||
Mesh.selected.forEach(mesh => {
|
||||
let original_vertices = Project.selected_vertices[mesh.uuid].slice();
|
||||
let original_vertices = mesh.getSelectedVertices();
|
||||
if (original_vertices.length < 3) return;
|
||||
let new_vertices;
|
||||
let selected_faces = [];
|
||||
@ -897,7 +898,7 @@ BARS.defineActions(function() {
|
||||
}).filter(vec => vec instanceof Array))
|
||||
if (!new_vertices.length) return;
|
||||
|
||||
Project.selected_vertices[mesh.uuid].replace(new_vertices);
|
||||
Project.mesh_selection[mesh.uuid].vertices.replace(new_vertices);
|
||||
|
||||
// Move Faces
|
||||
selected_faces.forEach(face => {
|
||||
@ -1461,6 +1462,7 @@ BARS.defineActions(function() {
|
||||
Mesh.selected.forEach(mesh => {
|
||||
|
||||
let selected_vertices = mesh.getSelectedVertices();
|
||||
let mesh_selection = Project.mesh_selection[mesh.uuid];
|
||||
|
||||
let copy = new Mesh(mesh);
|
||||
elements.push(copy);
|
||||
@ -1497,8 +1499,8 @@ BARS.defineActions(function() {
|
||||
|
||||
copy.name += '_selection'
|
||||
copy.sortInBefore(mesh, 1).init();
|
||||
delete Project.selected_vertices[mesh.uuid];
|
||||
Project.selected_vertices[copy.uuid] = selected_vertices;
|
||||
delete Project.mesh_selection[mesh.uuid];
|
||||
Project.mesh_selection[copy.uuid] = mesh_selection;
|
||||
mesh.preview_controller.updateGeometry(mesh);
|
||||
selected[selected.indexOf(mesh)] = copy;
|
||||
})
|
||||
|
@ -347,12 +347,10 @@ const Vertexsnap = {
|
||||
Vertexsnap.elements = Outliner.selected.slice();
|
||||
Vertexsnap.group = Group.selected;
|
||||
if (data.element instanceof Mesh && BarItems.selection_mode.value == 'vertex') {
|
||||
if (!Project.selected_vertices[data.element.uuid]) {
|
||||
Project.selected_vertices[data.element.uuid] = [];
|
||||
}
|
||||
Project.selected_vertices[data.element.uuid].safePush(data.vertex);
|
||||
let vertices = data.element.getSelectedVertices(true);
|
||||
vertices.safePush(data.vertex);
|
||||
}
|
||||
Vertexsnap.selected_vertices = JSON.parse(JSON.stringify(Project.selected_vertices));
|
||||
Vertexsnap.selected_vertices = JSON.parse(JSON.stringify(Project.mesh_selection));
|
||||
Vertexsnap.clearVertexGizmos()
|
||||
$('#preview').css('cursor', (Vertexsnap.step1 ? 'copy' : 'alias'))
|
||||
|
||||
@ -441,7 +439,7 @@ const Vertexsnap = {
|
||||
var cube_pos = new THREE.Vector3().copy(global_delta)
|
||||
|
||||
if (obj instanceof Mesh && Vertexsnap.selected_vertices && Vertexsnap.selected_vertices[obj.uuid]) {
|
||||
let vertices = Vertexsnap.selected_vertices[obj.uuid];
|
||||
let vertices = Vertexsnap.selected_vertices[obj.uuid].vertices;
|
||||
var q = obj.mesh.getWorldQuaternion(Reusable.quat1).invert();
|
||||
cube_pos.applyQuaternion(q);
|
||||
let cube_pos_array = cube_pos.toArray();
|
||||
@ -954,7 +952,7 @@ function rotateOnAxis(modify, axis, slider) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!Group.selected && obj instanceof Mesh && Project.selected_vertices[obj.uuid] && Project.selected_vertices[obj.uuid].length > 0) {
|
||||
if (!Group.selected && obj instanceof Mesh && Project.mesh_selection[obj.uuid] && Project.mesh_selection[obj.uuid].vertices.length > 0) {
|
||||
|
||||
let normal = axis == 0 ? THREE.NormalX : (axis == 1 ? THREE.NormalY : THREE.NormalZ)
|
||||
let rotWorldMatrix = new THREE.Matrix4();
|
||||
@ -976,7 +974,7 @@ function rotateOnAxis(modify, axis, slider) {
|
||||
let vector = new THREE.Vector3();
|
||||
let local_pivot = obj.mesh.worldToLocal(new THREE.Vector3().copy(Transformer.position))
|
||||
|
||||
Project.selected_vertices[obj.uuid].forEach(key => {
|
||||
Project.mesh_selection[obj.uuid].vertices.forEach(key => {
|
||||
vector.fromArray(obj.vertices[key]);
|
||||
vector.sub(local_pivot);
|
||||
vector.applyQuaternion(q);
|
||||
|
@ -910,7 +910,13 @@
|
||||
|
||||
//Center
|
||||
if (Toolbox.selected.id === 'rotate_tool' || Toolbox.selected.id === 'pivot_tool') {
|
||||
if (rotation_object instanceof Mesh && Toolbox.selected.id === 'rotate_tool' && Project.selected_vertices[rotation_object.uuid] && Project.selected_vertices[rotation_object.uuid].length > 0) {
|
||||
if (rotation_object instanceof Mesh && Toolbox.selected.id === 'rotate_tool' &&
|
||||
Project.mesh_selection[rotation_object.uuid] && (
|
||||
Project.mesh_selection[rotation_object.uuid].vertices.length > 0 ||
|
||||
Project.mesh_selection[rotation_object.uuid].edges.length > 0 ||
|
||||
Project.mesh_selection[rotation_object.uuid].faces.length > 0
|
||||
)
|
||||
) {
|
||||
this.position.copy(rotation_object.getWorldCenter())
|
||||
} else if (rotation_object.mesh) {
|
||||
rotation_object.mesh.getWorldPosition(this.position);
|
||||
|
@ -161,10 +161,7 @@ class MeshFace extends Face {
|
||||
[this.vertices[0], this.vertices[1]] = [this.vertices[1], this.vertices[0]];
|
||||
}
|
||||
isSelected() {
|
||||
let selected_vertices = Project.selected_vertices[this.mesh.uuid];
|
||||
return selected_vertices
|
||||
&& selected_vertices.length > 1
|
||||
&& !this.vertices.find(key => !selected_vertices.includes(key))
|
||||
return !!Project.mesh_selection[this.mesh.uuid] && Project.mesh_selection[this.mesh.uuid].faces.includes(this.getFaceKey());
|
||||
}
|
||||
getSortedVertices() {
|
||||
if (this.vertices.length < 4) return this.vertices;
|
||||
@ -322,13 +319,13 @@ class Mesh extends OutlinerElement {
|
||||
let key = edge.slice(0, 2).sort().join('_');
|
||||
return this.seams[key];
|
||||
}
|
||||
getWorldCenter(ignore_selected_vertices) {
|
||||
getWorldCenter(ignore_mesh_selection) {
|
||||
let m = this.mesh;
|
||||
let pos = Reusable.vec1.set(0, 0, 0);
|
||||
let vertice_count = 0;
|
||||
|
||||
for (let key in this.vertices) {
|
||||
if (ignore_selected_vertices || !Project.selected_vertices[this.uuid] || (Project.selected_vertices[this.uuid] && Project.selected_vertices[this.uuid].includes(key))) {
|
||||
if (ignore_mesh_selection || !Project.mesh_selection[this.uuid] || (Project.mesh_selection[this.uuid] && Project.mesh_selection[this.uuid].vertices.includes(key))) {
|
||||
let vector = this.vertices[key];
|
||||
pos.x += vector[0];
|
||||
pos.y += vector[1];
|
||||
@ -439,17 +436,16 @@ class Mesh extends OutlinerElement {
|
||||
return el;
|
||||
}
|
||||
getSelectedVertices(make) {
|
||||
if (make && !Project.selected_vertices[this.uuid]) Project.selected_vertices[this.uuid] = [];
|
||||
return Project.selected_vertices[this.uuid] || [];
|
||||
if (make && !Project.mesh_selection[this.uuid]) Project.mesh_selection[this.uuid] = {vertices: [], edges: [], faces: []};
|
||||
return Project.mesh_selection[this.uuid]?.vertices || [];
|
||||
}
|
||||
getSelectedFaces() {
|
||||
let faces = [];
|
||||
for (let key in this.faces) {
|
||||
if (this.faces[key].isSelected()) {
|
||||
faces.push(key);
|
||||
}
|
||||
}
|
||||
return faces;
|
||||
getSelectedEdges(make) {
|
||||
if (make && !Project.mesh_selection[this.uuid]) Project.mesh_selection[this.uuid] = {vertices: [], edges: [], faces: []};
|
||||
return Project.mesh_selection[this.uuid]?.edges || [];
|
||||
}
|
||||
getSelectedFaces(make) {
|
||||
if (make && !Project.mesh_selection[this.uuid]) Project.mesh_selection[this.uuid] = {vertices: [], edges: [], faces: []};
|
||||
return Project.mesh_selection[this.uuid]?.faces || [];
|
||||
}
|
||||
getSelectionRotation() {
|
||||
if (Transformer.dragging) {
|
||||
@ -621,7 +617,7 @@ class Mesh extends OutlinerElement {
|
||||
TickUpdates.selection = true;
|
||||
}
|
||||
resize(val, axis, negative, allow_negative, bidirectional) {
|
||||
let selected_vertices = Project.selected_vertices[this.uuid] || Object.keys(this.vertices);
|
||||
let selected_vertices = Project.mesh_selection[this.uuid]?.vertices || Object.keys(this.vertices);
|
||||
let range = [Infinity, -Infinity];
|
||||
let {vec1, vec2} = Reusable;
|
||||
let rotation_inverted = new THREE.Euler().copy(Transformer.rotation_selection).invert();
|
||||
@ -988,6 +984,8 @@ new NodePreviewController(Mesh, {
|
||||
let join_selected = new THREE.Color(0x6bffcb);
|
||||
let divide_selected = new THREE.Color(0xff8c69);
|
||||
let selected_vertices = element.getSelectedVertices();
|
||||
let selected_edges = element.getSelectedEdges();
|
||||
let selected_faces = element.getSelectedFaces();
|
||||
|
||||
if (BarItems.selection_mode.value == 'vertex') {
|
||||
let colors = [];
|
||||
@ -1011,7 +1009,10 @@ new NodePreviewController(Mesh, {
|
||||
let selected;
|
||||
if (!Modes.edit || BarItems.selection_mode.value == 'object') {
|
||||
color = gizmo_colors.outline;
|
||||
} else if (selected_vertices.includes(key) && selected_vertices.includes(key_b)) {
|
||||
} else if (BarItems.selection_mode.value == 'edge' && selected_edges.find(edge => sameMeshEdge([key, key_b], edge))) {
|
||||
color = white;
|
||||
selected = true;
|
||||
} else if (BarItems.selection_mode.value == 'face' && selected_faces.find(fkey => element.faces[fkey].vertices.includes(key) && element.faces[fkey].vertices.includes(key_b))) {
|
||||
color = white;
|
||||
selected = true;
|
||||
} else {
|
||||
@ -1046,13 +1047,14 @@ new NodePreviewController(Mesh, {
|
||||
) ? 1 : 0;
|
||||
|
||||
let array = new Array(mesh.geometry.attributes.highlight.count).fill(highlighted);
|
||||
let selection_mode = BarItems.selection_mode.value;
|
||||
|
||||
if (!force_off && element.selected && Modes.edit) {
|
||||
let i = 0;
|
||||
for (let fkey in element.faces) {
|
||||
let face = element.faces[fkey];
|
||||
if (face.vertices.length < 3) continue;
|
||||
if (face.isSelected()) {
|
||||
if (face.isSelected() && selection_mode == 'face') {
|
||||
for (let j = 0; j < face.vertices.length; j++) {
|
||||
array[i] = 2;
|
||||
i++;
|
||||
|
@ -1202,7 +1202,7 @@ BARS.defineActions(function() {
|
||||
|
||||
} else if (Modes.edit && Mesh.selected.length && Mesh.selected.length === Outliner.selected.length && BarItems.selection_mode.value !== 'object') {
|
||||
Mesh.selected.forEach(mesh => {
|
||||
delete Project.selected_vertices[mesh.uuid];
|
||||
delete Project.mesh_selection[mesh.uuid];
|
||||
})
|
||||
updateSelection();
|
||||
|
||||
|
@ -803,6 +803,8 @@ class Preview {
|
||||
|
||||
let mesh = data.element;
|
||||
let selected_vertices = mesh.getSelectedVertices(true);
|
||||
let selected_edges = mesh.getSelectedEdges(true);
|
||||
let selected_faces = mesh.getSelectedFaces(true);
|
||||
|
||||
if (event.altKey || Pressing.overrides.alt) {
|
||||
|
||||
@ -829,21 +831,22 @@ class Preview {
|
||||
|
||||
if (!(event.ctrlOrCmd || Pressing.overrides.ctrl || event.shiftKey || Pressing.overrides.shift)) {
|
||||
selected_vertices.empty();
|
||||
selected_edges.empty();
|
||||
selected_faces.empty();
|
||||
UVEditor.vue.selected_faces.empty();
|
||||
}
|
||||
|
||||
processed_faces.forEach(face => {
|
||||
Project.selected_vertices[data.element.uuid].safePush(...face.vertices);
|
||||
selected_vertices.safePush(...face.vertices);
|
||||
let fkey = face.getFaceKey();
|
||||
UVEditor.vue.selected_faces.push(fkey);
|
||||
selected_faces.push(fkey);
|
||||
});
|
||||
} else {
|
||||
if (!(event.ctrlOrCmd || Pressing.overrides.ctrl || event.shiftKey || Pressing.overrides.shift)) {
|
||||
}
|
||||
let face_vkeys = data.element.faces[data.face].vertices;
|
||||
|
||||
if (event.ctrlOrCmd || Pressing.overrides.ctrl || event.shiftKey || Pressing.overrides.shift) {
|
||||
if (face_vkeys.allAre(vkey => selected_vertices.includes(vkey))) {
|
||||
if (selected_faces.includes(data.face)) {
|
||||
let selected_faces = data.element.getSelectedFaces();
|
||||
let vkeys_to_remove = face_vkeys.filter(vkey => {
|
||||
return !selected_faces.find(fkey => {
|
||||
@ -853,13 +856,17 @@ class Preview {
|
||||
if (vkeys_to_remove.length == 0) vkeys_to_remove.push(face_vkeys[0]);
|
||||
selected_vertices.remove(...vkeys_to_remove);
|
||||
UVEditor.vue.selected_faces.remove(data.face);
|
||||
selected_faces.remove(data.face);
|
||||
} else {
|
||||
selected_vertices.safePush(...face_vkeys);
|
||||
UVEditor.vue.selected_faces.safePush(data.face);
|
||||
selected_faces.safePush(data.face);
|
||||
}
|
||||
} else {
|
||||
selected_edges.empty();
|
||||
selected_vertices.replace(face_vkeys);
|
||||
UVEditor.vue.selected_faces.replace([data.face]);
|
||||
selected_faces.replace([data.face]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -878,34 +885,38 @@ class Preview {
|
||||
|
||||
} else if (data.type == 'vertex' && Toolbox.selected.id !== 'vertex_snap_tool') {
|
||||
|
||||
if (!Project.selected_vertices[data.element.uuid]) {
|
||||
Project.selected_vertices[data.element.uuid] = [];
|
||||
}
|
||||
let list = Project.selected_vertices[data.element.uuid];
|
||||
let list = data.element.getSelectedVertices(true);
|
||||
let edges = data.element.getSelectedEdges(true);
|
||||
let faces = data.element.getSelectedEdges(true);
|
||||
|
||||
if (event.ctrlOrCmd || Pressing.overrides.ctrl || event.shiftKey || Pressing.overrides.shift) {
|
||||
list.toggle(data.vertex);
|
||||
} else {
|
||||
unselectOtherNodes()
|
||||
unselectOtherNodes();
|
||||
list.replace([data.vertex]);
|
||||
edges.empty();
|
||||
faces.empty();
|
||||
}
|
||||
updateSelection();
|
||||
} else if (data.type == 'line') {
|
||||
|
||||
if (!Project.selected_vertices[data.element.uuid]) {
|
||||
Project.selected_vertices[data.element.uuid] = [];
|
||||
}
|
||||
let list = Project.selected_vertices[data.element.uuid];
|
||||
let vertices = data.element.getSelectedVertices(true);
|
||||
let edges = data.element.getSelectedEdges(true);
|
||||
let faces = data.element.getSelectedEdges(true);
|
||||
|
||||
if (event.ctrlOrCmd || Pressing.overrides.ctrl || event.shiftKey || Pressing.overrides.shift) {
|
||||
if (list.includes(data.vertices[0]) && list.includes(data.vertices[1])) {
|
||||
list.remove(...data.vertices);
|
||||
let index = edges.findIndex(edge => sameMeshEdge(edge, data.vertices))
|
||||
if (index >= 0) {
|
||||
vertices.remove(...data.vertices);
|
||||
edges.splice(index, 1);
|
||||
} else {
|
||||
list.remove(...data.vertices);
|
||||
list.push(...data.vertices);
|
||||
edges.push(data.vertices);
|
||||
vertices.push(...data.vertices);
|
||||
}
|
||||
} else {
|
||||
list.replace(data.vertices);
|
||||
faces.empty();
|
||||
edges.splice(0, Infinity, data.vertices);
|
||||
vertices.replace(data.vertices);
|
||||
unselectOtherNodes();
|
||||
}
|
||||
if (event.altKey || Pressing.overrides.alt) {
|
||||
@ -935,7 +946,8 @@ class Preview {
|
||||
let opposite_index_diff = sorted_vertices.indexOf(opposite_vertices[0]) - sorted_vertices.indexOf(opposite_vertices[1]);
|
||||
if (opposite_index_diff == 1 || opposite_index_diff < -2) opposite_vertices.reverse();
|
||||
|
||||
list.safePush(...side_vertices);
|
||||
vertices.safePush(...side_vertices);
|
||||
edges.push(side_vertices);
|
||||
|
||||
// Find next (and previous) face
|
||||
function doNextFace(index) {
|
||||
@ -1080,10 +1092,7 @@ class Preview {
|
||||
$(this.node).append(this.selection.box)
|
||||
this.selection.activated = false;
|
||||
this.selection.old_selected = Outliner.selected.slice();
|
||||
this.selection.old_vertices_selected = {};
|
||||
for (let uuid in Project.selected_vertices) {
|
||||
this.selection.old_vertices_selected[uuid] = Project.selected_vertices[uuid].slice();
|
||||
}
|
||||
this.selection.old_mesh_selection = JSON.parse(JSON.stringify(Project.mesh_selection));
|
||||
|
||||
this.moveSelRect(event)
|
||||
}
|
||||
@ -1163,15 +1172,15 @@ class Preview {
|
||||
|
||||
if (element instanceof Mesh && (selection_mode == 'object' || scope.selection.old_selected.includes(element))) {
|
||||
|
||||
let selected_vertices;
|
||||
let mesh_selection;
|
||||
if (selection_mode != 'object') {
|
||||
isSelected = true;
|
||||
if (!Project.selected_vertices[element.uuid]) {
|
||||
selected_vertices = Project.selected_vertices[element.uuid] = [];
|
||||
if (!Project.mesh_selection[element.uuid]) {
|
||||
mesh_selection = Project.mesh_selection[element.uuid] = {vertices: [], edges: [], faces: []};
|
||||
} else {
|
||||
selected_vertices = Project.selected_vertices[element.uuid];
|
||||
mesh_selection = Project.mesh_selection[element.uuid];
|
||||
}
|
||||
if (!extend_selection) selected_vertices.empty();
|
||||
if (!extend_selection) mesh_selection.vertices.empty();
|
||||
}
|
||||
|
||||
let vertex_points = {};
|
||||
@ -1183,19 +1192,17 @@ class Preview {
|
||||
is_on_screen = true;
|
||||
}
|
||||
}
|
||||
if (is_on_screen && extend_selection) {
|
||||
for (let vkey in element.vertices) {
|
||||
if (extend_selection && this.selection.old_vertices_selected[element.uuid] && this.selection.old_vertices_selected[element.uuid].includes(vkey)) {
|
||||
selected_vertices.safePush(vkey);
|
||||
}
|
||||
}
|
||||
if (extend_selection && this.selection.old_mesh_selection[element.uuid]) {
|
||||
mesh_selection.vertices.safePush(...this.selection.old_mesh_selection[element.uuid].vertices);
|
||||
mesh_selection.edges.safePush(...this.selection.old_mesh_selection[element.uuid].edges);
|
||||
mesh_selection.faces.safePush(...this.selection.old_mesh_selection[element.uuid].faces);
|
||||
}
|
||||
if (!is_on_screen) {
|
||||
} else if (selection_mode == 'vertex') {
|
||||
for (let vkey in element.vertices) {
|
||||
let point = vertex_points[vkey];
|
||||
if (!selected_vertices.includes(vkey) && pointInRectangle(point, rect_start, rect_end)) {
|
||||
selected_vertices.push(vkey);
|
||||
if (!mesh_selection.vertices.includes(vkey) && pointInRectangle(point, rect_start, rect_end)) {
|
||||
mesh_selection.vertices.push(vkey);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1209,7 +1216,11 @@ class Preview {
|
||||
let p1 = vertex_points[vkey];
|
||||
let p2 = vertex_points[vkey2];
|
||||
if (lineIntersectsReactangle(p1, p2, rect_start, rect_end)) {
|
||||
selected_vertices.safePush(vkey);
|
||||
mesh_selection.vertices.safePush(vkey);
|
||||
let edge = [vkey, vkey2];
|
||||
if (!mesh_selection.edges.find(edge2 => sameMeshEdge(edge, edge2))) {
|
||||
mesh_selection.edges.push(edge);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1229,16 +1240,18 @@ class Preview {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (face_intersects && selection_mode == 'object') {
|
||||
if (selection_mode == 'object') {
|
||||
if (face_intersects) {
|
||||
isSelected = true;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (face_intersects) {
|
||||
selected_vertices.safePush(...face.vertices);
|
||||
mesh_selection.vertices.safePush(...face.vertices);
|
||||
mesh_selection.faces.safePush(fkey);
|
||||
UVEditor.vue.selected_faces.safePush(fkey);
|
||||
} else {
|
||||
mesh_selection.faces.remove(fkey);
|
||||
UVEditor.vue.selected_faces.remove(fkey);
|
||||
}
|
||||
}
|
||||
|
@ -551,9 +551,9 @@ const UVEditor = {
|
||||
obj.preview_controller.updateUV(obj);
|
||||
})
|
||||
Mesh.selected.forEach(mesh => {
|
||||
let selected_vertices = Project.selected_vertices[mesh.uuid];
|
||||
let selected_vertices = mesh.getSelectedVertices();
|
||||
|
||||
if (selected_vertices) {
|
||||
if (selected_vertices.length) {
|
||||
UVEditor.vue.selected_faces.forEach(fkey => {
|
||||
if (!mesh.faces[fkey]) return
|
||||
selected_vertices.forEach(vkey => {
|
||||
@ -2344,7 +2344,7 @@ Interface.definePanels(function() {
|
||||
|
||||
UVEditor.getMappableElements().forEach(el => {
|
||||
if (el instanceof Mesh) {
|
||||
delete Project.selected_vertices[el.uuid];
|
||||
delete Project.mesh_selection[el.uuid];
|
||||
}
|
||||
})
|
||||
|
||||
@ -3328,7 +3328,7 @@ Interface.definePanels(function() {
|
||||
} else if (elements[0] instanceof Mesh) {
|
||||
var face = UVEditor.getReferenceFace();
|
||||
if (face) {
|
||||
let selected_vertices = Project.selected_vertices[elements[0].uuid];
|
||||
let selected_vertices = elements[0].getSelectedVertices();
|
||||
let has_selected_vertices = selected_vertices && face.vertices.find(vkey => selected_vertices.includes(vkey))
|
||||
let min = Infinity;
|
||||
face.vertices.forEach(vkey => {
|
||||
|
10
js/undo.js
10
js/undo.js
@ -292,8 +292,8 @@ class UndoSystem {
|
||||
elements.forEach(function(obj) {
|
||||
if (save.selection.includes(obj.uuid)) {
|
||||
obj.selectLow()
|
||||
if (save.selected_vertices[obj.uuid]) {
|
||||
Project.selected_vertices[obj.uuid] = save.selected_vertices[obj.uuid];
|
||||
if (save.mesh_selection[obj.uuid]) {
|
||||
Project.mesh_selection[obj.uuid] = save.mesh_selection[obj.uuid];
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -496,11 +496,11 @@ UndoSystem.save = class {
|
||||
|
||||
if (aspects.selection) {
|
||||
this.selection = [];
|
||||
this.selected_vertices = {};
|
||||
this.mesh_selection = {};
|
||||
selected.forEach(obj => {
|
||||
this.selection.push(obj.uuid);
|
||||
if (obj instanceof Mesh) {
|
||||
this.selected_vertices[obj.uuid] = Mesh.selected[0].getSelectedVertices().slice();
|
||||
if (obj instanceof Mesh && Project.mesh_selection[obj.uuid]) {
|
||||
this.mesh_selection[obj.uuid] = JSON.parse(JSON.stringify(Project.mesh_selection[obj.uuid]));
|
||||
}
|
||||
})
|
||||
if (Group.selected) {
|
||||
|
Loading…
Reference in New Issue
Block a user