2010-02-11 23:27:34 +00:00
|
|
|
# ##### BEGIN GPL LICENSE BLOCK #####
|
|
|
|
#
|
|
|
|
# This program is free software; you can redistribute it and/or
|
|
|
|
# modify it under the terms of the GNU General Public License
|
|
|
|
# as published by the Free Software Foundation; either version 2
|
|
|
|
# of the License, or (at your option) any later version.
|
|
|
|
#
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
|
# along with this program; if not, write to the Free Software Foundation,
|
2010-02-12 13:34:04 +00:00
|
|
|
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2010-02-11 23:27:34 +00:00
|
|
|
#
|
|
|
|
# ##### END GPL LICENSE BLOCK #####
|
|
|
|
|
|
|
|
# <pep8 compliant>
|
|
|
|
|
|
|
|
import bpy
|
2010-04-11 14:22:27 +00:00
|
|
|
from mathutils import Vector
|
2010-02-11 23:27:34 +00:00
|
|
|
|
|
|
|
|
2010-02-15 06:01:13 +00:00
|
|
|
def align_objects(align_x, align_y, align_z, align_mode, relative_to):
|
2010-02-11 23:27:34 +00:00
|
|
|
|
2010-02-12 01:03:22 +00:00
|
|
|
cursor = bpy.context.scene.cursor_location
|
|
|
|
|
2010-04-17 19:05:53 +00:00
|
|
|
Left_Up_Front_SEL = [[], [], []]
|
|
|
|
Right_Down_Back_SEL = [[], [], []]
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-12 05:02:29 +00:00
|
|
|
flag_first = True
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-12 05:02:29 +00:00
|
|
|
for obj in bpy.context.selected_objects:
|
2010-02-17 08:57:40 +00:00
|
|
|
if obj.type == 'MESH':
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-07-03 17:39:29 +00:00
|
|
|
bb_world = [obj.matrix_world * Vector(v[:]) for v in obj.bound_box]
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
Left_Up_Front = bb_world[1]
|
|
|
|
Right_Down_Back = bb_world[7]
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
# Active Center
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
if obj == bpy.context.active_object:
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-04-17 19:05:53 +00:00
|
|
|
center_active_x = (Left_Up_Front[0] + Right_Down_Back[0]) / 2
|
|
|
|
center_active_y = (Left_Up_Front[1] + Right_Down_Back[1]) / 2
|
|
|
|
center_active_z = (Left_Up_Front[2] + Right_Down_Back[2]) / 2
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-04-17 19:05:53 +00:00
|
|
|
size_active_x = (Right_Down_Back[0] - Left_Up_Front[0]) / 2
|
|
|
|
size_active_y = (Right_Down_Back[1] - Left_Up_Front[1]) / 2
|
|
|
|
size_active_z = (Left_Up_Front[2] - Right_Down_Back[2]) / 2
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
# Selection Center
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
if flag_first:
|
|
|
|
flag_first = False
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-12 05:02:29 +00:00
|
|
|
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]
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-12 05:02:29 +00:00
|
|
|
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]
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
else:
|
|
|
|
# X axis
|
|
|
|
if Left_Up_Front[0] < Left_Up_Front_SEL[0]:
|
|
|
|
Left_Up_Front_SEL[0] = Left_Up_Front[0]
|
|
|
|
# Y axis
|
|
|
|
if Left_Up_Front[1] < Left_Up_Front_SEL[1]:
|
|
|
|
Left_Up_Front_SEL[1] = Left_Up_Front[1]
|
|
|
|
# Z axis
|
|
|
|
if Left_Up_Front[2] > Left_Up_Front_SEL[2]:
|
|
|
|
Left_Up_Front_SEL[2] = Left_Up_Front[2]
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
# X axis
|
|
|
|
if Right_Down_Back[0] > Right_Down_Back_SEL[0]:
|
|
|
|
Right_Down_Back_SEL[0] = Right_Down_Back[0]
|
|
|
|
# Y axis
|
|
|
|
if Right_Down_Back[1] > Right_Down_Back_SEL[1]:
|
|
|
|
Right_Down_Back_SEL[1] = Right_Down_Back[1]
|
|
|
|
# Z axis
|
|
|
|
if Right_Down_Back[2] < Right_Down_Back_SEL[2]:
|
|
|
|
Right_Down_Back_SEL[2] = Right_Down_Back[2]
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-04-17 19:05:53 +00:00
|
|
|
center_sel_x = (Left_Up_Front_SEL[0] + Right_Down_Back_SEL[0]) / 2
|
|
|
|
center_sel_y = (Left_Up_Front_SEL[1] + Right_Down_Back_SEL[1]) / 2
|
|
|
|
center_sel_z = (Left_Up_Front_SEL[2] + Right_Down_Back_SEL[2]) / 2
|
2010-02-12 05:02:29 +00:00
|
|
|
|
2010-02-13 23:29:26 +00:00
|
|
|
# Main Loop
|
2010-02-12 05:02:29 +00:00
|
|
|
|
2010-02-11 23:27:34 +00:00
|
|
|
for obj in bpy.context.selected_objects:
|
2010-02-17 08:57:40 +00:00
|
|
|
if obj.type == 'MESH':
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
loc_world = obj.location
|
2010-07-03 17:39:29 +00:00
|
|
|
bb_world = [obj.matrix_world * Vector(v[:]) for v in obj.bound_box]
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
Left_Up_Front = bb_world[1]
|
|
|
|
Right_Down_Back = bb_world[7]
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-04-17 19:05:53 +00:00
|
|
|
center_x = (Left_Up_Front[0] + Right_Down_Back[0]) / 2
|
|
|
|
center_y = (Left_Up_Front[1] + Right_Down_Back[1]) / 2
|
|
|
|
center_z = (Left_Up_Front[2] + Right_Down_Back[2]) / 2
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
positive_x = Right_Down_Back[0]
|
|
|
|
positive_y = Right_Down_Back[1]
|
|
|
|
positive_z = Left_Up_Front[2]
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
negative_x = Left_Up_Front[0]
|
|
|
|
negative_y = Left_Up_Front[1]
|
|
|
|
negative_z = Right_Down_Back[2]
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
obj_loc = obj.location
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
if align_x:
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
# Align Mode
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
if relative_to == 'OPT_4': # Active relative
|
|
|
|
if align_mode == 'OPT_1':
|
|
|
|
obj_x = obj_loc[0] - negative_x - size_active_x
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
elif align_mode == 'OPT_3':
|
|
|
|
obj_x = obj_loc[0] - positive_x + size_active_x
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
else: # Everything else relative
|
|
|
|
if align_mode == 'OPT_1':
|
|
|
|
obj_x = obj_loc[0] - negative_x
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
elif align_mode == 'OPT_3':
|
|
|
|
obj_x = obj_loc[0] - positive_x
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
if align_mode == 'OPT_2': # All relative
|
|
|
|
obj_x = obj_loc[0] - center_x
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
# Relative To
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
if relative_to == 'OPT_1':
|
|
|
|
loc_x = obj_x
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
elif relative_to == 'OPT_2':
|
|
|
|
loc_x = obj_x + cursor[0]
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
elif relative_to == 'OPT_3':
|
|
|
|
loc_x = obj_x + center_sel_x
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
elif relative_to == 'OPT_4':
|
|
|
|
loc_x = obj_x + center_active_x
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
obj.location[0] = loc_x
|
2010-02-22 23:32:58 +00:00
|
|
|
|
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
if align_y:
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
# Align Mode
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
if relative_to == 'OPT_4': # Active relative
|
|
|
|
if align_mode == 'OPT_1':
|
|
|
|
obj_y = obj_loc[1] - negative_y - size_active_y
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
elif align_mode == 'OPT_3':
|
|
|
|
obj_y = obj_loc[1] - positive_y + size_active_y
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
else: # Everything else relative
|
|
|
|
if align_mode == 'OPT_1':
|
|
|
|
obj_y = obj_loc[1] - negative_y
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
elif align_mode == 'OPT_3':
|
|
|
|
obj_y = obj_loc[1] - positive_y
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
if align_mode == 'OPT_2': # All relative
|
|
|
|
obj_y = obj_loc[1] - center_y
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
# Relative To
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
if relative_to == 'OPT_1':
|
|
|
|
loc_y = obj_y
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
elif relative_to == 'OPT_2':
|
|
|
|
loc_y = obj_y + cursor[1]
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
elif relative_to == 'OPT_3':
|
|
|
|
loc_y = obj_y + center_sel_y
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
elif relative_to == 'OPT_4':
|
|
|
|
loc_y = obj_y + center_active_y
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
obj.location[1] = loc_y
|
2010-02-22 23:32:58 +00:00
|
|
|
|
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
if align_z:
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
# Align Mode
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
if relative_to == 'OPT_4': # Active relative
|
|
|
|
if align_mode == 'OPT_1':
|
|
|
|
obj_z = obj_loc[2] - negative_z - size_active_z
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
elif align_mode == 'OPT_3':
|
|
|
|
obj_z = obj_loc[2] - positive_z + size_active_z
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
else: # Everything else relative
|
|
|
|
if align_mode == 'OPT_1':
|
|
|
|
obj_z = obj_loc[2] - negative_z
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
elif align_mode == 'OPT_3':
|
|
|
|
obj_z = obj_loc[2] - positive_z
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
if align_mode == 'OPT_2': # All relative
|
|
|
|
obj_z = obj_loc[2] - center_z
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
# Relative To
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
if relative_to == 'OPT_1':
|
|
|
|
loc_z = obj_z
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
elif relative_to == 'OPT_2':
|
|
|
|
loc_z = obj_z + cursor[2]
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
elif relative_to == 'OPT_3':
|
|
|
|
loc_z = obj_z + center_sel_z
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
elif relative_to == 'OPT_4':
|
|
|
|
loc_z = obj_z + center_active_z
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-17 08:57:40 +00:00
|
|
|
obj.location[2] = loc_z
|
2010-02-11 23:27:34 +00:00
|
|
|
|
|
|
|
|
|
|
|
from bpy.props import *
|
|
|
|
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-12 05:02:29 +00:00
|
|
|
class AlignObjects(bpy.types.Operator):
|
2010-02-11 23:27:34 +00:00
|
|
|
'''Align Objects'''
|
|
|
|
bl_idname = "object.align"
|
2010-02-15 10:06:27 +00:00
|
|
|
bl_label = "Align Objects"
|
2010-03-01 00:03:51 +00:00
|
|
|
bl_options = {'REGISTER', 'UNDO'}
|
2010-02-12 01:03:22 +00:00
|
|
|
|
2010-02-15 06:01:13 +00:00
|
|
|
align_mode = bpy.props.EnumProperty(items=(
|
|
|
|
('OPT_1', "Negative Sides", ""),
|
|
|
|
('OPT_2', "Centers", ""),
|
2010-04-17 19:05:53 +00:00
|
|
|
('OPT_3', "Positive Sides", "")),
|
2010-02-15 06:01:13 +00:00
|
|
|
name="Align Mode:",
|
|
|
|
description="",
|
|
|
|
default='OPT_2')
|
|
|
|
|
2010-02-12 01:03:22 +00:00
|
|
|
relative_to = bpy.props.EnumProperty(items=(
|
2010-02-12 05:02:29 +00:00
|
|
|
('OPT_1', "Scene Origin", ""),
|
|
|
|
('OPT_2', "3D Cursor", ""),
|
2010-02-13 23:29:26 +00:00
|
|
|
('OPT_3', "Selection", ""),
|
2010-04-17 19:05:53 +00:00
|
|
|
('OPT_4', "Active", "")),
|
2010-02-12 01:03:22 +00:00
|
|
|
name="Relative To:",
|
2010-02-12 05:02:29 +00:00
|
|
|
description="",
|
2010-02-15 06:01:13 +00:00
|
|
|
default='OPT_4')
|
|
|
|
|
2010-02-11 23:27:34 +00:00
|
|
|
align_x = BoolProperty(name="Align X",
|
|
|
|
description="Align in the X axis", default=False)
|
|
|
|
|
|
|
|
align_y = BoolProperty(name="Align Y",
|
|
|
|
description="Align in the Y axis", default=False)
|
|
|
|
|
|
|
|
align_z = BoolProperty(name="Align Z",
|
|
|
|
description="Align in the Z axis", default=False)
|
|
|
|
|
2010-08-09 01:37:09 +00:00
|
|
|
@classmethod
|
|
|
|
def poll(cls, context):
|
2010-02-22 13:25:32 +00:00
|
|
|
return context.mode == 'OBJECT'
|
|
|
|
|
2010-02-11 23:27:34 +00:00
|
|
|
def execute(self, context):
|
2010-09-09 18:03:57 +00:00
|
|
|
align_objects(self.align_x, self.align_y, self.align_z, self.align_mode, self.relative_to)
|
2010-02-11 23:27:34 +00:00
|
|
|
|
|
|
|
return {'FINISHED'}
|
|
|
|
|
|
|
|
|
|
|
|
def menu_func(self, context):
|
|
|
|
if context.mode == 'OBJECT':
|
2010-02-12 05:02:29 +00:00
|
|
|
self.layout.operator(AlignObjects.bl_idname,
|
2010-02-11 23:27:34 +00:00
|
|
|
text="Align Objects")
|
|
|
|
|
2010-02-14 11:21:21 +00:00
|
|
|
|
|
|
|
def register():
|
|
|
|
bpy.types.VIEW3D_MT_transform.append(menu_func)
|
|
|
|
|
2010-02-22 23:32:58 +00:00
|
|
|
|
2010-02-14 11:21:21 +00:00
|
|
|
def unregister():
|
2010-02-15 10:06:27 +00:00
|
|
|
bpy.types.VIEW3D_MT_transform.remove(menu_func)
|
2010-02-16 09:55:07 +00:00
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
register()
|