Skip to content

Commit a814b65

Browse files
committed
Add a temporary modifier class for convenience
1 parent 1cbf9ef commit a814b65

File tree

3 files changed

+44
-29
lines changed

3 files changed

+44
-29
lines changed

helpers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ def wrapper(*args, **kwargs):
283283
logd(f"Couldn't patch {self.module_name}.{self.function_name}, module not found")
284284
return self
285285

286-
def __exit__(self, type, value, traceback):
286+
def __exit__(self, exc_type, exc_value, exc_traceback):
287287
module = sys.modules.get(self.module_name)
288288
if module:
289289
wrapper = getattr(module, self.function_name, None)

mesh/graft.py

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import bmesh
44
import bpy
55

6-
from .helpers import new_vgroup, new_modifier, edit_mesh_elements, bmesh_vertex_group_bleed
6+
from .helpers import new_vgroup, new_modifier, TempModifier, edit_mesh_elements, bmesh_vertex_group_bleed
77
from ..helpers import get_context, link_properties, load_selection, save_selection
88

99
class GRET_OT_graft(bpy.types.Operator):
@@ -206,39 +206,38 @@ def _execute(self, context):
206206

207207
ctx = get_context(obj)
208208
if self.transfer_normals:
209-
mod = new_modifier(obj, type='DATA_TRANSFER', at_top=True)
210-
mod.object = dst_obj
211-
mod.vertex_group = boundary_vg.name
212-
mod.use_object_transform = True
213-
mod.use_loop_data = True
214-
mod.data_types_loops = {'CUSTOM_NORMAL'}
215-
mod.loop_mapping = 'POLYINTERP_NEAREST'
216209
obj.data.use_auto_smooth = True
217210
obj.data.auto_smooth_angle = pi
218211
bpy.ops.mesh.customdata_custom_splitnormals_clear(ctx)
219-
bpy.ops.object.modifier_apply(ctx, modifier=mod.name)
212+
213+
with TempModifier(obj, type='DATA_TRANSFER') as data_mod:
214+
data_mod.object = dst_obj
215+
data_mod.vertex_group = boundary_vg.name
216+
data_mod.use_object_transform = True
217+
data_mod.use_loop_data = True
218+
data_mod.data_types_loops = {'CUSTOM_NORMAL'}
219+
data_mod.loop_mapping = 'POLYINTERP_NEAREST'
220220

221221
if self.transfer_vertex_groups or self.transfer_uv:
222-
mod = new_modifier(obj, type='DATA_TRANSFER', at_top=True)
223-
mod.object = dst_obj
224-
mod.use_object_transform = True
225-
if self.transfer_vertex_groups:
226-
mod.use_vert_data = True
227-
mod.data_types_verts = {'VGROUP_WEIGHTS'}
228-
mod.vert_mapping = 'EDGEINTERP_NEAREST'
229-
if self.transfer_uv:
230-
mod.use_loop_data = True
231-
mod.data_types_loops = {'UV'} # Automatically turns on use_poly_data
232-
mod.loop_mapping = 'POLYINTERP_NEAREST'
233-
bpy.ops.object.datalayout_transfer(ctx, modifier=mod.name)
234-
bpy.ops.object.modifier_apply(ctx, modifier=mod.name)
222+
with TempModifier(obj, type='DATA_TRANSFER') as data_mod:
223+
data_mod.object = dst_obj
224+
data_mod.use_object_transform = True
225+
if self.transfer_vertex_groups:
226+
data_mod.use_vert_data = True
227+
data_mod.data_types_verts = {'VGROUP_WEIGHTS'}
228+
data_mod.vert_mapping = 'EDGEINTERP_NEAREST'
229+
if self.transfer_uv:
230+
data_mod.use_loop_data = True
231+
data_mod.data_types_loops = {'UV'} # Automatically turns on use_poly_data
232+
data_mod.loop_mapping = 'POLYINTERP_NEAREST'
233+
bpy.ops.object.datalayout_transfer(ctx, modifier=data_mod.name)
235234

236235
# If requested, create a mask modifier that will hide the intersection's inner verts
237236
if self.create_mask:
238237
mask_vg = new_vgroup(orig_dst_obj, f"_mask_{obj.name}")
239238
intersecting_verts = (dst_mesh.vertices[i] for i in intersecting_vert_indices)
240239
mask_vg.add([v.index for v in intersecting_verts if not v.select], 1.0, 'REPLACE')
241-
mask_mod = new_modifier(orig_dst_obj, type='MASK', name=mask_vg.name, at_top=True)
240+
mask_mod = new_modifier(orig_dst_obj, type='MASK', name=mask_vg.name)
242241
mask_mod.vertex_group = mask_vg.name
243242
mask_mod.invert_vertex_group = True
244243
mod_dp = f'modifiers["{mask_mod.name}"]'

mesh/helpers.py

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,33 @@ def new_vgroup(obj, name):
2323
vgroup = obj.vertex_groups.new(name=name)
2424
return vgroup
2525

26-
def new_modifier(obj, type, name="", at_top=False):
27-
"""Ensures that a modifier with the given name exists. Moved first to avoid warnings on applying."""
26+
def new_modifier(obj, type, name=""):
27+
"""Ensures that a modifier with the given name exists."""
28+
# Should it clear an existing modifier?
2829

2930
modifier = obj.modifiers.get(name) if name else None
3031
if not modifier or modifier.type != type:
3132
modifier = obj.modifiers.new(type=type, name=name)
32-
if at_top:
33-
ctx = get_context(obj)
34-
bpy.ops.object.modifier_move_to_index(ctx, modifier=modifier.name, index=0)
3533
return modifier
3634

35+
class TempModifier:
36+
"""Convenient modifier wrapper to use in a `with` block to be automatically applied at the end."""
37+
38+
def __init__(self, obj, type):
39+
self.obj = obj
40+
self.type = type
41+
42+
def __enter__(self):
43+
self.modifier = self.obj.modifiers.new(type=self.type, name="")
44+
# Move first to avoid the warning on applying
45+
ctx = get_context(self.obj)
46+
bpy.ops.object.modifier_move_to_index(ctx, modifier=self.modifier.name, index=0)
47+
return self.modifier
48+
49+
def __exit__(self, exc_type, exc_value, exc_traceback):
50+
ctx = get_context(self.obj)
51+
bpy.ops.object.modifier_apply(ctx, modifier=self.modifier.name)
52+
3753
def edit_mesh_elements(obj, type='VERT', indices=None, key=None):
3854
"""
3955
Enters edit mode and selects elements of a mesh to be operated on.

0 commit comments

Comments
 (0)