Skip to content
Snippets Groups Projects
ui.py 161 KiB
Newer Older
  • Learn to ignore specific revisions
  • Luca Bonavita's avatar
    Luca Bonavita 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>
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
    """User interface for the POV tools"""
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    import bpy
    
    import sys  # really import here and in render.py?
    import os  # really import here and in render.py?
    
    import addon_utils
    from time import sleep
    
    from bpy.app.handlers import persistent
    
    from bl_operators.presets import AddPresetBase
    
    from bpy.utils import register_class, unregister_class
    
    from bpy.types import (
    
        UIList,
        Panel,
        Brush,
        Material,
        Light,
        World,
        ParticleSettings,
        FreestyleLineStyle,
    )
    
    
    # Example of wrapping every class 'as is'
    from bl_ui import properties_output
    
    for member in dir(properties_output):
        subclass = getattr(properties_output, member)
        try:
    
            subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
    
        except:
            pass
    del properties_output
    
    
    from bl_ui import properties_freestyle
    for member in dir(properties_freestyle):
        subclass = getattr(properties_freestyle, member)
        try:
            if not (subclass.bl_space_type == 'PROPERTIES'
                and subclass.bl_context == "render"):
                subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
                #subclass.bl_parent_id = "RENDER_PT_POV_filter"
        except:
            pass
    del properties_freestyle
    
    
    from bl_ui import properties_view_layer
    
    for member in dir(properties_view_layer):
        subclass = getattr(properties_view_layer, member)
        try:
    
            subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
    
        except:
            pass
    del properties_view_layer
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    # Use some of the existing buttons.
    
    from bl_ui import properties_render
    
    
    # DEPRECATED#properties_render.RENDER_PT_render.COMPAT_ENGINES.add('POVRAY_RENDER')
    # DEPRECATED#properties_render.RENDER_PT_dimensions.COMPAT_ENGINES.add('POVRAY_RENDER')
    
    # properties_render.RENDER_PT_antialiasing.COMPAT_ENGINES.add('POVRAY_RENDER')
    
    # TORECREATE##DEPRECATED#properties_render.RENDER_PT_shading.COMPAT_ENGINES.add('POVRAY_RENDER')
    # DEPRECATED#properties_render.RENDER_PT_output.COMPAT_ENGINES.add('POVRAY_RENDER')
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    del properties_render
    
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    # Use only a subset of the world panels
    
    from bl_ui import properties_world
    
    
    # TORECREATE##DEPRECATED#properties_world.WORLD_PT_preview.COMPAT_ENGINES.add('POVRAY_RENDER')
    
    properties_world.WORLD_PT_context_world.COMPAT_ENGINES.add('POVRAY_RENDER')
    
    # TORECREATE##DEPRECATED#properties_world.WORLD_PT_world.COMPAT_ENGINES.add('POVRAY_RENDER')
    # TORECREATE##DEPRECATED#properties_world.WORLD_PT_mist.COMPAT_ENGINES.add('POVRAY_RENDER')
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    del properties_world
    
    
    # Example of wrapping every class 'as is'
    
    from bl_ui import properties_texture
    
    from bl_ui.properties_texture import context_tex_datablock
    
    from bl_ui.properties_texture import texture_filter_common
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    for member in dir(properties_texture):
        subclass = getattr(properties_texture, member)
        try:
    
            subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        except:
            pass
    del properties_texture
    
    
    # Physics Main wrapping every class 'as is'
    from bl_ui import properties_physics_common
    
    for member in dir(properties_physics_common):
        subclass = getattr(properties_physics_common, member)
        try:
            subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
        except:
            pass
    del properties_physics_common
    
    # Physics Rigid Bodies wrapping every class 'as is'
    from bl_ui import properties_physics_rigidbody
    
    for member in dir(properties_physics_rigidbody):
        subclass = getattr(properties_physics_rigidbody, member)
        try:
            subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
        except:
            pass
    del properties_physics_rigidbody
    
    # Physics Rigid Body Constraint wrapping every class 'as is'
    from bl_ui import properties_physics_rigidbody_constraint
    
    for member in dir(properties_physics_rigidbody_constraint):
        subclass = getattr(properties_physics_rigidbody_constraint, member)
        try:
            subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
        except:
            pass
    del properties_physics_rigidbody_constraint
    
    # Physics Smoke wrapping every class 'as is'
    
    from bl_ui import properties_physics_fluid
    
    for member in dir(properties_physics_fluid):
        subclass = getattr(properties_physics_fluid, member)
    
        try:
            subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
        except:
            pass
    
    del properties_physics_fluid
    
    
    # Physics softbody wrapping every class 'as is'
    from bl_ui import properties_physics_softbody
    
    for member in dir(properties_physics_softbody):
        subclass = getattr(properties_physics_softbody, member)
        try:
            subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
        except:
            pass
    del properties_physics_softbody
    
    # Physics Fluid wrapping every class 'as is'
    from bl_ui import properties_physics_fluid
    
    for member in dir(properties_physics_fluid):
        subclass = getattr(properties_physics_fluid, member)
        try:
            subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
        except:
            pass
    del properties_physics_fluid
    
    # Physics Field wrapping every class 'as is'
    from bl_ui import properties_physics_field
    
    for member in dir(properties_physics_field):
        subclass = getattr(properties_physics_field, member)
        try:
            subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
        except:
            pass
    del properties_physics_field
    
    # Physics Cloth wrapping every class 'as is'
    from bl_ui import properties_physics_cloth
    
    for member in dir(properties_physics_cloth):
        subclass = getattr(properties_physics_cloth, member)
        try:
            subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
        except:
            pass
    del properties_physics_cloth
    
    # Physics Dynamic Paint wrapping every class 'as is'
    from bl_ui import properties_physics_dynamicpaint
    
    for member in dir(properties_physics_dynamicpaint):
        subclass = getattr(properties_physics_dynamicpaint, member)
        try:
            subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
        except:
            pass
    del properties_physics_dynamicpaint
    
    
    # Example of wrapping every class 'as is'
    from bl_ui import properties_data_modifier
    
    for member in dir(properties_data_modifier):
        subclass = getattr(properties_data_modifier, member)
        try:
            subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
        except:
            pass
    del properties_data_modifier
    
    
    # Example of wrapping every class 'as is' except some
    from bl_ui import properties_material
    
    for member in dir(properties_material):
        subclass = getattr(properties_material, member)
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            # mat=bpy.context.active_object.active_material
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            # if (mat and mat.pov.type == "SURFACE"
    
            # and not (mat.pov.material_use_nodes or mat.use_nodes)):
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            # and (engine in cls.COMPAT_ENGINES)) if subclasses were sorted
    
            subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
    
    from bl_ui import properties_data_camera
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    for member in dir(properties_data_camera):
        subclass = getattr(properties_data_camera, member)
        try:
    
            subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        except:
            pass
    del properties_data_camera
    
    
    from bl_ui import properties_particle as properties_particle
    
    
    for member in dir(
        properties_particle
    ):  # add all "particle" panels from blender
    
        subclass = getattr(properties_particle, member)
        try:
            subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
        except:
            pass
    del properties_particle
    
    
    ############# POV-Centric WORSPACE #############
    @persistent
    def povCentricWorkspace(dummy):
    
        """Set up a POV centric Workspace if addon was activated and saved as default renderer
    
    
        This would bring a ’_RestrictData’ error because UI needs to be fully loaded before
        workspace changes so registering this function in bpy.app.handlers is needed.
        By default handlers are freed when loading new files, but here we want the handler
        to stay running across multiple files as part of this add-on. That is why the the
        bpy.app.handlers.persistent decorator is used (@persistent) above.
        """
    
        wsp = bpy.data.workspaces.get('Scripting')
        context = bpy.context
    
        if wsp is not None and context.scene.render.engine == 'POVRAY_RENDER':
    
            new_wsp = bpy.ops.workspace.duplicate({'workspace': wsp})
            bpy.data.workspaces['Scripting.001'].name='POV'
            # Already done it would seem, but explicitly make this workspaces the active one
            context.window.workspace = bpy.data.workspaces['POV']
            pov_screen = bpy.data.workspaces['POV'].screens[0]
            pov_workspace = pov_screen.areas
    
    
            override = bpy.context.copy()
    
            for area in pov_workspace:
                if area.type == 'VIEW_3D':
                    for region in [r for r in area.regions if r.type == 'WINDOW']:
                        for space in area.spaces:
                            if space.type == 'VIEW_3D':
                                #override['screen'] = pov_screen
                                override['area'] = area
                                override['region']= region
                                #bpy.data.workspaces['POV'].screens[0].areas[6].spaces[0].width = 333 # Read only, how do we set ?
                                #This has a glitch:
                                #bpy.ops.screen.area_move(override, x=(area.x + area.width), y=(area.y + 5), delta=100)
                                #bpy.ops.screen.area_move(override, x=(area.x + 5), y=area.y, delta=-100)
    
                                bpy.ops.screen.space_type_set_or_cycle(override, space_type = 'TEXT_EDITOR')
    
                                space.show_region_ui = True
    
                                #bpy.ops.screen.region_scale(override)
                                #bpy.ops.screen.region_scale()
                                break
    
                elif area.type == 'CONSOLE':
                    for region in [r for r in area.regions if r.type == 'WINDOW']:
                        for space in area.spaces:
                            if space.type == 'CONSOLE':
                                #override['screen'] = pov_screen
                                override['area'] = area
                                override['region']= region
                                bpy.ops.screen.space_type_set_or_cycle(override, space_type = 'INFO')
    
                                break
                elif area.type == 'INFO':
                    for region in [r for r in area.regions if r.type == 'WINDOW']:
                        for space in area.spaces:
                            if space.type == 'INFO':
                                #override['screen'] = pov_screen
                                override['area'] = area
                                override['region']= region
                                bpy.ops.screen.space_type_set_or_cycle(override, space_type = 'CONSOLE')
    
                                break
    
                elif area.type == 'TEXT_EDITOR':
                    for region in [r for r in area.regions if r.type == 'WINDOW']:
                        for space in area.spaces:
                            if space.type == 'TEXT_EDITOR':
                                #override['screen'] = pov_screen
                                override['area'] = area
                                override['region']= region
                                #bpy.ops.screen.space_type_set_or_cycle(space_type='VIEW_3D')
                                #space.type = 'VIEW_3D'
                                bpy.ops.screen.space_type_set_or_cycle(override, space_type = 'VIEW_3D')
    
                                #bpy.ops.screen.area_join(override, cursor=(area.x, area.y + area.height))
    
                                break
    
    
                if area.type == 'VIEW_3D':
                    for region in [r for r in area.regions if r.type == 'WINDOW']:
                        for space in area.spaces:
                            if space.type == 'VIEW_3D':
                                #override['screen'] = pov_screen
                                override['area'] = area
                                override['region']= region
                                bpy.ops.screen.region_quadview(override)
                                space.region_3d.view_perspective = 'CAMERA'
                                #bpy.ops.screen.space_type_set_or_cycle(override, space_type = 'TEXT_EDITOR')
                                #bpy.ops.screen.region_quadview(override)
    
    
    
    
    
            bpy.data.workspaces.update()
            # Already outliners but invert both types
            pov_workspace[1].spaces[0].display_mode = 'LIBRARIES'
            pov_workspace[3].spaces[0].display_mode = 'VIEW_LAYER'
    
            '''
            for window in bpy.context.window_manager.windows:
                for area in [a for a in window.screen.areas if a.type == 'VIEW_3D']:
                    for region in [r for r in area.regions if r.type == 'WINDOW']:
                        context_override = {
                            'window': window,
                            'screen': window.screen,
                            'area': area,
                            'region': region,
                            'space_data': area.spaces.active,
                            'scene': bpy.context.scene
                            }
                        bpy.ops.view3d.camera_to_view(context_override)
            '''
    
    
        else:
            print("default 'Scripting' workspace needed for POV centric Workspace")
    
    
    
    
    
    
    
    class WORLD_MT_POV_presets(Menu):
    
        bl_label = "World Presets"
        preset_subdir = "pov/world"
        preset_operator = "script.execute_preset"
        draw = bpy.types.Menu.draw_preset
    
    
    
    class WORLD_OT_POV_add_preset(AddPresetBase, Operator):
    
        """Add a World Preset"""
    
        bl_idname = "object.world_preset_add"
        bl_label = "Add World Preset"
    
        preset_menu = "WORLD_MT_POV_presets"
    
    
        # variable used for all preset values
    
        preset_defines = ["scene = bpy.context.scene"]
    
    
        # properties to store in the preset
        preset_values = [
            "scene.world.use_sky_blend",
            "scene.world.horizon_color",
            "scene.world.zenith_color",
            "scene.world.ambient_color",
            "scene.world.mist_settings.use_mist",
            "scene.world.mist_settings.intensity",
            "scene.world.mist_settings.depth",
            "scene.world.mist_settings.start",
            "scene.pov.media_enable",
            "scene.pov.media_scattering_type",
            "scene.pov.media_samples",
            "scene.pov.media_diffusion_scale",
            "scene.pov.media_diffusion_color",
            "scene.pov.media_absorption_scale",
            "scene.pov.media_absorption_color",
            "scene.pov.media_eccentricity",
    
    
        # where to store the preset
        preset_subdir = "pov/world"
    
    def check_material(mat):
        if mat is not None:
            if mat.use_nodes:
    
                if (
                    not mat.node_tree
                ):  # FORMERLY : #mat.active_node_material is not None:
    
                    return True
                return False
            return True
        return False
    
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        """Test if a material uses nodes"""
    
        if (mat is not None) and (not mat.use_nodes):
            return True
        return False
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        """Test if Add mesh extra objects addon is activated
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        This addon is currently used to generate the proxy for POV parametric
        surface which is almost the same priciple as its Math xyz surface
        """
    
        if "add_mesh_extra_objects" in bpy.context.preferences.addons.keys():
    
    def check_render_freestyle_svg():
        """Test if Freestyle SVG Exporter addon is activated
    
        This addon is currently used to generate the SVG lines file
        when Freestyle is enabled alongside POV
        """
        if "render_freestyle_svg" in bpy.context.preferences.addons.keys():
            return True
        return False
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        """POV can be installed with some include files.
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        Get their path as defined in user preferences or registry keys for
        the user to be able to invoke them."""
    
        addon_prefs = bpy.context.preferences.addons[__package__].preferences
    
        # Use the system preference if its set.
        pov_documents = addon_prefs.docpath_povray
        if pov_documents:
            if os.path.exists(pov_documents):
                return pov_documents
            else:
    
                print(
                    "User Preferences path to povray documents %r NOT FOUND, checking $PATH"
                    % pov_documents
                )
    
    
        # Windows Only
        if sys.platform[:3] == "win":
            import winreg
    
                win_reg_key = winreg.OpenKey(
                    winreg.HKEY_CURRENT_USER, "Software\\POV-Ray\\v3.7\\Windows"
                )
    
                win_docpath = winreg.QueryValueEx(win_reg_key, "DocPath")[0]
                pov_documents = os.path.join(win_docpath, "Insert Menu")
                if os.path.exists(pov_documents):
                    return pov_documents
            except FileNotFoundError:
    
        # search the path all os's
        pov_documents_default = "include"
    
        os_path_ls = os.getenv("PATH").split(':') + [""]
    
        for dir_name in os_path_ls:
            pov_documents = os.path.join(dir_name, pov_documents_default)
            if os.path.exists(pov_documents):
                return pov_documents
        return ""
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
    def pov_context_tex_datablock(context):
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        """Texture context type recreated as deprecated in blender 2.8"""
    
        idblock = context.brush
    
        if idblock and context.scene.texture_context == 'OTHER':
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            return idblock
    
    
        # idblock = bpy.context.active_object.active_material
    
        idblock = context.view_layer.objects.active.active_material
        if idblock and context.scene.texture_context == 'MATERIAL':
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            return idblock
    
    
        idblock = context.scene.world
        if idblock and context.scene.texture_context == 'WORLD':
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            return idblock
    
        idblock = context.light
    
        if idblock and context.scene.texture_context == 'LIGHT':
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            return idblock
    
    
        if context.particle_system and context.scene.texture_context == 'PARTICLES':
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            idblock = context.particle_system.settings
    
        return idblock
    
    
        idblock = context.line_style
    
        if idblock and context.scene.texture_context == 'LINESTYLE':
    
    
    class RenderButtonsPanel:
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        """Use this class to define buttons from the render tab of
        properties window."""
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        bl_space_type = 'PROPERTIES'
        bl_region_type = 'WINDOW'
        bl_context = "render"
        # COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
    
    
        @classmethod
        def poll(cls, context):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
            rd = context.scene.render
    
            return rd.engine in cls.COMPAT_ENGINES
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
    
    class ModifierButtonsPanel:
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        """Use this class to define buttons from the modifier tab of
        properties window."""
    
        bl_space_type = 'PROPERTIES'
        bl_region_type = 'WINDOW'
        bl_context = "modifier"
        # COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
    
        @classmethod
        def poll(cls, context):
            mods = context.object.modifiers
            rd = context.scene.render
    
            return mods and (rd.engine in cls.COMPAT_ENGINES)
    
    
    class MaterialButtonsPanel:
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        """Use this class to define buttons from the material tab of
        properties window."""
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        bl_space_type = 'PROPERTIES'
        bl_region_type = 'WINDOW'
        bl_context = "material"
        # COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
    
        @classmethod
        def poll(cls, context):
            mat = context.material
            rd = context.scene.render
    
            return mat and (rd.engine in cls.COMPAT_ENGINES)
    
    class TextureButtonsPanel:
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        """Use this class to define buttons from the texture tab of
        properties window."""
    
        bl_space_type = 'PROPERTIES'
        bl_region_type = 'WINDOW'
        bl_context = "texture"
        # COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
    
        @classmethod
        def poll(cls, context):
            tex = context.texture
            rd = context.scene.render
    
            return tex and (rd.engine in cls.COMPAT_ENGINES)
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
    
    
    # class TextureTypePanel(TextureButtonsPanel):
    
    
    # @classmethod
    # def poll(cls, context):
    # tex = context.texture
    # engine = context.scene.render.engine
    # return tex and ((tex.type == cls.tex_type and not tex.use_nodes) and (engine in cls.COMPAT_ENGINES))
    
    class ObjectButtonsPanel:
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        """Use this class to define buttons from the object tab of
        properties window."""
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        bl_space_type = 'PROPERTIES'
        bl_region_type = 'WINDOW'
        bl_context = "object"
        # COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
    
        @classmethod
        def poll(cls, context):
            obj = context.object
            rd = context.scene.render
    
            return obj and (rd.engine in cls.COMPAT_ENGINES)
    
    
    class CameraDataButtonsPanel:
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        """Use this class to define buttons from the camera data tab of
        properties window."""
    
        bl_space_type = 'PROPERTIES'
        bl_region_type = 'WINDOW'
        bl_context = "data"
        # COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
    
        @classmethod
        def poll(cls, context):
            cam = context.camera
            rd = context.scene.render
    
            return cam and (rd.engine in cls.COMPAT_ENGINES)
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        """Use this class to define buttons from the world tab of
        properties window."""
    
        bl_space_type = 'PROPERTIES'
        bl_region_type = 'WINDOW'
        bl_context = "world"
        # COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
    
        @classmethod
        def poll(cls, context):
            wld = context.world
            rd = context.scene.render
    
            return wld and (rd.engine in cls.COMPAT_ENGINES)
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        """Use this class to define buttons from the side tab of
        text window."""
    
        bl_space_type = 'TEXT_EDITOR'
        bl_region_type = 'UI'
    
        # COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
    
        @classmethod
        def poll(cls, context):
            text = context.space_data
            rd = context.scene.render
    
            return text and (rd.engine in cls.COMPAT_ENGINES)
    
    from bl_ui import properties_data_mesh
    
    # These panels are kept
    
    properties_data_mesh.DATA_PT_custom_props_mesh.COMPAT_ENGINES.add(
        'POVRAY_RENDER'
    )
    
    properties_data_mesh.DATA_PT_context_mesh.COMPAT_ENGINES.add('POVRAY_RENDER')
    
    ## make some native panels contextual to some object variable
    ## by recreating custom panels inheriting their properties
    
    class PovDataButtonsPanel(properties_data_mesh.MeshButtonsPanel):
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        """Use this class to define buttons from the edit data tab of
        properties window."""
    
        COMPAT_ENGINES = {'POVRAY_RENDER'}
    
        POV_OBJECT_TYPES = {
            'PLANE',
            'BOX',
            'SPHERE',
            'CYLINDER',
            'CONE',
            'TORUS',
            'BLOB',
            'ISOSURFACE',
            'SUPERELLIPSOID',
            'SUPERTORUS',
            'HEIGHT_FIELD',
            'PARAMETRIC',
            'POLYCIRCLE',
        }
    
        @classmethod
        def poll(cls, context):
            engine = context.scene.render.engine
            obj = context.object
            # We use our parent class poll func too, avoids to re-define too much things...
    
            return (
                super(PovDataButtonsPanel, cls).poll(context)
                and obj
                and obj.pov.object_as not in cls.POV_OBJECT_TYPES
            )
    
    # We cannot inherit from RNA classes (like e.g. properties_data_mesh.DATA_PT_vertex_groups).
    # Complex py/bpy/rna interactions (with metaclass and all) simply do not allow it to work.
    # So we simply have to explicitly copy here the interesting bits. ;)
    
    class DATA_PT_POV_normals(PovDataButtonsPanel, Panel):
    
        bl_label = properties_data_mesh.DATA_PT_normals.bl_label
    
        draw = properties_data_mesh.DATA_PT_normals.draw
    
    class DATA_PT_POV_texture_space(PovDataButtonsPanel, Panel):
    
        bl_label = properties_data_mesh.DATA_PT_texture_space.bl_label
        bl_options = properties_data_mesh.DATA_PT_texture_space.bl_options
    
        draw = properties_data_mesh.DATA_PT_texture_space.draw
    
    class DATA_PT_POV_vertex_groups(PovDataButtonsPanel, Panel):
    
        bl_label = properties_data_mesh.DATA_PT_vertex_groups.bl_label
    
        draw = properties_data_mesh.DATA_PT_vertex_groups.draw
    
    
    
    class DATA_PT_POV_shape_keys(PovDataButtonsPanel, Panel):
    
        bl_label = properties_data_mesh.DATA_PT_shape_keys.bl_label
    
    
        draw = properties_data_mesh.DATA_PT_shape_keys.draw
    
    
    
    class DATA_PT_POV_uv_texture(PovDataButtonsPanel, Panel):
    
        bl_label = properties_data_mesh.DATA_PT_uv_texture.bl_label
    
    
        draw = properties_data_mesh.DATA_PT_uv_texture.draw
    
    
    
    class DATA_PT_POV_vertex_colors(PovDataButtonsPanel, Panel):
    
        bl_label = properties_data_mesh.DATA_PT_vertex_colors.bl_label
    
    
        draw = properties_data_mesh.DATA_PT_vertex_colors.draw
    
    
    
    class DATA_PT_POV_customdata(PovDataButtonsPanel, Panel):
    
        bl_label = properties_data_mesh.DATA_PT_customdata.bl_label
    
        bl_options = properties_data_mesh.DATA_PT_customdata.bl_options
    
        draw = properties_data_mesh.DATA_PT_customdata.draw
    
    
    
    del properties_data_mesh
    
    
    
    ################################################################################
    
    # from bl_ui import properties_data_light
    # for member in dir(properties_data_light):
    
    # subclass = getattr(properties_data_light, member)
    # try:
    # subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
    # except:
    # pass
    
    # del properties_data_light
    #########################LIGHTS################################
    
    from bl_ui import properties_data_light
    
    properties_data_light.DATA_PT_custom_props_light.COMPAT_ENGINES.add(
        'POVRAY_RENDER'
    )
    
    properties_data_light.DATA_PT_context_light.COMPAT_ENGINES.add('POVRAY_RENDER')
    
    ## make some native panels contextual to some object variable
    ## by recreating custom panels inheriting their properties
    
    class PovLampButtonsPanel(properties_data_light.DataButtonsPanel):
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        """Use this class to define buttons from the light data tab of
        properties window."""
    
        COMPAT_ENGINES = {'POVRAY_RENDER'}
        POV_OBJECT_TYPES = {'RAINBOW'}
    
        @classmethod
        def poll(cls, context):
            engine = context.scene.render.engine
            obj = context.object
            # We use our parent class poll func too, avoids to re-define too much things...
    
            return (
                super(PovLampButtonsPanel, cls).poll(context)
                and obj
                and obj.pov.object_as not in cls.POV_OBJECT_TYPES
            )
    
    # We cannot inherit from RNA classes (like e.g. properties_data_mesh.DATA_PT_vertex_groups).
    # Complex py/bpy/rna interactions (with metaclass and all) simply do not allow it to work.
    # So we simply have to explicitly copy here the interesting bits. ;)
    
    class LIGHT_PT_POV_preview(PovLampButtonsPanel, Panel):
    
        bl_label = properties_data_light.DATA_PT_preview.bl_label
    
        draw = properties_data_light.DATA_PT_preview.draw
    
    class LIGHT_PT_POV_light(PovLampButtonsPanel, Panel):
    
        bl_label = properties_data_light.DATA_PT_light.bl_label
    
        draw = properties_data_light.DATA_PT_light.draw
    
    class LIGHT_MT_POV_presets(Menu):
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        """Use this class to define preset menu for pov lights."""
    
    
        bl_label = "Lamp Presets"
    
        preset_subdir = "pov/light"
    
        preset_operator = "script.execute_preset"
        draw = bpy.types.Menu.draw_preset
    
    
    
    class LIGHT_OT_POV_add_preset(AddPresetBase, Operator):
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        """Use this class to define pov world buttons."""
    
    
        '''Add a Light Preset'''
    
        bl_idname = "object.light_preset_add"
    
        bl_label = "Add Light Preset"
    
        preset_menu = "LIGHT_MT_POV_presets"
    
    
        # variable used for all preset values
    
        preset_defines = ["lightdata = bpy.context.object.data"]
    
    
        # properties to store in the preset
    
        preset_values = ["lightdata.type", "lightdata.color"]
    
    
        # where to store the preset
    
        preset_subdir = "pov/light"
    
    # Draw into the existing light panel
    
    def light_panel_func(self, context):
    
        layout = self.layout
    
        row = layout.row(align=True)
    
        row.menu(LIGHT_MT_POV_presets.__name__, text=LIGHT_MT_POV_presets.bl_label)
        row.operator(LIGHT_OT_POV_add_preset.bl_idname, text="", icon='ADD')
    
        row.operator(
            LIGHT_OT_POV_add_preset.bl_idname, text="", icon='REMOVE'
        ).remove_active = True
    
    
    '''#TORECREATE##DEPRECATED#
    
    class LIGHT_PT_POV_sunsky(PovLampButtonsPanel, Panel):
    
        bl_label = properties_data_light.DATA_PT_sunsky.bl_label
    
        @classmethod
        def poll(cls, context):
    
            lamp = context.light
    
            engine = context.scene.render.engine
            return (lamp and lamp.type == 'SUN') and (engine in cls.COMPAT_ENGINES)
    
    
        draw = properties_data_light.DATA_PT_sunsky.draw
    
    class LIGHT_PT_POV_shadow(PovLampButtonsPanel, Panel):
    
        COMPAT_ENGINES = {'POVRAY_RENDER'}
    
        @classmethod
        def poll(cls, context):
            lamp = context.lamp
            engine = context.scene.render.engine
            return lamp and (engine in cls.COMPAT_ENGINES)
    
        def draw(self, context):
            layout = self.layout
    
            lamp = context.lamp
    
            layout.row().prop(lamp, "shadow_method", expand=True)
    
            split = layout.split()
    
            col = split.column()
            sub = col.column()
            sub.prop(lamp, "spot_size", text="Size")
            sub.prop(lamp, "spot_blend", text="Blend", slider=True)
            col.prop(lamp, "use_square")
            col.prop(lamp, "show_cone")
    
            col = split.column()
    
    
            col.active = (
                lamp.shadow_method != 'BUFFER_SHADOW'
                or lamp.shadow_buffer_type != 'DEEP'
            )
    
            col.prop(lamp, "use_halo")
            sub = col.column(align=True)
            sub.active = lamp.use_halo
            sub.prop(lamp, "halo_intensity", text="Intensity")
            if lamp.shadow_method == 'BUFFER_SHADOW':
                sub.prop(lamp, "halo_step", text="Step")
            if lamp.shadow_method == 'NOSHADOW' and lamp.type == 'AREA':
                split = layout.split()
    
                col = split.column()
                col.label(text="Form factor sampling:")
    
                sub = col.row(align=True)
    
                if lamp.shape == 'SQUARE':
                    sub.prop(lamp, "shadow_ray_samples_x", text="Samples")
                elif lamp.shape == 'RECTANGLE':
                    sub.prop(lamp.pov, "shadow_ray_samples_x", text="Samples X")
                    sub.prop(lamp.pov, "shadow_ray_samples_y", text="Samples Y")
    
            if lamp.shadow_method != 'NOSHADOW':
                split = layout.split()
    
                col = split.column()
                col.prop(lamp, "shadow_color", text="")
    
                col = split.column()
                col.prop(lamp, "use_shadow_layer", text="This Layer Only")
                col.prop(lamp, "use_only_shadow")
    
            if lamp.shadow_method == 'RAY_SHADOW':
                split = layout.split()
    
                col = split.column()
                col.label(text="Sampling:")
    
                if lamp.type in {'POINT', 'SUN', 'SPOT'}:
                    sub = col.row()
    
                    sub.prop(lamp, "shadow_ray_samples", text="Samples")
                    sub.prop(lamp, "shadow_soft_size", text="Soft Size")
    
                elif lamp.type == 'AREA':
                    sub = col.row(align=True)
    
                    if lamp.shape == 'SQUARE':
                        sub.prop(lamp, "shadow_ray_samples_x", text="Samples")
                    elif lamp.shape == 'RECTANGLE':
                        sub.prop(lamp, "shadow_ray_samples_x", text="Samples X")
                        sub.prop(lamp, "shadow_ray_samples_y", text="Samples Y")
    
            if lamp.shadow_method == 'NOSHADOW' and lamp.type == 'AREA':
                split = layout.split()
    
                col = split.column()
                col.label(text="Form factor sampling:")
    
                sub = col.row(align=True)
    
                if lamp.shape == 'SQUARE':
                    sub.prop(lamp, "shadow_ray_samples_x", text="Samples")
                elif lamp.shape == 'RECTANGLE':
                    sub.prop(lamp, "shadow_ray_samples_x", text="Samples X")
                    sub.prop(lamp, "shadow_ray_samples_y", text="Samples Y")
    
            if lamp.shadow_method != 'NOSHADOW':
                split = layout.split()
    
                col = split.column()
                col.prop(lamp, "shadow_color", text="")
    
                col = split.column()
                col.prop(lamp, "use_shadow_layer", text="This Layer Only")
                col.prop(lamp, "use_only_shadow")
    
            if lamp.shadow_method == 'RAY_SHADOW':
                split = layout.split()
    
                col = split.column()
                col.label(text="Sampling:")
    
                if lamp.type in {'POINT', 'SUN', 'SPOT'}: