initial commit. made changes suggested in patch tracker. removing cameras now does...
[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://coleingraham.com/2011/11/14/using-the-surround-projection-tools-addon-for-blender-2-6/",
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 = bpy.context.active_object
100             originExists = True
101             break
102       
103       if not originExists:
104          bpy.ops.object.add()
105          origin = bpy.context.active_object
106          origin.name = "CameraOrigin"
107          origin.location = bpy.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 = bpy.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 = bpy.context.scene.name
153       renderpath = bpy.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          bpy.context.scene.name = thisScene
161          
162          bpy.context.scene.camera = bpy.data.objects["Camera" + str(i)]
163          
164          bpy.context.scene.render.filepath = renderpath + thisScene
165
166       bpy.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     pass
223     
224 def unregister():
225     bpy.utils.unregister_module(__name__)
226     
227     pass
228     
229 if __name__ == "__main__":
230     register()