update for new api changes
[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,2),
26     'blender': (2, 6, 0),
27     'category': '3D View'
28 }
29
30 import bpy
31 from bpy.props import IntProperty
32 from bpy.props import BoolProperty
33 from math import pi
34 import re
35
36 CAMERA_ORIGIN_NAME = "CameraOrigin"
37
38 # property for how many screens to add
39 bpy.types.WindowManager.num_surround_screens = IntProperty(
40     name="Number of screens",
41     description="How many screens to add",
42     default=4,
43     min=3)
44
45 # safeguard for removing previous cameras/scenes
46 bpy.types.WindowManager.previous_num_surround_screens = IntProperty(
47     name="Previous number of screens",
48     description="used for removing cameras/scenes",
49     default=-1)
50
51 # used to enable/disable make/remove scenes and cameras
52 bpy.types.WindowManager.surround_screens_init = BoolProperty(
53     name="SurroundScenesInit",
54     default=False)
55
56 # GUI panel
57 class AddSurroundCamerasPanel(bpy.types.Panel):
58     bl_space_type = 'VIEW_3D'
59     bl_region_type = 'TOOLS'
60     bl_label = "Surround Projection"
61
62     def draw(self, context):
63         layout = self.layout
64         col = layout.column(align=True)
65
66         row = col.row()
67         row.prop(context.window_manager, "num_surround_screens")
68         row = col.row()
69         
70         if context.window_manager.previous_num_surround_screens is not -1:
71              row.operator('objects.remove_surround_cameras', icon='X')
72         else:
73              row.operator('objects.add_surround_cameras', icon='CAMERA_DATA')
74         
75         row = col.row()
76         
77         if context.window_manager.surround_screens_init is True:
78              row.operator('objects.remove_linked_scenes_for_surround_cameras', icon='X')
79         else:
80              row.operator('scene.add_linked_scenes_for_surround_cameras', icon='SCENE_DATA')
81
82         #col = layout.column(align=True)
83         #row = col.row()
84         #row.operator('objects.remove_surround_cameras', icon='X')
85         #row = col.row()
86         #row.operator('objects.remove_linked_scenes_for_surround_cameras', icon='X')
87
88
89 # operator for adding cameras
90 class AddSurroundCamerasOperator(bpy.types.Operator):
91     bl_idname = 'objects.add_surround_cameras'
92     bl_label = "Add Cameras"
93     bl_description = "Add n cameras"
94     bl_options = {'REGISTER', 'UNDO'}
95
96     @classmethod
97     def poll(cls, context):
98         return context.window_manager.previous_num_surround_screens is -1
99
100     def execute(self, context):
101
102         scene = context.scene
103         numScreens = context.window_manager.num_surround_screens
104
105         # add an empty for the camera origin if not already present
106         obj_origin = scene.objects.get(CAMERA_ORIGIN_NAME)
107         if not obj_origin:
108             bpy.ops.object.add()
109             obj_origin = context.active_object
110             obj_origin.name = CAMERA_ORIGIN_NAME
111             obj_origin.location = scene.cursor_location
112
113         for i in range(0,numScreens):
114
115             # add a new camer
116             bpy.ops.object.camera_add()
117
118             # get the current camera
119             cam = context.active_object
120
121             # name the camera
122             cameraName = "Camera" + str(i)
123             cam.name = cameraName
124             cam.data.name = cameraName
125
126             # position camera
127             cam.location = 0,0,0
128             cam.rotation_euler = (pi/2), 0, ((-2*pi)/numScreens) * i
129
130             # set the field of view angle
131             cam.data.angle = (2*pi)/numScreens
132
133             # make the parent of the camera the origin
134             cam.parent = obj_origin
135
136         # sel/activate origin
137         bpy.ops.object.select_all(action='DESELECT')
138         obj_origin.select = True
139         scene.objects.active = obj_origin
140
141         context.window_manager.previous_num_surround_screens = numScreens
142         return {'FINISHED'}
143
144
145 # operator for creating new linked scenes for each camera
146 class AddSurroundScenesOperator(bpy.types.Operator):
147     bl_idname = 'scene.add_linked_scenes_for_surround_cameras'
148     bl_label = "Make Scenes"
149     bl_description = "Creates new scenes with linked object data for each camera"
150     bl_options = {'REGISTER', 'UNDO'}
151
152     @classmethod
153     def poll(cls, context):
154         if context.window_manager.previous_num_surround_screens is not -1 and context.window_manager.surround_screens_init is False:
155             return True
156         return False
157
158     def execute(self, context):
159         scene_base = context.scene
160         numScreens = context.window_manager.previous_num_surround_screens
161         sceneName = scene_base.name
162         renderpath = scene_base.render.filepath
163
164         for i in range(0, numScreens):
165
166             thisScene = sceneName + "-Camera" + str(i)
167
168             bpy.ops.scene.new(type='EMPTY')
169             scene_new = context.scene
170             scene_new.name = thisScene
171
172             camera_object = bpy.data.objects["Camera" + str(i)]
173             scene_new.camera = camera_object
174             scene_new.background_set = scene_base
175             
176             # not essential but nice to have the camera in the scene
177             scene_new.objects.link(camera_object)
178
179             scene_new.render.filepath = renderpath + thisScene
180
181         context.screen.scene = scene_base
182         context.window_manager.surround_screens_init = True
183         return {'FINISHED'}
184
185
186 # operator for removing the surround scenes
187 class RemoveSurroundScenesOperator(bpy.types.Operator):
188     bl_idname = 'objects.remove_linked_scenes_for_surround_cameras'
189     bl_label = "Remove Scenes"
190     bl_description = "Removes all surround scenes"
191     bl_options = {'REGISTER', 'UNDO'}
192
193     @classmethod
194     def poll(cls, context):
195         return context.window_manager.surround_screens_init is True
196
197     def execute(self, context):
198         numScreens = context.window_manager.previous_num_surround_screens
199
200         for scene in list(bpy.data.scenes):
201             if re.search("-Camera",scene.name):
202                 bpy.data.scenes.remove(scene)
203
204         context.window_manager.surround_screens_init = False
205         return {'FINISHED'}
206
207
208 # operator for removing the surround cameras/scenes
209 class RemoveSurroundCamerasOperator(bpy.types.Operator):
210     bl_idname = 'objects.remove_surround_cameras'
211     bl_label = "Remove Cameras"
212     bl_description = "Removes all surround cameras"
213     bl_options = {'REGISTER', 'UNDO'}
214
215     @classmethod
216     def poll(cls, context):
217         if context.window_manager.previous_num_surround_screens is not -1 and context.window_manager.surround_screens_init is False:
218             return True
219         return False
220
221     def execute(self, context):
222
223         scene = context.scene
224
225         # XXX. shouldnt there be some less general way to do this?
226         # like check if they are the child of origin? - campbell
227         for obj in scene.objects[:]:
228             if obj.type == 'CAMERA':
229                 scene.objects.unlink(obj)
230
231         context.window_manager.previous_num_surround_screens = -1
232         return {'FINISHED'}
233
234
235
236 def register():
237     bpy.utils.register_module(__name__)
238
239
240 def unregister():
241     bpy.utils.unregister_module(__name__)
242
243
244 if __name__ == "__main__":
245     register()