Skip to content

Commit

Permalink
Change mesh selection system
Browse files Browse the repository at this point in the history
Faces and edges can now be selected individually rather than vertex based
Closes #1050
  • Loading branch information
JannisX11 committed Dec 4, 2022
1 parent afd73e8 commit 98b59b7
Show file tree
Hide file tree
Showing 12 changed files with 177 additions and 135 deletions.
70 changes: 38 additions & 32 deletions js/interface/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -1695,31 +1695,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];
Expand All @@ -1729,31 +1728,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];

Expand All @@ -1777,6 +1780,9 @@ const BARS = {
}
}
})
} else {
Mesh.selected.remove(mesh);
mesh.remove(false);
}
})

Expand Down
4 changes: 2 additions & 2 deletions js/io/formats/bbmodel.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand Down Expand Up @@ -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();
Expand Down
7 changes: 5 additions & 2 deletions js/io/project.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -178,10 +178,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);
Expand Down
30 changes: 20 additions & 10 deletions js/misc.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,15 +110,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];
}
}
})
Expand Down Expand Up @@ -192,13 +202,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;
Expand Down Expand Up @@ -231,7 +241,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));
}
Expand Down Expand Up @@ -261,8 +271,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;
}
Expand Down
34 changes: 18 additions & 16 deletions js/modeling/mesh_editing.js
Original file line number Diff line number Diff line change
@@ -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',
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -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 => {
Expand Down Expand Up @@ -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 = [];
Expand Down Expand Up @@ -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 => {
Expand Down Expand Up @@ -1458,6 +1459,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);
Expand Down Expand Up @@ -1494,8 +1496,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;
})
Expand Down
8 changes: 4 additions & 4 deletions js/modeling/transform.js
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ const Vertexsnap = {
Vertexsnap.move_origin = typeof data.vertex !== 'string' && data.vertex.allEqual(0);
Vertexsnap.elements = Outliner.selected.slice();
Vertexsnap.group = Group.selected;
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'))

Expand Down Expand Up @@ -435,7 +435,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();
Expand Down Expand Up @@ -948,7 +948,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();
Expand All @@ -970,7 +970,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);
Expand Down
8 changes: 7 additions & 1 deletion js/modeling/transform_gizmo.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Loading

0 comments on commit 98b59b7

Please sign in to comment.