diff --git a/psychoblend/__init__.py b/psychoblend/__init__.py index b0fd999..5a8be22 100644 --- a/psychoblend/__init__.py +++ b/psychoblend/__init__.py @@ -2,21 +2,16 @@ bl_info = { "name": "PsychoBlend", "version": (0, 1), "author": "Nathan Vegdahl", - "blender": (2, 70, 0), + "blender": (3, 1, 0), "description": "Psychopath renderer integration", "location": "", - "wiki_url": "https://github.com/cessen/psychopath/wiki", - "tracker_url": "https://github.com/cessen/psychopath/issues", - "category": "Render"} + # "wiki_url": "https://github.com/cessen/psychopath/wiki", + # "tracker_url": "https://github.com/cessen/psychopath/issues", + "category": "Render" +} -if "bpy" in locals(): - import imp - imp.reload(ui) - imp.reload(psy_export) - imp.reload(render) -else: - from . import ui, psy_export, render +from . import ui, psy_export, render import bpy from bpy.types import (AddonPreferences, @@ -33,53 +28,46 @@ from bpy.props import (StringProperty, ) -# Custom Scene settings +# Custom Scene settings. class RenderPsychopathSettingsScene(PropertyGroup): - spp = IntProperty( + spp: IntProperty( name="Samples Per Pixel", description="Total number of samples to take per pixel", min=1, max=65536, default=16 ) - bucket_size = IntProperty( + bucket_size: IntProperty( name="Bucket Size", description="The height and width of each render bucket in pixels.", min=1, max=4096, soft_max=256, default=32 ) - dicing_rate = FloatProperty( + dicing_rate: FloatProperty( name="Dicing Rate", description="The target microgeometry width in pixels", min=0.0001, max=100.0, soft_min=0.125, soft_max=1.0, default=0.25 ) - motion_blur_segments = IntProperty( + motion_blur_segments: IntProperty( name="Motion Segments", description="The number of segments to use in motion blur. Zero means no motion blur. Will be rounded down to the nearest power of two.", min=0, max=256, default=0 ) - shutter_start = FloatProperty( + shutter_start: FloatProperty( name="Shutter Open", description="The time during the frame that the shutter opens, for motion blur", min=-1.0, max=1.0, soft_min=0.0, soft_max=1.0, default=0.0 ) - shutter_end = FloatProperty( + shutter_end: FloatProperty( name="Shutter Close", description="The time during the frame that the shutter closes, for motion blur", min=-1.0, max=1.0, soft_min=0.0, soft_max=1.0, default=0.5 ) - export_path = StringProperty( + export_path: StringProperty( name="Export Path", description="The path to where the .psy files should be exported when rendering. If left blank, /tmp or the equivalent is used.", subtype='FILE_PATH' ) -# Custom Camera properties -class PsychopathCamera(bpy.types.PropertyGroup): - aperture_radius = FloatProperty( - name="Aperture Radius", description="Size of the camera's aperture, for DoF", - min=0.0, max=10000.0, soft_min=0.0, soft_max=2.0, default=0.0 - ) - -# Psychopath material +# Psychopath material. class PsychopathLight(bpy.types.PropertyGroup): - color_type = EnumProperty( + color_type: EnumProperty( name="Color Type", description="", items=[ ('Rec709', 'Rec709', ""), @@ -89,27 +77,27 @@ class PsychopathLight(bpy.types.PropertyGroup): default="Rec709" ) - color_blackbody_temp = FloatProperty( + color_blackbody_temp: FloatProperty( name="Temperature", description="Blackbody temperature in kelvin", min=0.0, soft_min=800.0, soft_max=6500.0, default=1200.0 ) -# Custom Mesh properties +# Custom Mesh properties. class PsychopathMesh(bpy.types.PropertyGroup): - is_subdivision_surface = BoolProperty( + is_subdivision_surface: BoolProperty( name="Is Subdivision Surface", description="Whether this is a sibdivision surface or just a normal mesh", default=False ) # Psychopath material class PsychopathMaterial(bpy.types.PropertyGroup): - surface_shader_type = EnumProperty( + surface_shader_type: EnumProperty( name="Surface Shader Type", description="", items=[('Emit', 'Emit', ""), ('Lambert', 'Lambert', ""), ('GGX', 'GGX', "")], default="Lambert" ) - color_type = EnumProperty( + color_type: EnumProperty( name="Color Type", description="", items=[ ('Rec709', 'Rec709', ""), @@ -119,39 +107,47 @@ class PsychopathMaterial(bpy.types.PropertyGroup): default="Rec709" ) - color = FloatVectorProperty( + color: FloatVectorProperty( name="Color", description="", subtype='COLOR', min=0.0, soft_min=0.0, soft_max = 1.0, default=[0.8,0.8,0.8] ) - color_blackbody_temp = FloatProperty( + color_blackbody_temp: FloatProperty( name="Temperature", description="Blackbody temperature in kelvin", min=0.0, soft_min=800.0, soft_max=6500.0, default=1200.0 ) - roughness = FloatProperty( + roughness: FloatProperty( name="Roughness", description="", min=-1.0, max=1.0, soft_min=0.0, soft_max=1.0, default=0.1 ) - tail_shape = FloatProperty( + tail_shape: FloatProperty( name="Tail Shape", description="", min=0.0, max=8.0, soft_min=1.0, soft_max=3.0, default=2.0 ) - fresnel = FloatProperty( + fresnel: FloatProperty( name="Fresnel", description="", min=0.0, max=1.0, soft_min=0.0, soft_max=1.0, default=0.9 ) +# Psychopath world. +class PsychopathWorld(bpy.types.PropertyGroup): + background_color: FloatVectorProperty( + name="Background Color", description="", + subtype='COLOR', + min=0.0, soft_min=0.0, soft_max = 1.0, + default=[0.8,0.8,0.8] + ) -# Addon Preferences +# Addon Preferences. class PsychopathPreferences(AddonPreferences): bl_idname = __name__ - filepath_psychopath = StringProperty( + filepath_psychopath: StringProperty( name="Psychopath Location", description="Path to renderer executable", subtype='DIR_PATH', @@ -166,15 +162,15 @@ class PsychopathPreferences(AddonPreferences): def register(): bpy.utils.register_class(PsychopathPreferences) bpy.utils.register_class(RenderPsychopathSettingsScene) - bpy.utils.register_class(PsychopathCamera) bpy.utils.register_class(PsychopathLight) bpy.utils.register_class(PsychopathMesh) bpy.utils.register_class(PsychopathMaterial) + bpy.utils.register_class(PsychopathWorld) bpy.types.Scene.psychopath = PointerProperty(type=RenderPsychopathSettingsScene) - bpy.types.Camera.psychopath = PointerProperty(type=PsychopathCamera) - bpy.types.Lamp.psychopath = PointerProperty(type=PsychopathLight) + bpy.types.Light.psychopath = PointerProperty(type=PsychopathLight) bpy.types.Mesh.psychopath = PointerProperty(type=PsychopathMesh) bpy.types.Material.psychopath = PointerProperty(type=PsychopathMaterial) + bpy.types.World.psychopath = PointerProperty(type=PsychopathWorld) render.register() ui.register() @@ -182,14 +178,14 @@ def register(): def unregister(): bpy.utils.unregister_class(PsychopathPreferences) bpy.utils.unregister_class(RenderPsychopathSettingsScene) - bpy.utils.unregister_class(PsychopathCamera) bpy.utils.unregister_class(PsychopathLight) bpy.utils.unregister_class(PsychopathMesh) bpy.utils.unregister_class(PsychopathMaterial) + bpy.utils.unregister_class(PsychopathWorld) del bpy.types.Scene.psychopath - del bpy.types.Camera.psychopath - del bpy.types.Lamp.psychopath + del bpy.types.Light.psychopath del bpy.types.Mesh.psychopath del bpy.types.Material.psychopath + del bpy.types.World.psychopath render.unregister() ui.unregister() diff --git a/psychoblend/render.py b/psychoblend/render.py index f3eb576..1dad4af 100644 --- a/psychoblend/render.py +++ b/psychoblend/render.py @@ -9,7 +9,48 @@ from . import psy_export class PsychopathRender(bpy.types.RenderEngine): bl_idname = 'PSYCHOPATH_RENDER' bl_label = "Psychopath" - DELAY = 1.0 + bl_use_preview = False + + def __init__(self): + pass + + def __del__(self): + pass + + def update(self, data, depsgraph): + print("Psychopath scene update!") + + def render(self, depsgraph): + print("Psychopath render!") + scene = depsgraph.scene + scale = scene.render.resolution_percentage / 100.0 + self.size_x = int(scene.render.resolution_x * scale) + self.size_y = int(scene.render.resolution_y * scale) + + # Fill the render result with a flat color. The framebuffer is + # defined as a list of pixels, each pixel itself being a list of + # R,G,B,A values. + if self.is_preview: + color = [0.1, 0.2, 0.1, 1.0] + else: + color = [0.2, 0.1, 0.1, 1.0] + + pixel_count = self.size_x * self.size_y + rect = [color] * pixel_count + + # Here we write the pixel values to the RenderResult + result = self.begin_result(0, 0, self.size_x, self.size_y) + layer = result.layers[0].passes["Combined"] + layer.rect = rect + self.end_result(result) + + def view_update(self, context, depsgraph): + pass + + def view_draw(self, context, depsgraph): + pass + + #---------------------------------------------------------- @staticmethod def _locate_binary(): @@ -23,7 +64,7 @@ class PsychopathRender(bpy.types.RenderEngine): else: print("User Preference to psychopath %r NOT FOUND, checking $PATH" % psy_binary) - # search the path all os's + # Search for the path. psy_binary_default = "psychopath" os_path_ls = os.getenv("PATH").split(':') + [""] diff --git a/psychoblend/ui.py b/psychoblend/ui.py index 5bc2bae..284005c 100644 --- a/psychoblend/ui.py +++ b/psychoblend/ui.py @@ -1,18 +1,292 @@ import bpy -# Use some of the existing buttons. -from bl_ui import properties_render -properties_render.RENDER_PT_render.COMPAT_ENGINES.add('PSYCHOPATH_RENDER') -properties_render.RENDER_PT_dimensions.COMPAT_ENGINES.add('PSYCHOPATH_RENDER') -properties_render.RENDER_PT_output.COMPAT_ENGINES.add('PSYCHOPATH_RENDER') -del properties_render +#-------------------------------------------------------------- +# Specify which existing Blender UI panels Psychopath +# uses/is compatible with. -from bl_ui import properties_data_camera -properties_data_camera.DATA_PT_lens.COMPAT_ENGINES.add('PSYCHOPATH_RENDER') -properties_data_camera.DATA_PT_camera.COMPAT_ENGINES.add('PSYCHOPATH_RENDER') -properties_data_camera.DATA_PT_camera_display.COMPAT_ENGINES.add('PSYCHOPATH_RENDER') -properties_data_camera.DATA_PT_custom_props_camera.COMPAT_ENGINES.add('PSYCHOPATH_RENDER') -del properties_data_camera +import bl_ui + +def register_engine_with_panels(area, list): + # TODO: reverse this, so we're checking if the list item is + # in the real panels, and throw an error if it's not. That + # way things don't just silently fail. + for p in list: + eval("bl_ui.{}.{}.COMPAT_ENGINES.add('PSYCHOPATH_RENDER')".format(area, p)) + +register_engine_with_panels( + "properties_render", + [ + "RENDER_PT_color_management", + "RENDER_PT_color_management_curves", + ] +) + +register_engine_with_panels( + "properties_output", + [ + "RENDER_PT_encoding", + "RENDER_PT_encoding_audio", + "RENDER_PT_encoding_video", + "RENDER_PT_format", + "RENDER_PT_frame_range", + "RENDER_PT_output", + "RENDER_PT_output_views", + "RENDER_PT_post_processing", + "RENDER_PT_stamp", + "RENDER_PT_stamp_burn", + "RENDER_PT_stamp_note", + # "RENDER_PT_stereoscopy", + "RENDER_PT_time_stretching", + ] +) + +register_engine_with_panels( + "properties_view_layer", + [ + "VIEWLAYER_PT_layer", + ] +) + +register_engine_with_panels( + "properties_data_camera", + [ + "DATA_PT_context_camera", + "DATA_PT_custom_props_camera", + "DATA_PT_camera", + "DATA_PT_lens", + "DATA_PT_camera_dof", + "DATA_PT_camera_dof_aperture", + "DATA_PT_camera_display", + "DATA_PT_camera_display_composition_guides", + "DATA_PT_camera_safe_areas", + "DATA_PT_camera_safe_areas_center_cut", + "DATA_PT_camera_background_image", + ] +) + +register_engine_with_panels( + "properties_data_mesh", + [ + "DATA_PT_context_mesh", + "DATA_PT_custom_props_mesh", + "DATA_PT_customdata", + "DATA_PT_face_maps", + "DATA_PT_mesh_attributes", + "DATA_PT_normals", + "DATA_PT_remesh", + "DATA_PT_sculpt_vertex_colors", + "DATA_PT_shape_keys", + "DATA_PT_texture_space", + "DATA_PT_uv_texture", + "DATA_PT_vertex_colors", + "DATA_PT_vertex_groups", + ] +) + +register_engine_with_panels( + "properties_particle", + [ + "PARTICLE_MT_context_menu", + "PARTICLE_PT_boidbrain", + "PARTICLE_PT_cache", + "PARTICLE_PT_children", + "PARTICLE_PT_children_clumping", + "PARTICLE_PT_children_clumping_noise", + "PARTICLE_PT_children_kink", + "PARTICLE_PT_children_parting", + "PARTICLE_PT_children_roughness", + "PARTICLE_PT_context_particles", + "PARTICLE_PT_custom_props", + "PARTICLE_PT_draw", + "PARTICLE_PT_emission", + "PARTICLE_PT_emission_source", + "PARTICLE_PT_field_weights", + "PARTICLE_PT_force_fields", + "PARTICLE_PT_force_fields_type1", + "PARTICLE_PT_force_fields_type1_falloff", + "PARTICLE_PT_force_fields_type2", + "PARTICLE_PT_force_fields_type2_falloff", + "PARTICLE_PT_hair_dynamics", + "PARTICLE_PT_hair_dynamics_collision", + "PARTICLE_PT_hair_dynamics_presets", + "PARTICLE_PT_hair_dynamics_structure", + "PARTICLE_PT_hair_dynamics_volume", + "PARTICLE_PT_hair_shape", + "PARTICLE_PT_physics", + "PARTICLE_PT_physics_boids_battle", + "PARTICLE_PT_physics_boids_misc", + "PARTICLE_PT_physics_boids_movement", + "PARTICLE_PT_physics_deflection", + "PARTICLE_PT_physics_fluid_advanced", + "PARTICLE_PT_physics_fluid_interaction", + "PARTICLE_PT_physics_fluid_springs", + "PARTICLE_PT_physics_fluid_springs_advanced", + "PARTICLE_PT_physics_fluid_springs_viscoelastic", + "PARTICLE_PT_physics_forces", + "PARTICLE_PT_physics_integration", + "PARTICLE_PT_physics_relations", + "PARTICLE_PT_render", + "PARTICLE_PT_render_collection", + "PARTICLE_PT_render_collection_use_count", + "PARTICLE_PT_render_extra", + "PARTICLE_PT_render_object", + "PARTICLE_PT_render_path", + "PARTICLE_PT_render_path_timing", + "PARTICLE_PT_rotation", + "PARTICLE_PT_rotation_angular_velocity", + "PARTICLE_PT_textures", + "PARTICLE_PT_velocity", + "PARTICLE_PT_vertexgroups", + ] +) + +# Physics. +# (Why these require renderer compatibility settings +# is beyond me. But they do.) +register_engine_with_panels( + "properties_physics_cloth", + [ + "PHYSICS_PT_cloth", + "PHYSICS_PT_cloth_cache", + "PHYSICS_PT_cloth_collision", + "PHYSICS_PT_cloth_damping", + "PHYSICS_PT_cloth_field_weights", + "PHYSICS_PT_cloth_internal_springs", + "PHYSICS_PT_cloth_object_collision", + "PHYSICS_PT_cloth_physical_properties", + "PHYSICS_PT_cloth_pressure", + "PHYSICS_PT_cloth_property_weights", + "PHYSICS_PT_cloth_self_collision", + "PHYSICS_PT_cloth_shape", + "PHYSICS_PT_cloth_stiffness", + ], +) +register_engine_with_panels( + "properties_physics_common", + [ + "PHYSICS_PT_add", + ] +) +register_engine_with_panels( + "properties_physics_dynamicpaint", + [ + "PHYSICS_PT_dp_brush_source", + "PHYSICS_PT_dp_brush_source_color_ramp", + "PHYSICS_PT_dp_brush_velocity", + "PHYSICS_PT_dp_brush_velocity_color_ramp", + "PHYSICS_PT_dp_brush_velocity_smudge", + "PHYSICS_PT_dp_brush_wave", + "PHYSICS_PT_dp_cache", + "PHYSICS_PT_dp_canvas_initial_color", + "PHYSICS_PT_dp_canvas_output", + "PHYSICS_PT_dp_canvas_output_paintmaps", + "PHYSICS_PT_dp_canvas_output_wetmaps", + "PHYSICS_PT_dp_effects", + "PHYSICS_PT_dp_effects_drip", + "PHYSICS_PT_dp_effects_drip_weights", + "PHYSICS_PT_dp_effects_shrink", + "PHYSICS_PT_dp_effects_spread", + "PHYSICS_PT_dp_surface_canvas", + "PHYSICS_PT_dp_surface_canvas_paint_dissolve", + "PHYSICS_PT_dp_surface_canvas_paint_dry", + "PHYSICS_PT_dynamic_paint", + "PHYSICS_PT_dynamic_paint_settings", + ] +) +register_engine_with_panels( + "properties_physics_field", + [ + "PHYSICS_PT_collision", + "PHYSICS_PT_collision_particle", + "PHYSICS_PT_collision_softbody", + "PHYSICS_PT_field", + "PHYSICS_PT_field_falloff", + "PHYSICS_PT_field_falloff_angular", + "PHYSICS_PT_field_falloff_radial", + "PHYSICS_PT_field_settings", + "PHYSICS_PT_field_settings_kink", + "PHYSICS_PT_field_settings_texture_select", + ] +) +register_engine_with_panels( + "properties_physics_fluid", + [ + "PHYSICS_PT_adaptive_domain", + "PHYSICS_PT_borders", + "PHYSICS_PT_cache", + "PHYSICS_PT_collections", + "PHYSICS_PT_diffusion", + "PHYSICS_PT_export", + "PHYSICS_PT_field_weights", + "PHYSICS_PT_fire", + "PHYSICS_PT_flow_initial_velocity", + "PHYSICS_PT_flow_source", + "PHYSICS_PT_flow_texture", + "PHYSICS_PT_fluid", + "PHYSICS_PT_guide", + "PHYSICS_PT_liquid", + "PHYSICS_PT_mesh", + "PHYSICS_PT_noise", + "PHYSICS_PT_particles", + "PHYSICS_PT_settings", + "PHYSICS_PT_smoke", + "PHYSICS_PT_smoke_dissolve", + "PHYSICS_PT_viscosity", + ] +) +register_engine_with_panels( + "properties_physics_rigidbody", + [ + "PHYSICS_PT_rigid_body", + "PHYSICS_PT_rigid_body_collisions", + "PHYSICS_PT_rigid_body_collisions_collections", + "PHYSICS_PT_rigid_body_collisions_sensitivity", + "PHYSICS_PT_rigid_body_collisions_surface", + "PHYSICS_PT_rigid_body_dynamics", + "PHYSICS_PT_rigid_body_dynamics_deactivation", + "PHYSICS_PT_rigid_body_settings", + ] +) +register_engine_with_panels( + "properties_physics_rigidbody_constraint", + [ + "PHYSICS_PT_rigid_body_constraint", + "PHYSICS_PT_rigid_body_constraint_limits", + "PHYSICS_PT_rigid_body_constraint_limits_angular", + "PHYSICS_PT_rigid_body_constraint_limits_linear", + "PHYSICS_PT_rigid_body_constraint_motor", + "PHYSICS_PT_rigid_body_constraint_motor_angular", + "PHYSICS_PT_rigid_body_constraint_motor_linear", + "PHYSICS_PT_rigid_body_constraint_objects", + "PHYSICS_PT_rigid_body_constraint_override_iterations", + "PHYSICS_PT_rigid_body_constraint_settings", + "PHYSICS_PT_rigid_body_constraint_springs", + "PHYSICS_PT_rigid_body_constraint_springs_angular", + "PHYSICS_PT_rigid_body_constraint_springs_linear", + ] +) +register_engine_with_panels( + "properties_physics_softbody", + [ + "PHYSICS_PT_softbody", + "PHYSICS_PT_softbody_cache", + "PHYSICS_PT_softbody_collision", + "PHYSICS_PT_softbody_edge", + "PHYSICS_PT_softbody_edge_aerodynamics", + "PHYSICS_PT_softbody_edge_stiffness", + "PHYSICS_PT_softbody_field_weights", + "PHYSICS_PT_softbody_goal", + "PHYSICS_PT_softbody_goal_settings", + "PHYSICS_PT_softbody_goal_strengths", + "PHYSICS_PT_softbody_object", + "PHYSICS_PT_softbody_simulation", + "PHYSICS_PT_softbody_solver", + "PHYSICS_PT_softbody_solver_diagnostics", + "PHYSICS_PT_softbody_solver_helpers", + ] +) + +#-------------------------------------------------------------- class PsychopathPanel(): COMPAT_ENGINES = {'PSYCHOPATH_RENDER'} @@ -20,7 +294,7 @@ class PsychopathPanel(): @classmethod def poll(cls, context): rd = context.scene.render - return (rd.use_game_engine is False) and (rd.engine in cls.COMPAT_ENGINES) + return rd.engine in cls.COMPAT_ENGINES class RENDER_PT_psychopath_render_settings(PsychopathPanel, bpy.types.Panel): @@ -78,29 +352,7 @@ class WORLD_PT_psychopath_background(PsychopathPanel, bpy.types.Panel): layout = self.layout world = context.world - layout.prop(world, "horizon_color", text="Color") - - -class DATA_PT_psychopath_camera_dof(PsychopathPanel, bpy.types.Panel): - bl_label = "Depth of Field" - bl_space_type = 'PROPERTIES' - bl_region_type = 'WINDOW' - bl_context = "data" - - @classmethod - def poll(cls, context): - engine = context.scene.render.engine - return context.camera and PsychopathPanel.poll(context) - - def draw(self, context): - ob = context.active_object - layout = self.layout - - col = layout.column() - - col.prop(ob.data, "dof_object") - col.prop(ob.data, "dof_distance") - col.prop(ob.data.psychopath, "aperture_radius") + layout.prop(world.psychopath, "background_color", text="Color") class DATA_PT_psychopath_lamp(PsychopathPanel, bpy.types.Panel): @@ -112,7 +364,7 @@ class DATA_PT_psychopath_lamp(PsychopathPanel, bpy.types.Panel): @classmethod def poll(cls, context): engine = context.scene.render.engine - return context.lamp and PsychopathPanel.poll(context) + return context.active_object.type == 'LIGHT' and PsychopathPanel.poll(context) def draw(self, context): ob = context.active_object @@ -144,22 +396,23 @@ class DATA_PT_psychopath_area_lamp(PsychopathPanel, bpy.types.Panel): @classmethod def poll(cls, context): - lamp = context.lamp engine = context.scene.render.engine - return (lamp and lamp.type == 'AREA') and (engine in cls.COMPAT_ENGINES) + return context.active_object.type == 'LIGHT' \ + and context.active_object.data.type == 'AREA' \ + and (engine in cls.COMPAT_ENGINES) def draw(self, context): layout = self.layout - lamp = context.lamp + lamp = context.active_object.data col = layout.column() col.row().prop(lamp, "shape", expand=True) sub = col.row(align=True) - if lamp.shape == 'SQUARE': + if lamp.shape == 'SQUARE' or lamp.shape == 'DISK': sub.prop(lamp, "size") - elif lamp.shape == 'RECTANGLE': + elif lamp.shape == 'RECTANGLE' or lamp.shape == 'ELLIPSE': sub.prop(lamp, "size", text="Size X") sub.prop(lamp, "size_y", text="Size Y") @@ -271,7 +524,6 @@ def register(): bpy.utils.register_class(RENDER_PT_psychopath_render_settings) bpy.utils.register_class(RENDER_PT_psychopath_export_settings) bpy.utils.register_class(WORLD_PT_psychopath_background) - bpy.utils.register_class(DATA_PT_psychopath_camera_dof) bpy.utils.register_class(DATA_PT_psychopath_mesh) bpy.utils.register_class(DATA_PT_psychopath_lamp) bpy.utils.register_class(DATA_PT_psychopath_area_lamp) @@ -282,8 +534,7 @@ def unregister(): bpy.utils.unregister_class(RENDER_PT_psychopath_render_settings) bpy.utils.unregister_class(RENDER_PT_psychopath_export_settings) bpy.utils.unregister_class(WORLD_PT_psychopath_background) - bpy.utils.unregister_class(DATA_PT_psychopath_camera_dof) - bpy.utils.register_class(DATA_PT_psychopath_mesh) + bpy.utils.unregister_class(DATA_PT_psychopath_mesh) bpy.utils.unregister_class(DATA_PT_psychopath_lamp) bpy.utils.unregister_class(DATA_PT_psychopath_area_lamp) bpy.utils.unregister_class(MATERIAL_PT_psychopath_context_material)