Skip to content
__init__.py 5.9 KiB
Newer Older
Dalai Felinto's avatar
Dalai Felinto committed
#====================== 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 ========================

# <pep8 compliant>
bl_info = {
    "name": "Virtual Reality Viewport",
    "author": "Dalai Felinto",
    "version": (0, 9),
    "blender": (2, 7, 5),
    "location": "Window Menu",
    "description": "",
    "warning": "",
    "wiki_url": "",
    "tracker_url": "",
    "category": "3D View"}


import bpy

from bgl import (
        Buffer,
        GL_INT,
        GL_RGBA,
        )

from .opengl_helper import (
        calculate_image_size,
        create_image,
        create_shader,
        delete_image,
        draw_callback_px,
        resize,
        )


def get_context_3dview (context):
    """returns area and space"""
    screen = context.screen

    for area in screen.areas:
        if area.type == 'VIEW_3D':
            for region in area.regions:
                if region.type == 'WINDOW':
                    return area, region

    return None, None


def get_space_3dview(context):
    area = context.area
    for space in area.spaces:
        if space.type == 'VIEW_3D':
            return space
    return None


def get_glsl_shader():
    import os
    folderpath = os.path.dirname(os.path.abspath(__file__))
    filepath = os.path.join(folderpath, 'oculus_dk2.glsl')
    f = open(filepath, 'r')
    data = f.read()
    f.close()
    return data


class VirtualRealityViewportOperator(bpy.types.Operator):
    """"""
    bl_idname = "view3d.virtual_reality_toggle"
    bl_label = "Toggle Virtual Reality Mode"
    bl_description = ""

    _enabled = True
    _timer = None

    def modal(self, context, event):
        if event.type == 'ESC':
            return self.cancel(context)

        if event.type == 'TIMER':

            # bug, waiting for fix: "[#31026] context.region broken after QuadView on + off"
            # http://projects.blender.org/tracker/index.php?func=detail&aid=31026&group_id=9&atid=498
            if not context.region or \
                not context.space_data or \
                context.space_data.type != 'VIEW_3D':
                return {'PASS_THROUGH'}

            viewport_shade = context.space_data.viewport_shade
            self._enabled = (viewport_shade != 'RENDERED')

            if (self.width != context.region.width) or (self.height != context.region.height):
                resize(self, context)


        return {'PASS_THROUGH'}

    def invoke(self, context, event):
        """
        * Create a fullscreen window with the editor in fullscreen with clean UI.
        * Views should be on, and this window should have stereo 3d mode set to side-by-side
        * Also you should lock a camera to the viewport to make sure you always look nicely
        * Sync the Oculus rotation + translation to the Blender camera
        * Now the opengl fun ... create a GLSL screen shader to run the warping distortions.
        """

        if context.area.type == 'VIEW_3D':
            #if bpy.ops.wm.window_fullscreen_toggle.poll():
            #    bpy.ops.wm.window_fullscreen_toggle()

            context.scene.render.use_multiview = True
            context.window.stereo_3d_display.display_mode = 'SIDEBYSIDE'

            #if bpy.ops.screen.screen_full_area.poll():
            #    bpy.ops.screen.screen_full_area(use_hide_panels=True)

            if bpy.ops.view3d.view_all.poll():
                bpy.ops.view3d.view_all()

            space = get_space_3dview(context)
            space.show_only_render = True
            space.stereo_3d_camera = 'S3D'

            #bpy.v3d = get_context_3dview(context)
            #bpy.space = space
            bpy.ops.view3d.viewnumpad(type='CAMERA')

            self._timer = context.window_manager.event_timer_add(0.1, context.window)
            self._handle = bpy.types.SpaceView3D.draw_handler_add(draw_callback_px, (self, context), 'WINDOW', 'POST_VIEW')
            context.window_manager.modal_handler_add(self)

            self.viewport = Buffer(GL_INT, 4)
            self.width = context.region.width
            self.height = context.region.height

            # power of two dimensions
            self.buffer_width, self.buffer_height = calculate_image_size(self.width, self.height)

            # images to dump the screen buffers
            self.color_id = create_image(self.buffer_width, self.buffer_height, GL_RGBA)

            # glsl shaders
            fragment_shader = get_glsl_shader()
            self.program_shader = create_shader(fragment_shader)

            return {'RUNNING_MODAL'}
        else:
            self.report({'WARNING'}, "View3D not found, cannot run operator")
            return {'CANCELLED'}

    def cancel(self, context):
        if self._handle:
            bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
            del self._handle

        if self._timer:
            context.window_manager.event_timer_remove(self._timer)
            del self._timer

        self.quit()
        return {'CANCELLED'}

    def quit(self):
        """garbage colect"""
        if self.color_id:
            delete_image(self.color_id)


def register():
    bpy.utils.register_module(__name__)


def unregister():
    bpy.utils.unregister_module(__name__)


if __name__ == '__main__':
    register()