merge with trunk r38787
This commit is contained in:
@@ -16,105 +16,211 @@
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
# <pep8-80 compliant>
|
||||
|
||||
import bpy
|
||||
from mathutils import Vector
|
||||
from blf import gettext as _
|
||||
|
||||
def GlobalBB_LQ(bb_world):
|
||||
|
||||
def align_objects(align_x, align_y, align_z, align_mode, relative_to):
|
||||
# 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:
|
||||
bb_world = [Vector(v[:]) * obj.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]
|
||||
|
||||
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)
|
||||
|
||||
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
|
||||
Left_Front_Up = GBB[0]
|
||||
Right_Back_Down = GBB[1]
|
||||
|
||||
positive_x = Right_Down_Back[0]
|
||||
positive_y = Right_Down_Back[1]
|
||||
positive_z = Left_Up_Front[2]
|
||||
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
|
||||
|
||||
negative_x = Left_Up_Front[0]
|
||||
negative_y = Left_Up_Front[1]
|
||||
negative_z = Right_Down_Back[2]
|
||||
positive_x = Right_Back_Down[0]
|
||||
positive_y = Right_Back_Down[1]
|
||||
positive_z = Left_Front_Up[2]
|
||||
|
||||
negative_x = Left_Front_Up[0]
|
||||
negative_y = Left_Front_Up[1]
|
||||
negative_z = Right_Back_Down[2]
|
||||
|
||||
obj_loc = obj.location
|
||||
|
||||
@@ -229,7 +335,7 @@ 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):
|
||||
@@ -238,6 +344,11 @@ class AlignObjects(bpy.types.Operator):
|
||||
bl_label = _("Align Objects")
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
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(items=(
|
||||
('OPT_1', "Negative Sides", ""),
|
||||
('OPT_2', "Centers", ""),
|
||||
@@ -270,7 +381,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")
|
||||
|
||||
Reference in New Issue
Block a user