Skip to content
Snippets Groups Projects
space_view3d_add_surround_cameras.py 8.05 KiB
Newer Older
  • Learn to ignore specific revisions
  • # ##### BEGIN GPL LICENSE BLOCK #####
    #
    #  This program is free software; you can redistribute it and/or
    #  modify it under the terms of the GNU General Public License
    #  as published by the Free Software Foundation; either version 2
    #  of the License, or (at your option) any later version.
    #
    #  This program is distributed in the hope that it will be useful,
    #  but WITHOUT ANY WARRANTY; without even the implied warranty of
    #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    #  GNU General Public License for more details.
    #
    #  You should have received a copy of the GNU General Public License
    #  along with this program; if not, write to the Free Software Foundation,
    #  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
    #
    # ##### END GPL LICENSE BLOCK #####
    
    bl_info = {
    
    Campbell Barton's avatar
    Campbell Barton committed
        "name": "Surround Projection Tools",
        "author": "Cole Ingraham",
    
    Campbell Barton's avatar
    Campbell Barton committed
        "location": "View3D > Tool Shelf > Surround Projection panel",
        "description": "Setup cameras and create rendering scenes for n-screen surround projection.",
        "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.6/Py/Scripts/3D_interaction/Surround_Projection_Tools",
    
        "tracker_url": "https://developer.blender.org/T29266",
        "category": "3D View"}
    
    
    
    import bpy
    from bpy.props import IntProperty
    from bpy.props import BoolProperty
    from math import pi
    import re
    
    
    CAMERA_ORIGIN_NAME = "CameraOrigin"
    
    
    # property for how many screens to add
    bpy.types.WindowManager.num_surround_screens = IntProperty(
        name="Number of screens",
        description="How many screens to add",
        default=4,
        min=3)
    
    # safeguard for removing previous cameras/scenes
    bpy.types.WindowManager.previous_num_surround_screens = IntProperty(
        name="Previous number of screens",
        description="used for removing cameras/scenes",
        default=-1)
    
    # used to enable/disable make/remove scenes and cameras
    bpy.types.WindowManager.surround_screens_init = BoolProperty(
        name="SurroundScenesInit",
        default=False)
    
    # GUI panel
    class AddSurroundCamerasPanel(bpy.types.Panel):
    
        bl_space_type = 'VIEW_3D'
        bl_region_type = 'TOOLS'
        bl_label = "Surround Projection"
    
        bl_options = {'DEFAULT_CLOSED'}
    
        def draw(self, context):
            layout = self.layout
            col = layout.column(align=True)
    
            row = col.row()
            row.prop(context.window_manager, "num_surround_screens")
            row = col.row()
    
            if context.window_manager.previous_num_surround_screens is not -1:
                 row.operator('objects.remove_surround_cameras', icon='X')
            else:
                 row.operator('objects.add_surround_cameras', icon='CAMERA_DATA')
    
            if context.window_manager.surround_screens_init is True:
                 row.operator('objects.remove_linked_scenes_for_surround_cameras', icon='X')
            else:
                 row.operator('scene.add_linked_scenes_for_surround_cameras', icon='SCENE_DATA')
    
            #col = layout.column(align=True)
            #row = col.row()
            #row.operator('objects.remove_surround_cameras', icon='X')
            #row = col.row()
            #row.operator('objects.remove_linked_scenes_for_surround_cameras', icon='X')
    
    
    # operator for adding cameras
    class AddSurroundCamerasOperator(bpy.types.Operator):
    
        bl_idname = 'objects.add_surround_cameras'
        bl_label = "Add Cameras"
        bl_description = "Add n cameras"
        bl_options = {'REGISTER', 'UNDO'}
    
        @classmethod
        def poll(cls, context):
            return context.window_manager.previous_num_surround_screens is -1
    
        def execute(self, context):
    
    
            scene = context.scene
    
            numScreens = context.window_manager.num_surround_screens
    
            # add an empty for the camera origin if not already present
    
            obj_origin = scene.objects.get(CAMERA_ORIGIN_NAME)
            if not obj_origin:
    
                obj_origin = context.active_object
                obj_origin.name = CAMERA_ORIGIN_NAME
                obj_origin.location = scene.cursor_location
    
    
            for i in range(0,numScreens):
    
                # add a new camer
                bpy.ops.object.camera_add()
    
                # get the current camera
                cam = context.active_object
    
                # name the camera
                cameraName = "Camera" + str(i)
                cam.name = cameraName
                cam.data.name = cameraName
    
                # position camera
                cam.location = 0,0,0
                cam.rotation_euler = (pi/2), 0, ((-2*pi)/numScreens) * i
    
                # set the field of view angle
                cam.data.angle = (2*pi)/numScreens
    
                # make the parent of the camera the origin
    
                cam.parent = obj_origin
    
            # sel/activate origin
            bpy.ops.object.select_all(action='DESELECT')
            obj_origin.select = True
            scene.objects.active = obj_origin
    
    
            context.window_manager.previous_num_surround_screens = numScreens
            return {'FINISHED'}
    
    
    
    # operator for creating new linked scenes for each camera
    class AddSurroundScenesOperator(bpy.types.Operator):
    
        bl_idname = 'scene.add_linked_scenes_for_surround_cameras'
        bl_label = "Make Scenes"
        bl_description = "Creates new scenes with linked object data for each camera"
        bl_options = {'REGISTER', 'UNDO'}
    
        @classmethod
        def poll(cls, context):
            if context.window_manager.previous_num_surround_screens is not -1 and context.window_manager.surround_screens_init is False:
                return True
            return False
    
        def execute(self, context):
    
            scene_base = context.scene
    
            numScreens = context.window_manager.previous_num_surround_screens
    
            sceneName = scene_base.name
            renderpath = scene_base.render.filepath
    
    
            for i in range(0, numScreens):
    
                thisScene = sceneName + "-Camera" + str(i)
    
    
                bpy.ops.scene.new(type='EMPTY')
    
                scene_new = context.scene
                scene_new.name = thisScene
    
                camera_object = bpy.data.objects["Camera" + str(i)]
                scene_new.camera = camera_object
                scene_new.background_set = scene_base
    
                # not essential but nice to have the camera in the scene
                scene_new.objects.link(camera_object)
    
                scene_new.render.filepath = renderpath + thisScene
    
            context.screen.scene = scene_base
    
            context.window_manager.surround_screens_init = True
            return {'FINISHED'}
    
    
    
    # operator for removing the surround scenes
    class RemoveSurroundScenesOperator(bpy.types.Operator):
    
        bl_idname = 'objects.remove_linked_scenes_for_surround_cameras'
        bl_label = "Remove Scenes"
        bl_description = "Removes all surround scenes"
        bl_options = {'REGISTER', 'UNDO'}
    
        @classmethod
        def poll(cls, context):
            return context.window_manager.surround_screens_init is True
    
        def execute(self, context):
            numScreens = context.window_manager.previous_num_surround_screens
    
            for scene in list(bpy.data.scenes):
                if re.search("-Camera",scene.name):
                    bpy.data.scenes.remove(scene)
    
            context.window_manager.surround_screens_init = False
            return {'FINISHED'}
    
    
    
    # operator for removing the surround cameras/scenes
    class RemoveSurroundCamerasOperator(bpy.types.Operator):
    
        bl_idname = 'objects.remove_surround_cameras'
        bl_label = "Remove Cameras"
        bl_description = "Removes all surround cameras"
        bl_options = {'REGISTER', 'UNDO'}
    
        @classmethod
        def poll(cls, context):
            if context.window_manager.previous_num_surround_screens is not -1 and context.window_manager.surround_screens_init is False:
                return True
            return False
    
        def execute(self, context):
    
    
            scene = context.scene
    
            # XXX. shouldnt there be some less general way to do this?
            # like check if they are the child of origin? - campbell
            for obj in scene.objects[:]:
                if obj.type == 'CAMERA':
                    scene.objects.unlink(obj)
    
    
            context.window_manager.previous_num_surround_screens = -1
            return {'FINISHED'}
    
    def unregister():
        bpy.utils.unregister_module(__name__)