change python scripts so modules which register with blender have a register() functi...
[blender.git] / release / scripts / op / object_align.py
1 # ##### BEGIN GPL LICENSE BLOCK #####
2 #
3 #  This program is free software; you can redistribute it and/or
4 #  modify it under the terms of the GNU General Public License
5 #  as published by the Free Software Foundation; either version 2
6 #  of the License, or (at your option) any later version.
7 #
8 #  This program is distributed in the hope that it will be useful,
9 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 #  GNU General Public License for more details.
12 #
13 #  You should have received a copy of the GNU General Public License
14 #  along with this program; if not, write to the Free Software Foundation,
15 #  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 #
17 # ##### END GPL LICENSE BLOCK #####
18
19 # <pep8 compliant>
20
21 import bpy
22 from Mathutils import Vector
23
24
25 def align_objects(align_x, align_y, align_z, relative_to):
26
27     cursor = bpy.context.scene.cursor_location
28
29     Left_Up_Front_SEL = [[],[],[]]
30     Right_Down_Back_SEL = [[],[],[]]
31     
32     flag_first = True
33     
34     for obj in bpy.context.selected_objects:
35             
36         bb_world = [obj.matrix * Vector(v[:]) for v in obj.bound_box]
37         
38         Left_Up_Front = bb_world[1]
39         Right_Down_Back = bb_world[7]
40
41         # Active Center
42
43         if obj == bpy.context.active_object:
44             
45             center_active_x = ( Left_Up_Front[0] + Right_Down_Back[0] ) / 2
46             center_active_y = ( Left_Up_Front[1] + Right_Down_Back[1] ) / 2
47             center_active_z = ( Left_Up_Front[2] + Right_Down_Back[2] ) / 2
48
49         # Selection Center
50
51         if flag_first:
52             flag_first = False
53     
54             Left_Up_Front_SEL[0] = Left_Up_Front[0]
55             Left_Up_Front_SEL[1] = Left_Up_Front[1]
56             Left_Up_Front_SEL[2] = Left_Up_Front[2]
57     
58             Right_Down_Back_SEL[0] = Right_Down_Back[0]
59             Right_Down_Back_SEL[1] = Right_Down_Back[1]
60             Right_Down_Back_SEL[2] = Right_Down_Back[2]
61     
62         else:
63             # X axis
64             if Left_Up_Front[0] < Left_Up_Front_SEL[0]:
65                 Left_Up_Front_SEL[0] = Left_Up_Front[0]
66             # Y axis
67             if Left_Up_Front[1] < Left_Up_Front_SEL[1]:
68                 Left_Up_Front_SEL[1] = Left_Up_Front[1]
69             # Z axis
70             if Left_Up_Front[2] > Left_Up_Front_SEL[2]:
71                 Left_Up_Front_SEL[2] = Left_Up_Front[2]
72     
73             # X axis
74             if Right_Down_Back[0] > Right_Down_Back_SEL[0]:
75                 Right_Down_Back_SEL[0] = Right_Down_Back[0]
76             # Y axis
77             if Right_Down_Back[1] > Right_Down_Back_SEL[1]:
78                 Right_Down_Back_SEL[1] = Right_Down_Back[1]
79             # Z axis
80             if Right_Down_Back[2] < Right_Down_Back_SEL[2]:
81                 Right_Down_Back_SEL[2] = Right_Down_Back[2]
82     
83     center_sel_x = ( Left_Up_Front_SEL[0] + Right_Down_Back_SEL[0] ) / 2
84     center_sel_y = ( Left_Up_Front_SEL[1] + Right_Down_Back_SEL[1] ) / 2
85     center_sel_z = ( Left_Up_Front_SEL[2] + Right_Down_Back_SEL[2] ) / 2
86
87     # Main Loop
88
89     for obj in bpy.context.selected_objects:
90         
91         loc_world = obj.location
92         bb_world = [obj.matrix * Vector(v[:]) for v in obj.bound_box]
93     
94         Left_Up_Front = bb_world[1]
95         Right_Down_Back = bb_world[7]
96     
97         center_x = ( Left_Up_Front[0] + Right_Down_Back[0] ) / 2
98         center_y = ( Left_Up_Front[1] + Right_Down_Back[1] ) / 2
99         center_z = ( Left_Up_Front[2] + Right_Down_Back[2] ) / 2
100
101         obj_loc = obj.location
102     
103         if align_x:
104
105             obj_x = obj_loc[0] - center_x
106
107             if relative_to == 'OPT_1':
108                 loc_x = obj_x
109             
110             elif relative_to == 'OPT_2':
111                 loc_x = obj_x + cursor[0]
112             
113             elif relative_to == 'OPT_3':
114                 loc_x = obj_x + center_sel_x
115
116             elif relative_to == 'OPT_4':
117                 loc_x = obj_x + center_active_x
118             
119             obj.location[0] = loc_x
120
121
122         if align_y:
123
124             obj_y = obj_loc[1] - center_y
125
126             if relative_to == 'OPT_1':
127                 loc_y = obj_y
128             
129             elif relative_to == 'OPT_2':
130                 loc_y = obj_y + cursor[1]
131             
132             elif relative_to == 'OPT_3':
133                 loc_y = obj_y + center_sel_y
134
135             elif relative_to == 'OPT_4':
136                 loc_y = obj_y + center_active_y
137             
138             obj.location[1] = loc_y
139
140
141         if align_z:
142
143             obj_z = obj_loc[2] - center_z
144
145             if relative_to == 'OPT_1':
146                 loc_z = obj_z
147             
148             elif relative_to == 'OPT_2':
149                 loc_z = obj_z + cursor[2]
150             
151             elif relative_to == 'OPT_3':
152                 loc_z = obj_z + center_sel_z
153
154             elif relative_to == 'OPT_4':
155                 loc_z = obj_z + center_active_z
156             
157             obj.location[2] = loc_z
158
159
160 from bpy.props import *
161
162 class AlignObjects(bpy.types.Operator):
163     '''Align Objects'''
164     bl_idname = "object.align"
165     bl_label = "Align Objets"
166     bl_register = True
167     bl_undo = True
168
169     relative_to = bpy.props.EnumProperty(items=(
170             ('OPT_1', "Scene Origin", ""),
171             ('OPT_2', "3D Cursor", ""),
172             ('OPT_3', "Selection", ""),
173             ('OPT_4', "Active", "")
174             ),
175         name="Relative To:",
176         description="",
177         default='OPT_1')
178     
179     align_x = BoolProperty(name="Align X",
180         description="Align in the X axis", default=False)
181
182     align_y = BoolProperty(name="Align Y",
183         description="Align in the Y axis", default=False)
184
185     align_z = BoolProperty(name="Align Z",
186         description="Align in the Z axis", default=False)
187
188     def execute(self, context):
189     
190         relative_to = self.properties.relative_to
191         align_x = self.properties.align_x
192         align_y = self.properties.align_y
193         align_z = self.properties.align_z
194
195         align_objects(align_x, align_y, align_z, relative_to)
196
197         return {'FINISHED'}
198
199
200 def menu_func(self, context):
201     if context.mode == 'OBJECT':
202         self.layout.operator(AlignObjects.bl_idname,
203         text="Align Objects")
204
205
206 def register():
207     bpy.types.register(AlignObjects)
208     bpy.types.VIEW3D_MT_transform.append(menu_func)
209
210 def unregister():
211     bpy.types.unregister(AlignObjects)
212     bpy.types.VIEW3D_MT_transform.remove(menu_func)