added Campbell's background scene patch. streamlined gui.
[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     '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         
69         if context.window_manager.previous_num_surround_screens is not -1:
70              row.operator('objects.remove_surround_cameras', icon='X')
71         else:
72              row.operator('objects.add_surround_cameras', icon='CAMERA_DATA')
73         
74         row = col.row()
75         
76         if context.window_manager.surround_screens_init is True:
77              row.operator('objects.remove_linked_scenes_for_surround_cameras', icon='X')
78         else:
79              row.operator('scene.add_linked_scenes_for_surround_cameras', icon='SCENE_DATA')
80
81         #col = layout.column(align=True)
82         #row = col.row()
83         #row.operator('objects.remove_surround_cameras', icon='X')
84         #row = col.row()
85         #row.operator('objects.remove_linked_scenes_for_surround_cameras', icon='X')
86
87
88 # operator for adding cameras
89 class AddSurroundCamerasOperator(bpy.types.Operator):
90     bl_idname = 'objects.add_surround_cameras'
91     bl_label = "Add Cameras"
92     bl_description = "Add n cameras"
93     bl_options = {'REGISTER', 'UNDO'}
94
95     @classmethod
96     def poll(cls, context):
97         return context.window_manager.previous_num_surround_screens is -1
98
99     def execute(self, context):
100
101         numScreens = context.window_manager.num_surround_screens
102
103         # add an empty for the camera origin if not already present
104         originExists = False
105         for object in bpy.data.objects:
106             if object.name == "CameraOrigin":
107                 bpy.ops.object.select_name(name="CameraOrigin")
108                 origin = context.active_object
109                 originExists = True
110                 break
111
112         if not originExists:
113             bpy.ops.object.add()
114             origin = context.active_object
115             origin.name = "CameraOrigin"
116             origin.location = context.scene.cursor_location
117
118         for i in range(0,numScreens):
119
120             # add a new camer
121             bpy.ops.object.camera_add()
122
123             # get the current camera
124             cam = context.active_object
125
126             # name the camera
127             cameraName = "Camera" + str(i)
128             cam.name = cameraName
129             cam.data.name = cameraName
130
131             # position camera
132             cam.location = 0,0,0
133             cam.rotation_euler = (pi/2), 0, ((-2*pi)/numScreens) * i
134
135             # set the field of view angle
136             cam.data.angle = (2*pi)/numScreens
137
138             # make the parent of the camera the origin
139             cam.parent = origin
140
141         bpy.ops.object.select_name(name="CameraOrigin")
142         context.window_manager.previous_num_surround_screens = numScreens
143         return {'FINISHED'}
144
145
146 # operator for creating new linked scenes for each camera
147 class AddSurroundScenesOperator(bpy.types.Operator):
148     bl_idname = 'scene.add_linked_scenes_for_surround_cameras'
149     bl_label = "Make Scenes"
150     bl_description = "Creates new scenes with linked object data for each camera"
151     bl_options = {'REGISTER', 'UNDO'}
152
153     @classmethod
154     def poll(cls, context):
155         if context.window_manager.previous_num_surround_screens is not -1 and context.window_manager.surround_screens_init is False:
156             return True
157         return False
158
159     def execute(self, context):
160         scene_base = context.scene
161         numScreens = context.window_manager.previous_num_surround_screens
162         sceneName = scene_base.name
163         renderpath = scene_base.render.filepath
164
165         for i in range(0, numScreens):
166
167             thisScene = sceneName + "-Camera" + str(i)
168
169             bpy.ops.scene.new(type='EMPTY')
170             scene_new = context.scene
171             scene_new.name = thisScene
172
173             camera_object = bpy.data.objects["Camera" + str(i)]
174             scene_new.camera = camera_object
175             scene_new.background_set = scene_base
176             
177             # not essential but nice to have the camera in the scene
178             scene_new.objects.link(camera_object)
179
180             scene_new.render.filepath = renderpath + thisScene
181
182         context.screen.scene = scene_base
183         context.window_manager.surround_screens_init = True
184         return {'FINISHED'}
185
186
187 # operator for removing the surround scenes
188 class RemoveSurroundScenesOperator(bpy.types.Operator):
189     bl_idname = 'objects.remove_linked_scenes_for_surround_cameras'
190     bl_label = "Remove Scenes"
191     bl_description = "Removes all surround scenes"
192     bl_options = {'REGISTER', 'UNDO'}
193
194     @classmethod
195     def poll(cls, context):
196         return context.window_manager.surround_screens_init is True
197
198     def execute(self, context):
199         numScreens = context.window_manager.previous_num_surround_screens
200
201         for scene in list(bpy.data.scenes):
202             if re.search("-Camera",scene.name):
203                 bpy.data.scenes.remove(scene)
204
205         context.window_manager.surround_screens_init = False
206         return {'FINISHED'}
207
208
209 # operator for removing the surround cameras/scenes
210 class RemoveSurroundCamerasOperator(bpy.types.Operator):
211     bl_idname = 'objects.remove_surround_cameras'
212     bl_label = "Remove Cameras"
213     bl_description = "Removes all surround cameras"
214     bl_options = {'REGISTER', 'UNDO'}
215
216     @classmethod
217     def poll(cls, context):
218         if context.window_manager.previous_num_surround_screens is not -1 and context.window_manager.surround_screens_init is False:
219             return True
220         return False
221
222     def execute(self, context):
223         numScreens = context.window_manager.previous_num_surround_screens
224
225         for object in bpy.data.objects:
226             if object.type == 'CAMERA':
227                 bpy.ops.object.select_name(name=object.name)
228                 bpy.ops.object.delete()
229
230         context.window_manager.previous_num_surround_screens = -1
231         return {'FINISHED'}
232
233
234
235 def register():
236     bpy.utils.register_module(__name__)
237
238
239 def unregister():
240     bpy.utils.unregister_module(__name__)
241
242
243 if __name__ == "__main__":
244     register()