-
Notifications
You must be signed in to change notification settings - Fork 14
/
op_LatticeApply.py
267 lines (208 loc) · 13 KB
/
op_LatticeApply.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
#Version 0.1.6
import bpy
from . import util
class Op_LatticeApplyOperator(bpy.types.Operator):
bl_idname = "object.op_lattice_apply"
bl_label = "Simple Lattice Apply"
bl_description = "Applies the lattice to all objects whose FFD modifiers are targeting it"
bl_space_type = "VIEW_3D"
bl_region_type = "TOOLS"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
lattice = context.active_object
if lattice.mode == "EDIT":
bpy.ops.object.editmode_toggle()
vertex_groups = []
for obj in context.view_layer.objects:
if obj.type in util.allowed_object_types:
vertex_groups.clear()
if obj.type == "MESH" or obj.type == "CURVE" or obj.type == "SURFACE":
for modifier in obj.modifiers:
if modifier.type == 'LATTICE' and "SimpleLattice" in modifier.name:
if modifier.object == lattice:
# checking for lattice on top of the modifiers stack (for any reason)
# https://blender.stackexchange.com/questions/233357/how-to-get-modifier-position
if obj.modifiers[0].type == "LATTICE" and obj.modifiers[0].object == lattice:
self.report({'INFO'}, 'Modifier applied')
else:
self.report({'INFO'}, 'Applied modifier was not first, result may not be as expected')
vertex_group = self.kill_lattice_modifer(context, modifier, lattice)
if vertex_group:
vertex_groups.append(vertex_group)
# Clear any selection
for f in obj.data.polygons:
f.select = False
for e in obj.data.edges:
e.select = False
for v in obj.data.vertices:
v.select = False
# Get verts in vertex group
verts = [v for v in obj.data.vertices if obj.vertex_groups[vertex_group].index in [i.group for i in v.groups]]
# Select verts in vertex group
for v in verts:
v.select = True
# if apply with vertex groups
# then select all objects and switch to EDIT mode
obj.select_set(True)
bpy.ops.object.editmode_toggle()
bpy.ops.mesh.select_mode(type="VERT")
if not vertex_group:
# if apply without vertex groups
# then select all objects and stay in OBJECT mode
obj.select_set(True)
if obj.type == "GPENCIL":
for modifier in obj.grease_pencil_modifiers:
if modifier.type == 'GP_LATTICE' and "SimpleLattice" in modifier.name:
if modifier.object == lattice:
# checking for lattice on top of the grease_pencil_modifiers stack (for any reason)
# https://blender.stackexchange.com/questions/233357/how-to-get-modifier-position
if obj.grease_pencil_modifiers[0].type == "GP_LATTICE" and obj.grease_pencil_modifiers[0].object == lattice:
self.report({'INFO'}, 'Modifier applied')
else:
self.report({'INFO'}, 'Applied modifier was not first, result may not be as expected')
vertex_group = self.kill_lattice_gpencil_modifer(context, modifier, lattice)
''' NOT IMPLEMENTED IN API YET
if vertex_group:
vertex_groups.append(vertex_group)
# Clear any selection
for layer in obj.data.layers:
for frame in layer.frames:
for stroke in frame.strokes:
for point in stroke.points:
point.select = False
# Get points in vertex group
all_points = []
for layer in obj.data.layers:
for frame in layer.frames:
for stroke in frame.strokes:
for point in stroke.points:
all_points.append(point)
points = [v for v in all_points if obj.vertex_groups[vertex_group].index in [i.group for i in v.groups]]
# Select points in vertex group
for point in points:
point.select = True
# if apply with vertex groups
# then select all objects and switch to EDIT mode
obj.select_set(True)
bpy.ops.object.editmode_toggle()
bpy.ops.mesh.select_mode(type="VERT")
'''
if not vertex_group:
# if apply without vertex groups
# then select all objects and stay in OBJECT mode
obj.select_set(True)
if obj.type == "FONT":
for modifier in obj.modifiers:
if modifier.type == 'LATTICE' and "SimpleLattice" in modifier.name:
if modifier.object == lattice:
# checking for lattice on top of the modifiers stack (for any reason)
# https://blender.stackexchange.com/questions/233357/how-to-get-modifier-position
if obj.modifiers[0].type == "LATTICE" and obj.modifiers[0].object == lattice:
self.report({'INFO'}, 'Modifier applied')
else:
self.report({'INFO'}, 'Applied modifier was not first, result may not be as expected')
vertex_group = self.kill_lattice_font_modifer(context, modifier, lattice)
self.kill_vertex_groups(obj, vertex_groups)
# try:
# self.kill_custom_orientation()
# except:
# pass
# removing Lattice object with its data
# https://blender.stackexchange.com/questions/233204/how-can-i-purge-recently-deleted-objects
lattice_obs = [o for o in context.selected_objects if o.type == 'LATTICE']
purge_data = set(o.data for o in lattice_obs)
bpy.data.batch_remove(lattice_obs)
bpy.data.batch_remove([o for o in purge_data if not o.users])
#self.report({'INFO'}, 'Applied modifier was not first, result may not be as expected')
context.view_layer.update()
return {'FINISHED'}
@classmethod
def poll(self, context):
return (len(context.selected_objects) == 1 and
context.active_object and
context.active_object.type == 'LATTICE' and
context.active_object.select_get())
def set_active(self, context, object):
context.view_layer.objects.active = object
def kill_lattice_modifer(self, context, modifier, target):
vertex_group = ""
if modifier.type != "LATTICE" or modifier.object != target:
return vertex_group
if context.active_object != modifier.id_data:
self.set_active(context, modifier.id_data)
if modifier.vertex_group != None:
vertex_group = modifier.vertex_group
if modifier.show_viewport:
if modifier.id_data.mode != 'OBJECT':
bpy.ops.object.editmode_toggle()
try:
bpy.ops.object.modifier_apply(modifier=modifier.name)
except:
self.report({'WARNING'}, 'Modifier applied to multi-user data. Creating single-user and applying.')
bpy.ops.object.modifier_apply(modifier=modifier.name, single_user=True)
else:
bpy.ops.object.modifier_remove(modifier=modifier.name)
return vertex_group
def kill_lattice_gpencil_modifer(self, context, modifier, target):
vertex_group = ""
if modifier.type != "GP_LATTICE" or modifier.object != target:
return vertex_group
if context.active_object != modifier.id_data:
self.set_active(context, modifier.id_data)
if modifier.vertex_group != None:
vertex_group = modifier.vertex_group
if modifier.show_viewport:
if modifier.id_data.mode != 'OBJECT':
bpy.ops.object.editmode_toggle()
try:
bpy.ops.object.gpencil_modifier_apply(modifier=modifier.name)
except:
self.report({'WARNING'}, 'Modifier applied to multi-user data. Creating single-user and applying.')
#all this for only one unimplemented yet single_user for bpy.ops.object.gpencil_modifier_apply(modifier=modifier.name, single_user=True)
bpy.context.view_layer.objects.active.name = modifier.name
bpy.context.view_layer.objects.active.select_set(True)
bpy.ops.object.make_single_user(object=True, obdata=True, material=False, animation=False, obdata_animation=False)
bpy.ops.object.gpencil_modifier_apply(modifier=modifier.name)
#=======================================================================================================================================
#bpy.ops.object.gpencil_modifier_apply(modifier=modifier.name, single_user=True)
else:
bpy.ops.object.gpencil_modifier_remove(modifier=modifier.name)
return vertex_group
def kill_lattice_font_modifer(self, context, modifier, target):
vertex_group = ""
if modifier.type != "LATTICE" or modifier.object != target:
return vertex_group
if context.active_object != modifier.id_data:
self.set_active(context, modifier.id_data)
if modifier.vertex_group != None:
vertex_group = modifier.vertex_group
if modifier.show_viewport:
if modifier.id_data.mode != 'OBJECT':
bpy.ops.object.editmode_toggle()
self.report({'WARNING'}, "Can't apply lattice for FONT object. Converting to MESH and applying.")
#all this for only one unimplemented yet single_user for bpy.ops.object.gpencil_modifier_apply(modifier=modifier.name, single_user=True)
bpy.context.view_layer.objects.active.name = modifier.name
bpy.context.view_layer.objects.active.select_set(True)
bpy.ops.object.convert(target='MESH')
bpy.ops.object.modifier_apply(modifier=modifier.name)
else:
bpy.ops.object.modifier_remove(modifier=modifier.name)
return vertex_group
def kill_vertex_groups(self, obj, vertex_groups):
if len(vertex_groups) == 0:
return
modifiers = filter(lambda modifier: hasattr(modifier, "vertex_group")
and modifier.vertex_group, obj.modifiers)
used_vertex_groups = set(
map(lambda modifier: modifier.vertex_group, modifiers))
obsolete = filter(
lambda group: group not in used_vertex_groups, vertex_groups)
for group in obsolete:
print(f"removed vertex_group: {group}")
vg = obj.vertex_groups.get(group)
obj.vertex_groups.remove(vg)
# def kill_custom_orientation(self):
# orig_transform = bpy.context.scene.transform_orientation_slots[0].type
# bpy.context.scene.transform_orientation_slots[0].type = 'SimpleLattice_Orientation'
# bpy.ops.transform.delete_orientation()
# bpy.data.scenes[0].transform_orientation_slots[0].type = orig_transform