diff options
Diffstat (limited to 'release/scripts/startup/bl_operators/object_align.py')
-rw-r--r-- | release/scripts/startup/bl_operators/object_align.py | 272 |
1 files changed, 196 insertions, 76 deletions
diff --git a/release/scripts/startup/bl_operators/object_align.py b/release/scripts/startup/bl_operators/object_align.py index 644f30a4745..50e9bfb5b98 100644 --- a/release/scripts/startup/bl_operators/object_align.py +++ b/release/scripts/startup/bl_operators/object_align.py @@ -16,106 +16,213 @@ # # ##### END GPL LICENSE BLOCK ##### -# <pep8 compliant> +# <pep8-80 compliant> import bpy +from bpy.types import Operator from mathutils import Vector -def align_objects(align_x, align_y, align_z, align_mode, relative_to): +def GlobalBB_LQ(bb_world): + + # Initialize the variables with the 8th vertex + left, right, front, back, down, up = (bb_world[7][0], + bb_world[7][0], + bb_world[7][1], + bb_world[7][1], + bb_world[7][2], + bb_world[7][2], + ) + + # Test against the other 7 verts + for i in range(7): + + # X Range + val = bb_world[i][0] + if val < left: + left = val + + if val > right: + right = val + + # Y Range + val = bb_world[i][1] + if val < front: + front = val + + if val > back: + back = val + + # Z Range + val = bb_world[i][2] + if val < down: + down = val + + if val > up: + up = val + + return (Vector((left, front, up)), Vector((right, back, down))) + + +def GlobalBB_HQ(obj): + + matrix_world = obj.matrix_world.copy() + + # Initialize the variables with the last vertex + + verts = obj.data.vertices + + val = matrix_world * verts[-1].co + + left, right, front, back, down, up = (val[0], + val[0], + val[1], + val[1], + val[2], + val[2], + ) + + # Test against all other verts + for i in range(len(verts) - 1): + + vco = matrix_world * verts[i].co + + # X Range + val = vco[0] + if val < left: + left = val + + if val > right: + right = val + + # Y Range + val = vco[1] + if val < front: + front = val + + if val > back: + back = val + + # Z Range + val = vco[2] + if val < down: + down = val + + if val > up: + up = val + + return Vector((left, front, up)), Vector((right, back, down)) + + +def align_objects(align_x, + align_y, + align_z, + align_mode, + relative_to, + bb_quality): cursor = bpy.context.scene.cursor_location - Left_Up_Front_SEL = [0.0, 0.0, 0.0] - Right_Down_Back_SEL = [0.0, 0.0, 0.0] + Left_Front_Up_SEL = [0.0, 0.0, 0.0] + Right_Back_Down_SEL = [0.0, 0.0, 0.0] flag_first = True objs = [] for obj in bpy.context.selected_objects: - matrix_world = obj.matrix_world - bb_world = [Vector(v[:]) * matrix_world for v in obj.bound_box] + matrix_world = obj.matrix_world.copy() + bb_world = [matrix_world * Vector(v[:]) for v in obj.bound_box] objs.append((obj, bb_world)) if not objs: return False for obj, bb_world in objs: - Left_Up_Front = bb_world[1] - Right_Down_Back = bb_world[7] + + if bb_quality: + GBB = GlobalBB_HQ(obj) + else: + GBB = GlobalBB_LQ(bb_world) + + Left_Front_Up = GBB[0] + Right_Back_Down = GBB[1] # Active Center if obj == bpy.context.active_object: - center_active_x = (Left_Up_Front[0] + Right_Down_Back[0]) / 2.0 - center_active_y = (Left_Up_Front[1] + Right_Down_Back[1]) / 2.0 - center_active_z = (Left_Up_Front[2] + Right_Down_Back[2]) / 2.0 + center_active_x = (Left_Front_Up[0] + Right_Back_Down[0]) / 2.0 + center_active_y = (Left_Front_Up[1] + Right_Back_Down[1]) / 2.0 + center_active_z = (Left_Front_Up[2] + Right_Back_Down[2]) / 2.0 - size_active_x = (Right_Down_Back[0] - Left_Up_Front[0]) / 2.0 - size_active_y = (Right_Down_Back[1] - Left_Up_Front[1]) / 2.0 - size_active_z = (Left_Up_Front[2] - Right_Down_Back[2]) / 2.0 + size_active_x = (Right_Back_Down[0] - Left_Front_Up[0]) / 2.0 + size_active_y = (Right_Back_Down[1] - Left_Front_Up[1]) / 2.0 + size_active_z = (Left_Front_Up[2] - Right_Back_Down[2]) / 2.0 # Selection Center if flag_first: flag_first = False - Left_Up_Front_SEL[0] = Left_Up_Front[0] - Left_Up_Front_SEL[1] = Left_Up_Front[1] - Left_Up_Front_SEL[2] = Left_Up_Front[2] + Left_Front_Up_SEL[0] = Left_Front_Up[0] + Left_Front_Up_SEL[1] = Left_Front_Up[1] + Left_Front_Up_SEL[2] = Left_Front_Up[2] - Right_Down_Back_SEL[0] = Right_Down_Back[0] - Right_Down_Back_SEL[1] = Right_Down_Back[1] - Right_Down_Back_SEL[2] = Right_Down_Back[2] + Right_Back_Down_SEL[0] = Right_Back_Down[0] + Right_Back_Down_SEL[1] = Right_Back_Down[1] + Right_Back_Down_SEL[2] = Right_Back_Down[2] else: # X axis - if Left_Up_Front[0] < Left_Up_Front_SEL[0]: - Left_Up_Front_SEL[0] = Left_Up_Front[0] + if Left_Front_Up[0] < Left_Front_Up_SEL[0]: + Left_Front_Up_SEL[0] = Left_Front_Up[0] # Y axis - if Left_Up_Front[1] < Left_Up_Front_SEL[1]: - Left_Up_Front_SEL[1] = Left_Up_Front[1] + if Left_Front_Up[1] < Left_Front_Up_SEL[1]: + Left_Front_Up_SEL[1] = Left_Front_Up[1] # Z axis - if Left_Up_Front[2] > Left_Up_Front_SEL[2]: - Left_Up_Front_SEL[2] = Left_Up_Front[2] + if Left_Front_Up[2] > Left_Front_Up_SEL[2]: + Left_Front_Up_SEL[2] = Left_Front_Up[2] # X axis - if Right_Down_Back[0] > Right_Down_Back_SEL[0]: - Right_Down_Back_SEL[0] = Right_Down_Back[0] + if Right_Back_Down[0] > Right_Back_Down_SEL[0]: + Right_Back_Down_SEL[0] = Right_Back_Down[0] # Y axis - if Right_Down_Back[1] > Right_Down_Back_SEL[1]: - Right_Down_Back_SEL[1] = Right_Down_Back[1] + if Right_Back_Down[1] > Right_Back_Down_SEL[1]: + Right_Back_Down_SEL[1] = Right_Back_Down[1] # Z axis - if Right_Down_Back[2] < Right_Down_Back_SEL[2]: - Right_Down_Back_SEL[2] = Right_Down_Back[2] + if Right_Back_Down[2] < Right_Back_Down_SEL[2]: + Right_Back_Down_SEL[2] = Right_Back_Down[2] - center_sel_x = (Left_Up_Front_SEL[0] + Right_Down_Back_SEL[0]) / 2.0 - center_sel_y = (Left_Up_Front_SEL[1] + Right_Down_Back_SEL[1]) / 2.0 - center_sel_z = (Left_Up_Front_SEL[2] + Right_Down_Back_SEL[2]) / 2.0 + center_sel_x = (Left_Front_Up_SEL[0] + Right_Back_Down_SEL[0]) / 2.0 + center_sel_y = (Left_Front_Up_SEL[1] + Right_Back_Down_SEL[1]) / 2.0 + center_sel_z = (Left_Front_Up_SEL[2] + Right_Back_Down_SEL[2]) / 2.0 # Main Loop for obj, bb_world in objs: + matrix_world = obj.matrix_world.copy() + bb_world = [matrix_world * Vector(v[:]) for v in obj.bound_box] - loc_world = obj.location - bb_world = [Vector(v[:]) * obj.matrix_world for v in obj.bound_box] + if bb_quality: + GBB = GlobalBB_HQ(obj) + else: + GBB = GlobalBB_LQ(bb_world) - Left_Up_Front = bb_world[1] - Right_Down_Back = bb_world[7] + Left_Front_Up = GBB[0] + Right_Back_Down = GBB[1] - center_x = (Left_Up_Front[0] + Right_Down_Back[0]) / 2.0 - center_y = (Left_Up_Front[1] + Right_Down_Back[1]) / 2.0 - center_z = (Left_Up_Front[2] + Right_Down_Back[2]) / 2.0 + center_x = (Left_Front_Up[0] + Right_Back_Down[0]) / 2.0 + center_y = (Left_Front_Up[1] + Right_Back_Down[1]) / 2.0 + center_z = (Left_Front_Up[2] + Right_Back_Down[2]) / 2.0 - positive_x = Right_Down_Back[0] - positive_y = Right_Down_Back[1] - positive_z = Left_Up_Front[2] + positive_x = Right_Back_Down[0] + positive_y = Right_Back_Down[1] + positive_z = Left_Front_Up[2] - negative_x = Left_Up_Front[0] - negative_y = Left_Up_Front[1] - negative_z = Right_Down_Back[2] + negative_x = Left_Front_Up[0] + negative_y = Left_Front_Up[1] + negative_z = Right_Back_Down[2] obj_loc = obj.location @@ -230,40 +337,48 @@ def align_objects(align_x, align_y, align_z, align_mode, relative_to): return True -from bpy.props import EnumProperty +from bpy.props import EnumProperty, BoolProperty -class AlignObjects(bpy.types.Operator): +class AlignObjects(Operator): '''Align Objects''' bl_idname = "object.align" bl_label = "Align Objects" bl_options = {'REGISTER', 'UNDO'} - align_mode = EnumProperty(items=( - ('OPT_1', "Negative Sides", ""), - ('OPT_2', "Centers", ""), - ('OPT_3', "Positive Sides", "")), - name="Align Mode:", - description="", - default='OPT_2') - - relative_to = EnumProperty(items=( - ('OPT_1', "Scene Origin", ""), - ('OPT_2', "3D Cursor", ""), - ('OPT_3', "Selection", ""), - ('OPT_4', "Active", "")), - name="Relative To:", - description="", - default='OPT_4') - - align_axis = EnumProperty(items=( - ('X', "X", ""), - ('Y', "Y", ""), - ('Z', "Z", ""), - ), - name="Align", - description="Align to axis", - options={'ENUM_FLAG'}) + bb_quality = BoolProperty( + name="High Quality", + description=("Enables high quality calculation of the " + "bounding box for perfect results on complex " + "shape meshes with rotation/scale (Slow)"), + default=True, + ) + align_mode = EnumProperty( + name="Align Mode:", + items=(('OPT_1', "Negative Sides", ""), + ('OPT_2', "Centers", ""), + ('OPT_3', "Positive Sides", ""), + ), + default='OPT_2', + ) + relative_to = EnumProperty( + name="Relative To:", + items=(('OPT_1', "Scene Origin", ""), + ('OPT_2', "3D Cursor", ""), + ('OPT_3', "Selection", ""), + ('OPT_4', "Active", ""), + ), + default='OPT_4', + ) + align_axis = EnumProperty( + name="Align", + description="Align to axis", + items=(('X', "X", ""), + ('Y', "Y", ""), + ('Z', "Z", ""), + ), + options={'ENUM_FLAG'}, + ) @classmethod def poll(cls, context): @@ -271,7 +386,12 @@ class AlignObjects(bpy.types.Operator): def execute(self, context): align_axis = self.align_axis - ret = align_objects('X' in align_axis, 'Y' in align_axis, 'Z' in align_axis, self.align_mode, self.relative_to) + ret = align_objects('X' in align_axis, + 'Y' in align_axis, + 'Z' in align_axis, + self.align_mode, + self.relative_to, + self.bb_quality) if not ret: self.report({'WARNING'}, "No objects with bound-box selected") |