Mesh vertex selection highlighting

This commit is contained in:
JannisX11 2021-08-02 22:55:30 +02:00
parent ecccb915bc
commit 7ed5813107
10 changed files with 107 additions and 35 deletions

View File

@ -105,11 +105,8 @@ function updateSelection(options = {}) {
if (Group.selected && Group.selected.locked) Group.selected.unselect()
Outliner.elements.forEach(element => {
if (element.visibility) {
var mesh = element.mesh
if (mesh && mesh.outline) {
mesh.outline.visible = element.selected
}
if (element.preview_controller.updateSelection) {
element.preview_controller.updateSelection(element);
}
})
for (var i = Outliner.selected.length-1; i >= 0; i--) {

View File

@ -1889,8 +1889,10 @@ const BARS = {
Toolbox = Toolbars.tools;
Toolbox.toggleTransforms = function() {
if (Toolbox.selected.id === 'move_tool') {
BarItems['resize_tool'].select()
if (Toolbox.selected.id === 'move_tool' && Mesh.selected.length) {
Modes.options.mesh.select()
} else if (Toolbox.selected.id === 'move_tool') {
BarItems['resize_tool'].select();
} else if (Toolbox.selected.id === 'resize_tool') {
BarItems['move_tool'].select()
}

View File

@ -571,6 +571,7 @@ const MenuBar = {
'edit_history',
'_',
'add_cube',
'add_mesh',
'add_group',
'add_locator',
'add_null_object',

View File

@ -26,6 +26,7 @@ class ModelProject {
this.groups = [];
this.selected_elements = [];
this.selected_group = null;
this.selected_vertices = {};
this.textures = [];
this.selected_texture = null;
this.outliner = [];
@ -57,7 +58,7 @@ class ModelProject {
get texture_height() {return this._texture_height}
set texture_width(n) {
n = parseInt(n)||16
Vue.nextTick(updateProjectResolution)
if (n != this._texture_width) Vue.nextTick(updateProjectResolution)
this._texture_width = n;
}
get optional_box_uv() {
@ -65,7 +66,7 @@ class ModelProject {
}
set texture_height(n) {
n = parseInt(n)||16
Vue.nextTick(updateProjectResolution)
if (n != this._texture_height) Vue.nextTick(updateProjectResolution)
this._texture_height = n;
}
get name() {
@ -196,6 +197,7 @@ class ModelProject {
setProjectTitle(this.name);
setStartScreen(!Project);
updateInterface();
updateProjectResolution();
Vue.nextTick(() => {
loadTextureDraggable();
})

View File

@ -184,16 +184,12 @@ class Group extends OutlinerNode {
Undo.initEdit({elements: elements, outliner: true, selection: true})
}
this.unselect()
super.remove();
var i = this.children.length-1
while (i >= 0) {
this.children[i].remove(false)
i--;
}
if (typeof this.parent === 'object') {
this.parent.children.remove(this)
} else {
Outliner.root.remove(this)
}
Animator.animations.forEach(animation => {
if (animation.animators && animation.animators[scope.uuid]) {
delete animation.animators[scope.uuid];
@ -204,7 +200,6 @@ class Group extends OutlinerNode {
})
TickUpdates.selection = true
this.constructor.all.remove(this);
delete Project.nodes_3d[this.uuid];
delete OutlinerNode.uuids[this.uuid];
if (undo) {
Undo.finishEdit('Delete group')

View File

@ -1,6 +1,7 @@
class MeshFace {
constructor(mesh, data) {
constructor(mesh, data, uuid) {
this.mesh = mesh;
this.uuid = uuid || guid();
//this.vertices = [];
//this.normal = [0, 1, 0];
this.texture = false;
@ -72,17 +73,17 @@ class Mesh extends OutlinerElement {
super(data, uuid)
this.vertices = {};
this.faces = [];
this.faces = {};
if (!data.vertices) {
this.addVertices([16, 16, 16], [16, 16, 0], [16, 0, 16], [16, 0, 0], [0, 16, 16], [0, 16, 0], [0, 0, 16], [0, 0, 0]);
let vertex_keys = Object.keys(this.vertices);
this.faces.push(new MeshFace( this, {vertices: [vertex_keys[0], vertex_keys[1], vertex_keys[2], vertex_keys[3]]} )); // East
this.faces.push(new MeshFace( this, {vertices: [vertex_keys[4], vertex_keys[5], vertex_keys[6], vertex_keys[7]]} )); // West
this.faces.push(new MeshFace( this, {vertices: [vertex_keys[0], vertex_keys[1], vertex_keys[4], vertex_keys[5]]} )); // Up
this.faces.push(new MeshFace( this, {vertices: [vertex_keys[2], vertex_keys[3], vertex_keys[6], vertex_keys[7]]} )); // Down
this.faces.push(new MeshFace( this, {vertices: [vertex_keys[0], vertex_keys[2], vertex_keys[4], vertex_keys[6]]} )); // South
this.faces.push(new MeshFace( this, {vertices: [vertex_keys[1], vertex_keys[3], vertex_keys[5], vertex_keys[7]]} )); // North
this.addFaces(new MeshFace( this, {vertices: [vertex_keys[0], vertex_keys[1], vertex_keys[2], vertex_keys[3]]} )); // East
//this.addFaces(new MeshFace( this, {vertices: [vertex_keys[4], vertex_keys[5], vertex_keys[6], vertex_keys[7]]} )); // West
//this.addFaces(new MeshFace( this, {vertices: [vertex_keys[0], vertex_keys[1], vertex_keys[4], vertex_keys[5]]} )); // Up
//this.addFaces(new MeshFace( this, {vertices: [vertex_keys[2], vertex_keys[3], vertex_keys[6], vertex_keys[7]]} )); // Down
//this.addFaces(new MeshFace( this, {vertices: [vertex_keys[0], vertex_keys[2], vertex_keys[4], vertex_keys[6]]} )); // South
//this.addFaces(new MeshFace( this, {vertices: [vertex_keys[1], vertex_keys[3], vertex_keys[5], vertex_keys[7]]} )); // North
}
for (var key in Mesh.properties) {
Mesh.properties[key].reset(this);
@ -127,10 +128,33 @@ class Mesh extends OutlinerElement {
this.vertices[key] = [...vector];
})
}
addFaces(...faces) {
faces.forEach(face => {
let key;
while (!key || this.faces[key]) {
key = bbuid(8);
}
this.faces[key] = face;
})
}
extend(object) {
for (var key in Mesh.properties) {
Mesh.properties[key].merge(this, object)
}
if (typeof object.vertices == 'object') {
for (let key in object.vertices) {
this.vertices[key] = object.vertices[key];
}
}
if (typeof object.faces == 'object') {
for (let key in object.faces) {
if (this.faces[key]) {
this.faces[key].extend(object.faces[key])
} else {
this.faces[key] = new Face(this, object.faces[key]);
}
}
}
this.sanitizeName();
return this;
}
@ -242,7 +266,7 @@ new NodePreviewController(Mesh, {
// Vertex Points
let material = new THREE.PointsMaterial({size: 5, sizeAttenuation: false, vertexColors: true});
let points = new THREE.Points(mesh.geometry, material);
let points = new THREE.Points(new THREE.BufferGeometry(), material);
points.geometry.setAttribute('color', new THREE.Float32BufferAttribute(new Array(24).fill(1), 3));
mesh.vertex_points = points;
outline.add(points);
@ -270,14 +294,17 @@ new NodePreviewController(Mesh, {
position_array.push(...vector);
}
element.faces.forEach(face => {
for (let key in element.faces) {
let face = element.faces[key];
// Test if point "check" is on the other side of the line between "base1" and "base2", compared to "top"
function test(base1, base2, top, check) {
base1 = new THREE.Vector3().fromArray(base1);
base2 = new THREE.Vector3().fromArray(base2);
top = new THREE.Vector3().fromArray(top);
check = new THREE.Vector3().fromArray(check);
// Construct a plane with coplanar points "base1" and "base2" with a normal towards "top"
let normal = new THREE.Vector3();
new THREE.Line3(base1, base2).closestPointToPoint(top, false, normal);
normal.sub(top);
@ -295,12 +322,12 @@ new NodePreviewController(Mesh, {
indices.push(index);
})
// Outline
face.vertices.forEach((key, i) => {
outline_positions.push(...element.vertices[key]);
if (i && i < face.vertices.length-1) outline_positions.push(...element.vertices[key]);
})
} else if (face.vertices.length == 4) {
let sorted_vertices = face.vertices;
@ -327,10 +354,13 @@ new NodePreviewController(Mesh, {
// Outline
sorted_vertices.forEach((key, i) => {
outline_positions.push(...element.vertices[key]);
if (i && i < sorted_vertices.length-1) outline_positions.push(...element.vertices[key]);
if (i != 0) outline_positions.push(...element.vertices[key]);
})
outline_positions.push(...element.vertices[sorted_vertices[0]]);
}
})
}
mesh.vertex_points.geometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array(position_array), 3));
mesh.geometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array(position_array), 3));
mesh.geometry.setIndex(indices);
@ -428,6 +458,24 @@ new NodePreviewController(Mesh, {
mesh.geometry.attributes.uv.needsUpdate = true;
return mesh.geometry;
},
updateSelection(element) {
NodePreviewController.prototype.updateSelection(element);
let mesh = element.mesh;
let colors = [];
for (let key in element.vertices) {
let color;
if (Project.selected_vertices[element.uuid] && Project.selected_vertices[element.uuid].includes(key)) {
color = gizmo_colors.outline;
} else {
color = gizmo_colors.wire;
}
colors.push(color.r, color.g, color.b);
}
mesh.vertex_points.geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
}
})
@ -477,4 +525,15 @@ BARS.defineActions(function() {
return base_mesh
}
})
new BarSelect('selection_mode', {
options: {
object: true,
vertex: true,
face: true,
},
condition: () => Format && Format.meshes,
onChange: function(slider) {
updateSelection();
}
})
})

View File

@ -222,9 +222,10 @@ class OutlinerNode {
return it(this)
}
remove() {
if (this.preview_controller) this.preview_controller.remove(this);
this.constructor.all.remove(this);
if (OutlinerNode.uuids[this.uuid] == this) delete OutlinerNode.uuids[this.uuid];
this.removeFromParent()
this.removeFromParent();
}
rename() {
this.showInOutliner()
@ -342,7 +343,8 @@ class OutlinerElement extends OutlinerNode {
super.init();
Project.elements.safePush(this);
if (!this.mesh || !this.mesh.parent) {
this.constructor.preview_controller.setup(this);
this.preview_controller.setup(this);
console.trace(this)
}
return this;
}
@ -523,6 +525,7 @@ class NodePreviewController {
this.updateUV = null;
this.updateFaces = null;
this.updatePaintingGrid = null;
this.updateSelection = null;
Object.assign(this, data);
}
@ -545,7 +548,7 @@ class NodePreviewController {
Canvas.outlines.remove(Canvas.outlines.getObjectByName(this.uuid+'_ghost_outline'))
}
}
delete Project.nodes_3d[obj.uuid];
delete Project.nodes_3d[element.uuid];
}
updateAll(element) {
this.updateTransform(element);
@ -590,6 +593,12 @@ class NodePreviewController {
updateVisibility(element) {
element.mesh.visible = element.visibility;
}
updateSelection(element) {
let {mesh} = element;
if (mesh && mesh.outline) {
mesh.outline.visible = element.selected
}
}
}
OutlinerElement.registerType = function(constructor, id) {

View File

@ -351,7 +351,9 @@ class Preview {
Outliner.elements.forEach(element => {
if (element.mesh.geometry && element.visibility && !element.locked) {
objects.push(element.mesh);
objects.push(element.mesh.vertex_points);
if (element.mesh.vertex_points) {
objects.push(element.mesh.vertex_points);
}
}
})
if (Vertexsnap.vertexes.children.length) {
@ -713,7 +715,7 @@ class Preview {
mousemove(event) {
if (Settings.get('highlight_cubes')) {
var data = this.raycast(event);
if (settings.highlight_cubes.value) updateCubeHighlights(data && data.element);
updateCubeHighlights(data && data.element);
}
}
mouseup(event) {

File diff suppressed because one or more lines are too long

View File

@ -953,6 +953,11 @@
"action.update_autouv.desc": "Update the auto UV mapping of the selected cubes",
"action.edit_material_instances": "Edit Material Instances",
"action.edit_material_instances.desc": "Edit material instance names for bedrock block geometries",
"action.selection_mode": "Selection Mode",
"action.selection_mode.desc": "Change how elements can be selected in the viewport",
"action.selection_mode.object": "Object",
"action.selection_mode.vertex": "Vertex",
"action.selection_mode.face": "Face",
"action.add_display_preset": "New Preset",
"action.add_display_preset.desc": "Add a new display setting preset",