From a61c1c4ab3ff0b432ca327d78cb2e2682dbc4d47 Mon Sep 17 00:00:00 2001 From: greisane Date: Tue, 19 Dec 2023 09:25:51 -0300 Subject: [PATCH] Bring back Graft face map output --- mesh/attribute_selection.py | 4 ++-- mesh/graft.py | 26 ++++++++++++++------------ mesh/helpers.py | 9 +++++++++ 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/mesh/attribute_selection.py b/mesh/attribute_selection.py index e3e359e..feef52d 100644 --- a/mesh/attribute_selection.py +++ b/mesh/attribute_selection.py @@ -11,7 +11,7 @@ class GRET_OT_attribute_to_selection(bpy.types.Operator): """Set the current face selection from a boolean face attribute""" bl_idname = 'gret.attribute_to_selection' - bl_label = "Select Faces By Values" + bl_label = "Select Faces by Values" bl_options = {'REGISTER', 'UNDO'} @classmethod @@ -50,7 +50,7 @@ class GRET_OT_attribute_from_selection(bpy.types.Operator): """Update or create a boolean face attribute from the current edit mode face selection""" bl_idname = 'gret.attribute_from_selection' - bl_label = "Face Selection To Values" + bl_label = "Face Selection to Values" bl_context = 'mesh_edit' bl_options = {'REGISTER', 'UNDO'} diff --git a/mesh/graft.py b/mesh/graft.py index 5b640d0..0edcbbf 100644 --- a/mesh/graft.py +++ b/mesh/graft.py @@ -2,9 +2,10 @@ from math import pi import bmesh import bpy +import numpy as np from ..math import get_dist_sq -from .helpers import edit_mesh_elements, bmesh_vertex_group_bleed +from .helpers import edit_mesh_elements, bmesh_vertex_group_bleed, get_face_map_attribute from ..helpers import with_object, get_modifier, get_vgroup, select_only, instant_modifier from ..operator import SaveContext @@ -95,20 +96,13 @@ def do_graft(context, save, obj, dst_obj, expand=0, cuts=0, blend_distance=0.0, try: ret = bmesh.ops.bridge_loops(bm, edges=edges1+edges2, use_pairs=False, use_cyclic=False, use_merge=False, merge_factor=0.5, twist_offset=0) - new_faces = ret['faces'] + new_face_indices = [face.index for face in ret['faces']] # for face in new_faces: # face.smooth = True except RuntimeError: bm.free() raise GraftError("Couldn't bridge loops.") - # If requested, fill a face map with the new faces - # Disabled for 4.0 since there is no actual replacement for face-based selection haha - # if face_map_name: - # face_map = obj.face_maps.get(face_map_name) or obj.face_maps.new(name=face_map_name) - # for face in new_faces: - # face[fm_layer] = face_map.index - if cuts > 0: bmesh.ops.subdivide_edges(bm, edges=ret['edges'], smooth=1.0, smooth_falloff='LINEAR', cuts=cuts) @@ -125,6 +119,14 @@ def do_graft(context, save, obj, dst_obj, expand=0, cuts=0, blend_distance=0.0, bm.to_mesh(obj.data) bm.free() + # If requested, fill a face map with the new faces + if face_map_name: + attr = get_face_map_attribute(obj, face_map_name) + values = np.empty(len(attr.data), dtype=bool) + attr.data.foreach_get('value', values) + values[new_face_indices] = True + attr.data.foreach_set('value', values) + # Transfer stuff if copy_normals: obj.data.use_auto_smooth = True @@ -195,8 +197,8 @@ class GRET_OT_graft(bpy.types.Operator): ) face_map_name: bpy.props.StringProperty( name="Face Map Name", - description="Optional name of a face map that contains the new geometry", - default="Grafts", + description="Optional name of a boolean face attribute that contains the new geometry", + default="", ) vertex_group_name: bpy.props.StringProperty( name="Vertex Group Name", @@ -312,7 +314,7 @@ def draw(self, context): # layout.prop_search(self, 'vertex_group_name', obj, 'vertex_groups') layout.prop(self, 'vertex_group_name', icon='GROUP_VERTEX') - # layout.prop(self, 'face_map_name', icon='FACE_MAPS') + layout.prop(self, 'face_map_name', icon='FACE_MAPS') row = layout.row(align=True, heading="Copy") row.prop(self, 'copy_normals', text="Norms.", toggle=1) diff --git a/mesh/helpers.py b/mesh/helpers.py index bd0fea5..3728cb3 100644 --- a/mesh/helpers.py +++ b/mesh/helpers.py @@ -117,6 +117,15 @@ def refresh_active_color_attribute(mesh): if mesh.color_attributes.render_color_index < 0: mesh.color_attributes.render_color_index = 0 +def get_face_map_attribute(obj, name): + """Ensures that a boolean face attribute with the given name exists.""" + + assert obj.type == 'MESH' + attr = obj.data.attributes.get(name) + if not attr or attr.domain != 'FACE' or attr.data_type != 'BOOLEAN': + attr = obj.data.attributes.new(name, type='BOOLEAN', domain='FACE') + return attr + def clear_object_data(obj, vertex_groups=True, shape_keys=True, face_maps=True, constraints=True, custom_properties=True, uv_layers=True, vertex_colors=True, attributes=True, materials=True): # Clear object data