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