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