From 419f290890104e47081525dcd2eb87bfa244e319 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 11 May 2021 09:46:10 +1000 Subject: PyAPI: replace iteritems with items Even though the code is commented, update for changes to Blender 3.0 --- io_export_dxf/model/migiusModel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/io_export_dxf/model/migiusModel.py b/io_export_dxf/model/migiusModel.py index 40f9e42b..25813395 100644 --- a/io_export_dxf/model/migiusModel.py +++ b/io_export_dxf/model/migiusModel.py @@ -28,7 +28,7 @@ except Exception: # global dxfColors # if dxfColors is None: # from dxfColorMap import color_map -# dxfColors = [(tuple(color),idx) for idx, color in color_map.iteritems()] +# dxfColors = [(tuple(color),idx) for idx, color in color_map.items()] # dxfColors.sort() # entry = (tuple(rgbcolor), -1) # dxfColors.append(entry) -- cgit v1.2.3 From 448eeb681aa414257a75356d7e6c65e0672980d5 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 9 Jun 2021 03:12:45 +1000 Subject: Update for changes in the Python API using keyword only arguments --- add_curve_extra_objects/__init__.py | 7 ++----- archipack/archipack_gl.py | 2 +- archipack/archipack_material.py | 4 +--- archipack/archipack_preset.py | 8 +++----- archipack/archipack_rendering.py | 6 ++---- archipack/bmesh_utils.py | 2 +- blender_id/profiles.py | 2 +- io_export_paper_model.py | 4 ++-- materials_library_vx/__init__.py | 2 +- mesh_looptools.py | 3 +-- mesh_tiny_cad/CCEN.py | 2 +- mesh_tiny_cad/E2F.py | 2 +- mesh_tiny_cad/VTX.py | 2 +- mesh_tools/mesh_cut_faces.py | 2 +- mesh_tools/mesh_edge_roundifier.py | 2 +- mesh_tools/mesh_edges_floor_plan.py | 4 ++-- mesh_tools/mesh_edges_length.py | 2 +- mesh_tools/split_solidify.py | 2 +- object_print3d_utils/mesh_helpers.py | 2 +- precision_drawing_tools/pdt_etof.py | 2 +- render_povray/render_gui.py | 6 +++--- rigify/utils/mechanism.py | 4 ++-- space_view3d_pie_menus/pie_sculpt_menu.py | 2 +- ui_translate/edit_translation.py | 9 ++++++--- ui_translate/update_addon.py | 2 +- 25 files changed, 39 insertions(+), 46 deletions(-) diff --git a/add_curve_extra_objects/__init__.py b/add_curve_extra_objects/__init__.py index 7a1a3ba7..22910bf9 100644 --- a/add_curve_extra_objects/__init__.py +++ b/add_curve_extra_objects/__init__.py @@ -80,8 +80,7 @@ def convert_old_presets(data_path, msg_data_path, old_preset_subdir, import os target_path = os.path.join("presets", old_preset_subdir) - target_path = bpy.utils.user_resource('SCRIPTS', - target_path) + target_path = bpy.utils.user_resource('SCRIPTS', path=target_path) # created an anytype op to run against preset op = type('', (), {})() @@ -93,9 +92,7 @@ def convert_old_presets(data_path, msg_data_path, old_preset_subdir, return None new_target_path = os.path.join("presets", new_preset_subdir) - new_target_path = bpy.utils.user_resource('SCRIPTS', - new_target_path, - create=True) + new_target_path = bpy.utils.user_resource('SCRIPTS', path=new_target_path, create=True) for f in files: file = open(os.path.join(target_path, f)) for line in file: diff --git a/archipack/archipack_gl.py b/archipack/archipack_gl.py index f0bf8482..8f69bea8 100644 --- a/archipack/archipack_gl.py +++ b/archipack/archipack_gl.py @@ -259,7 +259,7 @@ class Gl(): return self.get_render_location(context, coord) region = context.region rv3d = context.region_data - loc = view3d_utils.location_3d_to_region_2d(region, rv3d, coord, self.pos_2d) + loc = view3d_utils.location_3d_to_region_2d(region, rv3d, coord, default=self.pos_2d) return Vector(loc) def get_render_location(self, context, coord): diff --git a/archipack/archipack_material.py b/archipack/archipack_material.py index 27aaefab..e363f304 100644 --- a/archipack/archipack_material.py +++ b/archipack/archipack_material.py @@ -231,9 +231,7 @@ class MaterialSetManager(): def get_filename(self, object_type): target_path = os.path.join("presets", "archipack_materials") - target_path = bpy.utils.user_resource('SCRIPTS', - target_path, - create=True) + target_path = bpy.utils.user_resource('SCRIPTS', path=target_path, create=True) return os.path.join(target_path, object_type) + '.txt' def cleanup(self): diff --git a/archipack/archipack_preset.py b/archipack/archipack_preset.py index ae230295..fe4b9307 100644 --- a/archipack/archipack_preset.py +++ b/archipack/archipack_preset.py @@ -34,8 +34,8 @@ from .archipack_gl import ( ThumbHandle, Screen, GlRect, GlPolyline, GlPolygon, GlText, GlHandle ) -preset_paths = bpy.utils.script_paths("presets") -addons_paths = bpy.utils.script_paths("addons") +preset_paths = bpy.utils.script_paths(subdir="presets") +addons_paths = bpy.utils.script_paths(subdir="addons") class CruxHandle(GlHandle): @@ -570,9 +570,7 @@ class ArchipackPreset(AddPresetBase): filename = self.as_filename(name) target_path = os.path.join("presets", self.preset_subdir) - target_path = bpy.utils.user_resource('SCRIPTS', - target_path, - create=True) + target_path = bpy.utils.user_resource('SCRIPTS', path=target_path, create=True) preset = os.path.join(target_path, filename) + ".py" cls = self.preset_subdir[10:] diff --git a/archipack/archipack_rendering.py b/archipack/archipack_rendering.py index 09650ec8..f8bb07f9 100644 --- a/archipack/archipack_rendering.py +++ b/archipack/archipack_rendering.py @@ -99,9 +99,7 @@ class ARCHIPACK_OT_render_thumbs(Operator): not f.startswith('.')]) target_path = path.join("presets", category) - presets_path = bpy.utils.user_resource('SCRIPTS', - target_path, - create=True) + presets_path = bpy.utils.user_resource('SCRIPTS', path=target_path, create=True) # files from factory not found in user doesn't require a recompute skipfiles = [] for f in file_list: @@ -130,7 +128,7 @@ class ARCHIPACK_OT_render_thumbs(Operator): skipfiles = self.copy_to_user_path(category) # load user def presets - preset_paths = bpy.utils.script_paths("presets") + preset_paths = bpy.utils.script_paths(subdir="presets") for preset in preset_paths: presets_path = path.join(preset, category) if path.exists(presets_path): diff --git a/archipack/bmesh_utils.py b/archipack/bmesh_utils.py index 3c196bec..16be7a54 100644 --- a/archipack/bmesh_utils.py +++ b/archipack/bmesh_utils.py @@ -98,7 +98,7 @@ class BmeshEdit(): private, end bmesh editing of active object """ bm.normal_update() - bmesh.update_edit_mesh(o.data, True) + bmesh.update_edit_mesh(o.data, loop_triangles=True) bpy.ops.object.mode_set(mode='OBJECT') bm.free() diff --git a/blender_id/profiles.py b/blender_id/profiles.py index 2e872a50..7a4b3495 100644 --- a/blender_id/profiles.py +++ b/blender_id/profiles.py @@ -94,7 +94,7 @@ class BlenderIdProfile(metaclass=_BIPMeta): def register(): global profiles_path, profiles_file - profiles_path = bpy.utils.user_resource('CONFIG', 'blender_id', create=True) + profiles_path = bpy.utils.user_resource('CONFIG', path='blender_id', create=True) profiles_file = os.path.join(profiles_path, 'profiles.json') diff --git a/io_export_paper_model.py b/io_export_paper_model.py index 5f8e70f5..8ea8cf9f 100644 --- a/io_export_paper_model.py +++ b/io_export_paper_model.py @@ -177,7 +177,7 @@ class UnfoldError(ValueError): elem.select = False for elem in chain(*elems.values()): elem.select_set(True) - bmesh.update_edit_mesh(bpy.context.object.data, False, False) + bmesh.update_edit_mesh(bpy.context.object.data, loop_triangles=False, destructive=False) class Unfolder: @@ -2269,7 +2269,7 @@ class SelectIsland(bpy.types.Operator): edge.select = any(face.select for face in edge.link_faces) for vert in verts: vert.select = any(edge.select for edge in vert.link_edges) - bmesh.update_edit_mesh(me, False, False) + bmesh.update_edit_mesh(me, loop_triangles=False, destructive=False) return {'FINISHED'} diff --git a/materials_library_vx/__init__.py b/materials_library_vx/__init__.py index e8bc808e..8df8e2b9 100644 --- a/materials_library_vx/__init__.py +++ b/materials_library_vx/__init__.py @@ -1072,7 +1072,7 @@ def list_materials(): return sorted(list) def get_material(name, link=False): - with bpy.data.libraries.load("{0}", link, False) as (data_from, data_to): + with bpy.data.libraries.load("{0}", link=link, relative=False) as (data_from, data_to): data_to.materials = [name] if link: print(name + " linked.") diff --git a/mesh_looptools.py b/mesh_looptools.py index d13c4213..a2147cb7 100644 --- a/mesh_looptools.py +++ b/mesh_looptools.py @@ -3433,8 +3433,7 @@ class Bridge(Operator): if self.remove_faces and old_selected_faces: bridge_remove_internal_faces(bm, old_selected_faces) # make sure normals are facing outside - bmesh.update_edit_mesh(object.data, loop_triangles=False, - destructive=True) + bmesh.update_edit_mesh(object.data, loop_triangles=False, destructive=True) bpy.ops.mesh.normals_make_consistent() # cleaning up diff --git a/mesh_tiny_cad/CCEN.py b/mesh_tiny_cad/CCEN.py index 24604e8f..f97ca84b 100644 --- a/mesh_tiny_cad/CCEN.py +++ b/mesh_tiny_cad/CCEN.py @@ -65,7 +65,7 @@ def generate_bmesh_repr(p1, v1, axis, num_verts): idx2 = (i + 1) % num_verts bm.edges.new([v_refs[idx1], v_refs[idx2]]) - bmesh.update_edit_mesh(me, True) + bmesh.update_edit_mesh(me, loop_triangles=True) def generate_3PT(pts, obj, nv, mode=1): diff --git a/mesh_tiny_cad/E2F.py b/mesh_tiny_cad/E2F.py index 70b51298..33ac79f3 100644 --- a/mesh_tiny_cad/E2F.py +++ b/mesh_tiny_cad/E2F.py @@ -79,7 +79,7 @@ def extend_vertex(self): vertex_reference = v1_ref if (A_len < B_len) else v2_ref bm.edges.new([vertex_reference, new_vertex]) - bmesh.update_edit_mesh(me, True) + bmesh.update_edit_mesh(me, loop_triangles=True) else: failure_message_on_plane(self) diff --git a/mesh_tiny_cad/VTX.py b/mesh_tiny_cad/VTX.py index f98e85cb..fbd0bc28 100644 --- a/mesh_tiny_cad/VTX.py +++ b/mesh_tiny_cad/VTX.py @@ -170,6 +170,6 @@ class TCAutoVTX(bpy.types.Operator): bm.verts.index_update() bm.edges.index_update() - bmesh.update_edit_mesh(me, True) + bmesh.update_edit_mesh(me, loop_triangles=True) return {'FINISHED'} diff --git a/mesh_tools/mesh_cut_faces.py b/mesh_tools/mesh_cut_faces.py index 23324f1c..99f7c8ac 100644 --- a/mesh_tools/mesh_cut_faces.py +++ b/mesh_tools/mesh_cut_faces.py @@ -23,7 +23,7 @@ def bmesh_release(bm, object): mesh = object.data bm.select_flush_mode() if object.mode == 'EDIT': - bmesh.update_edit_mesh(mesh, True) + bmesh.update_edit_mesh(mesh, loop_triangles=True) else: bm.to_mesh(mesh) bm.free() diff --git a/mesh_tools/mesh_edge_roundifier.py b/mesh_tools/mesh_edge_roundifier.py index 418d97fd..994d2b6f 100644 --- a/mesh_tools/mesh_edge_roundifier.py +++ b/mesh_tools/mesh_edge_roundifier.py @@ -1213,7 +1213,7 @@ class EdgeRoundifier(Operator): verticesForDeletion.append(vi) bmesh.ops.delete(bm, geom=verticesForDeletion, context = 'VERTS') - bmesh.update_edit_mesh(mesh, True) + bmesh.update_edit_mesh(mesh, loop_triangles=True) bpy.ops.object.mode_set(mode='OBJECT') bpy.ops.object.mode_set(mode='EDIT') diff --git a/mesh_tools/mesh_edges_floor_plan.py b/mesh_tools/mesh_edges_floor_plan.py index 6a303ffb..a654a4c3 100644 --- a/mesh_tools/mesh_edges_floor_plan.py +++ b/mesh_tools/mesh_edges_floor_plan.py @@ -283,7 +283,7 @@ class MESH_OT_edges_floor_plan(Operator): if edge.is_boundary: edge.select = True - bm = bmesh.update_edit_mesh(ob.data, 1, 1) + bm = bmesh.update_edit_mesh(ob.data, loop_triangles=True, destructive=True) bpy.ops.object.mode_set(mode='OBJECT') self.solidify_mod(context, ob, wid, offset, self.only_rim) @@ -366,7 +366,7 @@ class MESH_OT_edges_floor_plan(Operator): if edge.is_boundary: edge.select = True - bm = bmesh.update_edit_mesh(ob.data, 1, 1) + bm = bmesh.update_edit_mesh(ob.data, loop_triangles=True, destructive=True) context.tool_settings.mesh_select_mode = store_selection_mode diff --git a/mesh_tools/mesh_edges_length.py b/mesh_tools/mesh_edges_length.py index adaee650..ee9ae15b 100644 --- a/mesh_tools/mesh_edges_length.py +++ b/mesh_tools/mesh_edges_length.py @@ -310,7 +310,7 @@ class LengthSet(Operator): '\n edge.verts[1].co' + str(verts[1]) + '\n vector' + str(vector) + '\n v1 > v0:' + str((verts[1] >= verts[0])) ) - bmesh.update_edit_mesh(obj.data, True) + bmesh.update_edit_mesh(obj.data, loop_triangles=True) return {'FINISHED'} diff --git a/mesh_tools/split_solidify.py b/mesh_tools/split_solidify.py index 7158089e..1ac952bc 100644 --- a/mesh_tools/split_solidify.py +++ b/mesh_tools/split_solidify.py @@ -101,7 +101,7 @@ def solidify_split(self, list_0): k.select = False bpy.ops.mesh.normals_make_consistent(inside=False) - bmesh.update_edit_mesh(self.me, True) + bmesh.update_edit_mesh(self.me, loop_triangles=True) class MESH_OT_split_solidify(Operator): diff --git a/object_print3d_utils/mesh_helpers.py b/object_print3d_utils/mesh_helpers.py index cffdf7c5..948a3bc7 100644 --- a/object_print3d_utils/mesh_helpers.py +++ b/object_print3d_utils/mesh_helpers.py @@ -76,7 +76,7 @@ def bmesh_to_object(obj, bm): me = obj.data if obj.mode == 'EDIT': - bmesh.update_edit_mesh(me, True) + bmesh.update_edit_mesh(me, loop_triangles=True) else: bm.to_mesh(me) me.update() diff --git a/precision_drawing_tools/pdt_etof.py b/precision_drawing_tools/pdt_etof.py index edb8ebc5..892bd6b2 100644 --- a/precision_drawing_tools/pdt_etof.py +++ b/precision_drawing_tools/pdt_etof.py @@ -115,7 +115,7 @@ def extend_vertex(context): vertex_reference = v1_ref if (a_len < b_len) else v2_ref bm.edges.new([vertex_reference, new_vertex]) - bmesh.update_edit_mesh(object_data, True) + bmesh.update_edit_mesh(object_data, loop_triangles=True) else: failure_message_on_plane(context) diff --git a/render_povray/render_gui.py b/render_povray/render_gui.py index 018821cb..5b659725 100755 --- a/render_povray/render_gui.py +++ b/render_povray/render_gui.py @@ -421,13 +421,13 @@ def rad_panel_func(self, context): # addon_utils.paths()[0] # addon_utils.modules() # mod.bl_info['name'] == 'Freestyle SVG Exporter': -bpy.utils.script_paths("addons") -# render_freestyle_svg = os.path.join(bpy.utils.script_paths("addons"), "render_freestyle_svg.py") +bpy.utils.script_paths(subdir="addons") +# render_freestyle_svg = os.path.join(bpy.utils.script_paths(subdir="addons"), "render_freestyle_svg.py") render_freestyle_svg = bpy.context.preferences.addons.get('render_freestyle_svg') # mpath=addon_utils.paths()[0].render_freestyle_svg # import mpath -# from mpath import render_freestyle_svg #= addon_utils.modules(['Freestyle SVG Exporter']) +# from mpath import render_freestyle_svg #= addon_utils.modules(module_cache=['Freestyle SVG Exporter']) # from scripts\\addons import render_freestyle_svg if check_render_freestyle_svg(): ''' diff --git a/rigify/utils/mechanism.py b/rigify/utils/mechanism.py index 6335514b..bc4e06ea 100644 --- a/rigify/utils/mechanism.py +++ b/rigify/utils/mechanism.py @@ -401,7 +401,7 @@ def deactivate_custom_properties(obj, *, reset=True): for key, value in obj.items(): valtype = type(value) if valtype in {int, float}: - info = rna_idprop_ui_prop_get(obj, key, False) or {} + info = rna_idprop_ui_prop_get(obj, key, create=False) or {} obj[key] = valtype(info.get("default", 0)) @@ -435,7 +435,7 @@ def copy_custom_properties(src, dest, *, prefix='', dest_prefix='', link_driver= dest[new_key] = value if info: - info2 = rna_idprop_ui_prop_get(dest, new_key, True) + info2 = rna_idprop_ui_prop_get(dest, new_key, create=True) for ki, vi in info.items(): info2[ki] = vi diff --git a/space_view3d_pie_menus/pie_sculpt_menu.py b/space_view3d_pie_menus/pie_sculpt_menu.py index e50a47fa..9d343dc1 100644 --- a/space_view3d_pie_menus/pie_sculpt_menu.py +++ b/space_view3d_pie_menus/pie_sculpt_menu.py @@ -136,7 +136,7 @@ brush_icons = {} def create_icons(): global brush_icons - icons_directory = bpy.utils.system_resource('DATAFILES', "icons") + icons_directory = bpy.utils.system_resource('DATAFILES', path="icons") brushes = ["crease", "blob", "smooth", "draw", "clay", "clay_strips", "inflate", "grab", "nudge", "thumb", "snake_hook", "rotate", "flatten", "scrape", "fill", "pinch", "layer", "mask"] diff --git a/ui_translate/edit_translation.py b/ui_translate/edit_translation.py index 1aeee13a..b42560d4 100644 --- a/ui_translate/edit_translation.py +++ b/ui_translate/edit_translation.py @@ -73,14 +73,17 @@ class UI_OT_i18n_edittranslation_update_mo(Operator): def execute(self, context): if self.clean_mo: - root = bpy.utils.user_resource('DATAFILES', settings.settings.MO_PATH_ROOT_RELATIVE) + root = bpy.utils.user_resource('DATAFILES', path=settings.settings.MO_PATH_ROOT_RELATIVE) if root: shutil.rmtree(root) elif not (self.lang and self.po_file): return {'CANCELLED'} else: - mo_dir = bpy.utils.user_resource('DATAFILES', settings.settings.MO_PATH_TEMPLATE_RELATIVE.format(self.lang), - create=True) + mo_dir = bpy.utils.user_resource( + 'DATAFILES', + path=settings.settings.MO_PATH_TEMPLATE_RELATIVE.format(self.lang), + create=True, + ) mo_file = os.path.join(mo_dir, settings.settings.MO_FILE_NAME) _get_messages(self.lang, self.po_file).write(kind='MO', dest=mo_file) diff --git a/ui_translate/update_addon.py b/ui_translate/update_addon.py index 38b0ac8a..2eedc897 100644 --- a/ui_translate/update_addon.py +++ b/ui_translate/update_addon.py @@ -71,7 +71,7 @@ def enum_addons(self, context): global _cached_enum_addons setts = getattr(self, "settings", settings.settings) if not _cached_enum_addons: - for mod in addon_utils.modules(addon_utils.addons_fake_modules): + for mod in addon_utils.modules(module_cache=addon_utils.addons_fake_modules): mod_info = addon_utils.module_bl_info(mod) # Skip OFFICIAL addons, they are already translated in main i18n system (together with Blender itself). if mod_info["support"] in {'OFFICIAL'}: -- cgit v1.2.3 From 3a409083e7dbc8e5fef5a68f6ac5be275acc5ca8 Mon Sep 17 00:00:00 2001 From: Ethan Simon Date: Tue, 8 Jun 2021 18:00:37 -0400 Subject: Add Curve Extra Objects: Fix invalid context traceback error This patch simply adds a preliminary check for the built-in Add Curve Extra Objects add-on. The check basically prevents a traceback in the console. Without this patch the add-on still functions as intended, just with a console prompt. Reviewed By: Blendify Differential Revision: https://developer.blender.org/D9666 --- add_curve_extra_objects/beveltaper_curve.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/add_curve_extra_objects/beveltaper_curve.py b/add_curve_extra_objects/beveltaper_curve.py index 27795ed1..5b71cf00 100644 --- a/add_curve_extra_objects/beveltaper_curve.py +++ b/add_curve_extra_objects/beveltaper_curve.py @@ -424,10 +424,11 @@ def menu_funcs(self, context): layout = self.layout - if bpy.context.view_layer.objects.active.type == "CURVE": - layout.operator("curve.bevelcurve") - layout.operator("curve.tapercurve") - layout.separator() + if context.view_layer.objects.active: + if context.view_layer.objects.active.type == "CURVE": + layout.operator("curve.bevelcurve") + layout.operator("curve.tapercurve") + layout.separator() # Register classes = [ -- cgit v1.2.3 From f86f25e62217264495d05f116ccb09d575fe9841 Mon Sep 17 00:00:00 2001 From: Maurice Raybaud Date: Wed, 9 Jun 2021 03:13:10 +0200 Subject: POV: Code formatting and bugfixes * fix: more imports cleanup and formatting * add: hair shape (from old MaterialStrand for now) * add: pixel / Non Blender units strand width * fix: an exception handling of df3_library * fix: gas flow_type typo --- render_povray/__init__.py | 43 +++--- render_povray/base_ui.py | 27 ++-- render_povray/df3_library.py | 60 ++++---- render_povray/object_curve_topology.py | 19 +-- render_povray/object_gui.py | 53 ++++--- render_povray/object_mesh_topology.py | 244 +++++++++++++++----------------- render_povray/object_particles.py | 84 ++++++++--- render_povray/object_primitives.py | 32 ++--- render_povray/object_properties.py | 58 ++++---- render_povray/render.py | 133 ++++++++--------- render_povray/render_gui.py | 79 +++++------ render_povray/render_properties.py | 12 +- render_povray/scenography.py | 75 +++++----- render_povray/scenography_gui.py | 36 ++--- render_povray/scenography_properties.py | 33 ++--- render_povray/scripting.py | 98 +++++++------ render_povray/scripting_gui.py | 20 +-- render_povray/scripting_properties.py | 10 +- render_povray/shading.py | 60 ++++---- render_povray/shading_gui.py | 102 ++++++------- render_povray/shading_nodes.py | 29 ++-- render_povray/shading_properties.py | 11 +- render_povray/texturing.py | 68 ++++----- render_povray/texturing_gui.py | 50 ++++--- render_povray/texturing_properties.py | 34 +++-- render_povray/update_files.py | 204 +++++++++++++------------- 26 files changed, 850 insertions(+), 824 deletions(-) diff --git a/render_povray/__init__.py b/render_povray/__init__.py index f0734c5f..2bc4f420 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 85374ba3..967080fa 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 f802fb2d..b5525741 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 5fa2b277..876952e2 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 9fbf8a8b..aebaa311 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 2b0ce008..1599d6d1 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 2d4f0dcc..4949af21 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 4556f2df..abbba148 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 8cea49af..f599da9b 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 45a94912..76bdf7c4 100755 --- a/render_povray/render.py +++ b/render_povray/render.py @@ -17,7 +17,9 @@ # #**** END GPL LICENSE BLOCK #**** # + """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 5b659725..8e584079 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 9096c986..0fbb60da 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 4b0c99e3..6f892b3e 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 6eb5aed9..e66931b2 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 dd886513..bdad0890 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 02ca6444..caa79b8c 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 99006af1..0dcdc4f1 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 3e743da3..d4529c18 100755 --- a/render_povray/scripting_properties.py +++ b/render_povray/scripting_properties.py @@ -17,17 +17,17 @@ # ##### END GPL LICENSE BLOCK ##### # -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 680be99c..985afd34 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 428542c8..5e563097 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 2e8484f9..eb7c2bd2 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 18895eba..3a3c944d 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 e070dbe9..225c5369 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 ad889f43..8d285383 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 bb89ee02..ceb60264 100755 --- a/render_povray/texturing_properties.py +++ b/render_povray/texturing_properties.py @@ -17,6 +17,7 @@ # ##### END GPL LICENSE BLOCK ##### # + """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 985f8468..f9696f8f 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", -- cgit v1.2.3