@@ -18,23 +18,50 @@ class MAPLUS_OT_AlignLinesBase(bpy.types.Operator):
18
18
target = None
19
19
20
20
def execute (self , context ):
21
- if not (maplus_geom .get_active_object () and maplus_geom .get_select_state (maplus_geom .get_active_object ())):
22
- self .report (
23
- {'ERROR' },
24
- ('Cannot complete: need at least'
25
- ' one active (and selected) object.' )
26
- )
27
- return {'CANCELLED' }
28
21
addon_data = bpy .context .scene .maplus_data
29
22
prims = addon_data .prim_list
30
23
previous_mode = maplus_geom .get_active_object ().mode
31
24
if hasattr (self , "quick_op_target" ):
32
25
active_item = addon_data .quick_align_lines_transf
33
26
else :
34
27
active_item = prims [addon_data .active_list_item ]
28
+ # Gather selected Blender object(s) to apply the transform to
29
+ multi_edit_targets = [
30
+ item for item in bpy .context .scene .objects if (
31
+ maplus_geom .get_select_state (item )
32
+ )
33
+ ]
34
+ # Check prerequisites for mesh level transforms, need an active/selected object
35
+ if (self .target != 'OBJECT' and not (maplus_geom .get_active_object ()
36
+ and maplus_geom .get_select_state (maplus_geom .get_active_object ()))):
37
+ self .report (
38
+ {'ERROR' },
39
+ ('Cannot complete: cannot perform mesh-level transform'
40
+ ' without an active (and selected) object.' )
41
+ )
42
+ return {'CANCELLED' }
43
+ # Check auto grab prerequisites
44
+ if addon_data .quick_align_lines_auto_grab_src :
45
+ if not (maplus_geom .get_active_object ()
46
+ and maplus_geom .get_select_state (maplus_geom .get_active_object ())):
47
+ self .report (
48
+ {'ERROR' },
49
+ ('Cannot complete: cannot auto-grab source verts '
50
+ ' without an active (and selected) object.' )
51
+ )
52
+ return {'CANCELLED' }
53
+ if maplus_geom .get_active_object ().type != 'MESH' :
54
+ self .report (
55
+ {'ERROR' },
56
+ ('Cannot complete: cannot auto-grab source verts '
57
+ ' from a non-mesh object.' )
58
+ )
59
+ return {'CANCELLED' }
35
60
36
- if (maplus_geom .get_active_object () and
37
- type (maplus_geom .get_active_object ().data ) == bpy .types .Mesh ):
61
+ # Proceed only if selected Blender objects are compatible with the transform target
62
+ # (Do not allow mesh-level transforms when there are non-mesh objects selected)
63
+ if not (self .target in {'MESH_SELECTED' , 'WHOLE_MESH' , 'OBJECT_ORIGIN' }
64
+ and [item for item in multi_edit_targets if item .type != 'MESH' ]):
38
65
39
66
if not hasattr (self , "quick_op_target" ):
40
67
if (prims [active_item .aln_src_line ].kind != 'LINE' or
@@ -46,14 +73,15 @@ def execute(self, context):
46
73
)
47
74
return {'CANCELLED' }
48
75
49
- # a bmesh can only be initialized in edit mode...
50
- if previous_mode != 'EDIT' :
51
- bpy .ops .object .editmode_toggle ()
52
- else :
53
- # else we could already be in edit mode with some stale
54
- # updates, exiting and reentering forces an update
55
- bpy .ops .object .editmode_toggle ()
56
- bpy .ops .object .editmode_toggle ()
76
+ if maplus_geom .get_active_object ().type == 'MESH' :
77
+ # a bmesh can only be initialized in edit mode...
78
+ if previous_mode != 'EDIT' :
79
+ bpy .ops .object .editmode_toggle ()
80
+ else :
81
+ # else we could already be in edit mode with some stale
82
+ # updates, exiting and reentering forces an update
83
+ bpy .ops .object .editmode_toggle ()
84
+ bpy .ops .object .editmode_toggle ()
57
85
58
86
# Get global coordinate data for each geometry item, with
59
87
# modifiers applied. Grab either directly from the scene data
@@ -112,18 +140,7 @@ def execute(self, context):
112
140
dest_start = dest_global_data [0 ]
113
141
dest_end = dest_global_data [1 ]
114
142
115
- # create common vars needed for object and for mesh
116
- # level transforms
117
- active_obj_transf = maplus_geom .get_active_object ().matrix_world .copy ()
118
- inverse_active = active_obj_transf .copy ()
119
- inverse_active .invert ()
120
-
121
- multi_edit_targets = [
122
- model for model in bpy .context .scene .objects if (
123
- maplus_geom .get_select_state (model ) and model .type == 'MESH'
124
- )
125
- ]
126
- if self .target == 'OBJECT' :
143
+ if self .target in {'OBJECT' , 'OBJECT_ORIGIN' }:
127
144
for item in multi_edit_targets :
128
145
# Get the object world matrix before we modify it here
129
146
item_matrix_unaltered = item .matrix_world .copy ()
@@ -171,7 +188,7 @@ def execute(self, context):
171
188
)
172
189
bpy .context .view_layer .update ()
173
190
174
- else :
191
+ if self . target in { 'MESH_SELECTED' , 'WHOLE_MESH' , 'OBJECT_ORIGIN' } :
175
192
for item in multi_edit_targets :
176
193
self .report (
177
194
{'WARNING' },
@@ -229,13 +246,20 @@ def execute(self, context):
229
246
src_pivot_to_loc_origin
230
247
)
231
248
232
- if self .target == 'MESHSELECTED ' :
249
+ if self .target == 'MESH_SELECTED ' :
233
250
src_mesh .transform (
234
251
loc_make_collinear ,
235
252
filter = {'SELECT' }
236
253
)
237
- elif self .target == 'WHOLEMESH ' :
254
+ elif self .target == 'WHOLE_MESH ' :
238
255
src_mesh .transform (loc_make_collinear )
256
+ elif self .target == 'OBJECT_ORIGIN' :
257
+ # Note: a target of 'OBJECT_ORIGIN' is equivalent
258
+ # to performing an object transf. + an inverse
259
+ # whole mesh level transf. To the user,
260
+ # the object appears to stay in the same place,
261
+ # while only the object's origin moves.
262
+ src_mesh .transform (loc_make_collinear .inverted ())
239
263
240
264
bpy .ops .object .mode_set (mode = 'OBJECT' )
241
265
src_mesh .to_mesh (item .data )
@@ -245,9 +269,13 @@ def execute(self, context):
245
269
bpy .ops .object .mode_set (mode = previous_mode )
246
270
247
271
else :
272
+ # The selected Blender objects are not compatible with the
273
+ # requested transformation type (we can't apply a transform
274
+ # to mesh data when there are non-mesh objects selected)
248
275
self .report (
249
276
{'ERROR' },
250
- 'Cannot transform: non-mesh or no active object.'
277
+ ('Cannot complete: Cannot apply mesh-level'
278
+ ' transformations to selected non-mesh objects.' )
251
279
)
252
280
return {'CANCELLED' }
253
281
@@ -271,12 +299,28 @@ class MAPLUS_OT_QuickAlignLinesObject(MAPLUS_OT_AlignLinesBase):
271
299
quick_op_target = True
272
300
273
301
302
+ class MAPLUS_OT_QuickAlignLinesObjectOrigin (MAPLUS_OT_AlignLinesBase ):
303
+ bl_idname = "maplus.quickalignlinesobjectorigin"
304
+ bl_label = "Align Lines"
305
+ bl_description = "Makes lines collinear (in line with each other)"
306
+ bl_options = {'REGISTER' , 'UNDO' }
307
+ target = 'OBJECT_ORIGIN'
308
+ quick_op_target = True
309
+
310
+ @classmethod
311
+ def poll (cls , context ):
312
+ addon_data = bpy .context .scene .maplus_data
313
+ if not addon_data .use_experimental :
314
+ return False
315
+ return True
316
+
317
+
274
318
class MAPLUS_OT_AlignLinesMeshSelected (MAPLUS_OT_AlignLinesBase ):
275
319
bl_idname = "maplus.alignlinesmeshselected"
276
320
bl_label = "Align Lines"
277
321
bl_description = "Makes lines collinear (in line with each other)"
278
322
bl_options = {'REGISTER' , 'UNDO' }
279
- target = 'MESHSELECTED '
323
+ target = 'MESH_SELECTED '
280
324
281
325
@classmethod
282
326
def poll (cls , context ):
@@ -291,7 +335,7 @@ class MAPLUS_OT_AlignLinesWholeMesh(MAPLUS_OT_AlignLinesBase):
291
335
bl_label = "Align Lines"
292
336
bl_description = "Makes lines collinear (in line with each other)"
293
337
bl_options = {'REGISTER' , 'UNDO' }
294
- target = 'WHOLEMESH '
338
+ target = 'WHOLE_MESH '
295
339
296
340
@classmethod
297
341
def poll (cls , context ):
@@ -306,7 +350,7 @@ class MAPLUS_OT_QuickAlignLinesMeshSelected(MAPLUS_OT_AlignLinesBase):
306
350
bl_label = "Align Lines"
307
351
bl_description = "Makes lines collinear (in line with each other)"
308
352
bl_options = {'REGISTER' , 'UNDO' }
309
- target = 'MESHSELECTED '
353
+ target = 'MESH_SELECTED '
310
354
quick_op_target = True
311
355
312
356
@classmethod
@@ -322,7 +366,7 @@ class MAPLUS_OT_QuickAlignLinesWholeMesh(MAPLUS_OT_AlignLinesBase):
322
366
bl_label = "Align Lines"
323
367
bl_description = "Makes lines collinear (in line with each other)"
324
368
bl_options = {'REGISTER' , 'UNDO' }
325
- target = 'WHOLEMESH '
369
+ target = 'WHOLE_MESH '
326
370
quick_op_target = True
327
371
328
372
@classmethod
@@ -654,12 +698,17 @@ def draw(self, context):
654
698
'use_experimental' ,
655
699
text = 'Enable Experimental Mesh Ops.'
656
700
)
657
- aln_apply_items = aln_gui .split (factor = .33 )
658
- aln_apply_items .operator (
701
+ aln_apply_items = aln_gui .row ()
702
+ aln_to_object_and_origin = aln_apply_items .column ()
703
+ aln_to_object_and_origin .operator (
659
704
"maplus.quickalignlinesobject" ,
660
705
text = "Object"
661
706
)
662
- aln_mesh_apply_items = aln_apply_items .row (align = True )
707
+ aln_to_object_and_origin .operator (
708
+ "maplus.quickalignlinesobjectorigin" ,
709
+ text = "Obj. Origin"
710
+ )
711
+ aln_mesh_apply_items = aln_apply_items .column (align = True )
663
712
aln_mesh_apply_items .operator (
664
713
"maplus.quickalignlinesmeshselected" ,
665
714
text = "Mesh Piece"
0 commit comments