set indent from 3 -> 4 spaces, replace bpy.context with context when its available
[blender-addons-contrib.git] / space_view3d_add_surround_cameras.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 bl_info = {
20     'name': "Surround Projection Tools",
21     'author': "Cole Ingraham",
22     'location': "View3D > Tool Shelf > Surround Projection panel",
23     'description': "Setup cameras and create rendering scenes for n-screen surround projection.",
24     'wiki_url': "http://wiki.blender.org/index.php/Extensions:2.5/Py/Scripts/3D_interaction/Surround_Projection_Tools",
25     'version': (0,1,1),
26     'blender': (2, 6, 0),
27     'api': 41769,
28     'category': '3D View'
29 }
30
31 import bpy
32 from bpy.props import IntProperty
33 from bpy.props import BoolProperty
34 from math import pi
35 import re
36
37 # property for how many screens to add
38 bpy.types.WindowManager.num_surround_screens = IntProperty(
39     name="Number of screens",
40     description="How many screens to add",
41     default=4,
42     min=3)
43
44 # safeguard for removing previous cameras/scenes
45 bpy.types.WindowManager.previous_num_surround_screens = IntProperty(
46     name="Previous number of screens",
47     description="used for removing cameras/scenes",
48     default=-1)
49
50 # used to enable/disable make/remove scenes and cameras
51 bpy.types.WindowManager.surround_screens_init = BoolProperty(
52     name="SurroundScenesInit",
53     default=False)
54
55 # GUI panel
56 class AddSurroundCamerasPanel(bpy.types.Panel):
57     bl_space_type = 'VIEW_3D'
58     bl_region_type = 'TOOLS'
59     bl_label = "Surround Projection"
60
61     def draw(self, context):
62         layout = self.layout
63         col = layout.column(align=True)
64
65         row = col.row()
66         row.prop(context.window_manager, "num_surround_screens")
67         row = col.row()
68         row.operator('objects.add_surround_cameras', icon='CAMERA_DATA')
69         row = col.row()
70         row.operator('scene.add_linked_scenes_for_surround_cameras', icon='SCENE_DATA')
71
72         col = layout.column(align=True)
73         row = col.row()
74         row.operator('objects.remove_surround_cameras', icon='X')
75         row = col.row()
76         row.operator('objects.remove_linked_scenes_for_surround_cameras', icon='X')
77
78
79 # operator for adding cameras
80 class AddSurroundCamerasOperator(bpy.types.Operator):
81     bl_idname = 'objects.add_surround_cameras'
82     bl_label = "Add Cameras"
83     bl_description = "Add n cameras"
84     bl_options = {'REGISTER', 'UNDO'}
85
86     @classmethod
87     def poll(cls, context):
88         return context.window_manager.previous_num_surround_screens is -1
89
90     def execute(self, context):
91
92         numScreens = context.window_manager.num_surround_screens
93
94         # add an empty for the camera origin if not already present
95         originExists = False
96         for object in bpy.data.objects:
97             if object.name == "CameraOrigin":
98                 bpy.ops.object.select_name(name="CameraOrigin")
99                 origin = context.active_object
100                 originExists = True
101                 break
102
103         if not originExists:
104             bpy.ops.object.add()
105             origin = context.active_object
106             origin.name = "CameraOrigin"
107             origin.location = context.scene.cursor_location
108
109         for i in range(0,numScreens):
110
111             # add a new camer
112             bpy.ops.object.camera_add()
113
114             # get the current camera
115             cam = context.active_object
116
117             # name the camera
118             cameraName = "Camera" + str(i)
119             cam.name = cameraName
120             cam.data.name = cameraName
121
122             # position camera
123             cam.location = 0,0,0
124             cam.rotation_euler = (pi/2), 0, ((-2*pi)/numScreens) * i
125
126             # set the field of view angle
127             cam.data.angle = (2*pi)/numScreens
128
129             # make the parent of the camera the origin
130             cam.parent = origin
131
132         bpy.ops.object.select_name(name="CameraOrigin")
133         context.window_manager.previous_num_surround_screens = numScreens
134         return {'FINISHED'}
135
136
137 # operator for creating new linked scenes for each camera
138 class AddSurroundScenesOperator(bpy.types.Operator):
139     bl_idname = 'scene.add_linked_scenes_for_surround_cameras'
140     bl_label = "Make Scenes"
141     bl_description = "Creates new scenes with linked object data for each camera"
142     bl_options = {'REGISTER', 'UNDO'}
143
144     @classmethod
145     def poll(cls, context):
146         if context.window_manager.previous_num_surround_screens is not -1 and context.window_manager.surround_screens_init is False:
147             return True
148         return False
149
150     def execute(self, context):
151         numScreens = context.window_manager.previous_num_surround_screens
152         sceneName = context.scene.name
153         renderpath = context.scene.render.filepath
154
155         for i in range(0, numScreens):
156
157             thisScene = sceneName + "-Camera" + str(i)
158
159             bpy.ops.scene.new(type='LINK_OBJECTS')
160             context.scene.name = thisScene
161
162             context.scene.camera = bpy.data.objects["Camera" + str(i)]
163
164             context.scene.render.filepath = renderpath + thisScene
165
166         context.screen.scene = bpy.data.scenes[sceneName]
167         context.window_manager.surround_screens_init = True
168         return {'FINISHED'}
169
170
171 # operator for removing the surround scenes
172 class RemoveSurroundScenesOperator(bpy.types.Operator):
173     bl_idname = 'objects.remove_linked_scenes_for_surround_cameras'
174     bl_label = "Remove Scenes"
175     bl_description = "Removes all surround scenes"
176     bl_options = {'REGISTER', 'UNDO'}
177
178     @classmethod
179     def poll(cls, context):
180         return context.window_manager.surround_screens_init is True
181
182     def execute(self, context):
183         numScreens = context.window_manager.previous_num_surround_screens
184
185         for scene in list(bpy.data.scenes):
186             if re.search("-Camera",scene.name):
187                 bpy.data.scenes.remove(scene)
188
189         context.window_manager.surround_screens_init = False
190         return {'FINISHED'}
191
192
193 # operator for removing the surround cameras/scenes
194 class RemoveSurroundCamerasOperator(bpy.types.Operator):
195     bl_idname = 'objects.remove_surround_cameras'
196     bl_label = "Remove Cameras"
197     bl_description = "Removes all surround cameras"
198     bl_options = {'REGISTER', 'UNDO'}
199
200     @classmethod
201     def poll(cls, context):
202         if context.window_manager.previous_num_surround_screens is not -1 and context.window_manager.surround_screens_init is False:
203             return True
204         return False
205
206     def execute(self, context):
207         numScreens = context.window_manager.previous_num_surround_screens
208
209         for object in bpy.data.objects:
210             if object.type == 'CAMERA':
211                 bpy.ops.object.select_name(name=object.name)
212                 bpy.ops.object.delete()
213
214         context.window_manager.previous_num_surround_screens = -1
215         return {'FINISHED'}
216
217
218
219 def register():
220     bpy.utils.register_module(__name__)
221
222
223 def unregister():
224     bpy.utils.unregister_module(__name__)
225
226
227 if __name__ == "__main__":
228     register()