diff --git a/render_povray/__init__.py b/render_povray/__init__.py
index f0734c5fe1d6233249c248ea7457b8c511697bb4..2bc4f42033b46af05d819302f2571c4fc02ddc09 100755
--- a/render_povray/__init__.py
+++ b/render_povray/__init__.py
@@ -94,7 +94,7 @@ scripting_gui.py :
     Display properties from scripting_properties.py for user to add his custom POV code
 
 scripting.py :
-    Insert POV native scene description elements to exported POV file
+    Insert POV native scene description elements into blender scene or to exported POV file
 
 df3_library.py
     Render smoke to *.df3 files
@@ -214,20 +214,26 @@ else:
         scripting_properties,
         render,
         object_primitives,  # for import and export of POV specific primitives
-        update_files,
     )
 
-###############################################################################
+# ---------------------------------------------------------------- #
 # Auto update.
-###############################################################################
+# ---------------------------------------------------------------- #
+
+
 class POV_OT_update_addon(bpy.types.Operator):
     """Update this addon to the latest version."""
 
     bl_idname = "pov.update_addon"
     bl_label = "Update POV addon"
 
-    def execute(self, context):
-        import os, tempfile, shutil, urllib.request, urllib.error, zipfile
+    def execute(self, context):  # sourcery no-metrics
+        import os
+        import tempfile
+        import shutil
+        import urllib.request
+        import urllib.error
+        import zipfile
 
         def recursive_overwrite(src, dest, ignore=None):
             if os.path.isdir(src):
@@ -250,7 +256,8 @@ class POV_OT_update_addon(bpy.types.Operator):
         with tempfile.TemporaryDirectory() as temp_dir_path:
             temp_zip_path = os.path.join(temp_dir_path, 'master.zip')
 
-            # Download zip archive of latest addons master branch commit (So we also get presets)
+            # Download zip archive of latest addons master branch commit
+            # More work needed so we also get files from the shared addons presets /pov folder
             # switch this URL back to the BF hosted one as soon as gitweb snapshot gets fixed
             url = 'https://github.com/blender/blender-addons/archive/refs/heads/master.zip'
             try:
@@ -303,7 +310,8 @@ class POV_OT_update_addon(bpy.types.Operator):
 
             # TODO: Create backup
 
-            # Delete old POV addon files (only directories and *.py files, the user might have other stuff in there!)
+            # Delete old POV addon files
+            # (only directories and *.py files, user might have other stuff in there!)
             print('Deleting old POV addon files')
             # remove __init__.py
             os.remove(os.path.join(render_povray_dir, '__init__.py'))
@@ -328,9 +336,9 @@ class POV_OT_update_addon(bpy.types.Operator):
         return {'FINISHED'}
 
 
-###############################################################################
+# ---------------------------------------------------------------- #
 # Povray Preferences.
-###############################################################################
+# ---------------------------------------------------------------- #
 
 
 class PovrayPreferences(bpy.types.AddonPreferences):
@@ -397,7 +405,10 @@ class PovrayPreferences(bpy.types.AddonPreferences):
         layout.operator("pov.update_addon", icon='FILE_REFRESH')
 
 
-classes = (POV_OT_update_addon, PovrayPreferences)
+classes = (
+    POV_OT_update_addon,
+    PovrayPreferences,
+)
 
 
 def register():
@@ -410,19 +421,15 @@ def register():
     texturing_properties.register()
     object_properties.register()
     scripting_properties.register()
-    scenography.register()
     render.register()
     base_ui.register()
-    scripting.register()
     object_primitives.register()
 
 
 def unregister():
     object_primitives.unregister()
-    scripting.unregister()
     base_ui.unregister()
     render.unregister()
-    scenography.unregister()
     scripting_properties.unregister()
     object_properties.unregister()
     texturing_properties.unregister()
@@ -437,6 +444,6 @@ def unregister():
 if __name__ == "__main__":
     register()
 
-# ------------8<---------[ BREAKPOINT ]--------------8<-----------#  Move this snippet around
-# __import__('code').interact(local=dict(globals(), **locals())) # < and uncomment this line
-# ----------------------------------------------------------------#  to inspect from Terminal
+# ------------8<---------[ BREAKPOINT ]--------------8<----------- #  Move this snippet around
+# __import__('code').interact(local=dict(globals(), **locals()))   # < and uncomment this line
+# ---------------------------------------------------------------- #  to inspect from Terminal
diff --git a/render_povray/base_ui.py b/render_povray/base_ui.py
index 85374ba36a95ff836b06ab02b7ac96bfc61a8684..967080faee6c1ae08681cede93ad2d892727ffb6 100755
--- a/render_povray/base_ui.py
+++ b/render_povray/base_ui.py
@@ -51,12 +51,13 @@ from . import (
     texturing_gui,
     shading_nodes,  # for POV specific nodes
     scripting_gui,
+    update_files,
 )
 
 
-############# POV-Centric WORKSPACE #############
+# ------------ POV-Centric WORKSPACE ------------ #
 @persistent
-def povCentricWorkspace(dummy):
+def pov_centric_moray_like_workspace(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
@@ -121,8 +122,8 @@ def povCentricWorkspace(dummy):
                                 override['area'] = area
                                 override['region'] = region
 
-                                area_x = area.x + (area.width / 2)
-                                area_y = area.y + area.height
+                                # area_x = area.x + (area.width / 2)
+                                # area_y = area.y + area.height
                                 bpy.ops.screen.space_type_set_or_cycle(override, space_type='INFO')
                                 try:
                                     if area == pov_workspace[6] and bpy.ops.screen.area_move.poll(
@@ -219,7 +220,7 @@ def povCentricWorkspace(dummy):
             "\nThe factory 'Scripting' workspace is needed before POV centric "
             "\nworkspace may activate when POV is set as your default renderer"
         )
-    ####################################UTF-8###################################
+    # -----------------------------------UTF-8---------------------------------- #
     # Check and fix all strings in current .blend file to be valid UTF-8 Unicode
     # sometimes needed for old, 2.4x / 2.6x area files
     bpy.ops.wm.blend_strings_utf8_validate()
@@ -237,10 +238,8 @@ def check_material(mat):
 
 
 def simple_material(mat):
-    """Test if a material uses nodes."""
-    if (mat is not None) and (not mat.use_nodes):
-        return True
-    return False
+    """Test if a material is nodeless."""
+    return (mat is not None) and (not mat.use_nodes)
 
 
 def pov_context_tex_datablock(context):
@@ -282,6 +281,7 @@ def pov_context_tex_datablock(context):
 
 
 def register():
+    update_files.register()
     render_gui.register()
     scenography_gui.register()
     object_gui.register()
@@ -290,13 +290,13 @@ def register():
     shading_nodes.register()
     scripting_gui.register()
 
-    if not povCentricWorkspace in bpy.app.handlers.load_post:
-        bpy.app.handlers.load_post.append(povCentricWorkspace)
+    if pov_centric_moray_like_workspace not in bpy.app.handlers.load_post:
+        bpy.app.handlers.load_post.append(pov_centric_moray_like_workspace)
 
 
 def unregister():
-    if povCentricWorkspace in bpy.app.handlers.load_post:
-        bpy.app.handlers.load_post.remove(povCentricWorkspace)
+    if pov_centric_moray_like_workspace in bpy.app.handlers.load_post:
+        bpy.app.handlers.load_post.remove(pov_centric_moray_like_workspace)
 
     scripting_gui.unregister()
     shading_nodes.unregister()
@@ -305,3 +305,4 @@ def unregister():
     object_gui.unregister()
     scenography_gui.unregister()
     render_gui.unregister()
+    update_files.unregister()
diff --git a/render_povray/df3_library.py b/render_povray/df3_library.py
index f802fb2dd8962c89f1e2741ddcfda91bb6b25d89..b5525741503b146666b6462f5853a90180afc3b6 100755
--- a/render_povray/df3_library.py
+++ b/render_povray/df3_library.py
@@ -19,7 +19,7 @@
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 #
 #
-################################################################################
+# -----------------------------------------------------------------------------
 #
 # Creation functions
 #     __init__(x=1, y=1, z=1) : default constructor
@@ -42,13 +42,12 @@
 #     exportDF3():
 #     importDF3():
 #
-################################################################################
+# -----------------------------------------------------------------------------
 
 import struct
 import os
 import stat
 import array
-import sys
 
 # -+-+-+- Start df3 Class -+-+-+-
 
@@ -78,7 +77,7 @@ class df3:
             self.voxel[i] = indf3.voxel[i]
         return self
 
-    #### Info Functions
+    # --- Info Functions
 
     def sizeX(self):
         return self.maxX
@@ -90,13 +89,12 @@ class df3:
         return self.maxZ
 
     def size(self):
-        tmp = []
-        tmp.append(self.sizeX())
+        tmp = [self.sizeX()]
         tmp.append(self.sizeY())
         tmp.append(self.sizeZ())
         return tmp
 
-    #### Voxel Access Functions
+    # --- Voxel Access Functions
 
     def get(self, x, y, z):
         return self.voxel[self.__voxa__(x, y, z)]
@@ -124,7 +122,7 @@ class df3:
 
         self.voxel[self.__voxa__(x, y, z)] = val
 
-    #### Scalar Functions
+    # --- Scalar Functions
 
     def mult(self, val):
         for i in range(self.sizeX() * self.sizeY() * self.sizeZ()):
@@ -156,7 +154,7 @@ class df3:
 
         return tmp
 
-    #### Vector Functions
+    # --- Vector Functions
 
     def compare(self, indf3):
         if self.__samesize__(indf3) == 0:
@@ -221,7 +219,7 @@ class df3:
 
         return self
 
-    #### Import/Export Functions
+    # --- Import/Export Functions
 
     def exportDF3(self, file, depth=8, rescale=1):
         x = self.sizeX()
@@ -230,7 +228,9 @@ class df3:
 
         try:
             f = open(file, 'wb')
-        except:
+        except BaseException as e:
+            print(e.__doc__)
+            print('An exception occurred: {}'.format(e))
             print("Could not open " + file + " for write")
             return
 
@@ -253,7 +253,9 @@ class df3:
             f = open(file, 'rb')
             size = os.stat(file)[stat.ST_SIZE]
 
-        except:
+        except BaseException as e:
+            print(e.__doc__)
+            print('An exception occurred: {}'.format(e))
             print("Could not open " + file + " for read")
             return []
 
@@ -272,19 +274,17 @@ class df3:
         elif size == 4 * x * y * z:
             format = 32
 
-        if format == 32:
-            for i in range(x * y * z):
+        for i in range(x * y * z):
+            if format == 32:
                 self.voxel[i] = float(struct.unpack(self.__struct4byte__, f.read(4))[0])
-        elif format == 16:
-            for i in range(x * y * z):
+            elif format == 16:
                 self.voxel[i] = float(struct.unpack(self.__struct2byte__, f.read(2))[0])
-        elif format == 8:
-            for i in range(x * y * z):
+            elif format == 8:
                 self.voxel[i] = float(struct.unpack(self.__struct1byte__, f.read(1))[0])
 
         return self
 
-    #### Local classes not intended for user use
+    # --- Local classes not intended for user use
 
     def __rip__(self, minX, maxX, minY, maxY, minZ, maxZ):
         sizeX = maxX - minX + 1
@@ -366,32 +366,32 @@ class df3:
 
 
 # -=-=-=- End df3 Class -=-=-=-
-##########DEFAULT EXAMPLES
+# --------DEFAULT EXAMPLES
 # if __name__ == '__main__':
 # localX = 80
 # localY = 90
 # localZ = 100
-## Generate an output
+# -- Generate an output
 # temp = df3(localX, localY, localZ)
 
 # for i in range(localX):
-# for j in range(localY):
-# for k in range(localZ):
-# if (i >= (localX/2)):
-# temp.set(i, j, k, 1.0)
+#   for j in range(localY):
+#       for k in range(localZ):
+#           if (i >= (localX/2)):
+#               temp.set(i, j, k, 1.0)
 
 # temp.exportDF3('temp.df3', 16)
-###############################################################################
-## Import
+# -----------------------------------------------------------------------------
+# -- Import
 # temp2 = df3().importDF3('temp.df3')
 # temp2.mult(1/temp2.max())
 
-## Compare
+# -- Compare
 # print(temp2.size())
 
 # if (temp.compare(temp2) == 0): print("DF3's Do Not Match")
 
-###############################################################################
+# -----------------------------------------------------------------------------
 # ChangeLog
 # ---------
 # 08/09/05: 0.20 released
@@ -400,4 +400,4 @@ class df3:
 #    + Convert from 3-d list structure to Array class for data storage
 #    + Add element access, scalar, and vector functions
 # 07/13/05: 0.10 released
-###############################################################################
+# -----------------------------------------------------------------------------
diff --git a/render_povray/object_curve_topology.py b/render_povray/object_curve_topology.py
index 5fa2b277bc3ac7f398f269b651634f4209215099..876952e2a334e5adcbdca1816e1b25d8154fda7c 100755
--- a/render_povray/object_curve_topology.py
+++ b/render_povray/object_curve_topology.py
@@ -25,20 +25,23 @@ meshes or curve based shapes.
 
 import bpy
 
-from .shading import write_object_material
+from .shading import write_object_material_interior
 
-################################ LOFT, ETC.
-def export_curves(ob, string_strip_hyphen, global_matrix, tab_write):
+# -------- LOFT, ETC.
+
+
+def export_curves(file, ob, string_strip_hyphen, global_matrix, tab_write):
     """write all curves based POV primitives to exported file """
-    name_orig = "OB" + ob.name
+    # name_orig = "OB" + ob.name # XXX Unused, check instanciation
     dataname_orig = "DATA" + ob.data.name
 
-    name = string_strip_hyphen(bpy.path.clean_name(name_orig))
+    # name = string_strip_hyphen(bpy.path.clean_name(name_orig)) # XXX Unused, check instanciation
     dataname = string_strip_hyphen(bpy.path.clean_name(dataname_orig))
 
-    matrix = global_matrix @ ob.matrix_world
+    # matrix = global_matrix @ ob.matrix_world # XXX Unused, check instanciation
     bezier_sweep = False
     if ob.pov.curveshape == 'sphere_sweep':
+        # TODO: Check radius ; shorten lines, may use tab_write() ? > fstrings since py 2.9
         # inlined spheresweep macro, which itself calls Shapes.inc:
         file.write('        #include "shapes.inc"\n')
 
@@ -959,12 +962,12 @@ def export_curves(ob, string_strip_hyphen, global_matrix, tab_write):
         if ob.pov.curveshape in {'birail'}:
             splines = '%s1,%s2,%s3,%s4' % (dataname, dataname, dataname, dataname)
             tab_write('object {Coons(%s, %s, %s, "")\n' % (splines, ob.pov.res_u, ob.pov.res_v))
-        pov_mat_name = "Default_texture"
+        # pov_mat_name = "Default_texture" # XXX! Unused, check instanciation
         if ob.active_material:
             # pov_mat_name = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name))
             try:
                 material = ob.active_material
-                write_object_material(material, ob, tab_write)
+                write_object_material_interior(material, ob, tab_write)
             except IndexError:
                 print(ob.data)
         # tab_write("texture {%s}\n"%pov_mat_name)
diff --git a/render_povray/object_gui.py b/render_povray/object_gui.py
index 9fbf8a8b469a984fc682d180aa60449a43f8012b..aebaa3119a01c49ad0df6b0799b6b55c8cd86933 100755
--- a/render_povray/object_gui.py
+++ b/render_povray/object_gui.py
@@ -45,8 +45,8 @@ from bl_ui import properties_data_mesh
 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
+# make some native panels contextual to some object variable
+# by recreating custom panels inheriting their properties
 
 
 from .scripting_gui import VIEW_MT_POV_import
@@ -59,7 +59,7 @@ class ModifierButtonsPanel:
     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
+    COMPAT_ENGINES = {'POVRAY_RENDER'}
 
     @classmethod
     def poll(cls, context):
@@ -75,7 +75,7 @@ class ObjectButtonsPanel:
     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
+    COMPAT_ENGINES = {'POVRAY_RENDER'}
 
     @classmethod
     def poll(cls, context):
@@ -107,7 +107,7 @@ class PovDataButtonsPanel(properties_data_mesh.MeshButtonsPanel):
 
     @classmethod
     def poll(cls, context):
-        engine = context.scene.render.engine
+        # engine = context.scene.render.engine # XXX Unused
         obj = context.object
         # We use our parent class poll func too, avoids to re-define too much things...
         return (
@@ -185,17 +185,16 @@ class MODIFIERS_PT_POV_modifiers(ModifierButtonsPanel, Panel):
         # Find Boolean Modifiers for displaying CSG option
         onceCSG = 0
         for mod in ob.modifiers:
-            if onceCSG == 0:
-                if mod:
-                    if mod.type == 'BOOLEAN':
-                        col.prop(ob.pov, "boolean_mod")
-                        onceCSG = 1
+            if onceCSG == 0 and mod:
+                if mod.type == 'BOOLEAN':
+                    col.prop(ob.pov, "boolean_mod")
+                    onceCSG = 1
 
-                    if ob.pov.boolean_mod == "POV":
-                        split = layout.split()
-                        col = layout.column()
-                        # Inside Vector for CSG
-                        col.prop(ob.pov, "inside_vector")
+                if ob.pov.boolean_mod == "POV":
+                    # split = layout.split() # better ?
+                    col = layout.column()
+                    # Inside Vector for CSG
+                    col.prop(ob.pov, "inside_vector")
 
 
 class OBJECT_PT_POV_obj_parameters(ObjectButtonsPanel, Panel):
@@ -256,6 +255,7 @@ class OBJECT_PT_POV_obj_sphere(PovDataButtonsPanel, Panel):
     bl_label = "POV Sphere"
     COMPAT_ENGINES = {'POVRAY_RENDER'}
     # bl_options = {'HIDE_HEADER'}
+
     @classmethod
     def poll(cls, context):
         engine = context.scene.render.engine
@@ -295,6 +295,7 @@ class OBJECT_PT_POV_obj_cylinder(PovDataButtonsPanel, Panel):
     bl_label = "POV Cylinder"
     COMPAT_ENGINES = {'POVRAY_RENDER'}
     # bl_options = {'HIDE_HEADER'}
+
     @classmethod
     def poll(cls, context):
         engine = context.scene.render.engine
@@ -311,14 +312,18 @@ class OBJECT_PT_POV_obj_cylinder(PovDataButtonsPanel, Panel):
         if obj.pov.object_as == 'CYLINDER':
             if not obj.pov.unlock_parameters:
                 col.prop(
-                    obj.pov, "unlock_parameters", text="Exported parameters below", icon='LOCKED'
+                    obj.pov, "unlock_parameters",
+                    text="Exported parameters below",
+                    icon='LOCKED'
                 )
                 col.label(text="Cylinder radius: " + str(obj.pov.cylinder_radius))
                 col.label(text="Cylinder cap location: " + str(obj.pov.cylinder_location_cap))
 
             else:
                 col.prop(
-                    obj.pov, "unlock_parameters", text="Edit exported parameters", icon='UNLOCKED'
+                    obj.pov, "unlock_parameters",
+                    text="Edit exported parameters",
+                    icon='UNLOCKED'
                 )
                 col.label(text="3D view proxy may get out of synch")
                 col.active = obj.pov.unlock_parameters
@@ -336,6 +341,7 @@ class OBJECT_PT_POV_obj_cone(PovDataButtonsPanel, Panel):
     bl_label = "POV Cone"
     COMPAT_ENGINES = {'POVRAY_RENDER'}
     # bl_options = {'HIDE_HEADER'}
+
     @classmethod
     def poll(cls, context):
         engine = context.scene.render.engine
@@ -380,6 +386,7 @@ class OBJECT_PT_POV_obj_superellipsoid(PovDataButtonsPanel, Panel):
     bl_label = "POV Superquadric ellipsoid"
     COMPAT_ENGINES = {'POVRAY_RENDER'}
     # bl_options = {'HIDE_HEADER'}
+
     @classmethod
     def poll(cls, context):
         engine = context.scene.render.engine
@@ -426,6 +433,7 @@ class OBJECT_PT_POV_obj_torus(PovDataButtonsPanel, Panel):
     bl_label = "POV Torus"
     COMPAT_ENGINES = {'POVRAY_RENDER'}
     # bl_options = {'HIDE_HEADER'}
+
     @classmethod
     def poll(cls, context):
         engine = context.scene.render.engine
@@ -470,6 +478,7 @@ class OBJECT_PT_POV_obj_supertorus(PovDataButtonsPanel, Panel):
     bl_label = "POV SuperTorus"
     COMPAT_ENGINES = {'POVRAY_RENDER'}
     # bl_options = {'HIDE_HEADER'}
+
     @classmethod
     def poll(cls, context):
         engine = context.scene.render.engine
@@ -528,6 +537,7 @@ class OBJECT_PT_POV_obj_parametric(PovDataButtonsPanel, Panel):
     bl_label = "POV Parametric surface"
     COMPAT_ENGINES = {'POVRAY_RENDER'}
     # bl_options = {'HIDE_HEADER'}
+
     @classmethod
     def poll(cls, context):
         engine = context.scene.render.engine
@@ -588,9 +598,9 @@ class OBJECT_PT_povray_replacement_text(ObjectButtonsPanel, Panel):
         col.prop(obj.pov, "replacement_text", text="")
 
 
-###############################################################################
-# Add Povray Objects
-###############################################################################
+# ---------------------------------------------------------------- #
+# Add POV objects
+# ---------------------------------------------------------------- #
 def check_add_mesh_extra_objects():
     """Test if Add mesh extra objects addon is activated
 
@@ -707,8 +717,6 @@ classes = (
 
 
 def register():
-    # from bpy.utils import register_class
-
     for cls in classes:
         register_class(cls)
 
@@ -721,7 +729,6 @@ def register():
 
 def unregister():
     # addon_utils.disable("add_mesh_extra_objects", default_set=False)
-
     bpy.types.VIEW3D_MT_add.remove(menu_func_add)
 
     for cls in reversed(classes):
diff --git a/render_povray/object_mesh_topology.py b/render_povray/object_mesh_topology.py
index 2b0ce008a8f1d4c6352056fcac9d42ccd540f705..1599d6d15792032f12f6f1ffd36d7ea82b03f10d 100755
--- a/render_povray/object_mesh_topology.py
+++ b/render_povray/object_mesh_topology.py
@@ -22,12 +22,10 @@
 
 meshes or curve based shapes."""
 
-####################
-## Faster mesh export
-import numpy as np
-
-####################
-import random  # used for hair
+# --------
+# -- Faster mesh export ...one day
+# import numpy as np
+# --------
 import bpy
 from . import texturing  # for how textures influence shaders
 from .scenography import export_smoke
@@ -70,7 +68,7 @@ def export_meshes(
     safety,
     write_object_modifiers,
     material_names_dictionary,
-    write_object_material,
+    write_object_material_interior,
     exported_lights_count,
     unpacked_images,
     image_format,
@@ -89,61 +87,62 @@ def export_meshes(
     info_callback,
 ):
     """write all meshes as POV mesh2{} syntax to exported file """
-    # some numpy functions to speed up mesh export NOT IN USE YET
-
-    # TODO: also write a numpy function to read matrices at object level?
-    # feed below with mesh object.data, but only after doing data.calc_loop_triangles()
-    def read_verts_co(self, mesh):
-        #'float64' would be a slower 64-bit floating-point number numpy datatype
-        # using 'float32' vert coordinates for now until any issue is reported
-        mverts_co = np.zeros((len(mesh.vertices) * 3), dtype=np.float32)
-        mesh.vertices.foreach_get("co", mverts_co)
-        return np.reshape(mverts_co, (len(mesh.vertices), 3))
-
-    def read_verts_idx(self, mesh):
-        mverts_idx = np.zeros((len(mesh.vertices)), dtype=np.int64)
-        mesh.vertices.foreach_get("index", mverts_idx)
-        return np.reshape(mverts_idx, (len(mesh.vertices), 1))
-
-    def read_verts_norms(self, mesh):
-        #'float64' would be a slower 64-bit floating-point number numpy datatype
-        # using less accurate 'float16' normals for now until any issue is reported
-        mverts_no = np.zeros((len(mesh.vertices) * 3), dtype=np.float16)
-        mesh.vertices.foreach_get("normal", mverts_no)
-        return np.reshape(mverts_no, (len(mesh.vertices), 3))
-
-    def read_faces_idx(self, mesh):
-        mfaces_idx = np.zeros((len(mesh.loop_triangles)), dtype=np.int64)
-        mesh.loop_triangles.foreach_get("index", mfaces_idx)
-        return np.reshape(mfaces_idx, (len(mesh.loop_triangles), 1))
-
-    def read_faces_verts_indices(self, mesh):
-        mfaces_verts_idx = np.zeros((len(mesh.loop_triangles) * 3), dtype=np.int64)
-        mesh.loop_triangles.foreach_get("vertices", mfaces_verts_idx)
-        return np.reshape(mfaces_verts_idx, (len(mesh.loop_triangles), 3))
-
-    # Why is below different from vertex indices?
-    def read_faces_verts_loops(self, mesh):
-        mfaces_verts_loops = np.zeros((len(mesh.loop_triangles) * 3), dtype=np.int64)
-        mesh.loop_triangles.foreach_get("loops", mfaces_verts_loops)
-        return np.reshape(mfaces_verts_loops, (len(mesh.loop_triangles), 3))
-
-    def read_faces_norms(self, mesh):
-        #'float64' would be a slower 64-bit floating-point number numpy datatype
-        # using less accurate 'float16' normals for now until any issue is reported
-        mfaces_no = np.zeros((len(mesh.loop_triangles) * 3), dtype=np.float16)
-        mesh.loop_triangles.foreach_get("normal", mfaces_no)
-        return np.reshape(mfaces_no, (len(mesh.loop_triangles), 3))
-
-    def read_faces_smooth(self, mesh):
-        mfaces_smth = np.zeros((len(mesh.loop_triangles) * 1), dtype=np.bool)
-        mesh.loop_triangles.foreach_get("use_smooth", mfaces_smth)
-        return np.reshape(mfaces_smth, (len(mesh.loop_triangles), 1))
-
-    def read_faces_material_indices(self, mesh):
-        mfaces_mats_idx = np.zeros((len(mesh.loop_triangles)), dtype=np.int16)
-        mesh.loop_triangles.foreach_get("material_index", mfaces_mats_idx)
-        return np.reshape(mfaces_mats_idx, (len(mesh.loop_triangles), 1))
+    # # some numpy functions to speed up mesh export NOT IN USE YET
+    # # Current 2.93 beta numpy linking has troubles so definitions commented off for now
+
+    # # TODO: also write a numpy function to read matrices at object level?
+    # # feed below with mesh object.data, but only after doing data.calc_loop_triangles()
+    # def read_verts_co(self, mesh):
+        # #'float64' would be a slower 64-bit floating-point number numpy datatype
+        # # using 'float32' vert coordinates for now until any issue is reported
+        # mverts_co = np.zeros((len(mesh.vertices) * 3), dtype=np.float32)
+        # mesh.vertices.foreach_get("co", mverts_co)
+        # return np.reshape(mverts_co, (len(mesh.vertices), 3))
+
+    # def read_verts_idx(self, mesh):
+        # mverts_idx = np.zeros((len(mesh.vertices)), dtype=np.int64)
+        # mesh.vertices.foreach_get("index", mverts_idx)
+        # return np.reshape(mverts_idx, (len(mesh.vertices), 1))
+
+    # def read_verts_norms(self, mesh):
+        # #'float64' would be a slower 64-bit floating-point number numpy datatype
+        # # using less accurate 'float16' normals for now until any issue is reported
+        # mverts_no = np.zeros((len(mesh.vertices) * 3), dtype=np.float16)
+        # mesh.vertices.foreach_get("normal", mverts_no)
+        # return np.reshape(mverts_no, (len(mesh.vertices), 3))
+
+    # def read_faces_idx(self, mesh):
+        # mfaces_idx = np.zeros((len(mesh.loop_triangles)), dtype=np.int64)
+        # mesh.loop_triangles.foreach_get("index", mfaces_idx)
+        # return np.reshape(mfaces_idx, (len(mesh.loop_triangles), 1))
+
+    # def read_faces_verts_indices(self, mesh):
+        # mfaces_verts_idx = np.zeros((len(mesh.loop_triangles) * 3), dtype=np.int64)
+        # mesh.loop_triangles.foreach_get("vertices", mfaces_verts_idx)
+        # return np.reshape(mfaces_verts_idx, (len(mesh.loop_triangles), 3))
+
+    # # Why is below different from vertex indices?
+    # def read_faces_verts_loops(self, mesh):
+        # mfaces_verts_loops = np.zeros((len(mesh.loop_triangles) * 3), dtype=np.int64)
+        # mesh.loop_triangles.foreach_get("loops", mfaces_verts_loops)
+        # return np.reshape(mfaces_verts_loops, (len(mesh.loop_triangles), 3))
+
+    # def read_faces_norms(self, mesh):
+        # #'float64' would be a slower 64-bit floating-point number numpy datatype
+        # # using less accurate 'float16' normals for now until any issue is reported
+        # mfaces_no = np.zeros((len(mesh.loop_triangles) * 3), dtype=np.float16)
+        # mesh.loop_triangles.foreach_get("normal", mfaces_no)
+        # return np.reshape(mfaces_no, (len(mesh.loop_triangles), 3))
+
+    # def read_faces_smooth(self, mesh):
+        # mfaces_smth = np.zeros((len(mesh.loop_triangles) * 1), dtype=np.bool)
+        # mesh.loop_triangles.foreach_get("use_smooth", mfaces_smth)
+        # return np.reshape(mfaces_smth, (len(mesh.loop_triangles), 1))
+
+    # def read_faces_material_indices(self, mesh):
+        # mfaces_mats_idx = np.zeros((len(mesh.loop_triangles)), dtype=np.int16)
+        # mesh.loop_triangles.foreach_get("material_index", mfaces_mats_idx)
+        # return np.reshape(mfaces_mats_idx, (len(mesh.loop_triangles), 1))
 
     #        obmatslist = []
     #        def hasUniqueMaterial():
@@ -166,7 +165,8 @@ def export_meshes(
     #                        return True
     #            return False
     # For objects using local material(s) only!
-    # This is a mapping between a tuple (dataname, material_names_dictionary, ...), and the POV dataname.
+    # This is a mapping between a tuple (dataname, material_names_dictionary, ...),
+    # and the POV dataname.
     # As only objects using:
     #     * The same data.
     #     * EXACTLY the same materials, in EXACTLY the same sockets.
@@ -222,11 +222,10 @@ def export_meshes(
         data_ref[dataname] = [(name, matrix_as_pov_string(matrix))]
         return dataname
 
-    # XXX TODO : Too many nested blocks in this object loop, split hair (+particles?) to their function in own file,
     ob_num = 0
+    depsgraph = bpy.context.evaluated_depsgraph_get()
     for ob in sel:
         # Using depsgraph
-        depsgraph = bpy.context.evaluated_depsgraph_get()
         ob = bpy.data.objects[ob.name].evaluated_get(depsgraph)
 
         # subtract original from the count of their instances as were not counted before 2.8
@@ -237,7 +236,7 @@ def export_meshes(
             #     for object we won't export here!
             if ob.type in {
                 'LIGHT',
-                'CAMERA',  #'EMPTY', #empties can bear dupligroups
+                'CAMERA',  # 'EMPTY', #empties can bear dupligroups
                 'META',
                 'ARMATURE',
                 'LATTICE',
@@ -277,32 +276,34 @@ def export_meshes(
                                 and mod.show_render
                                 and (p_sys.name == mod.particle_system.name)
                             ):
-                                export_hair(file, ob, p_sys, global_matrix, write_matrix)
+                                export_hair(file, ob, mod, p_sys, global_matrix, write_matrix)
                                 if not render_emitter:
                                     continue  # don't render mesh, skip to next object.
 
-                #############################################
+                # ------------------------------------------------
                 # Generating a name for object just like materials to be able to use it
                 # (baking for now or anything else).
                 # XXX I don't understand that if we are here, sel if a non-empty iterable,
                 #     so this condition is always True, IMO -- mont29
-                if ob.data:
-                    name_orig = "OB" + ob.name
-                    dataname_orig = "DATA" + ob.data.name
-                elif ob.is_instancer:
+                # EMPTY type objects treated  a little further below -- MR
+
+                # modified elif to if below as non EMPTY objects can also be instancers
+                if ob.is_instancer:
                     if ob.instance_type == 'COLLECTION':
                         name_orig = "OB" + ob.name
                         dataname_orig = "DATA" + ob.instance_collection.name
                     else:
                         # hoping only dupligroups have several source datablocks
                         # ob_dupli_list_create(scene) #deprecated in 2.8
-                        depsgraph = bpy.context.evaluated_depsgraph_get()
                         for eachduplicate in depsgraph.object_instances:
                             # Real dupli instance filtered because
                             # original included in list since 2.8
                             if eachduplicate.is_instance:
                                 dataname_orig = "DATA" + eachduplicate.object.name
                         # ob.dupli_list_clear() #just don't store any reference to instance since 2.8
+                elif ob.data: # not an EMPTY type object
+                    name_orig = "OB" + ob.name
+                    dataname_orig = "DATA" + ob.data.name
                 elif ob.type == 'EMPTY':
                     name_orig = "OB" + ob.name
                     dataname_orig = "DATA" + ob.name
@@ -311,18 +312,16 @@ def export_meshes(
                     dataname_orig = DEF_OBJ_NAME
                 name = string_strip_hyphen(bpy.path.clean_name(name_orig))
                 dataname = string_strip_hyphen(bpy.path.clean_name(dataname_orig))
-                ##            for slot in ob.material_slots:
-                ##                if slot.material is not None and slot.link == 'OBJECT':
-                ##                    obmaterial = slot.material
+                #            for slot in ob.material_slots:
+                #                if slot.material is not None and slot.link == 'OBJECT':
+                #                    obmaterial = slot.material
 
-                #############################################
+                # ------------------------------------------------
 
                 if info_callback:
                     info_callback("Object %2.d of %2.d (%s)" % (ob_num, len(sel), ob.name))
 
-                # if ob.type != 'MESH':
-                #    continue
-                # me = ob.data
+                me = ob.data
 
                 matrix = global_matrix @ ob.matrix_world
                 povdataname = store(scene, ob, name, dataname, matrix)
@@ -332,7 +331,7 @@ def export_meshes(
 
                 print("Writing Down First Occurrence of " + name)
 
-                ############################################Povray Primitives
+                # ------------ Povray Primitives ------------ #
                 # special export_curves() function takes care of writing
                 # lathe, sphere_sweep, birail, and loft except with modifiers
                 # converted to mesh
@@ -341,7 +340,7 @@ def export_meshes(
                         ob.pov.curveshape in {'lathe', 'sphere_sweep', 'loft'}
                     ):
                         continue  # Don't render proxy mesh, skip to next object
-
+                # pov_mat_name = "Default_texture" # Not used...remove?
                 if ob.pov.object_as == 'ISOSURFACE':
                     tab_write("#declare %s = isosurface{ \n" % povdataname)
                     tab_write("function{ \n")
@@ -379,12 +378,11 @@ def export_meshes(
                     else:
                         if ob.pov.max_trace > 1:
                             tab_write("max_trace %.6g\n" % ob.pov.max_trace)
-                    pov_mat_name = "Default_texture"
                     if ob.active_material:
                         # pov_mat_name = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name))
                         try:
                             material = ob.active_material
-                            write_object_material(material, ob, tab_write)
+                            write_object_material_interior(material, ob, tab_write)
                         except IndexError:
                             print(me)
                     # tab_write("texture {%s}\n"%pov_mat_name)
@@ -397,12 +395,11 @@ def export_meshes(
                         "#declare %s = superellipsoid{ <%.4f,%.4f>\n"
                         % (povdataname, ob.pov.se_n2, ob.pov.se_n1)
                     )
-                    pov_mat_name = "Default_texture"
                     if ob.active_material:
                         # pov_mat_name = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name))
                         try:
                             material = ob.active_material
-                            write_object_material(material, ob, tab_write)
+                            write_object_material_interior(material, ob, tab_write)
                         except IndexError:
                             print(me)
                     # tab_write("texture {%s}\n"%pov_mat_name)
@@ -417,7 +414,7 @@ def export_meshes(
                     cross = ob.pov.st_cross
                     accuracy = ob.pov.st_accuracy
                     gradient = ob.pov.st_max_gradient
-                    ############Inline Supertorus macro
+                    # --- Inline Supertorus macro
                     file.write(
                         "#macro Supertorus(RMj, RMn, MajorControl, MinorControl, Accuracy, MaxGradient)\n"
                     )
@@ -439,17 +436,16 @@ def export_meshes(
                     file.write("      accuracy Accuracy\n")
                     file.write("   }\n")
                     file.write("#end\n")
-                    ############
+                    # ---
                     tab_write(
                         "#declare %s = object{ Supertorus( %.4g,%.4g,%.4g,%.4g,%.4g,%.4g)\n"
                         % (povdataname, rad_maj, rad_min, ring, cross, accuracy, gradient)
                     )
-                    pov_mat_name = "Default_texture"
                     if ob.active_material:
                         # pov_mat_name = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name))
                         try:
                             material = ob.active_material
-                            write_object_material(material, ob, tab_write)
+                            write_object_material_interior(material, ob, tab_write)
                         except IndexError:
                             print(me)
                     # tab_write("texture {%s}\n"%pov_mat_name)
@@ -460,12 +456,11 @@ def export_meshes(
 
                 if ob.pov.object_as == 'PLANE':
                     tab_write("#declare %s = plane{ <0,0,1>,1\n" % povdataname)
-                    pov_mat_name = "Default_texture"
                     if ob.active_material:
                         # pov_mat_name = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name))
                         try:
                             material = ob.active_material
-                            write_object_material(material, ob, tab_write)
+                            write_object_material_interior(material, ob, tab_write)
                         except IndexError:
                             print(me)
                     # tab_write("texture {%s}\n"%pov_mat_name)
@@ -476,12 +471,11 @@ def export_meshes(
 
                 if ob.pov.object_as == 'BOX':
                     tab_write("#declare %s = box { -1,1\n" % povdataname)
-                    pov_mat_name = "Default_texture"
                     if ob.active_material:
                         # pov_mat_name = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name))
                         try:
                             material = ob.active_material
-                            write_object_material(material, ob, tab_write)
+                            write_object_material_interior(material, ob, tab_write)
                         except IndexError:
                             print(me)
                     # tab_write("texture {%s}\n"%pov_mat_name)
@@ -499,12 +493,11 @@ def export_meshes(
                         "#declare %s = cone { <0,0,%.4f>,%.4f,<0,0,%.4f>,%.4f\n"
                         % (povdataname, bz, br, cz, cr)
                     )
-                    pov_mat_name = "Default_texture"
                     if ob.active_material:
                         # pov_mat_name = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name))
                         try:
                             material = ob.active_material
-                            write_object_material(material, ob, tab_write)
+                            write_object_material_interior(material, ob, tab_write)
                         except IndexError:
                             print(me)
                     # tab_write("texture {%s}\n"%pov_mat_name)
@@ -522,12 +515,11 @@ def export_meshes(
                         "#declare %s = cylinder { <0,0,0>,<%6f,%6f,%6f>,%6f\n"
                         % (povdataname, x2, y2, z2, r)
                     )
-                    pov_mat_name = "Default_texture"
                     if ob.active_material:
                         # pov_mat_name = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name))
                         try:
                             material = ob.active_material
-                            write_object_material(material, ob, tab_write)
+                            write_object_material_interior(material, ob, tab_write)
                         except IndexError:
                             print(me)
                     # tab_write("texture {%s}\n"%pov_mat_name)
@@ -551,12 +543,11 @@ def export_meshes(
                         data += ' water_level %.4f' % ob.pov.hf_water
                     # hierarchy = ob.pov.hf_hierarchy
                     tab_write('#declare %s = height_field { %s\n' % (povdataname, data))
-                    pov_mat_name = "Default_texture"
                     if ob.active_material:
                         # pov_mat_name = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name))
                         try:
                             material = ob.active_material
-                            write_object_material(material, ob, tab_write)
+                            write_object_material_interior(material, ob, tab_write)
                         except IndexError:
                             print(me)
                     # tab_write("texture {%s}\n"%pov_mat_name)
@@ -572,12 +563,11 @@ def export_meshes(
                     tab_write(
                         "#declare %s = sphere { 0,%6f\n" % (povdataname, ob.pov.sphere_radius)
                     )
-                    pov_mat_name = "Default_texture"
                     if ob.active_material:
                         # pov_mat_name = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name))
                         try:
                             material = ob.active_material
-                            write_object_material(material, ob, tab_write)
+                            write_object_material_interior(material, ob, tab_write)
                         except IndexError:
                             print(me)
                     # tab_write("texture {%s}\n"%pov_mat_name)
@@ -591,12 +581,11 @@ def export_meshes(
                         "#declare %s = torus { %.4f,%.4f\n"
                         % (povdataname, ob.pov.torus_major_radius, ob.pov.torus_minor_radius)
                     )
-                    pov_mat_name = "Default_texture"
                     if ob.active_material:
                         # pov_mat_name = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name))
                         try:
                             material = ob.active_material
-                            write_object_material(material, ob, tab_write)
+                            write_object_material_interior(material, ob, tab_write)
                         except IndexError:
                             print(me)
                     # tab_write("texture {%s}\n"%pov_mat_name)
@@ -726,10 +715,8 @@ def export_meshes(
                     tab_write("}\n")
                     continue  # Don't render proxy mesh, skip to next object
 
-                ## In remaining cases; keep at end so no "elif" is needed,
-                #       (as not skipped by any previous "continue")
-                #           and for originals not their instances,
-                #               attempt to export mesh:
+                # Implicit else-if (as not skipped by previous "continue") Keep this last.
+                # For originals, but not their instances, attempt to export mesh:
                 if not ob.is_instancer:
                     # except duplis which should be instances groups for now but all duplis later
                     if ob.type == 'EMPTY':
@@ -743,8 +730,7 @@ def export_meshes(
                         )
                         continue  # Don't render empty object but this is later addition, watch it.
 
-                    depsgraph = bpy.context.evaluated_depsgraph_get()
-                    ob_eval = ob.evaluated_get(depsgraph)
+                    ob_eval = ob # not sure this is needed in case to_mesh_clear could damage ob ?
                     try:
                         me = ob_eval.to_mesh()
 
@@ -761,10 +747,10 @@ def export_meshes(
                         me.calc_loop_triangles()
                         me_materials = me.materials
                         me_faces = me.loop_triangles[:]
-                        ## numpytest
+                        # --- numpytest
                         # me_looptris = me.loops
 
-                        ## otypes = ['int32'] is a 32-bit signed integer number numpy datatype
+                        # Below otypes = ['int32'] is a 32-bit signed integer number numpy datatype
                         # get_v_index = np.vectorize(lambda l: l.vertex_index, otypes = ['int32'], cache = True)
                         # faces_verts_idx = get_v_index(me_looptris)
 
@@ -853,7 +839,7 @@ def export_meshes(
                         uniqueUVs = {}
                         # n = 0
                         for f in me_faces:  # me.faces in 2.7
-                            uvs = [uv_layer[l].uv[:] for l in f.loops]
+                            uvs = [uv_layer[loop_index].uv[:] for loop_index in f.loops]
 
                             for uv in uvs:
                                 uniqueUVs[uv[:]] = [-1]
@@ -903,7 +889,7 @@ def export_meshes(
                                 material
                             ):  # and material.use_vertex_color_paint: #Always use vertex color when there is some for now
 
-                                cols = [vcol_layer[l].color[:] for l in f.loops]
+                                cols = [vcol_layer[loop_index].color[:] for loop_index in f.loops]
 
                                 for col in cols:
                                     key = (
@@ -964,7 +950,7 @@ def export_meshes(
                             material_index = f.material_index
 
                             if vcol_layer:
-                                cols = [vcol_layer[l].color[:] for l in f.loops]
+                                cols = [vcol_layer[loop_index].color[:] for loop_index in f.loops]
 
                             if (
                                 not me_materials or me_materials[material_index] is None
@@ -1071,7 +1057,7 @@ def export_meshes(
                             tab_write("%d" % (len(me_faces)))  # faces count
                             tab_str = tab * tab_level
                             for f in me_faces:
-                                uvs = [uv_layer[l].uv[:] for l in f.loops]
+                                uvs = [uv_layer[loop_index].uv[:] for loop_index in f.loops]
 
                                 if linebreaksinlists:
                                     file.write(",\n")
@@ -1118,7 +1104,7 @@ def export_meshes(
                         if me.materials:
                             try:
                                 material = me.materials[0]  # dodgy
-                                write_object_material(material, ob, tab_write)
+                                write_object_material_interior(material, ob, tab_write)
                             except IndexError:
                                 print(me)
 
@@ -1142,7 +1128,7 @@ def export_meshes(
                         for i, material in enumerate(me_materials):
 
                             if (
-                                material and material.pov.material_use_nodes == False
+                                material and material.pov.material_use_nodes is False
                             ):  # WARNING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                                 # Multiply diffuse with SSS Color
                                 if material.pov_subsurface_scattering.use:
@@ -1171,15 +1157,12 @@ def export_meshes(
                                     vertCols[key] = [-1]
 
                                 idx = 0
-                                local_material_names = []
+                                local_material_names = [] #XXX track and revert
+                                material_finish = None
                                 for col, index in vertCols.items():
                                     # if me_materials:
                                     mater = me_materials[col[3]]
-                                    if me_materials is None:  # XXX working?
-                                        material_finish = DEF_MAT_NAME  # not working properly,
-                                        trans = 0.0
-
-                                    else:
+                                    if me_materials is not None:
                                         texturing.write_texture_influence(
                                             using_uberpov,
                                             mater,
@@ -1198,7 +1181,7 @@ def export_meshes(
                                             preview_dir,
                                             unpacked_images,
                                         )
-                                    ###################################################################
+                                    # ------------------------------------------------
                                     index[0] = idx
                                     idx += 1
 
@@ -1223,7 +1206,7 @@ def export_meshes(
                         if (
                             material
                             and ob.active_material is not None
-                            and material.pov.material_use_nodes == False
+                            and not material.pov.material_use_nodes
                         ):
                             if material.pov.replacement_text != "":
                                 file.write("\n")
@@ -1257,7 +1240,7 @@ def export_meshes(
                             material_index = f.material_index
 
                             if vcol_layer:
-                                cols = [vcol_layer[l].color[:] for l in f.loops]
+                                cols = [vcol_layer[loop_index].color[:] for loop_index in f.loops]
 
                             if (
                                 not me_materials or me_materials[material_index] is None
@@ -1366,7 +1349,7 @@ def export_meshes(
                             tab_write("%d" % (len(me_faces)))  # faces count
                             tab_str = tab * tab_level
                             for f in me_faces:
-                                uvs = [uv_layer[l].uv[:] for l in f.loops]
+                                uvs = [uv_layer[loop_index].uv[:] for loop_index in f.loops]
 
                                 if linebreaksinlists:
                                     file.write(",\n")
@@ -1413,7 +1396,7 @@ def export_meshes(
                         if me.materials:
                             try:
                                 material = me.materials[0]  # dodgy
-                                write_object_material(material, ob, tab_write)
+                                write_object_material_interior(material, ob, tab_write)
                             except IndexError:
                                 print(me)
 
@@ -1438,7 +1421,6 @@ def export_meshes(
             if ob.is_instancer:
                 tab_write("\n//--DupliObjects in %s--\n\n" % ob.name)
                 # ob.dupli_list_create(scene) #deprecated in 2.8
-                depsgraph = bpy.context.evaluated_depsgraph_get()
                 dup = ""
                 if ob.is_modified(scene, 'RENDER'):
                     # modified object always unique so using object name rather than data name
@@ -1456,7 +1438,7 @@ def export_meshes(
                         _dupname = eachduplicate.object.name
                         _dupobj = bpy.data.objects[_dupname]
                         # BEGIN introspection for troubleshooting purposes
-                        if not "name" in dir(_dupobj.data):
+                        if "name" not in dir(_dupobj.data):
                             if _dupname not in _dupnames_seen:
                                 print(
                                     "WARNING: bpy.data.objects[%s].data (of type %s) has no 'name' attribute"
diff --git a/render_povray/object_particles.py b/render_povray/object_particles.py
index 2d4f0dccc260d2fd531c4beece5146cce2bac981..4949af21ca91b761d745c14fcf73caa16cb4804d 100755
--- a/render_povray/object_particles.py
+++ b/render_povray/object_particles.py
@@ -20,9 +20,30 @@
 """Get some Blender particle objects translated to POV."""
 
 import bpy
+import random
 
 
-def export_hair(file, ob, p_sys, global_matrix, write_matrix):
+def pixel_relative_guess(ob):
+    """Convert some object x dimension to a rough pixel relative order of magnitude"""
+    from bpy_extras import object_utils
+    scene = bpy.context.scene
+    cam = scene.camera
+    render = scene.render
+    # Get rendered image resolution
+    output_x_res = render.resolution_x
+    focal_length = cam.data.lens
+    # Get object bounding box size
+    object_location = ob.location
+    object_dimension_x = ob.dimensions[0]
+    world_to_camera = object_utils.world_to_camera_view(scene, cam, object_location)
+
+    apparent_size = (object_dimension_x * focal_length) / world_to_camera[2]
+    sensor_width = cam.data.sensor_width
+    pixel_pitch_x = sensor_width / output_x_res
+    return apparent_size / pixel_pitch_x
+
+
+def export_hair(file, ob, mod, p_sys, global_matrix, write_matrix):
     """Get Blender path particles (hair strands) objects translated to POV sphere_sweep unions."""
     # tstart = time.time()
     textured_hair = 0
@@ -33,18 +54,30 @@ def export_hair(file, ob, p_sys, global_matrix, write_matrix):
             povtex = th.texture  # slot.name
             tex = bpy.data.textures[povtex]
 
-            if th and th.use:
-                if (tex.type == 'IMAGE' and tex.image) or tex.type != 'IMAGE':
-                    if th.use_map_color_diffuse:
-                        textured_hair = 1
+            if (
+                th
+                and th.use
+                and (
+                    (tex.type == 'IMAGE' and tex.image) or tex.type != 'IMAGE'
+                )
+                and th.use_map_color_diffuse
+            ):
+                textured_hair = 1
         if pmaterial.strand.use_blender_units:
             strand_start = pmaterial.strand.root_size
             strand_end = pmaterial.strand.tip_size
-            strand_shape = pmaterial.strand.shape
-        else:  # Blender unit conversion
-            strand_start = pmaterial.strand.root_size / 200.0
-            strand_end = pmaterial.strand.tip_size / 200.0
-            strand_shape = pmaterial.strand.shape
+        else:
+            try:
+                # inexact pixel size, just to make radius relative to screen and object size.
+                pixel_fac = pixel_relative_guess(ob)
+            except ZeroDivisionError:
+                # Fallback to hardwired constant value
+                pixel_fac = 4500
+                print("no pixel size found for stand radius, falling back to  %i" % pixel_fac)
+
+            strand_start = pmaterial.strand.root_size / pixel_fac
+            strand_end = pmaterial.strand.tip_size / pixel_fac
+        strand_shape = pmaterial.strand.shape
     else:
         pmaterial = "default"  # No material assigned in blender, use default one
         strand_start = 0.01
@@ -63,7 +96,7 @@ def export_hair(file, ob, p_sys, global_matrix, write_matrix):
     total_number_of_strands = p_sys.settings.count + p_sys.settings.rendered_child_count
     # hairCounter = 0
     file.write('#declare HairArray = array[%i] {\n' % total_number_of_strands)
-    for pindex in range(0, total_number_of_strands):
+    for pindex in range(total_number_of_strands):
 
         # if particle.is_exist and particle.is_visible:
         # hairCounter += 1
@@ -119,7 +152,7 @@ def export_hair(file, ob, p_sys, global_matrix, write_matrix):
                     else:
                         # only overwrite variable for each competing texture for now
                         init_color = tex.evaluate((init_coord[0], init_coord[1], init_coord[2]))
-        for step in range(0, steps):
+        for step in range(steps):
             coord = ob.matrix_world.inverted() @ (p_sys.co_hair(ob, particle_no=pindex, step=step))
             # for controlPoint in particle.hair_keys:
             if p_sys.settings.clump_factor != 0:
@@ -127,9 +160,16 @@ def export_hair(file, ob, p_sys, global_matrix, write_matrix):
             elif step == 0:
                 hair_strand_diameter = strand_start
             else:
-                hair_strand_diameter += (strand_end - strand_start) / (
+                if strand_shape != 0.0:
+                    if strand_shape < 0.0:
+                        fac = pow(step, (1.0 + strand_shape))
+                    else:
+                        fac = pow(step, (1.0 / (1.0 - strand_shape)))
+                else:
+                    fac = step
+                hair_strand_diameter += fac * (strand_end - strand_start) / (
                     p_sys.settings.display_step + 1
-                )  # XXX +1 or not? # XXX use strand_shape in formula
+                )  # XXX +1 or -1 or nothing ?
             if step == 0 and p_sys.settings.use_hair_bspline:
                 # Write three times the first point to compensate pov Bezier handling
                 file.write(
@@ -162,9 +202,7 @@ def export_hair(file, ob, p_sys, global_matrix, write_matrix):
 
             # All coordinates except the last need a following comma.
 
-            if step != steps - 1:
-                file.write(',\n')
-            else:
+            if step == steps - 1:
                 if textured_hair:
                     # Write pigment and alpha (between Pov and Blender,
                     # alpha 0 and 1 are reversed)
@@ -175,6 +213,8 @@ def export_hair(file, ob, p_sys, global_matrix, write_matrix):
                 # End the sphere_sweep declaration for this hair
                 file.write('}\n')
 
+            else:
+                file.write(',\n')
         # All but the final sphere_sweep (each array element) needs a terminating comma.
         if pindex != total_number_of_strands:
             file.write(',\n')
@@ -212,10 +252,10 @@ def export_hair(file, ob, p_sys, global_matrix, write_matrix):
     file.write('  #local I = 0;\n')
     file.write('  #while (I < %i)\n' % total_number_of_strands)
     file.write('    object {HairArray[I]')
-    if not textured_hair:
-        file.write(' texture{HairTexture}\n')
-    else:
+    if textured_hair:
         file.write('\n')
+    else:
+        file.write(' texture{HairTexture}\n')
     # Translucency of the hair:
     file.write('        hollow\n')
     file.write('        double_illuminate\n')
@@ -243,8 +283,8 @@ def export_hair(file, ob, p_sys, global_matrix, write_matrix):
     write_matrix(global_matrix @ ob.matrix_world)
 
     file.write('}')
-    print('Totals hairstrands written: %i' % total_number_of_strands)
-    print('Number of tufts (particle systems)', len(ob.particle_systems))
+    print("Totals hairstrands written: %i" % total_number_of_strands)
+    print("Number of tufts (particle systems)", len(ob.particle_systems))
 
     # Set back the displayed number of particles to preview count
     # p_sys.set_resolution(scene, ob, 'PREVIEW') #DEPRECATED
diff --git a/render_povray/object_primitives.py b/render_povray/object_primitives.py
index 4556f2df53d50ae4ac6d5117a82c9bcff736ac22..abbba148a4fe739b9b5a2f6bdcad621bd7a13412 100755
--- a/render_povray/object_primitives.py
+++ b/render_povray/object_primitives.py
@@ -155,7 +155,7 @@ class POVRAY_OT_lathe_add(Operator):
 
 
 def pov_superellipsoid_define(context, op, ob):
-    """Create the proxy mesh of a POV superellipsoid using the pov_superellipsoid_define() function."""
+    """Create the proxy mesh of a POV superellipsoid using pov_superellipsoid_define()."""
 
     if op:
         mesh = None
@@ -276,7 +276,7 @@ def pov_superellipsoid_define(context, op, ob):
 
 
 class POVRAY_OT_superellipsoid_add(Operator):
-    """Add the representation of POV superellipsoid using the pov_superellipsoid_define() function."""
+    """Add the representation of POV superellipsoid using the pov_superellipsoid_define()."""
 
     bl_idname = "pov.addsuperellipsoid"
     bl_label = "Add SuperEllipsoid"
@@ -435,7 +435,7 @@ def supertoroid(R, r, u, v, n1, n2):
 
 
 def pov_supertorus_define(context, op, ob):
-    """Pick POV supertorus properties either from operator (object creation/import) or data updating """
+    """Get POV supertorus properties from operator (object creation/import) or data update."""
     if op:
         mesh = None
         st_R = op.st_R
@@ -572,7 +572,7 @@ class POVRAY_OT_supertorus_update(Operator):
         return {'FINISHED'}
 
 
-#########################################################################################################
+# -----------------------------------------------------------------------------
 class POVRAY_OT_loft_add(Operator):
     """Create the representation of POV loft using Blender curves."""
 
@@ -780,7 +780,7 @@ def pov_cylinder_define(context, op, ob, radius, loc, loc_cap):
     bpy.ops.mesh.delete(type='VERT')
     bpy.ops.mesh.primitive_cylinder_add(
         radius=radius, depth=depth, location=loc, rotation=roteuler, end_fill_type='NGON'
-    )  #'NOTHING'
+    )  # 'NOTHING'
     bpy.ops.transform.translate(value=trans)
 
     bpy.ops.mesh.hide(unselected=False)
@@ -873,7 +873,7 @@ class POVRAY_OT_cylinder_update(Operator):
         return {'FINISHED'}
 
 
-################################SPHERE##########################################
+# ----------------------------------- SPHERE---------------------------------- #
 def pov_sphere_define(context, op, ob, loc):
     """create the representation of POV sphere using a Blender icosphere.
 
@@ -960,8 +960,8 @@ class POVRAY_OT_sphere_add(Operator):
         return {'FINISHED'}
 
     # def execute(self,context):
-    ## layers = 20*[False]
-    ## layers[0] = True
+    #  layers = 20*[False]
+    #  layers[0] = True
 
     # bpy.ops.mesh.primitive_ico_sphere_add(subdivisions=4, radius=ob.pov.sphere_radius)
     # ob = context.object
@@ -1001,7 +1001,7 @@ class POVRAY_OT_sphere_update(Operator):
         return {'FINISHED'}
 
 
-####################################CONE#######################################
+# ----------------------------------- CONE ---------------------------------- #
 def pov_cone_define(context, op, ob):
     """Add the representation of POV cone using pov_define_mesh() function.
 
@@ -1144,7 +1144,7 @@ class POVRAY_OT_cone_update(Operator):
         return {'FINISHED'}
 
 
-########################################ISOSURFACES##################################
+# ----------------------------------- ISOSURFACES ----------------------------------- #
 
 
 class POVRAY_OT_isosurface_box_add(Operator):
@@ -1350,7 +1350,7 @@ class POVRAY_OT_height_field_add(bpy.types.Operator, ImportHelper):
         ob.name = ob.data.name = '%s' % im_name
         ob.data.materials.append(mat)
         bpy.ops.object.mode_set(mode="EDIT")
-        # bpy.ops.mesh.noise(factor=1) # TODO replace by a displace modifier as noise deprecated in 2.8
+        # bpy.ops.mesh.noise(factor=1) # TODO replace by displace modifier, noise deprecated in 2.8
         bpy.ops.object.mode_set(mode="OBJECT")
 
         # needs a loop to select by index?
@@ -1368,7 +1368,7 @@ class POVRAY_OT_height_field_add(bpy.types.Operator, ImportHelper):
         return {'FINISHED'}
 
 
-############################TORUS############################################
+# ----------------------------------- TORUS ----------------------------------- #
 def pov_torus_define(context, op, ob):
     """Add the representation of POV torus using just a Blender torus.
 
@@ -1477,7 +1477,7 @@ class POVRAY_OT_torus_update(Operator):
         return {'FINISHED'}
 
 
-###################################################################################
+# -----------------------------------------------------------------------------
 
 
 class POVRAY_OT_prism_add(Operator):
@@ -1526,7 +1526,7 @@ class POVRAY_OT_prism_add(Operator):
         return {'FINISHED'}
 
 
-##############################PARAMETRIC######################################
+# ----------------------------------- PARAMETRIC ----------------------------------- #
 def pov_parametric_define(context, op, ob):
     """Add the representation of POV parametric surfaces by math surface from add mesh extra objects addon.
 
@@ -1670,7 +1670,7 @@ class POVRAY_OT_parametric_update(Operator):
         return {'FINISHED'}
 
 
-#######################################################################
+# -----------------------------------------------------------------------------
 
 
 class POVRAY_OT_shape_polygon_to_circle_add(Operator):
@@ -1769,5 +1769,5 @@ def register():
 
 
 def unregister():
-    for cls in classes:
+    for cls in reversed(classes):
         unregister_class(cls)
diff --git a/render_povray/object_properties.py b/render_povray/object_properties.py
index 8cea49af8c550155a719917c12e3649fc06d0a6c..f599da9b6ed611683e4830b36ab3bacd5625bb56 100755
--- a/render_povray/object_properties.py
+++ b/render_povray/object_properties.py
@@ -32,9 +32,9 @@ from bpy.props import (
 )
 
 
-###############################################################################
+# ---------------------------------------------------------------- #
 # Object POV properties.
-###############################################################################
+# ---------------------------------------------------------------- #
 
 
 class RenderPovSettingsObject(PropertyGroup):
@@ -84,7 +84,7 @@ class RenderPovSettingsObject(PropertyGroup):
         default=1.00,
     )
 
-    ##################################CustomPOV Code############################
+    # ----------------------------------- CustomPOV Code ----------------------------------- #
     # Only DUMMIES below for now:
     replacement_text: StringProperty(
         name="Declared name:",
@@ -93,7 +93,7 @@ class RenderPovSettingsObject(PropertyGroup):
         default="",
     )
 
-    #############POV specific object properties.############################
+    # -------- POV specific object properties. -------- #
     object_as: StringProperty(maxlen=1024)
 
     imported_loc: FloatVectorProperty(
@@ -200,9 +200,9 @@ class RenderPovSettingsObject(PropertyGroup):
 
     max_trace: IntProperty(name="Max Trace", min=1, max=100, default=1)
 
-    ###########Cylinder
+    # -------- Cylinder
     def prop_update_cylinder(self, context):
-        """Update POV cylinder primitive parameters not only at creation but anytime they are changed in UI."""
+        """Update POV cylinder primitive parameters at creation and anytime they change in UI."""
         if bpy.ops.pov.cylinder_update.poll():
             bpy.ops.pov.cylinder_update()
 
@@ -213,7 +213,7 @@ class RenderPovSettingsObject(PropertyGroup):
     cylinder_location_cap: FloatVectorProperty(
         name="Cylinder Cap Location",
         subtype="TRANSLATION",
-        description="The position of the 'other' end of the cylinder (relative to object location)",
+        description="Position of the 'other' end of the cylinder (relative to object location)",
         default=(0.0, 0.0, 2.0),
         update=prop_update_cylinder,
     )
@@ -226,10 +226,10 @@ class RenderPovSettingsObject(PropertyGroup):
         name="Imported Pov location", precision=6, default=(0.0, 0.0, 2.0)
     )
 
-    ###########Sphere
+    # -------- Sphere
     def prop_update_sphere(self, context):
 
-        """Update POV sphere primitive parameters not only at creation but anytime they are changed in UI."""
+        """Update POV sphere primitive parameters at creation and anytime they change in UI."""
 
         bpy.ops.pov.sphere_update()
 
@@ -237,10 +237,10 @@ class RenderPovSettingsObject(PropertyGroup):
         name="Sphere radius", min=0.00, max=10.0, default=0.5, update=prop_update_sphere
     )
 
-    ###########Cone
+    # -------- Cone
     def prop_update_cone(self, context):
 
-        """Update POV cone primitive parameters not only at creation but anytime they are changed in UI."""
+        """Update POV cone primitive parameters at creation and anytime they change in UI."""
 
         bpy.ops.pov.cone_update()
 
@@ -284,10 +284,10 @@ class RenderPovSettingsObject(PropertyGroup):
 
     cone_cap_z: FloatProperty()
 
-    ###########Parametric
+    # -------- Parametric
     def prop_update_parametric(self, context):
 
-        """Update POV parametric surface primitive parameters not only at creation but anytime they are changed in UI."""
+        """Update POV parametric surface primitive settings at creation and on any UI change."""
 
         bpy.ops.pov.parametric_update()
 
@@ -311,11 +311,11 @@ class RenderPovSettingsObject(PropertyGroup):
         maxlen=1024, default="sin(v)*(1+cos(u))*sin(v/8)", update=prop_update_parametric
     )
 
-    ###########Torus
+    # -------- Torus
 
     def prop_update_torus(self, context):
 
-        """Update POV torus primitive parameters not only at creation but anytime they are changed in UI."""
+        """Update POV torus primitive parameters at creation and anytime they change in UI."""
 
         bpy.ops.pov.torus_update()
 
@@ -355,7 +355,7 @@ class RenderPovSettingsObject(PropertyGroup):
         update=prop_update_torus,
     )
 
-    ###########Rainbow
+    # -------- Rainbow
     arc_angle: FloatProperty(
         name="Arc angle",
         description="The angle of the raynbow arc in degrees",
@@ -372,7 +372,7 @@ class RenderPovSettingsObject(PropertyGroup):
         max=360,
     )
 
-    ###########HeightFields
+    # -------- HeightFields
 
     quality: IntProperty(name="Quality", description="", default=100, min=1, max=100)
 
@@ -390,10 +390,10 @@ class RenderPovSettingsObject(PropertyGroup):
 
     hf_hierarchy: BoolProperty(name="Hierarchy", description="Height field hierarchy", default=True)
 
-    ##############Superellipsoid
+    # -------- Superellipsoid
     def prop_update_superellipsoid(self, context):
 
-        """Update POV superellipsoid primitive parameters not only at creation but anytime they are changed in UI."""
+        """Update POV superellipsoid primitive settings at creation and on any UI change."""
 
         bpy.ops.pov.superellipsoid_update()
 
@@ -445,7 +445,7 @@ class RenderPovSettingsObject(PropertyGroup):
         update=prop_update_superellipsoid,
     )
 
-    #############Used for loft but also Superellipsoid, etc.
+    # -------- Used for loft but also Superellipsoid, etc.
     curveshape: EnumProperty(
         name="Povray Shape Type",
         items=(
@@ -460,10 +460,10 @@ class RenderPovSettingsObject(PropertyGroup):
         default="sphere_sweep",
     )
 
-    #############Supertorus
+    # -------- Supertorus
     def prop_update_supertorus(self, context):
 
-        """Update POV supertorus primitive parameters not only at creation but anytime they are changed in UI."""
+        """Update POV supertorus primitive parameters not only at creation and on any UI change."""
 
         bpy.ops.pov.supertorus_update()
 
@@ -581,7 +581,7 @@ class RenderPovSettingsObject(PropertyGroup):
         name="", description="", default=False, options={"HIDDEN"}, update=prop_update_supertorus
     )
 
-    ########################Loft
+    # -------- Loft
     loft_n: IntProperty(
         name="Segments", description="Vertical segments", default=16, min=3, max=720
     )
@@ -610,17 +610,17 @@ class RenderPovSettingsObject(PropertyGroup):
         max=10.0,
     )
 
-    ###################Prism
+    # -------- Prism
     prism_n: IntProperty(name="Sides", description="Number of sides", default=5, min=3, max=720)
 
     prism_r: FloatProperty(name="Radius", description="Radius", default=1.0)
 
-    ##################Isosurface
+    # -------- Isosurface
     iso_function_text: StringProperty(
         name="Function Text", maxlen=1024
     )  # ,update=iso_props_update_callback)
 
-    ##################PolygonToCircle
+    # -------- PolygonToCircle
     polytocircle_resolution: IntProperty(
         name="Resolution", description="", default=3, min=0, max=256
     )
@@ -631,9 +631,9 @@ class RenderPovSettingsObject(PropertyGroup):
 
     polytocircle_circleR: FloatProperty(name="Circle Radius", description="", default=1.0)
 
-    ###############################################################################
+    # ---------------------------------------------------------------- #
     # Modifiers POV properties.
-    ###############################################################################
+    # ---------------------------------------------------------------- #
     # class RenderPovSettingsModifier(PropertyGroup):
     boolean_mod: EnumProperty(
         name="Operation",
@@ -646,7 +646,7 @@ class RenderPovSettingsObject(PropertyGroup):
         default="BMESH",
     )
 
-    #################Avogadro
+    # -------- Avogadro
     # filename_ext = ".png"
 
     # filter_glob = StringProperty(
diff --git a/render_povray/render.py b/render_povray/render.py
index 45a94912bb01d71748865158f506ace2874c01a9..76bdf7c47f252880fc91e5c07edff482cea3c802 100755
--- a/render_povray/render.py
+++ b/render_povray/render.py
@@ -17,7 +17,9 @@
 # #**** END GPL LICENSE BLOCK #****
 
 # <pep8 compliant>
+
 """Wirte the POV file using this file's functions and some from other modules then render it."""
+
 import bpy
 import subprocess
 import os
@@ -45,7 +47,7 @@ from . import object_curve_topology  # for curves based geometry
 
 from .scenography import image_format, img_map, img_map_transforms, path_image
 
-from .shading import write_object_material
+from .shading import write_object_material_interior
 from .object_primitives import write_object_modifiers
 
 
@@ -79,7 +81,7 @@ def safety(name, ref_level_bound):
     # prefix = "shader"
     # except BaseException as e:
     # print(e.__doc__)
-    # print('An exXXXception occurred: {}'.format(e))
+    # print('An exception occurred: {}'.format(e))
     # prefix = "" # rewritten below...
     prefix = "shader_"
     name = string_strip_hyphen(name)
@@ -93,8 +95,8 @@ def safety(name, ref_level_bound):
         return prefix + name + "1"  # used for 1 of specular map
 
 
-##############end safety string name material
-##############################EndSF###########################
+# -------- end safety string name material
+
 
 csg_list = []
 
@@ -120,7 +122,7 @@ unpacked_images = []
 user_dir = bpy.utils.resource_path('USER')
 preview_dir = os.path.join(user_dir, "preview")
 
-## Make sure Preview directory exists and is empty
+# Make sure Preview directory exists and is empty
 smoke_path = os.path.join(preview_dir, "smoke.df3")
 
 '''
@@ -306,7 +308,7 @@ def write_pov(filename, scene=None, info_callback=None):
     material_names_dictionary = {}
     DEF_MAT_NAME = ""  # or "Default"?
 
-    #################################################################
+    # -----------------------------------------------------------------------------
 
     def export_meta(metas):
         """write all POV blob primitives and Blender Metas to exported file """
@@ -319,7 +321,7 @@ def write_pov(filename, scene=None, info_callback=None):
         meta_elems = {}
         for ob in metas:
             prefix = ob.name.split(".")[0]
-            if not prefix in meta_group:
+            if prefix not in meta_group:
                 meta_group[prefix] = ob  # .data.threshold
             elems = [
                 (elem, ob)
@@ -335,7 +337,9 @@ def write_pov(filename, scene=None, info_callback=None):
             if len(elems) == 0:
                 tab_write("\n//dummy sphere to represent empty meta location\n")
                 tab_write(
-                    "sphere {<%.6g, %.6g, %.6g>,0 pigment{rgbt 1} no_image no_reflection no_radiosity photons{pass_through collect off} hollow}\n\n"
+                    "sphere {<%.6g, %.6g, %.6g>,0 pigment{rgbt 1} "
+                    "no_image no_reflection no_radiosity "
+                    "photons{pass_through collect off} hollow}\n\n"
                     % (ob.location.x, ob.location.y, ob.location.z)
                 )  # ob.name > povdataname)
             # other metaballs
@@ -504,13 +508,15 @@ def write_pov(filename, scene=None, info_callback=None):
                             )
                             tab_write("finish{%s} " % safety(material_finish, ref_level_bound=2))
                         else:
+                            material_finish = DEF_MAT_NAME
+                            trans = 0.0
                             tab_write(
-                                "pigment{srgb 1} finish{%s} "
-                                % (safety(DEF_MAT_NAME, ref_level_bound=2))
+                                "pigment{srgbt<1,1,1,%.3g} finish{%s} "
+                                % (trans, safety(material_finish, ref_level_bound=2))
                             )
 
-                            write_object_material(material, mob, tab_write)
-                            # write_object_material(material, elems[1])
+                            write_object_material_interior(material, mob, tab_write)
+                            # write_object_material_interior(material, elems[1])
                             tab_write("radiosity{importance %3g}\n" % mob.pov.importance_value)
                             tab_write("}\n\n")  # End of Metaball block
 
@@ -577,7 +583,7 @@ def write_pov(filename, scene=None, info_callback=None):
                     # Write the finish last.
                     tab_write("finish {%s}\n" % (safety(DEF_MAT_NAME, ref_level_bound=2)))
 
-                write_object_material(material, elems[1])
+                write_object_material_interior(material, elems[1])
 
                 write_matrix(global_matrix @ ob.matrix_world)
                 # Importance for radiosity sampling added here
@@ -732,12 +738,12 @@ def write_pov(filename, scene=None, info_callback=None):
     for ob in bpy.data.objects:
         if ob.type == 'MESH':
             for mod in ob.modifiers:
-                if mod.type == 'BOOLEAN':
-                    if mod.object not in csg_list:
+                if mod.type == 'BOOLEAN' and mod.object not in csg_list:
                         csg_list.append(mod.object)
     if csg_list != []:
         csg = False
         sel = no_renderable_objects()
+        #export non rendered boolean objects operands
         object_mesh_topology.export_meshes(
             preview_dir,
             file,
@@ -748,7 +754,7 @@ def write_pov(filename, scene=None, info_callback=None):
             safety,
             write_object_modifiers,
             material_names_dictionary,
-            write_object_material,
+            write_object_material_interior,
             scenography.exported_lights_count,
             unpacked_images,
             image_format,
@@ -797,7 +803,7 @@ def write_pov(filename, scene=None, info_callback=None):
             continue  # don't export as pov curves objects with modifiers, but as mesh
         # Implicit else-if (as not skipped by previous "continue")
         if c.type == 'CURVE' and (c.pov.curveshape in {'lathe', 'sphere_sweep', 'loft', 'birail'}):
-            object_curve_topology.export_curves(c, string_strip_hyphen, global_matrix, tab_write)
+            object_curve_topology.export_curves(file, c, string_strip_hyphen, global_matrix, tab_write)
 
     if comments:
         file.write("\n//--Material Definitions--\n\n")
@@ -875,7 +881,7 @@ def write_pov(filename, scene=None, info_callback=None):
         safety,
         write_object_modifiers,
         material_names_dictionary,
-        write_object_material,
+        write_object_material_interior,
         scenography.exported_lights_count,
         unpacked_images,
         image_format,
@@ -1024,16 +1030,6 @@ class PovrayRender(bpy.types.RenderEngine):
             if os.path.exists(pov_binary):
                 return pov_binary
 
-            # Then try 32bits UberPOV
-            pov_binary = os.path.join(win_home, "bin", "uberpov32.exe")
-            if os.path.exists(pov_binary):
-                return pov_binary
-
-            # Then try 32bits POV
-            pov_binary = os.path.join(win_home, "bin", "pvengine.exe")
-            if os.path.exists(pov_binary):
-                return pov_binary
-
         # search the path all os's
         pov_binary_default = "povray"
 
@@ -1331,14 +1327,14 @@ class PovrayRender(bpy.types.RenderEngine):
                 self._cleanup()
         else:
 
-            ##WIP output format
-            ##        if r.image_settings.file_format == 'OPENEXR':
-            ##            fformat = 'EXR'
-            ##            render.image_settings.color_mode = 'RGBA'
-            ##        else:
-            ##            fformat = 'TGA'
-            ##            r.image_settings.file_format = 'TARGA'
-            ##            r.image_settings.color_mode = 'RGBA'
+            # WIP output format
+            #         if r.image_settings.file_format == 'OPENEXR':
+            #             fformat = 'EXR'
+            #             render.image_settings.color_mode = 'RGBA'
+            #         else:
+            #             fformat = 'TGA'
+            #             r.image_settings.file_format = 'TARGA'
+            #             r.image_settings.color_mode = 'RGBA'
 
             blend_scene_name = bpy.data.filepath.split(os.path.sep)[-1].split(".")[0]
             pov_scene_name = ""
@@ -1424,13 +1420,8 @@ class PovrayRender(bpy.types.RenderEngine):
                 pov_path = os.path.join(pov_path, pov_scene_name)
                 pov_path = os.path.realpath(pov_path)
 
-                # for now this has to be the same like the pov output. Bug in POV-Ray RC3.
-                # image_render_path = image_render_path + "\\" + pov_scene_name
-                image_render_path = pov_path  # Bugfix for POV-Ray RC3 bug
-                # image_render_path = os.path.realpath(image_render_path)  # Bugfix for POV-Ray RC3 bug
-
-                # print("Export path: %s" % pov_path)
-                # print("Render Image path: %s" % image_render_path)
+                image_render_path = pov_path
+                # print("Render Image path: " + image_render_path)
 
             # start export
             self.update_stats("", "POV-Ray 3.7: Exporting data from Blender")
@@ -1594,22 +1585,28 @@ class PovrayRender(bpy.types.RenderEngine):
                         scr = win.screen
                         for area in scr.areas:
                             if area.type == 'CONSOLE':
+                                # pass # XXX temp override
                                 # context override
                                 # ctx = {'window': win, 'screen': scr, 'area':area}#bpy.context.copy()
-                                ctx = {}
-                                ctx['area'] = area
-                                ctx['region'] = area.regions[-1]
-                                ctx['space_data'] = area.spaces.active
-                                ctx['screen'] = scr  # C.screen
-                                ctx['window'] = win
-
-                                # bpy.ops.console.banner(ctx, text = "Hello world")
-                                bpy.ops.console.clear_line(ctx)
-                                stdmsg = msg.split('\n')  # XXX todo , test and see
-                                for i in stdmsg:
-                                    # Crashes if no Terminal displayed on Windows
-                                    bpy.ops.console.scrollback_append(ctx, text=i, type='INFO')
-                                    # bpy.ops.console.insert(ctx, text=(i + "\n"))
+                                try:
+                                    ctx = {}
+                                    ctx['area'] = area
+                                    ctx['region'] = area.regions[-1]
+                                    ctx['space_data'] = area.spaces.active
+                                    ctx['screen'] = scr  # C.screen
+                                    ctx['window'] = win
+
+                                    # bpy.ops.console.banner(ctx, text = "Hello world")
+                                    bpy.ops.console.clear_line(ctx)
+                                    stdmsg = msg.split('\n')  # XXX todo , test and see segfault crash?
+                                    for i in stdmsg:
+                                        # Crashes if no Terminal displayed on Windows
+                                        bpy.ops.console.scrollback_append(ctx, text=i, type='INFO')
+                                        # bpy.ops.console.insert(ctx, text=(i + "\n"))
+                                except BaseException as e:
+                                    print(e.__doc__)
+                                    print('An exception occurred: {}'.format(e))
+                                    pass
 
             self.update_stats("", "")
 
@@ -1679,9 +1676,9 @@ class PovrayRender(bpy.types.RenderEngine):
                 os.system("echo %s | espeak &" % (finished_render_message))
 
 
-##################################################################################
-#################################Operators########################################
-##################################################################################
+# --------------------------------------------------------------------------------- #
+# ----------------------------------- Operators ----------------------------------- #
+# --------------------------------------------------------------------------------- #
 class RenderPovTexturePreview(Operator):
     """Export only files necessary to texture preview and render image"""
 
@@ -1692,14 +1689,14 @@ class RenderPovTexturePreview(Operator):
         tex = bpy.context.object.active_material.active_texture  # context.texture
         tex_prev_name = string_strip_hyphen(bpy.path.clean_name(tex.name)) + "_prev"
 
-        ## Make sure Preview directory exists and is empty
+        # Make sure Preview directory exists and is empty
         if not os.path.isdir(preview_dir):
             os.mkdir(preview_dir)
 
         ini_prev_file = os.path.join(preview_dir, "Preview.ini")
         input_prev_file = os.path.join(preview_dir, "Preview.pov")
         output_prev_file = os.path.join(preview_dir, tex_prev_name)
-        ##################### ini ##########################################
+        # ---------------------------------- ini ---------------------------------- #
         file_ini = open("%s" % ini_prev_file, "w")
         file_ini.write('Version=3.8\n')
         file_ini.write('Input_File_Name="%s"\n' % input_prev_file)
@@ -1715,7 +1712,7 @@ class RenderPovTexturePreview(Operator):
         file_ini.write('Antialias_Depth=3\n')
         file_ini.write('-d\n')
         file_ini.close()
-        ##################### pov ##########################################
+        # ---------------------------------- pov ---------------------------------- #
         file_pov = open("%s" % input_prev_file, "w")
         pat_name = "PAT_" + string_strip_hyphen(bpy.path.clean_name(tex.name))
         file_pov.write("#declare %s = \n" % pat_name)
@@ -1748,7 +1745,7 @@ class RenderPovTexturePreview(Operator):
         file_pov.write("    translate <0.000000, 0.000000, 0.000000>\n")
         file_pov.write("}\n")
         file_pov.close()
-        ##################### end write ##########################################
+        # ------------------------------- end write ------------------------------- #
 
         pov_binary = PovrayRender._locate_binary()
 
@@ -1807,14 +1804,20 @@ class RunPovTextRender(Operator):
         return {'FINISHED'}
 
 
-classes = (PovrayRender, RenderPovTexturePreview, RunPovTextRender)
+classes = (
+    PovrayRender,
+    RenderPovTexturePreview,
+    RunPovTextRender,
+)
 
 
 def register():
     for cls in classes:
         register_class(cls)
+    scripting.register()
 
 
 def unregister():
+    scripting.unregister()
     for cls in reversed(classes):
         unregister_class(cls)
diff --git a/render_povray/render_gui.py b/render_povray/render_gui.py
index 5b6597257f174761509ec264dde134db985cbc44..8e584079b5f37b60ab36daed004db480e608a35c 100755
--- a/render_povray/render_gui.py
+++ b/render_povray/render_gui.py
@@ -20,6 +20,7 @@
 
 """User interface for rendering parameters"""
 
+
 import bpy
 from sys import platform  # really import here, as in render.py?
 
@@ -27,7 +28,6 @@ from sys import platform  # really import here, as in render.py?
 # from os.path import isfile
 from bl_operators.presets import AddPresetBase
 from bpy.utils import register_class, unregister_class
-from bpy.props import EnumProperty
 from bpy.types import Operator, Menu, Panel
 
 
@@ -44,10 +44,12 @@ from bl_ui import properties_freestyle
 
 for member in dir(properties_freestyle):
     subclass = getattr(properties_freestyle, member)
-    if hasattr(subclass, "COMPAT_ENGINES"):
-        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"
+    if hasattr(subclass, "COMPAT_ENGINES") and (
+        subclass.bl_space_type != 'PROPERTIES'
+        or subclass.bl_context != "render"
+    ):
+        subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
+        # subclass.bl_parent_id = "RENDER_PT_POV_filter"
 del properties_freestyle
 
 from bl_ui import properties_view_layer
@@ -75,9 +77,7 @@ def check_render_freestyle_svg():
     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
+    return "render_freestyle_svg" in bpy.context.preferences.addons.keys()
 
 
 class RenderButtonsPanel:
@@ -258,6 +258,27 @@ class RENDER_PT_POV_antialias(RenderButtonsPanel, Panel):
         else:
             self.layout.prop(scene.pov, "antialias_enable", text="", icon='ALIASED')
 
+    def uberpov_only_qmc_til_pov38release(self, layout):
+            col = layout.column()
+            col.alignment = 'CENTER'
+            col.label(text="Stochastic Anti Aliasing is")
+            col.label(text="Only Available with UberPOV")
+            col.label(text="Feature Set in User Preferences.")
+            col.label(text="Using Type 2 (recursive) instead")
+
+    def no_qmc_fallbacks(self, row, scene, layout):
+        row.prop(scene.pov, "jitter_enable", text="Jitter")
+
+        split = layout.split()
+        col = split.column()
+        col.prop(scene.pov, "antialias_depth", text="AA Depth")
+        sub = split.column()
+        sub.prop(scene.pov, "jitter_amount", text="Jitter Amount")
+        sub.enabled = bool(scene.pov.jitter_enable)
+        row = layout.row()
+        row.prop(scene.pov, "antialias_threshold", text="AA Threshold")
+        row.prop(scene.pov, "antialias_gamma", text="AA Gamma")
+
     def draw(self, context):
         prefs = bpy.context.preferences.addons[__package__].preferences
         layout = self.layout
@@ -269,37 +290,13 @@ class RENDER_PT_POV_antialias(RenderButtonsPanel, Panel):
         row.prop(scene.pov, "antialias_method", text="")
 
         if prefs.branch_feature_set_povray != 'uberpov' and scene.pov.antialias_method == '2':
-            col = layout.column()
-            col.alignment = 'CENTER'
-            col.label(text="Stochastic Anti Aliasing is")
-            col.label(text="Only Available with UberPOV")
-            col.label(text="Feature Set in User Preferences.")
-            col.label(text="Using Type 2 (recursive) instead")
+            self.uberpov_only_qmc_til_pov38release(layout)
         else:
-            row.prop(scene.pov, "jitter_enable", text="Jitter")
-
-            split = layout.split()
-            col = split.column()
-            col.prop(scene.pov, "antialias_depth", text="AA Depth")
-            sub = split.column()
-            sub.prop(scene.pov, "jitter_amount", text="Jitter Amount")
-            if scene.pov.jitter_enable:
-                sub.enabled = True
-            else:
-                sub.enabled = False
-
+            self.no_qmc_fallbacks(row, scene, layout)
+        if prefs.branch_feature_set_povray == 'uberpov':
             row = layout.row()
-            row.prop(scene.pov, "antialias_threshold", text="AA Threshold")
-            row.prop(scene.pov, "antialias_gamma", text="AA Gamma")
-
-            if prefs.branch_feature_set_povray == 'uberpov':
-                row = layout.row()
-                row.prop(scene.pov, "antialias_confidence", text="AA Confidence")
-                if scene.pov.antialias_method == '2':
-                    row.enabled = True
-                else:
-                    row.enabled = False
-
+            row.prop(scene.pov, "antialias_confidence", text="AA Confidence")
+            row.enabled = scene.pov.antialias_method == '2'
 
 class RENDER_PT_POV_radiosity(RenderButtonsPanel, Panel):
     """Use this class to define pov radiosity buttons."""
@@ -414,9 +411,9 @@ def rad_panel_func(self, context):
     ).remove_active = True
 
 
-###############################################################################
+# ---------------------------------------------------------------- #
 # Freestyle
-###############################################################################
+# ---------------------------------------------------------------- #
 # import addon_utils
 # addon_utils.paths()[0]
 # addon_utils.modules()
@@ -537,10 +534,10 @@ classes = (
 def register():
     for cls in classes:
         register_class(cls)
-    bpy.types.RENDER_PT_POV_radiosity.prepend(rad_panel_func)
+    RENDER_PT_POV_radiosity.prepend(rad_panel_func)
 
 
 def unregister():
-    bpy.types.RENDER_PT_POV_radiosity.remove(rad_panel_func)
+    RENDER_PT_POV_radiosity.remove(rad_panel_func)
     for cls in reversed(classes):
         unregister_class(cls)
diff --git a/render_povray/render_properties.py b/render_povray/render_properties.py
index 9096c9864d264c52bd1f230758af5cec31348359..0fbb60dac7565b6a35d19d24b1bcd6eaa92670b9 100755
--- a/render_povray/render_properties.py
+++ b/render_povray/render_properties.py
@@ -32,9 +32,9 @@ from bpy.props import (
     PointerProperty,
 )
 
-###############################################################################
+# ---------------------------------------------------------------- #
 # Scene POV properties.
-###############################################################################
+# ---------------------------------------------------------------- #
 class RenderPovSettingsScene(PropertyGroup):
 
     """Declare scene level properties controllable in UI and translated to POV"""
@@ -445,7 +445,7 @@ class RenderPovSettingsScene(PropertyGroup):
         default=2,
     )
 
-    ########################### PHOTONS #######################################
+    # -------- PHOTONS -------- #
     photon_enable: BoolProperty(name="Photons", description="Enable global photons", default=False)
 
     photon_enable_count: BoolProperty(
@@ -519,7 +519,7 @@ class RenderPovSettingsScene(PropertyGroup):
 
     photon_map_file: StringProperty(name="File", description="", maxlen=1024, subtype="FILE_PATH")
 
-    #########RADIOSITY########
+    # -------- RADIOSITY -------- #
     radio_adc_bailout: FloatProperty(
         name="ADC Bailout",
         description="The adc_bailout for radiosity rays. Use "
@@ -672,7 +672,9 @@ class RenderPovSettingsScene(PropertyGroup):
     )
 
 
-classes = (RenderPovSettingsScene,)
+classes = (
+    RenderPovSettingsScene,
+)
 
 
 def register():
diff --git a/render_povray/scenography.py b/render_povray/scenography.py
index 4b0c99e32627b751dc6d728ab9a336421f61f2cf..6f892b3ec29c82ccc26048215db0273e5cfae560 100755
--- a/render_povray/scenography.py
+++ b/render_povray/scenography.py
@@ -23,14 +23,17 @@
 with world, sky, atmospheric effects such as rainbows or smoke """
 
 import bpy
-from bpy.utils import register_class, unregister_class
+
 import os
 from imghdr import what  # imghdr is a python lib to identify image file types
 from math import atan, pi, sqrt, degrees
 from . import df3_library  # for smoke rendering
 from .object_primitives import write_object_modifiers
 
-##############find image texture # used for export_world
+
+# -------- find image texture # used for export_world -------- #
+
+
 def image_format(imgF):
     """Identify input image filetypes to transmit to POV."""
     # First use the below explicit extensions to identify image file prospects
@@ -68,8 +71,8 @@ def img_map(ts):
     elif ts.mapping == 'TUBE':
         image_map = "map_type 2 "
 
-    ## map_type 3 and 4 in development (?) (ENV in pov 3.8)
-    ## for POV-Ray, currently they just seem to default back to Flat (type 0)
+    # map_type 3 and 4 in development (?) (ENV in pov 3.8)
+    # for POV-Ray, currently they just seem to default back to Flat (type 0)
     # elif ts.mapping=="?":
     #    image_map = " map_type 3 "
     # elif ts.mapping=="?":
@@ -133,7 +136,7 @@ def img_map_bg(wts):
     tex = bpy.data.textures[wts.texture]
     image_mapBG = ""
     # texture_coords refers to the mapping of world textures:
-    if wts.texture_coords == 'VIEW' or wts.texture_coords == 'GLOBAL':
+    if wts.texture_coords in ['VIEW', 'GLOBAL']:
         image_mapBG = " map_type 0 "
     elif wts.texture_coords == 'ANGMAP':
         image_mapBG = " map_type 1 "
@@ -192,7 +195,7 @@ def export_camera(scene, global_matrix, render, tab_write):
 
     else:
         if camera.data.type == 'ORTHO':
-            # todo: track when SensorHeightRatio was added to see if needed (not used)
+            # XXX todo: track when SensorHeightRatio was added to see if needed (not used)
             sensor_height_ratio = (
                 render.resolution_x * camera.data.ortho_scale / render.resolution_y
             )
@@ -392,16 +395,16 @@ def export_world(world, scene, global_matrix, tab_write):
     """write world as POV backgrounbd and sky_sphere to exported file """
     render = scene.pov
     camera = scene.camera
-    matrix = global_matrix @ camera.matrix_world  # view dependant for later use
+    # matrix = global_matrix @ camera.matrix_world  # view dependant for later use NOT USED
     if not world:
         return
-    #############Maurice####################################
+
     # These lines added to get sky gradient (visible with PNG output)
     if world:
         # For simple flat background:
         if not world.pov.use_sky_blend:
-            # Non fully transparent background could premultiply alpha and avoid anti-aliasing
-            # display issue:
+            # Non fully transparent background could premultiply alpha and avoid
+            # anti-aliasing display issue:
             if render.alpha_mode == 'TRANSPARENT':
                 tab_write(
                     "background {rgbt<%.3g, %.3g, %.3g, 0.75>}\n" % (world.pov.horizon_color[:])
@@ -526,7 +529,7 @@ def export_world(world, scene, global_matrix, tab_write):
         # scene.pov.radio_enable = world.pov.light_settings.use_indirect_light
         # and other such translations but maybe this would not be allowed either?
 
-    ###############################################################
+    # -----------------------------------------------------------------------------
 
     mist = world.mist_settings
 
@@ -570,9 +573,10 @@ def export_world(world, scene, global_matrix, tab_write):
         tab_write("}\n")
 
 
-####################################################################################################
+# -----------------------------------------------------------------------------
 def export_rainbows(rainbows, file, scene, global_matrix, write_matrix, tab_write):
     """write all POV rainbows primitives to exported file """
+    pov_mat_name = "Default_texture"
     for ob in rainbows:
         povdataname = ob.data.name  # enough? XXX not used nor matrix fn?
         angle = degrees(ob.data.spot_size / 2.5)  # radians in blender (2
@@ -631,7 +635,6 @@ def export_rainbows(rainbows, file, scene, global_matrix, write_matrix, tab_writ
         tab_write("[1.000  color srgbt<1.0, 0.2, 0.2, 1.0>]\n")
         tab_write("}\n")
 
-        pov_mat_name = "Default_texture"
         # tab_write("texture {%s}\n"%pov_mat_name)
         write_object_modifiers(scene, ob, file)
         # tab_write("rotate x*90\n")
@@ -652,20 +655,17 @@ def export_smoke(file, smoke_obj_name, smoke_path, comments, global_matrix, writ
     # Search smoke domain target for smoke modifiers
     for mod in smoke_obj.modifiers:
         if mod.type == 'FLUID':
-            if mod.fluid_type == 'FLOW':
-                if mod.flow_settings.flow_type == 'BOTH':
-                    flowtype = 2
-                else:
-                    if mod.flow_settings.smoke_flow_type == 'SMOKE':
-                        flowtype = 0
-                    else:
-                        if mod.flow_settings.smoke_flow_type == 'FIRE':
-                            flowtype = 1
-
             if mod.fluid_type == 'DOMAIN':
                 domain = smoke_obj
                 smoke_modifier = mod
 
+            elif mod.fluid_type == 'FLOW':
+                if mod.flow_settings.flow_type == 'BOTH':
+                    flowtype = 2
+                elif mod.flow_settings.flow_type == 'FIRE':
+                    flowtype = 1
+                elif mod.flow_settings.flow_type == 'SMOKE':
+                    flowtype = 0
     eps = 0.000001  # XXX not used currently. restore from corner case ... zero div?
     if domain is not None:
         mod_set = smoke_modifier.domain_settings
@@ -673,7 +673,7 @@ def export_smoke(file, smoke_obj_name, smoke_path, comments, global_matrix, writ
         for v in mod_set.density_grid:
             channeldata.append(v.real)
             print(v.real)
-        ## Usage en voxel texture:
+        # -------- Usage in voxel texture:
         # channeldata = []
         # if channel == 'density':
         # for v in mod_set.density_grid:
@@ -695,7 +695,7 @@ def export_smoke(file, smoke_obj_name, smoke_path, comments, global_matrix, writ
             big_res[2] = big_res[2] * (mod_set.noise_scale + 1)
         # else:
         # p = []
-        ##gather smoke domain settings
+        # -------- gather smoke domain settings
         # BBox = domain.bound_box
         # p.append([BBox[0][0], BBox[0][1], BBox[0][2]])
         # p.append([BBox[6][0], BBox[6][1], BBox[6][2]])
@@ -710,7 +710,7 @@ def export_smoke(file, smoke_obj_name, smoke_path, comments, global_matrix, writ
         # fire = ret[4]
 
         # if res_x * res_y * res_z > 0:
-        ##new cache format
+        # -------- new cache format
         # big_res = []
         # big_res.append(res_x)
         # big_res.append(res_y)
@@ -771,15 +771,17 @@ def export_smoke(file, smoke_obj_name, smoke_path, comments, global_matrix, writ
             for y in range(sim_sizeY):
                 for z in range(sim_sizeZ):
                     mydf3.set(x, y, z, channeldata[((z * sim_sizeY + y) * sim_sizeX + x)])
-
-        mydf3.exportDF3(smoke_path)
+        try:
+            mydf3.exportDF3(smoke_path)
+        except ZeroDivisionError:
+            print("Show smoke simulation in 3D view before export")
         print('Binary smoke.df3 file written in preview directory')
         if comments:
             file.write("\n//--Smoke--\n\n")
 
         # Note: We start with a default unit cube.
-        #       This is mandatory to read correctly df3 data - otherwise we could just directly use bbox
-        #       coordinates from the start, and avoid scale/translate operations at the end...
+        #       This is mandatory to read correctly df3 data - otherwise we could just directly use
+        #       bbox coordinates from the start, and avoid scale/translate operations at the end...
         file.write("box{<0,0,0>, <1,1,1>\n")
         file.write("    pigment{ rgbt 1 }\n")
         file.write("    hollow\n")
@@ -832,16 +834,3 @@ def export_smoke(file, smoke_obj_name, smoke_path, comments, global_matrix, writ
         # file.write("               frequency 0\n")
         # file.write("   }\n")
         # file.write("}\n")
-
-
-classes = ()
-
-
-def register():
-    for cls in classes:
-        register_class(cls)
-
-
-def unregister():
-    for cls in classes:
-        unregister_class(cls)
diff --git a/render_povray/scenography_gui.py b/render_povray/scenography_gui.py
index 6eb5aed907ea8c147b0c9fe14885e7925bbbc989..e66931b2efa19a5a573f6aec5c2e5e7e292b1cd1 100755
--- a/render_povray/scenography_gui.py
+++ b/render_povray/scenography_gui.py
@@ -35,8 +35,7 @@ for member in dir(properties_data_camera):
         subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
 del properties_data_camera
 
-# ##################################
-# # Use only a subset of the world panels
+# -------- 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')
@@ -44,7 +43,7 @@ del properties_data_camera
 # # TORECREATE##DEPRECATED#properties_world.WORLD_PT_world.COMPAT_ENGINES.add('POVRAY_RENDER')
 # del properties_world
 
-##################################
+# -------- #
 # Physics Main wrapping every class 'as is'
 from bl_ui import properties_physics_common
 
@@ -158,9 +157,9 @@ class WorldButtonsPanel:
         return wld and (rd.engine in cls.COMPAT_ENGINES)
 
 
-###############################################################################
+# ---------------------------------------------------------------- #
 # Camera Settings
-###############################################################################
+# ---------------------------------------------------------------- #
 class CAMERA_PT_POV_cam_dof(CameraDataButtonsPanel, Panel):
     """Use this class for camera depth of field focal blur buttons."""
 
@@ -236,9 +235,9 @@ class CAMERA_PT_POV_replacement_text(CameraDataButtonsPanel, Panel):
         col.prop(cam.pov, "replacement_text", text="")
 
 
-###############################################################################
+# ---------------------------------------------------------------- #
 # World background and sky sphere Settings
-###############################################################################
+# ---------------------------------------------------------------- #
 
 
 class WORLD_PT_POV_world(WorldButtonsPanel, Panel):
@@ -386,11 +385,11 @@ class RENDER_PT_POV_media(WorldButtonsPanel, Panel):
             col.prop(scene.pov, "media_eccentricity", text="Eccentricity")
 
 
-###############################################################################
+# ---------------------------------------------------------------- #
 # Lights settings
-###############################################################################
+# ---------------------------------------------------------------- #
 
-################################################################################
+# ----------------------------------------------------------------
 # from bl_ui import properties_data_light
 # for member in dir(properties_data_light):
 # subclass = getattr(properties_data_light, member)
@@ -401,16 +400,18 @@ class RENDER_PT_POV_media(WorldButtonsPanel, Panel):
 # print('An exception occurred: {}'.format(e))
 # pass
 # del properties_data_light
-#########################LIGHTS################################
+# -------- LIGHTS -------- #
 
 from bl_ui import properties_data_light
 
-# # These panels are kept
+# -------- These panels are kept
 # 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
+# make some native panels contextual to some object variable
+# by recreating custom panels inheriting their properties
+
+
 class PovLightButtonsPanel(properties_data_light.DataButtonsPanel):
     """Use this class to define buttons from the light data tab of
     properties window."""
@@ -682,6 +683,7 @@ class OBJECT_PT_POV_rainbow(PovLightButtonsPanel, Panel):
     bl_label = "POV-Ray Rainbow"
     COMPAT_ENGINES = {'POVRAY_RENDER'}
     # bl_options = {'HIDE_HEADER'}
+
     @classmethod
     def poll(cls, context):
         engine = context.scene.render.engine
@@ -750,12 +752,10 @@ def register():
 
     for cls in classes:
         register_class(cls)
-    bpy.types.LIGHT_PT_POV_light.prepend(light_panel_func)
+    LIGHT_PT_POV_light.prepend(light_panel_func)
 
 
 def unregister():
-
-    bpy.types.LIGHT_PT_POV_light.remove(light_panel_func)
+    LIGHT_PT_POV_light.remove(light_panel_func)
     for cls in reversed(classes):
         unregister_class(cls)
-
diff --git a/render_povray/scenography_properties.py b/render_povray/scenography_properties.py
index dd88651354f6f1856b4127f558fd1f37e1574b06..bdad0890ab6180e698088514c45d791421329bbf 100755
--- a/render_povray/scenography_properties.py
+++ b/render_povray/scenography_properties.py
@@ -29,18 +29,17 @@ from bpy.props import (
     FloatProperty,
     EnumProperty,
     PointerProperty,
-    CollectionProperty,
 )
 
 from .shading_properties import (
-    active_texture_name_from_uilist,
-    active_texture_name_from_search,
     brush_texture_update,
 )
 
-###############################################################################
+# ---------------------------------------------------------------- #
 # Camera POV properties.
-###############################################################################
+# ---------------------------------------------------------------- #
+
+
 class RenderPovSettingsCamera(PropertyGroup):
 
     """Declare camera properties controllable in UI and translated to POV."""
@@ -138,7 +137,7 @@ class RenderPovSettingsCamera(PropertyGroup):
 
     scale: FloatProperty(name="Scale", min=0.0, default=1.0)
 
-    ##################################CustomPOV Code############################
+    # ----------------------------------- CustomPOV Code ----------------------------------- #
     # Only DUMMIES below for now:
     replacement_text: StringProperty(
         name="Texts in blend file",
@@ -148,9 +147,9 @@ class RenderPovSettingsCamera(PropertyGroup):
     )
 
 
-###############################################################################
+# ---------------------------------------------------------------- #
 # Light POV properties.
-###############################################################################
+# ---------------------------------------------------------------- #
 class RenderPovSettingsLight(PropertyGroup):
 
     """Declare light properties controllable in UI and translated to POV."""
@@ -251,9 +250,9 @@ class RenderPovSettingsLight(PropertyGroup):
     )
 
 
-###############################################################################
+# ---------------------------------------------------------------- #
 # World POV properties.
-###############################################################################
+# ---------------------------------------------------------------- #
 class RenderPovSettingsWorld(PropertyGroup):
 
     """Declare world properties controllable in UI and translated to POV."""
@@ -353,20 +352,6 @@ class RenderPovSettingsWorld(PropertyGroup):
     )
 
 
-"""
-# class WORLD_TEXTURE_SLOTS_UL_layerlist(bpy.types.UIList):
-#    texture_slots:
-
-class WorldTextureSlots(bpy.props.PropertyGroup):
-    index = bpy.prop.PropertyInt(name='index')
-    # foo  = random prop
-
-bpy.types.World.texture_slots = bpy.props.CollectionProperty(type=PropertyGroup)
-
-for i in range(18):  # length of world texture slots
-    world.texture_slots.add()
-"""
-
 classes = (
     RenderPovSettingsCamera,
     RenderPovSettingsLight,
diff --git a/render_povray/scripting.py b/render_povray/scripting.py
index 02ca6444b122f315e87be8e0babc0a34fd3e3753..caa79b8c1c20bdfc77fc3d659af83935e37cbbcd 100755
--- a/render_povray/scripting.py
+++ b/render_povray/scripting.py
@@ -25,9 +25,10 @@ load, create or edit"""
 import bpy
 from bpy.props import StringProperty, BoolProperty, CollectionProperty
 from bpy_extras.io_utils import ImportHelper
+from bpy.utils import register_class, unregister_class
 
 from mathutils import Vector
-from math import pi
+from math import pi, sqrt
 
 
 def export_custom_code(file):
@@ -44,7 +45,7 @@ def export_custom_code(file):
             file.write("\n")
 
 
-#############################IMPORT
+# ----------------------------------- IMPORT
 
 
 class ImportPOV(bpy.types.Operator, ImportHelper):
@@ -75,8 +76,8 @@ class ImportPOV(bpy.types.Operator, ImportHelper):
         verts = []
         faces = []
         materials = []
-        blend_mats = []  ##############
-        pov_mats = []  ##############
+        blend_mats = []  # XXX
+        pov_mats = []  # XXX
         colors = []
         mat_names = []
         lenverts = None
@@ -91,32 +92,28 @@ class ImportPOV(bpy.types.Operator, ImportHelper):
         cylinder_search = False
         sphere_search = False
         cone_search = False
-        tex_search = False  ##################
+        tex_search = False  # XXX
         cache = []
         matrixes = {}
         write_matrix = False
         index = None
         value = None
-        # file_pov = bpy.path.abspath(self.filepath) #was used for single files
+        # file_pov = bpy.path.abspath(self.filepath) # was used for single files
 
         def mat_search(cache):
             r = g = b = 0.5
             f = t = 0
             color = None
-
             for item, value in enumerate(cache):
-
-                if value == 'texture':
-                    pass
-
+                # if value == 'texture': # add more later
                 if value == 'pigment':
-
+                    # Todo: create function for all color models.
+                    # instead of current pass statements
+                    # distinguish srgb from rgb into blend option
                     if cache[item + 2] in {'rgb', 'srgb'}:
                         pass
-
                     elif cache[item + 2] in {'rgbf', 'srgbf'}:
                         pass
-
                     elif cache[item + 2] in {'rgbt', 'srgbt'}:
                         try:
                             r, g, b, t = (
@@ -197,8 +194,8 @@ class ImportPOV(bpy.types.Operator, ImportHelper):
                 S = S.replace(";", " ; ")
                 S = S.split()
                 # lenS = len(S) # Not used... why written?
-                for i, word in enumerate(S):
-                    ##################Primitives Import##################
+                for word in enumerate(S):
+                    # -------- Primitives Import -------- #
                     if word == 'cone':
                         cone_search = True
                         name_search = False
@@ -340,7 +337,7 @@ class ImportPOV(bpy.types.Operator, ImportHelper):
                             mat_search(cache)
                             cache = []
                             sphere_search = False
-                    ##################End Primitives Import##################
+                    # -------- End Primitives Import -------- #
                     if word == '#declare':
                         name_search = True
                     if name_search:
@@ -374,16 +371,16 @@ class ImportPOV(bpy.types.Operator, ImportHelper):
                             cache = []
                     # if word == 'face_indices':
                     # faces_search = True
-                    if word == 'texture_list':  ########
-                        tex_search = True  #######
-                    if tex_search:  #########
+                    if word == 'texture_list':  # XXX
+                        tex_search = True  # XXX
+                    if tex_search:  # XXX
                         if (
                             word not in {'texture_list', 'texture', '{', '}', 'face_indices'}
                             and not word.isdigit()
-                        ):  ##############
-                            pov_mats.append(word)  #################
+                        ):  # XXX
+                            pov_mats.append(word)  # XXX
                     if word == 'face_indices':
-                        tex_search = False  ################
+                        tex_search = False  # XXX
                         faces_search = True
                     if faces_search:
                         cache.append(word)
@@ -423,34 +420,34 @@ class ImportPOV(bpy.types.Operator, ImportHelper):
                             # mesh = pov_define_mesh(None, verts, [], faces, name, hide_geometry=False)
                             # ob = object_utils.object_data_add(context, mesh, operator=None)
 
-                            me = bpy.data.meshes.new(name)  ########
-                            ob = bpy.data.objects.new(name, me)  ##########
-                            bpy.context.collection.objects.link(ob)  #########
-                            me.from_pydata(verts, [], faces)  ############
+                            me = bpy.data.meshes.new(name)  # XXX
+                            ob = bpy.data.objects.new(name, me)  # XXX
+                            bpy.context.collection.objects.link(ob)  # XXX
+                            me.from_pydata(verts, [], faces)  # XXX
 
-                            for mat in bpy.data.materials:  ##############
-                                blend_mats.append(mat.name)  #############
-                            for m_name in pov_mats:  #####################
-                                if m_name not in blend_mats:  ###########
-                                    povMat = bpy.data.materials.new(m_name)  #################
+                            for mat in bpy.data.materials:  # XXX
+                                blend_mats.append(mat.name)  # XXX
+                            for m_name in pov_mats:  # XXX
+                                if m_name not in blend_mats:  # XXX
+                                    bpy.data.materials.new(m_name)  # XXX
                                     mat_search(cache)
                                 ob.data.materials.append(
                                     bpy.data.materials[m_name]
-                                )  ###################
-                            if materials:  ##################
-                                for l, val in enumerate(materials):  ####################
-                                    try:  ###################
+                                )  # XXX
+                            if materials:  # XXX
+                                for idx, val in enumerate(materials):  # XXX
+                                    try:  # XXX
                                         ob.data.polygons[
-                                            l
-                                        ].material_index = val  ####################
-                                    except TypeError:  ###################
-                                        ob.data.polygons[l].material_index = int(
+                                            idx
+                                        ].material_index = val  # XXX
+                                    except TypeError:  # XXX
+                                        ob.data.polygons[idx].material_index = int(
                                             val[0]
-                                        )  ##################
+                                        )  # XXX
 
-                            blend_mats = []  #########################
-                            pov_mats = []  #########################
-                            materials = []  #########################
+                            blend_mats = []  # XXX
+                            pov_mats = []  # XXX
+                            materials = []  # XXX
                             cache = []
                             name_search = True
                             if name in matrixes and not self.import_at_cur:
@@ -510,7 +507,7 @@ class ImportPOV(bpy.types.Operator, ImportHelper):
                     # if color == colors[m]:
                     # ob.data.materials.append(bpy.data.materials[mat_names[m]])
 
-        ##To keep Avogadro Camera angle:
+        # To keep Avogadro Camera angle:
         # for obj in bpy.context.view_layer.objects:
         # if obj.type == "CAMERA":
         # track = obj.constraints.new(type = "TRACK_TO")
@@ -521,9 +518,16 @@ class ImportPOV(bpy.types.Operator, ImportHelper):
         return {'FINISHED'}
 
 
+classes = (
+    ImportPOV,
+)
+
+
 def register():
-    bpy.utils.register_class(ImportPOV)
+    for cls in classes:
+        register_class(cls)
 
 
 def unregister():
-    bpy.utils.unregister_class(ImportPOV)
+    for cls in reversed(classes):
+        unregister_class(cls)
diff --git a/render_povray/scripting_gui.py b/render_povray/scripting_gui.py
index 99006af1586ef19e4094574d0ec09f70e3d740e7..0dcdc4f1a9d2b2c9b3684d9f4b02ac156f98a2a0 100755
--- a/render_povray/scripting_gui.py
+++ b/render_povray/scripting_gui.py
@@ -72,7 +72,9 @@ def locate_docpath():
     return ""
 
 
-################################################################################
+# ---------------------------------------------------------------- #
+
+
 class TextButtonsPanel:
     """Use this class to define buttons from the side tab of
     text window."""
@@ -89,13 +91,13 @@ class TextButtonsPanel:
         return text and (rd.engine in cls.COMPAT_ENGINES)
 
 
-###############################################################################
+# ---------------------------------------------------------------- #
 # Text Povray Settings
-###############################################################################
+# ---------------------------------------------------------------- #
 
 
 class TEXT_OT_POV_insert(Operator):
-    """Use this class to create blender text editor operator to insert pov snippets like other pov IDEs"""
+    """Create blender text editor operator to insert pov snippets like other pov IDEs"""
 
     bl_idname = "text.povray_insert"
     bl_label = "Insert"
@@ -125,7 +127,7 @@ def validinsert(ext):
 
 
 class TEXT_MT_POV_insert(Menu):
-    """Use this class to create a menu launcher in text editor for the TEXT_OT_POV_insert operator ."""
+    """Create a menu launcher in text editor for the TEXT_OT_POV_insert operator ."""
 
     bl_label = "Insert"
     bl_idname = "TEXT_MT_POV_insert"
@@ -197,7 +199,7 @@ class TEXT_PT_POV_custom_code(TextButtonsPanel, Panel):
                 layout.label(text="replacement fields")
 
 
-###############################################
+# ---------------------------------------------------------------- #
 # Text editor templates from header menu
 
 
@@ -220,8 +222,10 @@ def menu_func_templates(self, context):
     self.layout.menu("TEXT_MT_POV_templates")
 
 
-###############################################
+# ---------------------------------------------------------------- #
 # POV Import menu
+
+
 class VIEW_MT_POV_import(Menu):
     """Use this class for the import menu."""
 
@@ -251,7 +255,6 @@ classes = (
 
 
 def register():
-
     for cls in classes:
         register_class(cls)
 
@@ -260,7 +263,6 @@ def register():
 
 
 def unregister():
-
     bpy.types.TEXT_MT_templates.remove(menu_func_templates)
     bpy.types.TOPBAR_MT_file_import.remove(menu_func_import)
 
diff --git a/render_povray/scripting_properties.py b/render_povray/scripting_properties.py
index 3e743da37e1039ceb7569cb1c7a81104449342d3..d4529c181ae3ef0f2ed021440962cd91ea77be3d 100755
--- a/render_povray/scripting_properties.py
+++ b/render_povray/scripting_properties.py
@@ -17,17 +17,17 @@
 # ##### END GPL LICENSE BLOCK #####
 
 # <pep8 compliant>
-import bpy
 
 """Declare pov native file syntax properties controllable in UI hooks and text blocks"""
 
+import bpy
 from bpy.utils import register_class, unregister_class
 from bpy.types import PropertyGroup
 from bpy.props import EnumProperty, PointerProperty
 
-###############################################################################
+# ---------------------------------------------------------------- #
 # Text POV properties.
-###############################################################################
+# ---------------------------------------------------------------- #
 
 
 class RenderPovSettingsText(PropertyGroup):
@@ -42,7 +42,9 @@ class RenderPovSettingsText(PropertyGroup):
     )
 
 
-classes = (RenderPovSettingsText,)
+classes = (
+    RenderPovSettingsText,
+)
 
 
 def register():
diff --git a/render_povray/shading.py b/render_povray/shading.py
index 680be99cd39da9204c5fcde4d427fe8f20a19e73..985afd34aeb607ba9c3181a046c5d18897ff1a9c 100755
--- a/render_povray/shading.py
+++ b/render_povray/shading.py
@@ -23,10 +23,11 @@
 import bpy
 
 
-def write_object_material(material, ob, tab_write):
+def write_object_material_interior(material, ob, tab_write):
     """Translate some object level material from Blender UI (VS data level)
 
     to POV interior{} syntax and write it to exported file.
+    This is called in object_mesh_topology.export_meshes
     """
     # DH - modified some variables to be function local, avoiding RNA write
     # this should be checked to see if it is functionally correct
@@ -107,23 +108,28 @@ def write_object_material(material, ob, tab_write):
 
 
 def write_material(
-    using_uberpov, DEF_MAT_NAME, tab_write, safety, comments, unique_name, material_names, material
+    using_uberpov,
+    DEF_MAT_NAME,
+    tab_write,
+    safety,
+    comments,
+    unique_name,
+    material_names_dictionary,
+    material
 ):
-    """Translate Blender material POV texture{} block and write to exported file."""
+    """Translate Blender material to POV texture{} block and write in exported file."""
     # Assumes only called once on each material
     if material:
         name_orig = material.name
-        name = material_names[name_orig] = unique_name(
-            bpy.path.clean_name(name_orig), material_names
+        name = material_names_dictionary[name_orig] = unique_name(
+            bpy.path.clean_name(name_orig), material_names_dictionary
         )
-    else:
-        name = name_orig = DEF_MAT_NAME
-
-    if material:
         # If saturation(.s) is not zero, then color is not grey, and has a tint
         colored_specular_found = (material.pov.specular_color.s > 0.0) and (
             material.pov.diffuse_shader != "MINNAERT"
         )
+    else:
+        name = name_orig = DEF_MAT_NAME
 
     ##################
     # Several versions of the finish: ref_level_bound conditions are variations for specular/Mirror
@@ -185,7 +191,7 @@ def write_material(
             # add a small value because 0.0 is invalid.
             roughness += 1.0 / 511.0
 
-            ################################Diffuse Shader######################################
+            # ------------------------------ Diffuse Shader ------------------------------ #
             # Not used for Full spec (ref_level_bound=3) of the shader.
             if material.pov.diffuse_shader == "OREN_NAYAR" and ref_level_bound != 3:
                 # Blender roughness is what is generally called oren nayar Sigma,
@@ -209,7 +215,7 @@ def write_material(
                 tab_write("brilliance 1\n")
 
             if ref_level_bound == 2:
-                ###########################Specular Shader######################################
+                # ------------------------------ Specular Shader ------------------------------ #
                 # No difference between phong and cook torrence in blender HaHa!
                 if (
                     material.pov.specular_shader == "COOKTORR"
@@ -247,7 +253,7 @@ def write_material(
                     # specular for some values.
                     tab_write("brilliance %.4g\n" % (1.8 - material.pov.specular_slope * 1.8))
 
-            ####################################################################################
+            # -------------------------------------------------------------------------------- #
             elif ref_level_bound == 1:
                 if (
                     material.pov.specular_shader == "COOKTORR"
@@ -472,7 +478,7 @@ def export_pattern(texture):
     # pov noise_generator 3 means perlin noise
     if tex.type not in {"NONE", "IMAGE"} and pat.tex_pattern_type == "emulator":
         text_strg += "pigment {\n"
-        ####################### EMULATE BLENDER VORONOI TEXTURE ####################
+        # ------------------------- EMULATE BLENDER VORONOI TEXTURE ------------------------- #
         if tex.type == "VORONOI":
             text_strg += "crackle\n"
             text_strg += "    offset %.4g\n" % tex.nabla
@@ -504,7 +510,7 @@ def export_pattern(texture):
                 text_strg += "[1 color rgbt<1,1,1,0>]\n"
                 text_strg += "}\n"
 
-        ####################### EMULATE BLENDER CLOUDS TEXTURE ####################
+        # ------------------------- EMULATE BLENDER CLOUDS TEXTURE ------------------------- #
         if tex.type == "CLOUDS":
             if tex.noise_type == "SOFT_NOISE":
                 text_strg += "wrinkles\n"
@@ -519,7 +525,7 @@ def export_pattern(texture):
                 text_strg += "[1 color rgbt<1,1,1,0>]\n"
                 text_strg += "}\n"
 
-        ####################### EMULATE BLENDER WOOD TEXTURE ####################
+        # ------------------------- EMULATE BLENDER WOOD TEXTURE ------------------------- #
         if tex.type == "WOOD":
             if tex.wood_type == "RINGS":
                 text_strg += "wood\n"
@@ -552,7 +558,7 @@ def export_pattern(texture):
                 text_strg += "[1 color rgbt<1,1,1,0>]\n"
                 text_strg += "}\n"
 
-        ####################### EMULATE BLENDER STUCCI TEXTURE ####################
+        # ------------------------- EMULATE BLENDER STUCCI TEXTURE ------------------------- #
         if tex.type == "STUCCI":
             text_strg += "bozo\n"
             text_strg += "scale 0.25\n"
@@ -574,7 +580,7 @@ def export_pattern(texture):
                     text_strg += "[1 color rgbt<1,1,1,0>]\n"
                     text_strg += "}\n"
 
-        ####################### EMULATE BLENDER MAGIC TEXTURE ####################
+        # ------------------------- EMULATE BLENDER MAGIC TEXTURE ------------------------- #
         if tex.type == "MAGIC":
             text_strg += "leopard\n"
             if tex.use_color_ramp:
@@ -589,7 +595,7 @@ def export_pattern(texture):
                 text_strg += "}\n"
             text_strg += "scale 0.1\n"
 
-        ####################### EMULATE BLENDER MARBLE TEXTURE ####################
+        # ------------------------- EMULATE BLENDER MARBLE TEXTURE ------------------------- #
         if tex.type == "MARBLE":
             text_strg += "marble\n"
             text_strg += "turbulence 0.5\n"
@@ -622,7 +628,7 @@ def export_pattern(texture):
             if tex.noise_basis_2 == "SAW":
                 text_strg += "ramp_wave\n"
 
-        ####################### EMULATE BLENDER BLEND TEXTURE ####################
+        # ------------------------- EMULATE BLENDER BLEND TEXTURE ------------------------- #
         if tex.type == "BLEND":
             if tex.progression == "RADIAL":
                 text_strg += "radial\n"
@@ -665,7 +671,7 @@ def export_pattern(texture):
             if tex.progression == "EASING":
                 text_strg += "    poly_wave 1.5\n"
 
-        ####################### EMULATE BLENDER MUSGRAVE TEXTURE ####################
+        # ------------------------- EMULATE BLENDER MUSGRAVE TEXTURE ------------------------- #
         # if tex.type == 'MUSGRAVE':
         # text_strg+="function{ f_ridged_mf( x, y, 0, 1, 2, 9, -0.5, 3,3 )*0.5}\n"
         # text_strg+="color_map {\n"
@@ -683,7 +689,7 @@ def export_pattern(texture):
                     "color_map {[0.5 color rgbf<0,0,0,1>][1 color rgbt<1,1,1,0>]}ramp_wave \n"
                 )
 
-        ####################### EMULATE BLENDER DISTORTED NOISE TEXTURE ####################
+        # ------------------------- EMULATE BLENDER DISTORTED NOISE TEXTURE ------------------------- #
         if tex.type == "DISTORTED_NOISE":
             text_strg += "average\n"
             text_strg += "  pigment_map {\n"
@@ -747,7 +753,7 @@ def export_pattern(texture):
                 text_strg += "]\n"
             text_strg += "  }\n"
 
-        ####################### EMULATE BLENDER NOISE TEXTURE ####################
+        # ------------------------- EMULATE BLENDER NOISE TEXTURE ------------------------- #
         if tex.type == "NOISE":
             text_strg += "cells\n"
             text_strg += "turbulence 3\n"
@@ -760,7 +766,7 @@ def export_pattern(texture):
                 text_strg += "[1 color rgb<1,1,1,>]\n"
                 text_strg += "}\n"
 
-        ####################### IGNORE OTHER BLENDER TEXTURE ####################
+        # ------------------------- IGNORE OTHER BLENDER TEXTURE ------------------------- #
         else:  # non translated textures
             pass
         text_strg += "}\n\n"
@@ -839,7 +845,7 @@ def export_pattern(texture):
                 num_pattern,
                 pat.pave_form,
             )
-        ################ functions ##########################################################
+        # ------------------------- functions ------------------------- #
         if pat.tex_pattern_type == "function":
             text_strg += "{ %s" % pat.func_list
             text_strg += "(x"
@@ -973,7 +979,7 @@ def export_pattern(texture):
                 text_strg += ",%.4g" % pat.func_P8
                 text_strg += ",%.4g" % pat.func_P9
             text_strg += ")}\n"
-        ############## end functions ###############################################################
+        # ------------------------- end functions ------------------------- #
         if pat.tex_pattern_type not in {"checker", "hexagon", "square", "triangular", "brick"}:
             text_strg += "color_map {\n"
         num_color = 0
@@ -1041,7 +1047,7 @@ def string_strip_hyphen(name):
     return name.replace("-", "")
 
 
-# WARNING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+# WARNING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 def write_nodes(scene, pov_mat_name, ntree, file):
     """Translate Blender node trees to pov and write them to file."""
     # such function local inlined import are official guidelines
@@ -1490,7 +1496,7 @@ def write_nodes(scene, pov_mat_name, ntree, file):
                                         link.to_node == node
                                         and link.from_node.bl_idname == "ShaderPatternNode"
                                     ):
-                                        ########### advanced ###############################################
+                                        # ------------ advanced ------------------------- #
                                         lfn = link.from_node
                                         pattern = lfn.pattern
                                         if pattern == "agate":
diff --git a/render_povray/shading_gui.py b/render_povray/shading_gui.py
index 428542c83ac127fa78a2a6ac0876be4287b84065..5e5630976398094efa94d58ab024ef1d402a3f3b 100755
--- a/render_povray/shading_gui.py
+++ b/render_povray/shading_gui.py
@@ -38,14 +38,11 @@ from .shading_properties import check_material
 
 def simple_material(mat):
     """Test if a material uses nodes"""
-    if (mat is not None) and (not mat.use_nodes):
-        return True
-    return False
+    return (mat is not None) and (not mat.use_nodes)
 
 
 class MaterialButtonsPanel:
-    """Use this class to define buttons from the material tab of
-    properties window."""
+    """Use this class to define buttons from the material tab of properties window."""
 
     bl_space_type = 'PROPERTIES'
     bl_region_type = 'WINDOW'
@@ -163,8 +160,9 @@ class MATERIAL_PT_POV_activate_node(MaterialButtonsPanel, Panel):
         return (
             mat
             and mat.pov.type == "SURFACE"
-            and (engine in cls.COMPAT_ENGINES)
-            and not (mat.pov.material_use_nodes or mat.use_nodes)
+            and engine in cls.COMPAT_ENGINES
+            and not mat.pov.material_use_nodes
+            and not mat.use_nodes
         )
 
     def draw(self, context):
@@ -196,50 +194,31 @@ class MATERIAL_PT_POV_active_node(MaterialButtonsPanel, Panel):
         )
 
     def draw(self, context):
-        layout = self.layout
         mat = context.material
         node_tree = mat.node_tree
-        if node_tree:
+        if node_tree and mat.use_nodes:
+            layout = self.layout
             node = node_tree.nodes.active
-            if mat.use_nodes:
-                if node:
-                    layout.prop(mat.pov, "material_active_node")
-                    if node.bl_idname == "PovrayMaterialNode":
-                        layout.context_pointer_set("node", node)
-                        if hasattr(node, "draw_buttons_ext"):
-                            node.draw_buttons_ext(context, layout)
-                        elif hasattr(node, "draw_buttons"):
-                            node.draw_buttons(context, layout)
-                        value_inputs = [
-                            socket
-                            for socket in node.inputs
-                            if socket.enabled and not socket.is_linked
-                        ]
-                        if value_inputs:
-                            layout.separator()
-                            layout.label(text="Inputs:")
-                            for socket in value_inputs:
-                                row = layout.row()
-                                socket.draw(context, row, node, socket.name)
-                    else:
-                        layout.context_pointer_set("node", node)
-                        if hasattr(node, "draw_buttons_ext"):
-                            node.draw_buttons_ext(context, layout)
-                        elif hasattr(node, "draw_buttons"):
-                            node.draw_buttons(context, layout)
-                        value_inputs = [
-                            socket
-                            for socket in node.inputs
-                            if socket.enabled and not socket.is_linked
-                        ]
-                        if value_inputs:
-                            layout.separator()
-                            layout.label(text="Inputs:")
-                            for socket in value_inputs:
-                                row = layout.row()
-                                socket.draw(context, row, node, socket.name)
-                else:
-                    layout.label(text="No active nodes!")
+            if node:
+                layout.prop(mat.pov, "material_active_node")
+                layout.context_pointer_set("node", node)
+                if hasattr(node, "draw_buttons_ext"):
+                    node.draw_buttons_ext(context, layout)
+                elif hasattr(node, "draw_buttons"):
+                    node.draw_buttons(context, layout)
+                value_inputs = [
+                    socket
+                    for socket in node.inputs
+                    if socket.enabled and not socket.is_linked
+                ]
+                if value_inputs:
+                    layout.separator()
+                    layout.label(text="Inputs:")
+                    for socket in value_inputs:
+                        row = layout.row()
+                        socket.draw(context, row, node, socket.name)
+            else:
+                layout.label(text="No active nodes!")
 
 
 class MATERIAL_PT_POV_specular(MaterialButtonsPanel, Panel):
@@ -452,8 +431,9 @@ class MATERIAL_PT_POV_reflection(MaterialButtonsPanel, Panel):
         return (
             mat
             and mat.pov.type == "SURFACE"
-            and (engine in cls.COMPAT_ENGINES)
-            and not (mat.pov.material_use_nodes or mat.use_nodes)
+            and engine in cls.COMPAT_ENGINES
+            and not mat.pov.material_use_nodes
+            and not mat.use_nodes
         )
 
     def draw(self, context):
@@ -491,7 +471,9 @@ class MATERIAL_PT_POV_interior(MaterialButtonsPanel, Panel):
     def poll(cls, context):
         engine = context.scene.render.engine
         mat=context.material
-        return mat and mat.pov.type == "SURFACE" and (engine in cls.COMPAT_ENGINES) and not (mat.pov.material_use_nodes or mat.use_nodes)
+        return mat and mat.pov.type == "SURFACE"
+                    and (engine in cls.COMPAT_ENGINES)
+                    and not (mat.pov.material_use_nodes or mat.use_nodes)
 
 
     def draw_header(self, context):
@@ -513,8 +495,9 @@ class MATERIAL_PT_POV_fade_color(MaterialButtonsPanel, Panel):
         return (
             mat
             and mat.pov.type == "SURFACE"
-            and (engine in cls.COMPAT_ENGINES)
-            and not (mat.pov.material_use_nodes or mat.use_nodes)
+            and engine in cls.COMPAT_ENGINES
+            and not mat.pov.material_use_nodes
+            and not mat.use_nodes
         )
 
     def draw_header(self, context):
@@ -523,10 +506,10 @@ class MATERIAL_PT_POV_fade_color(MaterialButtonsPanel, Panel):
         self.layout.prop(mat.pov, "interior_fade_color", text="")
 
     def draw(self, context):
-        layout = self.layout
         mat = context.material
-        # layout.active = mat.pov.interior_fade_color
         if mat.pov.interior_fade_color != (0.0, 0.0, 0.0):
+            layout = self.layout
+            # layout.active = mat.pov.interior_fade_color
             layout.label(text="Raytrace transparency")
             layout.label(text="depth max Limit needs")
             layout.label(text="to be non zero to fade")
@@ -545,8 +528,9 @@ class MATERIAL_PT_POV_caustics(MaterialButtonsPanel, Panel):
         return (
             mat
             and mat.pov.type == "SURFACE"
-            and (engine in cls.COMPAT_ENGINES)
-            and not (mat.pov.material_use_nodes or mat.use_nodes)
+            and engine in cls.COMPAT_ENGINES
+            and not mat.pov.material_use_nodes
+            and not mat.use_nodes
         )
 
     def draw_header(self, context):
@@ -661,7 +645,7 @@ classes = (
     MATERIAL_PT_POV_mirror,
     MATERIAL_PT_POV_transp,
     MATERIAL_PT_POV_reflection,
-    ## MATERIAL_PT_POV_interior,
+    # MATERIAL_PT_POV_interior,
     MATERIAL_PT_POV_fade_color,
     MATERIAL_PT_POV_caustics,
     MATERIAL_PT_POV_replacement_text,
@@ -669,12 +653,10 @@ classes = (
 
 
 def register():
-
     for cls in classes:
         register_class(cls)
 
 
 def unregister():
-
     for cls in reversed(classes):
         unregister_class(cls)
diff --git a/render_povray/shading_nodes.py b/render_povray/shading_nodes.py
index 2e8484f9cad21df2bd1aa622d32b323a14119601..eb7c2bd256d81a82d2ccb91a12436f9b3083740a 100755
--- a/render_povray/shading_nodes.py
+++ b/render_povray/shading_nodes.py
@@ -34,9 +34,9 @@ import nodeitems_utils
 from nodeitems_utils import NodeCategory, NodeItem
 
 
-###############################################################################
+# ---------------------------------------------------------------- #
 # Pov Nodes init
-###############################################################################
+# ---------------------------------------------------------------- #
 
 
 class PovraySocketUniversal(NodeSocket):
@@ -550,9 +550,9 @@ node_categories = [
     PovraySceneNodeCategory("ISOSURFACE", "Isosurface", items=[NodeItem("IsoPropsNode")]),
     PovraySceneNodeCategory("FOG", "Fog", items=[NodeItem("PovrayFogNode")]),
 ]
-############### end nodes init
-############### nodes ui
-##############Nodes
+# -------- end nodes init
+# -------- nodes ui
+# -------- Nodes
 
 # def find_node_input(node, name):
 # for input in node.inputs:
@@ -604,7 +604,7 @@ def menu_func_nodes(self, context):
                 self.layout.prop(tex.pov, "texture_use_nodes")
 
 
-############### object
+# -------- object
 
 
 class ObjectNodeTree(bpy.types.NodeTree):
@@ -633,7 +633,7 @@ class ObjectNodeTree(bpy.types.NodeTree):
         self.refresh = True
 
 
-################### output #############################################################################################
+# -------- output # ---------------------------------------------------------------- #
 
 
 class PovrayOutputNode(Node, ObjectNodeTree):
@@ -661,7 +661,7 @@ class PovrayOutputNode(Node, ObjectNodeTree):
         return "Output"
 
 
-################### material ###########################################################################################
+# -------- material # ---------------------------------------------------------------- #
 class PovrayTextureNode(Node, ObjectNodeTree):
     '''Texture'''
 
@@ -867,7 +867,7 @@ class PovraySubsurfaceNode(Node, ObjectNodeTree):
         return "Subsurface"
 
 
-#####################################################################################################
+# ---------------------------------------------------------------- #
 
 
 class PovrayMappingNode(Node, ObjectNodeTree):
@@ -1612,7 +1612,7 @@ class PovraySlopeNode(Node, TextureNodeTree):
         return "Slope Map"
 
 
-######################################## Texture nodes ###############################
+# -------- Texture nodes # ---------------------------------------------------------------- #
 class TextureOutputNode(Node, TextureNodeTree):
     '''Output'''
 
@@ -1634,9 +1634,9 @@ class TextureOutputNode(Node, TextureNodeTree):
         return "Color Map"
 
 
-##################################################################################
-#################################Operators########################################
-##################################################################################
+# ------------------------------------------------------------------------------ #
+# --------------------------------- Operators ---------------------------------- #
+# ------------------------------------------------------------------------------ #
 
 
 class NODE_OT_iso_add(Operator):
@@ -1995,7 +1995,6 @@ classes = (
 
 
 def register():
-    # from bpy.utils import register_class
     bpy.types.NODE_HT_header.append(menu_func_nodes)
     nodeitems_utils.register_node_categories("POVRAYNODES", node_categories)
     for cls in classes:
@@ -2003,8 +2002,6 @@ def register():
 
 
 def unregister():
-    # from bpy.utils import unregister_class
-
     for cls in reversed(classes):
         unregister_class(cls)
     nodeitems_utils.unregister_node_categories("POVRAYNODES")
diff --git a/render_povray/shading_properties.py b/render_povray/shading_properties.py
index 18895eba16e456bf497acb10a9024db3f6616f9c..3a3c944d56d07c97283355c982c3f0156856bc90 100755
--- a/render_povray/shading_properties.py
+++ b/render_povray/shading_properties.py
@@ -127,7 +127,7 @@ def brush_texture_update(self, context):
 class RenderPovSettingsMaterial(PropertyGroup):
     """Declare material level properties controllable in UI and translated to POV."""
 
-    ######################Begin Old Blender Internal Props#########################
+    # --------------------------- Begin Old Blender Internal Props --------------------------- #
     # former Space properties from  removed Blender Internal
     use_limited_texture_context: BoolProperty(
         name="",
@@ -854,7 +854,7 @@ class RenderPovSettingsMaterial(PropertyGroup):
         default="1",
     )
 
-    ##################################CustomPOV Code############################
+    # ------------------------------ CustomPOV Code ------------------------------ #
     replacement_text: StringProperty(
         name="Declared name:",
         description="Type the variable name as declared either directly inlined "
@@ -936,12 +936,9 @@ class RenderPovSettingsMaterial(PropertyGroup):
                 return node
 
     def node_enum_callback(self, context):
-        items = []
         mat = context.material
         nodes = mat.node_tree.nodes
-        for node in nodes:
-            items.append(("%s" % node.name, "%s" % node.name, ""))
-        return items
+        return [("%s" % node.name, "%s" % node.name, "") for node in nodes]
 
     def pigment_normal_callback(self, context):
         render = context.scene.pov.render  # XXX comment out > remove?
@@ -2252,7 +2249,7 @@ class MaterialStrandSettings(PropertyGroup):
     """
 
 
-#######################End Old Blender Internal Props##########################
+# ------------------------------ End Old Blender Internal Props ------------------------------ #
 
 
 classes = (
diff --git a/render_povray/texturing.py b/render_povray/texturing.py
index e070dbe97e7a2811893eaa42a495e18293131f36..225c536934617b0e16d5a7ae2a8f039a380c1fe8 100755
--- a/render_povray/texturing.py
+++ b/render_povray/texturing.py
@@ -59,7 +59,6 @@ def write_texture_influence(
     else:
         pov_filter = 0.0
 
-    ##############SF
     texture_dif = ""
     texture_spec = ""
     texture_norm = ""
@@ -166,7 +165,7 @@ def write_texture_influence(
                         # was the above used? --MR
                         t_alpha = t
 
-    ####################################################################################
+    # -----------------------------------------------------------------------------
 
     tab_write("\n")
     # THIS AREA NEEDS TO LEAVE THE TEXTURE OPEN UNTIL ALL MAPS ARE WRITTEN DOWN.
@@ -174,11 +173,11 @@ def write_texture_influence(
     current_material_name = string_strip_hyphen(material_names_dictionary[mater.name])
     local_material_names.append(current_material_name)
     tab_write("\n#declare MAT_%s = \ntexture{\n" % current_material_name)
-    ################################################################################
+    # -----------------------------------------------------------------------------
 
     if mater.pov.replacement_text != "":
         tab_write("%s\n" % mater.pov.replacement_text)
-    #################################################################################
+    # -----------------------------------------------------------------------------
     # XXX TODO: replace by new POV MINNAERT rather than aoi
     if mater.pov.diffuse_shader == "MINNAERT":
         tab_write("\n")
@@ -221,14 +220,13 @@ def write_texture_influence(
             mapping_spec = img_map_transforms(t_spec)
             if texture_spec and texture_spec.startswith("PAT_"):
                 tab_write("function{f%s(x,y,z).grey}\n" % texture_spec)
-                tab_write("%s\n" % mapping_spec)
             else:
 
                 tab_write(
                     'uv_mapping image_map{%s "%s" %s}\n'
                     % (image_format(texture_spec), texture_spec, img_map(t_spec))
                 )
-                tab_write("%s\n" % mapping_spec)
+            tab_write("%s\n" % mapping_spec)
             tab_write("}\n")
             tab_write("texture_map {\n")
             tab_write("[0 \n")
@@ -270,14 +268,6 @@ def write_texture_influence(
                     % (col[0], col[1], col[2], pov_filter, trans)
                 )
 
-            if texture_spec != "":
-                # ref_level_bound 1 is no specular
-                tab_write("finish {%s}\n" % (safety(material_finish, ref_level_bound=1)))
-
-            else:
-                # ref_level_bound 2 is translated spec
-                tab_write("finish {%s}\n" % (safety(material_finish, ref_level_bound=2)))
-
         else:
             mapping_dif = img_map_transforms(t_dif)
 
@@ -333,25 +323,25 @@ def write_texture_influence(
                         )
                     )
 
-            if texture_spec != "":
-                # ref_level_bound 1 is no specular
-                tab_write("finish {%s}\n" % (safety(material_finish, ref_level_bound=1)))
+                    # scale 1 rotate y*0
+                    # imageMap = ("{image_map {%s \"%s\" %s }\n" % \
+                    #            (image_format(textures),textures,img_map(t_dif)))
+                    # tab_write("uv_mapping pigment %s} %s finish {%s}\n" % \
+                    #         (imageMap,mapping,safety(material_finish)))
+                    # tab_write("pigment {uv_mapping image_map {%s \"%s\" %s}%s} " \
+                    #         "finish {%s}\n" % \
+                    #         (image_format(texture_dif), texture_dif, img_map(t_dif),
+                    #          mapping_dif, safety(material_finish)))
+        if texture_spec != "":
+            # ref_level_bound 1 is no specular
+            tab_write("finish {%s}\n" % (safety(material_finish, ref_level_bound=1)))
+
+        else:
+            # ref_level_bound 2 is translated spec
+            tab_write("finish {%s}\n" % (safety(material_finish, ref_level_bound=2)))
 
-            else:
-                # ref_level_bound 2 is translated specular
-                tab_write("finish {%s}\n" % (safety(material_finish, ref_level_bound=2)))
-
-            ## scale 1 rotate y*0
-            # imageMap = ("{image_map {%s \"%s\" %s }\n" % \
-            #            (image_format(textures),textures,img_map(t_dif)))
-            # tab_write("uv_mapping pigment %s} %s finish {%s}\n" % \
-            #         (imageMap,mapping,safety(material_finish)))
-            # tab_write("pigment {uv_mapping image_map {%s \"%s\" %s}%s} " \
-            #         "finish {%s}\n" % \
-            #         (image_format(texture_dif), texture_dif, img_map(t_dif),
-            #          mapping_dif, safety(material_finish)))
         if texture_norm != "":
-            ## scale 1 rotate y*0
+            # scale 1 rotate y*0
 
             mapping_normal = img_map_transforms(t_nor)
 
@@ -362,7 +352,8 @@ def write_texture_influence(
                 )
             else:
                 tab_write("normal {\n")
-                # XXX TODO: fix and propagate the micro normals reflection blur below to non textured materials
+                # XXX TODO: fix and propagate the micro normals reflection blur below
+                #  to non textured materials
                 if (
                     mater.pov_raytrace_mirror.use
                     and mater.pov_raytrace_mirror.gloss_factor < 1.0
@@ -464,10 +455,10 @@ def write_texture_influence(
                     tab_write("]}}\n")
                 else:
                     tab_write("]}\n")
-        if texture_spec != "":
-            tab_write("]\n")
-            ##################Second index for mapping specular max value###############
-            tab_write("[1 \n")
+    if texture_spec != "":
+        tab_write("]\n")
+        # -------- Second index for mapping specular max value -------- #
+        tab_write("[1 \n")
 
     if texture_dif == "" and mater.pov.replacement_text == "":
         if texture_alpha != "":
@@ -673,7 +664,7 @@ def write_texture_influence(
             # ref_level_bound 2 is translated specular
             tab_write("finish {%s}\n" % (safety(material_finish, ref_level_bound=2)))
 
-        ## scale 1 rotate y*0
+        # scale 1 rotate y*0
         # imageMap = ("{image_map {%s \"%s\" %s }" % \
         #            (image_format(textures), textures,img_map(t_dif)))
         # tab_write("\n\t\t\tuv_mapping pigment %s} %s finish {%s}" % \
@@ -693,7 +684,8 @@ def write_texture_influence(
             )
         else:
             tab_write("normal {\n")
-            # XXX TODO: fix and propagate the micro normals reflection blur below to non textured materials
+            # XXX TODO: fix and propagate the micro normals reflection blur below
+            #  to non textured materials
             if (
                 mater.pov_raytrace_mirror.use
                 and mater.pov_raytrace_mirror.gloss_factor < 1.0
diff --git a/render_povray/texturing_gui.py b/render_povray/texturing_gui.py
index ad889f4327778ed6711cf2896c7404bbc9aac780..8d285383229074e906a05c3ad656b615ff6a1f5e 100755
--- a/render_povray/texturing_gui.py
+++ b/render_povray/texturing_gui.py
@@ -83,13 +83,14 @@ class TEXTURE_MT_POV_specials(Menu):
 
 
 class WORLD_TEXTURE_SLOTS_UL_POV_layerlist(UIList):
-    """Use this class to show pov texture slots list."""  # XXX Not used yet
+    """Use this class to show pov texture slots list."""
 
     index: bpy.props.IntProperty(name='index')
     # should active_propname be index or..?
+
     def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
-        world = context.scene.world  # .pov
-        active_data = world.pov
+        # world = context.scene.world  # .pov  # NOT USED
+        # active_data = world.pov # NOT USED
         # tex = context.texture #may be needed later?
 
         # We could write some code to decide which icon to use here...
@@ -120,6 +121,7 @@ class MATERIAL_TEXTURE_SLOTS_UL_POV_layerlist(UIList):
     #    texture_slots:
     index: bpy.props.IntProperty(name='index')
     # foo  = random prop
+
     def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
         # ob = data
         slot = item
@@ -149,6 +151,7 @@ class TEXTURE_PT_context(TextureButtonsPanel, Panel):
     COMPAT_ENGINES = {'POVRAY_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
     # register but not unregistered because
     # the modified parts concern only POVRAY_RENDER
+
     @classmethod
     def poll(cls, context):
         return (
@@ -247,14 +250,16 @@ class TEXTURE_PT_POV_context_texture(TextureButtonsPanel, Panel):
             if mat.pov_texture_slots:
                 index = mat.pov.active_texture_index
                 slot = mat.pov_texture_slots[index]
-                povtex = slot.texture  # slot.name
-                tex = bpy.data.textures[povtex]
-                col.prop(tex, 'use_fake_user', text='')
-                # layout.label(text='Linked Texture data browser:')
-                # propname = slot.texture_search
-                # if slot.texture was a pointer to texture data rather than just a name string:
-                # layout.template_ID(povtex, "texture", new="texture.new")
-
+                try:
+                    povtex = slot.texture  # slot.name
+                    tex = bpy.data.textures[povtex]
+                    col.prop(tex, 'use_fake_user', text='')
+                    # layout.label(text='Linked Texture data browser:')
+                    # propname = slot.texture_search
+                    # if slot.texture was a pointer to texture data rather than just a name string:
+                    # layout.template_ID(povtex, "texture", new="texture.new")
+                except KeyError:
+                    tex = None
                 layout.prop_search(
                     slot, 'texture_search', bpy.data, 'textures', text='', icon='TEXTURE'
                 )
@@ -308,7 +313,7 @@ class TEXTURE_PT_POV_context_texture(TextureButtonsPanel, Panel):
                 tex = bpy.data.textures[povtex]
                 col.prop(tex, 'use_fake_user', text='')
                 # layout.label(text='Linked Texture data browser:')
-                propname = slot.texture_search
+                # propname = slot.texture_search # NOT USED
                 # if slot.texture was a pointer to texture data rather than just a name string:
                 # layout.template_ID(povtex, "texture", new="texture.new")
 
@@ -614,10 +619,9 @@ class TEXTURE_PT_POV_parameters(TextureButtonsPanel, Panel):
 
     def draw(self, context):
         # mat = bpy.context.active_object.active_material # Unused
-        layout = self.layout
         tex = context.texture
-        align = True
         if tex is not None and tex.pov.tex_pattern_type != 'emulator':
+            layout = self.layout
             if tex.pov.tex_pattern_type == 'agate':
                 layout.prop(tex.pov, "modifier_turbulence", text="Agate Turbulence")
             if tex.pov.tex_pattern_type in {'spiral1', 'spiral2'}:
@@ -626,6 +630,7 @@ class TEXTURE_PT_POV_parameters(TextureButtonsPanel, Panel):
                 layout.prop(tex.pov, "modifier_numbers", text="Pattern number")
             if tex.pov.tex_pattern_type == 'magnet':
                 layout.prop(tex.pov, "magnet_style", text="Magnet style")
+            align = True
             if tex.pov.tex_pattern_type == 'quilted':
                 row = layout.row(align=align)
                 row.prop(tex.pov, "modifier_control0", text="Control0")
@@ -825,7 +830,7 @@ class TEXTURE_PT_POV_parameters(TextureButtonsPanel, Panel):
                     row = layout.row(align=align)
                     row.prop(tex.pov, "func_P8", text="P8")
                     row.prop(tex.pov, "func_P9", text="P9")
-            ###################################################End Patterns############################
+            # ------------------------- End Patterns ------------------------- #
 
             layout.prop(tex.pov, "warp_types", text="Warp types")  # warp
             if tex.pov.warp_types == "TOROIDAL":
@@ -987,6 +992,7 @@ class TEXTURE_PT_POV_influence(TextureSlotPanel, Panel):
     bl_space_type = 'PROPERTIES'
     bl_region_type = 'WINDOW'
     # bl_context = 'texture'
+
     @classmethod
     def poll(cls, context):
         idblock = pov_context_tex_datablock(context)
@@ -1015,8 +1021,11 @@ class TEXTURE_PT_POV_influence(TextureSlotPanel, Panel):
         texslot = idblock.pov_texture_slots[
             idblock.pov.active_texture_index
         ]  # bpy.data.textures[mat.active_texture_index]
-        # below tex is unused
-        tex = bpy.data.textures[idblock.pov_texture_slots[idblock.pov.active_texture_index].texture]
+        # below tex unused yet ...maybe for particles?
+        try:
+            tex = bpy.data.textures[idblock.pov_texture_slots[idblock.pov.active_texture_index].texture]  # NOT USED
+        except KeyError:
+            tex = None  # NOT USED
 
         def factor_but(layout, toggle, factor, name):
             row = layout.row(align=True)
@@ -1224,6 +1233,7 @@ class TEXTURE_PT_POV_tex_gamma(TextureButtonsPanel, Panel):
 classes = (
     WORLD_TEXTURE_SLOTS_UL_POV_layerlist,
     TEXTURE_MT_POV_specials,
+    # TEXTURE_PT_context # todo: solve UI design for painting
     TEXTURE_PT_POV_context_texture,
     TEXTURE_PT_colors,
     TEXTURE_PT_POV_type,
@@ -1239,13 +1249,11 @@ classes = (
 
 
 def register():
-
     for cls in classes:
         register_class(cls)
 
 
 def unregister():
-
     for cls in reversed(classes):
-        if cls != TEXTURE_PT_context:
-            unregister_class(cls)
+        # if cls != TEXTURE_PT_context:
+        unregister_class(cls)
diff --git a/render_povray/texturing_properties.py b/render_povray/texturing_properties.py
index bb89ee025f5157dc7419f7b124279fced066c58e..ceb6026413e55e003ab01d2243ff7b640ab8afee 100755
--- a/render_povray/texturing_properties.py
+++ b/render_povray/texturing_properties.py
@@ -17,6 +17,7 @@
 # ##### END GPL LICENSE BLOCK #####
 
 # <pep8 compliant>
+
 """Declare texturing properties controllable in UI."""
 
 import bpy
@@ -35,9 +36,11 @@ from bpy.props import (
 
 from .shading_properties import active_texture_name_from_uilist, active_texture_name_from_search
 
-###############################################################################
+# ---------------------------------------------------------------- #
 # Texture slots (Material context) exported as POV texture properties.
-###############################################################################
+# ---------------------------------------------------------------- #
+
+
 class MaterialTextureSlot(PropertyGroup):
     """Declare material texture slot level properties for UI and translated to POV."""
 
@@ -381,7 +384,7 @@ class MaterialTextureSlot(PropertyGroup):
         default=0.0,
     )
 
-    #######################################
+    # ---------------------------------------------------------------- #
 
     blend_factor: FloatProperty(
         name="Blend",
@@ -461,9 +464,9 @@ class MaterialTextureSlot(PropertyGroup):
     )
 
 
-###############################################################################
+# ---------------------------------------------------------------- #
 # Texture slots (World context) exported as POV texture properties.
-###############################################################################
+# ---------------------------------------------------------------- #
 class WorldTextureSlot(PropertyGroup):
     """Declare world texture slot level properties for UI and translated to POV."""
 
@@ -583,9 +586,9 @@ class WorldTextureSlot(PropertyGroup):
     )
 
 
-###############################################################################
+# ---------------------------------------------------------------- #
 # Space properties from  removed former Blender Internal
-###############################################################################
+# ---------------------------------------------------------------- #
 
 # added below at superclass level so as to be available in World, Material,
 # and Light, for texture slots use
@@ -614,9 +617,9 @@ bpy.types.ID.texture_context = EnumProperty(
 # )
 
 
-###############################################################################
+# ---------------------------------------------------------------- #
 # Texture POV properties.
-###############################################################################
+# ---------------------------------------------------------------- #
 
 
 class RenderPovSettingsTexture(PropertyGroup):
@@ -682,7 +685,7 @@ class RenderPovSettingsTexture(PropertyGroup):
         default=1.00,
     )
 
-    ##################################CustomPOV Code############################
+    # ----------------------------------- CustomPOV Code ----------------------------------- #
     # commented out below if we wanted custom pov code in texture only, inside exported material:
     # replacement_text = StringProperty(
     #        name="Declared name:",
@@ -953,8 +956,7 @@ class RenderPovSettingsTexture(PropertyGroup):
 
     pave_form: IntProperty(name="Pavement form", description="", min=0, max=4, default=0)
 
-    #########FUNCTIONS#############################################################################
-    #########FUNCTIONS#############################################################################
+    # -------- FUNCTIONS# ---------------------------------------------------------------- #
 
     func_list: EnumProperty(
         name="Functions",
@@ -1090,7 +1092,7 @@ class RenderPovSettingsTexture(PropertyGroup):
 
     func_P9: FloatProperty(name="P9", description="", min=0.0, max=25.0, default=1.0)
 
-    #########################################
+    # ----------------------------------- #
     tex_rot_x: FloatProperty(name="Rotate X", description="", min=-180.0, max=180.0, default=0.0)
 
     tex_rot_y: FloatProperty(name="Rotate Y", description="", min=-180.0, max=180.0, default=0.0)
@@ -1116,7 +1118,11 @@ class RenderPovSettingsTexture(PropertyGroup):
     tex_scale_z: FloatProperty(name="Scale Z", description="", min=0.0, max=10000.0, default=1.0)
 
 
-classes = (MaterialTextureSlot, WorldTextureSlot, RenderPovSettingsTexture)
+classes = (
+    MaterialTextureSlot,
+    WorldTextureSlot,
+    RenderPovSettingsTexture,
+)
 
 
 def register():
diff --git a/render_povray/update_files.py b/render_povray/update_files.py
index 985f846842125d3ad7f6f320ab3303910d5d674e..f9696f8f6045c0fed2f52e8b6a38e00ec42ee3f5 100755
--- a/render_povray/update_files.py
+++ b/render_povray/update_files.py
@@ -55,105 +55,119 @@ def update2_0_0_9():
     # Mapping old names -> old default values
     # XXX We could also store the new name, but as it is just the same without leading pov_ ...
     # Get default values of pov scene props.
-    old_sce_props = {}
-    for k in [
-        "pov_tempfiles_enable",
-        "pov_deletefiles_enable",
-        "pov_scene_name",
-        "pov_scene_path",
-        "pov_renderimage_path",
-        "pov_list_lf_enable",
-        "pov_radio_enable",
-        "pov_radio_display_advanced",
-        "pov_media_enable",
-        "pov_media_samples",
-        "pov_media_color",
-        "pov_baking_enable",
-        "pov_indentation_character",
-        "pov_indentation_spaces",
-        "pov_comments_enable",
-        "pov_command_line_switches",
-        "pov_antialias_enable",
-        "pov_antialias_method",
-        "pov_antialias_depth",
-        "pov_antialias_threshold",
-        "pov_jitter_enable",
-        "pov_jitter_amount",
-        "pov_antialias_gamma",
-        "pov_max_trace_level",
-        "pov_photon_spacing",
-        "pov_photon_max_trace_level",
-        "pov_photon_adc_bailout",
-        "pov_photon_gather_min",
-        "pov_photon_gather_max",
-        "pov_radio_adc_bailout",
-        "pov_radio_always_sample",
-        "pov_radio_brightness",
-        "pov_radio_count",
-        "pov_radio_error_bound",
-        "pov_radio_gray_threshold",
-        "pov_radio_low_error_factor",
-        "pov_radio_media",
-        "pov_radio_minimum_reuse",
-        "pov_radio_nearest_count",
-        "pov_radio_normal",
-        "pov_radio_recursion_limit",
-        "pov_radio_pretrace_start",
-        "pov_radio_pretrace_end",
-    ]:
-        old_sce_props[k] = getattr(bpy.types.Scene, k)[1].get('default', None)
+    old_sce_props = {
+        k: getattr(bpy.types.Scene, k)[1].get('default', None)
+        for k in [
+            "pov_tempfiles_enable",
+            "pov_deletefiles_enable",
+            "pov_scene_name",
+            "pov_scene_path",
+            "pov_renderimage_path",
+            "pov_list_lf_enable",
+            "pov_radio_enable",
+            "pov_radio_display_advanced",
+            "pov_media_enable",
+            "pov_media_samples",
+            "pov_media_color",
+            "pov_baking_enable",
+            "pov_indentation_character",
+            "pov_indentation_spaces",
+            "pov_comments_enable",
+            "pov_command_line_switches",
+            "pov_antialias_enable",
+            "pov_antialias_method",
+            "pov_antialias_depth",
+            "pov_antialias_threshold",
+            "pov_jitter_enable",
+            "pov_jitter_amount",
+            "pov_antialias_gamma",
+            "pov_max_trace_level",
+            "pov_photon_spacing",
+            "pov_photon_max_trace_level",
+            "pov_photon_adc_bailout",
+            "pov_photon_gather_min",
+            "pov_photon_gather_max",
+            "pov_radio_adc_bailout",
+            "pov_radio_always_sample",
+            "pov_radio_brightness",
+            "pov_radio_count",
+            "pov_radio_error_bound",
+            "pov_radio_gray_threshold",
+            "pov_radio_low_error_factor",
+            "pov_radio_media",
+            "pov_radio_minimum_reuse",
+            "pov_radio_nearest_count",
+            "pov_radio_normal",
+            "pov_radio_recursion_limit",
+            "pov_radio_pretrace_start",
+            "pov_radio_pretrace_end",
+        ]
+    }
 
     # Get default values of pov material props.
-    old_mat_props = {}
-    for k in [
-        "pov_irid_enable",
-        "pov_mirror_use_IOR",
-        "pov_mirror_metallic",
-        "pov_conserve_energy",
-        "pov_irid_amount",
-        "pov_irid_thickness",
-        "pov_irid_turbulence",
-        "pov_interior_fade_color",
-        "pov_caustics_enable",
-        "pov_fake_caustics",
-        "pov_fake_caustics_power",
-        "pov_photons_refraction",
-        "pov_photons_dispersion",
-        "pov_photons_reflection",
-        "pov_refraction_type",
-        "pov_replacement_text",
-    ]:
-        old_mat_props[k] = getattr(bpy.types.Material, k)[1].get('default', None)
+    old_mat_props = {
+        k: getattr(bpy.types.Material, k)[1].get('default', None)
+        for k in [
+            "pov_irid_enable",
+            "pov_mirror_use_IOR",
+            "pov_mirror_metallic",
+            "pov_conserve_energy",
+            "pov_irid_amount",
+            "pov_irid_thickness",
+            "pov_irid_turbulence",
+            "pov_interior_fade_color",
+            "pov_caustics_enable",
+            "pov_fake_caustics",
+            "pov_fake_caustics_power",
+            "pov_photons_refraction",
+            "pov_photons_dispersion",
+            "pov_photons_reflection",
+            "pov_refraction_type",
+            "pov_replacement_text",
+        ]
+    }
 
     # Get default values of pov texture props.
-    old_tex_props = {}
-    for k in ["pov_tex_gamma_enable", "pov_tex_gamma_value", "pov_replacement_text"]:
-        old_tex_props[k] = getattr(bpy.types.Texture, k)[1].get('default', None)
+    old_tex_props = {
+        k: getattr(bpy.types.Texture, k)[1].get('default', None)
+        for k in [
+            "pov_tex_gamma_enable",
+            "pov_tex_gamma_value",
+            "pov_replacement_text",
+        ]
+    }
 
     # Get default values of pov object props.
-    old_obj_props = {}
-    for k in ["pov_importance_value", "pov_collect_photons", "pov_replacement_text"]:
-        old_obj_props[k] = getattr(bpy.types.Object, k)[1].get('default', None)
+    old_obj_props = {
+        k: getattr(bpy.types.Object, k)[1].get('default', None)
+        for k in [
+            "pov_importance_value",
+            "pov_collect_photons",
+            "pov_replacement_text",
+        ]
+    }
 
     # Get default values of pov camera props.
-    old_cam_props = {}
-    for k in [
-        "pov_dof_enable",
-        "pov_dof_aperture",
-        "pov_dof_samples_min",
-        "pov_dof_samples_max",
-        "pov_dof_variance",
-        "pov_dof_confidence",
-        "pov_replacement_text",
-    ]:
-        old_cam_props[k] = getattr(bpy.types.Camera, k)[1].get('default', None)
+    old_cam_props = {
+        k: getattr(bpy.types.Camera, k)[1].get('default', None)
+        for k in [
+            "pov_dof_enable",
+            "pov_dof_aperture",
+            "pov_dof_samples_min",
+            "pov_dof_samples_max",
+            "pov_dof_variance",
+            "pov_dof_confidence",
+            "pov_replacement_text",
+        ]
+    }
 
     # Get default values of pov text props.
-    old_txt_props = {}
-    for k in ["pov_custom_code"]:
-        old_txt_props[k] = getattr(bpy.types.Text, k)[1].get('default', None)
+    old_txt_props = {
+        k: getattr(bpy.types.Text, k)[1].get('default', None)
+        for k in ["pov_custom_code"]
+    }
 
-    ################################################################################################
+    # -----------------------------------------------------------------------------
     # Now, update !
     # For each old pov property of each scene, if its value is not equal to the default one,
     # copy it to relevant new prop...
@@ -215,7 +229,7 @@ def register():
     Obj = bpy.types.Object
     Cam = bpy.types.Camera
     Text = bpy.types.Text
-    ###########################SCENE##################################
+    # -------------------------------------- SCENE --------------------------------------#
 
     # File Options
     Scene.pov_tempfiles_enable = BoolProperty(
@@ -549,7 +563,7 @@ def register():
         precision=3,
     )
 
-    #############################MATERIAL######################################
+    # -------------------------------------- MATERIAL -------------------------------------- #
 
     Mat.pov_irid_enable = BoolProperty(
         name="Enable Iridescence",
@@ -668,7 +682,7 @@ def register():
         description="use fake caustics (fast) or true photons for refractive Caustics",
         default="1",
     )
-    ##################################CustomPOV Code############################
+    # -------------------------------------- CustomPOV Code -------------------------------------- #
     Mat.pov_replacement_text = StringProperty(
         name="Declared name:",
         description="Type the declared name in custom POV code or an external .inc it points at. texture {} expected",
@@ -693,7 +707,7 @@ def register():
         description="Type the declared name in custom POV code or an external .inc it points at. camera {} expected",
         default="",
     )
-    ##############################TEXTURE######################################
+    # -------------------------------------- TEXTURE -------------------------------------- #
 
     # Custom texture gamma
     Tex.pov_tex_gamma_enable = BoolProperty(
@@ -712,7 +726,7 @@ def register():
         default=1.00,
     )
 
-    #################################OBJECT####################################
+    # -------------------------------------- OBJECT -------------------------------------- #
 
     # Importance sampling
     Obj.pov_importance_value = FloatProperty(
@@ -730,7 +744,7 @@ def register():
         default=True,
     )
 
-    ##################################CAMERA###################################
+    # -------------------------------------- CAMERA -------------------------------------- #
 
     # DOF Toggle
     Cam.pov_dof_enable = BoolProperty(
@@ -780,7 +794,7 @@ def register():
         default=0.90,
     )
 
-    ###################################TEXT####################################
+    # -------------------------------------- TEXT -------------------------------------- #
 
     Text.pov_custom_code = BoolProperty(
         name="Custom Code",