diff options
205 files changed, 6393 insertions, 7100 deletions
@@ -15,3 +15,6 @@ __pycache__/ Thumbs.db ehthumbs.db Desktop.ini + +# external addons +cycles/ diff --git a/add_advanced_objects_menu/__init__.py b/add_advanced_objects_menu/__init__.py index 42a33445..32bbbd7f 100644 --- a/add_advanced_objects_menu/__init__.py +++ b/add_advanced_objects_menu/__init__.py @@ -92,8 +92,8 @@ from bpy.props import ( # Define the "Scenes" menu -class INFO_MT_scene_elements_add(Menu): - bl_idname = "INFO_MT_scene_elements" +class VIEW3D_MT_scene_elements_add(Menu): + bl_idname = "VIEW3D_MT_scene_elements" bl_label = "Test Scenes" def draw(self, context): @@ -108,8 +108,8 @@ class INFO_MT_scene_elements_add(Menu): # Define the "Lights" menu -class INFO_MT_mesh_lamps_add(Menu): - bl_idname = "INFO_MT_scene_lamps" +class VIEW3D_MT_mesh_lights_add(Menu): + bl_idname = "VIEW3D_MT_scene_lights" bl_label = "Lighting Sets" def draw(self, context): @@ -122,8 +122,8 @@ class INFO_MT_mesh_lamps_add(Menu): # Define the "Chains" menu -class INFO_MT_mesh_chain_add(Menu): - bl_idname = "INFO_MT_mesh_chain" +class VIEW3D_MT_mesh_chain_add(Menu): + bl_idname = "VIEW3D_MT_mesh_chain" bl_label = "Chains" def draw(self, context): @@ -134,15 +134,15 @@ class INFO_MT_mesh_chain_add(Menu): # Define the "Array" Menu -class INFO_MT_array_mods_add(Menu): - bl_idname = "INFO_MT_array_mods" +class VIEW3D_MT_array_mods_add(Menu): + bl_idname = "VIEW3D_MT_array_mods" bl_label = "Array Mods" def draw(self, context): layout = self.layout layout.operator_context = 'INVOKE_REGION_WIN' - layout.menu("INFO_MT_mesh_chain", icon="LINKED") + layout.menu("VIEW3D_MT_mesh_chain", icon="LINKED") layout.operator("objects.circle_array_operator", text="Circle Array", icon="MOD_ARRAY") @@ -153,8 +153,8 @@ class INFO_MT_array_mods_add(Menu): # Define the "Blocks" Menu -class INFO_MT_quick_blocks_add(Menu): - bl_idname = "INFO_MT_quick_tools" +class VIEW3D_MT_quick_blocks_add(Menu): + bl_idname = "VIEW3D_MT_quick_tools" bl_label = "Block Tools" def draw(self, context): @@ -171,8 +171,8 @@ class INFO_MT_quick_blocks_add(Menu): # Define the "Phsysics Tools" Menu -class INFO_MT_Physics_tools_add(Menu): - bl_idname = "INFO_MT_physics_tools" +class VIEW3D_MT_Physics_tools_add(Menu): + bl_idname = "VIEW3D_MT_physics_tools" bl_label = "Physics Tools" def draw(self, context): @@ -190,12 +190,12 @@ def menu(self, context): layout = self.layout layout.operator_context = 'INVOKE_REGION_WIN' self.layout.separator() - self.layout.menu("INFO_MT_scene_elements", icon="SCENE_DATA") - self.layout.menu("INFO_MT_scene_lamps", icon="LAMP_SPOT") + self.layout.menu("VIEW3D_MT_scene_elements", icon="SCENE_DATA") + self.layout.menu("VIEW3D_MT_scene_lights", icon="LIGHT_SPOT") self.layout.separator() - self.layout.menu("INFO_MT_array_mods", icon="MOD_ARRAY") - self.layout.menu("INFO_MT_quick_tools", icon="MOD_BUILD") - self.layout.menu("INFO_MT_physics_tools", icon="PHYSICS") + self.layout.menu("VIEW3D_MT_array_mods", icon="MOD_ARRAY") + self.layout.menu("VIEW3D_MT_quick_tools", icon="MOD_BUILD") + self.layout.menu("VIEW3D_MT_physics_tools", icon="PHYSICS") # Addons Preferences @@ -524,7 +524,7 @@ def register(): ) # Add "Extras" menu to the "Add" menu - bpy.types.INFO_MT_add.append(menu) + bpy.types.VIEW3D_MT_add.append(menu) try: bpy.types.VIEW3D_MT_AddMenu.append(menu) except: @@ -533,7 +533,7 @@ def register(): def unregister(): # Remove "Extras" menu from the "Add" menu. - bpy.types.INFO_MT_add.remove(menu) + bpy.types.VIEW3D_MT_add.remove(menu) try: bpy.types.VIEW3D_MT_AddMenu.remove(menu) except: diff --git a/add_advanced_objects_menu/add_light_template.py b/add_advanced_objects_menu/add_light_template.py index 9e2c139f..5b4fbc86 100644 --- a/add_advanced_objects_menu/add_light_template.py +++ b/add_advanced_objects_menu/add_light_template.py @@ -5,10 +5,10 @@ from bpy.types import Operator from bpy.props import BoolProperty -def add_lamps(self, context): +def add_lights(self, context): if self.bKeyLight: - keyLight = bpy.data.lamps.new(name="Key_Light", type="SPOT") + keyLight = bpy.data.lights.new(name="Key_Light", type="SPOT") ob = bpy.data.objects.new("Key_Light", keyLight) constraint = ob.constraints.new(type='COPY_LOCATION') constraint.use_offset = True @@ -23,7 +23,7 @@ def add_lamps(self, context): ob.rotation_euler[2] = -0.785398 if self.bFillLight: - fillLight = bpy.data.lamps.new(name="Fill_Light", type="SPOT") + fillLight = bpy.data.lights.new(name="Fill_Light", type="SPOT") ob = bpy.data.objects.new("Fill_Light", fillLight) constraint = ob.constraints.new(type='COPY_LOCATION') constraint.use_offset = True @@ -39,7 +39,7 @@ def add_lamps(self, context): ob.data.energy = 0.3 if self.bBackLight: - backLight = bpy.data.lamps.new(name="Back_Light", type="SPOT") + backLight = bpy.data.lights.new(name="Back_Light", type="SPOT") ob = bpy.data.objects.new("Back_Light", backLight) constraint = ob.constraints.new(type='COPY_LOCATION') constraint.use_offset = True @@ -121,7 +121,7 @@ class OBJECT_OT_add_light_template(Operator): self.target = context.active_object self.camera = context.scene.camera - add_lamps(self, context) + add_lights(self, context) except Exception as e: self.report({'WARNING'}, diff --git a/add_advanced_objects_menu/copy2.py b/add_advanced_objects_menu/copy2.py index 489f6dee..9a94ac1d 100644 --- a/add_advanced_objects_menu/copy2.py +++ b/add_advanced_objects_menu/copy2.py @@ -168,7 +168,7 @@ def copy_to_from(scene, to_obj, from_obj, copymode, axes, edgescale, scale): if copymode == 'E': # don't pass edgescalling to object types that cannot be scaled - if from_obj.type in ["CAMERA", "LAMP", "EMPTY", "ARMATURE", "SPEAKER", "META"]: + if from_obj.type in ["CAMERA", "LIGHT", "EMPTY", "ARMATURE", "SPEAKER", "META"]: edgescale = False edge_copy(scene, to_obj, from_obj, axes, edgescale, scale) diff --git a/add_advanced_objects_menu/mesh_easylattice.py b/add_advanced_objects_menu/mesh_easylattice.py index cdb165bd..3eb483e2 100644 --- a/add_advanced_objects_menu/mesh_easylattice.py +++ b/add_advanced_objects_menu/mesh_easylattice.py @@ -63,7 +63,7 @@ def createLattice(context, obj, props): # the rotation comes from the combined obj world # matrix which was converted to euler pairs ob.rotation_euler = buildRot_World(obj) - ob.show_x_ray = True + ob.show_in_front = True # Link object to scene scn = context.scene diff --git a/add_advanced_objects_menu/rope_alpha.py b/add_advanced_objects_menu/rope_alpha.py index 2815c7c6..f0bd5dd7 100644 --- a/add_advanced_objects_menu/rope_alpha.py +++ b/add_advanced_objects_menu/rope_alpha.py @@ -622,7 +622,7 @@ class BallRope(Operator): bpy.ops.rigidbody.objects_add(type='ACTIVE') bpy.context.object.name = "CubeLink" if n != 0: - bpy.context.object.draw_type = 'WIRE' + bpy.context.object.display_type = 'WIRE' bpy.context.object.hide_render = True n += 1 bpy.context.object.scale.z = (longitud * 2) / (segmentos * 2) - separation diff --git a/add_advanced_objects_menu/scene_objects_bi.py b/add_advanced_objects_menu/scene_objects_bi.py index f189bb11..94bda4bc 100644 --- a/add_advanced_objects_menu/scene_objects_bi.py +++ b/add_advanced_objects_menu/scene_objects_bi.py @@ -43,11 +43,11 @@ class add_BI_scene(Operator): ) cam = bpy.context.active_object.data cam.lens = 35 - cam.draw_size = 0.1 + cam.display_size = 0.1 bpy.ops.view3d.viewnumpad(type='CAMERA') # add point lamp - bpy.ops.object.lamp_add( + bpy.ops.object.light_add( type="POINT", location=(4.07625, 1.00545, 5.90386), rotation=(0.650328, 0.055217, 1.866391) ) @@ -59,7 +59,7 @@ class add_BI_scene(Operator): lamp1.use_sphere = True # add point lamp2 - bpy.ops.object.lamp_add( + bpy.ops.object.light_add( type="POINT", location=(-0.57101, -4.24586, 5.53674), rotation=(1.571, 0, 0.785) ) diff --git a/add_advanced_objects_menu/scene_objects_cycles.py b/add_advanced_objects_menu/scene_objects_cycles.py index 85e85867..7158b02f 100644 --- a/add_advanced_objects_menu/scene_objects_cycles.py +++ b/add_advanced_objects_menu/scene_objects_cycles.py @@ -43,11 +43,11 @@ class add_cycles_scene(Operator): ) cam = bpy.context.active_object.data cam.lens = 35 - cam.draw_size = 0.1 + cam.display_size = 0.1 bpy.ops.view3d.viewnumpad(type='CAMERA') # add point lamp - bpy.ops.object.lamp_add( + bpy.ops.object.light_add( type="POINT", location=(4.07625, 1.00545, 5.90386), rotation=(0.650328, 0.055217, 1.866391) ) @@ -59,7 +59,7 @@ class add_cycles_scene(Operator): lamp1.use_sphere = True # add point lamp2 - bpy.ops.object.lamp_add( + bpy.ops.object.light_add( type="POINT", location=(-0.57101, -4.24586, 5.53674), rotation=(1.571, 0, 0.785) ) diff --git a/add_advanced_objects_menu/scene_texture_render.py b/add_advanced_objects_menu/scene_texture_render.py index 02d6490b..0f9ccc2b 100644 --- a/add_advanced_objects_menu/scene_texture_render.py +++ b/add_advanced_objects_menu/scene_texture_render.py @@ -43,7 +43,7 @@ class add_texture_scene(Operator): ) cam = bpy.context.active_object.data cam.lens = 35 - cam.draw_size = 0.1 + cam.display_size = 0.1 # add plane bpy.ops.mesh.primitive_plane_add(enter_editmode=True, location=(0, 0, 0)) diff --git a/add_advanced_objects_menu/trilighting.py b/add_advanced_objects_menu/trilighting.py index e0068e66..c163a894 100644 --- a/add_advanced_objects_menu/trilighting.py +++ b/add_advanced_objects_menu/trilighting.py @@ -173,7 +173,7 @@ class TriLighting(Operator): backx = obj_position.x + self.distance * singleback_vector.x backy = obj_position.y + self.distance * singleback_vector.y - backData = bpy.data.lamps.new(name="TriLamp-Back", type=self.secondarytype) + backData = bpy.data.lights.new(name="TriLamp-Back", type=self.secondarytype) backData.energy = backEnergy backLamp = bpy.data.objects.new(name="TriLamp-Back", object_data=backData) @@ -196,7 +196,7 @@ class TriLighting(Operator): rightx = obj_position.x + self.distance * singleright_vector.x righty = obj_position.y + self.distance * singleright_vector.y - rightData = bpy.data.lamps.new(name="TriLamp-Fill", type=self.secondarytype) + rightData = bpy.data.lights.new(name="TriLamp-Fill", type=self.secondarytype) rightData.energy = fillEnergy rightLamp = bpy.data.objects.new(name="TriLamp-Fill", object_data=rightData) scene.objects.link(rightLamp) @@ -215,7 +215,7 @@ class TriLighting(Operator): leftx = obj_position.x + self.distance * singleleft_vector.x lefty = obj_position.y + self.distance * singleleft_vector.y - leftData = bpy.data.lamps.new(name="TriLamp-Key", type=self.primarytype) + leftData = bpy.data.lights.new(name="TriLamp-Key", type=self.primarytype) leftData.energy = keyEnergy leftLamp = bpy.data.objects.new(name="TriLamp-Key", object_data=leftData) diff --git a/add_advanced_objects_panels/object_laplace_lightning.py b/add_advanced_objects_panels/object_laplace_lightning.py index fa50afd3..15e6730f 100644 --- a/add_advanced_objects_panels/object_laplace_lightning.py +++ b/add_advanced_objects_panels/object_laplace_lightning.py @@ -1087,7 +1087,7 @@ def setupObjects(): bpy.context.scene.objects.link(oOB) gOB = bpy.data.objects.new('ELground', None) - gOB.empty_draw_type = 'ARROWS' + gOB.empty_display_type = 'ARROWS' bpy.context.scene.objects.link(gOB) cME = makeMeshCube(1) diff --git a/add_advanced_objects_panels/unfold_transition.py b/add_advanced_objects_panels/unfold_transition.py index 42d8c3ba..44051bf0 100644 --- a/add_advanced_objects_panels/unfold_transition.py +++ b/add_advanced_objects_panels/unfold_transition.py @@ -129,8 +129,8 @@ class Set_Up_Fold(Operator): scn.objects.link(rig) scn.objects.active = rig bpy.ops.object.mode_set(mode="EDIT") - arm.draw_type = "WIRE" - rig.show_x_ray = True + arm.display_type = "WIRE" + rig.show_in_front = True mod = obj.modifiers.new("UnFold", "ARMATURE") mod.show_in_editmode = True mod.object = rig diff --git a/add_curve_extra_objects/__init__.py b/add_curve_extra_objects/__init__.py index 42ae2d44..5c093af4 100644 --- a/add_curve_extra_objects/__init__.py +++ b/add_curve_extra_objects/__init__.py @@ -225,9 +225,9 @@ class CurveExtraObjectsAddonPreferences(AddonPreferences): icon="LAYER_USED") -class INFO_MT_curve_knots_add(Menu): +class VIEW3D_MT_curve_knots_add(Menu): # Define the "Extras" menu - bl_idname = "INFO_MT_curve_knots_add" + bl_idname = "VIEW3D_MT_curve_knots_add" bl_label = "Plants" def draw(self, context): @@ -253,7 +253,7 @@ def menu_func(self, context): icon='CURVE_DATA') layout.separator() - layout.menu(INFO_MT_curve_knots_add.bl_idname, text="Knots", icon='CURVE_DATA') + layout.menu(VIEW3D_MT_curve_knots_add.bl_idname, text="Knots", icon='CURVE_DATA') layout.separator() layout.operator("curve.curlycurve", text="Curly Curve", icon='CURVE_DATA') @@ -282,17 +282,17 @@ def register(): bpy.utils.register_module(__name__) # Add "Extras" menu to the "Add Curve" menu - bpy.types.INFO_MT_curve_add.append(menu_func) + bpy.types.VIEW3D_MT_curve_add.append(menu_func) # Add "Extras" menu to the "Add Surface" menu - bpy.types.INFO_MT_surface_add.append(menu_surface) + bpy.types.VIEW3D_MT_surface_add.append(menu_surface) def unregister(): add_curve_simple.unregister() # Remove "Extras" menu from the "Add Curve" menu. - bpy.types.INFO_MT_curve_add.remove(menu_func) + bpy.types.VIEW3D_MT_curve_add.remove(menu_func) # Remove "Extras" menu from the "Add Surface" menu. - bpy.types.INFO_MT_surface_add.remove(menu_surface) + bpy.types.VIEW3D_MT_surface_add.remove(menu_surface) bpy.utils.unregister_module(__name__) diff --git a/add_curve_extra_objects/add_curve_curly.py b/add_curve_extra_objects/add_curve_curly.py index 779689a9..d3950787 100644 --- a/add_curve_extra_objects/add_curve_curly.py +++ b/add_curve_extra_objects/add_curve_curly.py @@ -479,12 +479,12 @@ def add_curlycurve_button(self, context): def register(): bpy.utils.register_class(add_curlycurve) - bpy.types.INFO_MT_curve_add.append(add_curlycurve_button) + bpy.types.VIEW3D_MT_curve_add.append(add_curlycurve_button) def unregister(): bpy.utils.unregister_class(add_curlycurve) - bpy.types.INFO_MT_curve_add.remove(add_curlycurve_button) + bpy.types.VIEW3D_MT_curve_add.remove(add_curlycurve_button) if __name__ == "__main__": diff --git a/add_curve_extra_objects/add_curve_simple.py b/add_curve_extra_objects/add_curve_simple.py index d8ff9ad7..a1ed873e 100644 --- a/add_curve_extra_objects/add_curve_simple.py +++ b/add_curve_extra_objects/add_curve_simple.py @@ -1645,8 +1645,8 @@ class SimpleVariables(PropertyGroup): ) -class INFO_MT_simple_menu(Menu): - bl_idname = "INFO_MT_simple_menu" +class VIEW3D_MT_simple_menu(Menu): + bl_idname = "VIEW3D_MT_simple_menu" bl_label = "2D Objects" def draw(self, context): @@ -1714,7 +1714,7 @@ class INFO_MT_simple_menu(Menu): def Simple_button(self, context): layout = self.layout layout.separator() - self.layout.menu("INFO_MT_simple_menu", icon="MOD_CURVE") + self.layout.menu("VIEW3D_MT_simple_menu", icon="MOD_CURVE") def register(): @@ -1723,10 +1723,10 @@ def register(): bpy.utils.register_class(BezierDivide) bpy.utils.register_class(SimplePanel) bpy.utils.register_class(SimpleEdit) - bpy.utils.register_class(INFO_MT_simple_menu) + bpy.utils.register_class(VIEW3D_MT_simple_menu) bpy.utils.register_class(SimpleVariables) - bpy.types.INFO_MT_curve_add.append(Simple_button) + bpy.types.VIEW3D_MT_curve_add.append(Simple_button) bpy.types.Object.s_curve = PointerProperty(type=SimpleVariables) @@ -1737,10 +1737,10 @@ def unregister(): bpy.utils.unregister_class(BezierDivide) bpy.utils.unregister_class(SimplePanel) bpy.utils.unregister_class(SimpleEdit) - bpy.utils.unregister_class(INFO_MT_simple_menu) + bpy.utils.unregister_class(VIEW3D_MT_simple_menu) bpy.utils.unregister_class(SimpleVariables) - bpy.types.INFO_MT_curve_add.remove(Simple_button) + bpy.types.VIEW3D_MT_curve_add.remove(Simple_button) del bpy.types.Object.s_curve diff --git a/add_curve_extra_objects/add_curve_spirofit_bouncespline.py b/add_curve_extra_objects/add_curve_spirofit_bouncespline.py index 382b2d6b..e80c6ee1 100644 --- a/add_curve_extra_objects/add_curve_spirofit_bouncespline.py +++ b/add_curve_extra_objects/add_curve_spirofit_bouncespline.py @@ -933,7 +933,7 @@ def add_curve_object( bpy.context.scene.objects.active = cur cur.select = True if x_ray is True: - cur.show_x_ray = x_ray + cur.show_in_front = x_ray return diff --git a/add_curve_sapling/__init__.py b/add_curve_sapling/__init__.py index f49823b5..a63e55c1 100644 --- a/add_curve_sapling/__init__.py +++ b/add_curve_sapling/__init__.py @@ -1126,13 +1126,13 @@ def menu_func(self, context): def register(): bpy.utils.register_module(__name__) - bpy.types.INFO_MT_curve_add.append(menu_func) + bpy.types.VIEW3D_MT_curve_add.append(menu_func) def unregister(): bpy.utils.unregister_module(__name__) - bpy.types.INFO_MT_curve_add.remove(menu_func) + bpy.types.VIEW3D_MT_curve_add.remove(menu_func) if __name__ == "__main__": diff --git a/add_curve_sapling/utils.py b/add_curve_sapling/utils.py index 87ae57fe..7f6a45b7 100644 --- a/add_curve_sapling/utils.py +++ b/add_curve_sapling/utils.py @@ -735,13 +735,13 @@ def create_armature(armAnim, leafP, cu, frameRate, leafMesh, leafObj, leafVertSi newAction = bpy.data.actions.new(name='windAction') armOb.animation_data_create() armOb.animation_data.action = newAction - arm.draw_type = 'STICK' + arm.display_type = 'STICK' arm.use_deform_delay = True # Add the armature modifier to the curve armMod = treeOb.modifiers.new('windSway', 'ARMATURE') if previewArm: armMod.show_viewport = False - arm.draw_type = 'WIRE' + arm.display_type = 'WIRE' treeOb.hide = True armMod.use_apply_on_spline = True armMod.object = armOb @@ -1996,7 +1996,7 @@ def addTree(props): armMod = treeObj.modifiers.new('windSway', 'ARMATURE') if previewArm: bpy.data.objects['treeArm'].hide = True - bpy.data.armatures['tree'].draw_type = 'STICK' + bpy.data.armatures['tree'].display_type = 'STICK' armMod.object = bpy.data.objects['treeArm'] armMod.use_bone_envelopes = False armMod.use_vertex_groups = True diff --git a/add_mesh_BoltFactory/__init__.py b/add_mesh_BoltFactory/__init__.py index 46d250de..d441a0e8 100644 --- a/add_mesh_BoltFactory/__init__.py +++ b/add_mesh_BoltFactory/__init__.py @@ -49,14 +49,14 @@ def add_mesh_bolt_button(self, context): def register(): bpy.utils.register_module(__name__) - bpy.types.INFO_MT_mesh_add.append(add_mesh_bolt_button) + bpy.types.VIEW3D_MT_mesh_add.append(add_mesh_bolt_button) # bpy.types.VIEW3D_PT_tools_objectmode.prepend(add_mesh_bolt_button) # just for testing def unregister(): bpy.utils.unregister_module(__name__) - bpy.types.INFO_MT_mesh_add.remove(add_mesh_bolt_button) + bpy.types.VIEW3D_MT_mesh_add.remove(add_mesh_bolt_button) # bpy.types.VIEW3D_PT_tools_objectmode.remove(add_mesh_bolt_button) # just for testing diff --git a/add_mesh_extra_objects/__init__.py b/add_mesh_extra_objects/__init__.py index ecc023df..1197738c 100644 --- a/add_mesh_extra_objects/__init__.py +++ b/add_mesh_extra_objects/__init__.py @@ -107,9 +107,9 @@ from bpy.props import ( ) -class INFO_MT_mesh_vert_add(Menu): +class VIEW3D_MT_mesh_vert_add(Menu): # Define the "Single Vert" menu - bl_idname = "INFO_MT_mesh_vert_add" + bl_idname = "VIEW3D_MT_mesh_vert_add" bl_label = "Single Vert" def draw(self, context): @@ -126,9 +126,9 @@ class INFO_MT_mesh_vert_add(Menu): text="Object Origin Mirrored") -class INFO_MT_mesh_gears_add(Menu): +class VIEW3D_MT_mesh_gears_add(Menu): # Define the "Gears" menu - bl_idname = "INFO_MT_mesh_gears_add" + bl_idname = "VIEW3D_MT_mesh_gears_add" bl_label = "Gears" def draw(self, context): @@ -140,9 +140,9 @@ class INFO_MT_mesh_gears_add(Menu): text="Worm") -class INFO_MT_mesh_diamonds_add(Menu): +class VIEW3D_MT_mesh_diamonds_add(Menu): # Define the "Diamonds" menu - bl_idname = "INFO_MT_mesh_diamonds_add" + bl_idname = "VIEW3D_MT_mesh_diamonds_add" bl_label = "Diamonds" def draw(self, context): @@ -156,9 +156,9 @@ class INFO_MT_mesh_diamonds_add(Menu): text="Gem") -class INFO_MT_mesh_math_add(Menu): +class VIEW3D_MT_mesh_math_add(Menu): # Define the "Math Function" menu - bl_idname = "INFO_MT_mesh_math_add" + bl_idname = "VIEW3D_MT_mesh_math_add" bl_label = "Math Functions" def draw(self, context): @@ -172,29 +172,29 @@ class INFO_MT_mesh_math_add(Menu): self.layout.operator("mesh.make_triangle", icon="MESH_DATA") -class INFO_MT_mesh_mech(Menu): +class VIEW3D_MT_mesh_mech(Menu): # Define the "Math Function" menu - bl_idname = "INFO_MT_mesh_mech_add" + bl_idname = "VIEW3D_MT_mesh_mech_add" bl_label = "Mechanical" def draw(self, context): layout = self.layout layout.operator_context = 'INVOKE_REGION_WIN' - layout.menu("INFO_MT_mesh_pipe_joints_add", + layout.menu("VIEW3D_MT_mesh_pipe_joints_add", text="Pipe Joints", icon="SNAP_PEEL_OBJECT") - layout.menu("INFO_MT_mesh_gears_add", + layout.menu("VIEW3D_MT_mesh_gears_add", text="Gears", icon="SCRIPTWIN") -class INFO_MT_mesh_extras_add(Menu): +class VIEW3D_MT_mesh_extras_add(Menu): # Define the "Extra Objects" menu - bl_idname = "INFO_MT_mesh_extras_add" + bl_idname = "VIEW3D_MT_mesh_extras_add" bl_label = "Extras" def draw(self, context): layout = self.layout layout.operator_context = 'INVOKE_REGION_WIN' - layout.menu("INFO_MT_mesh_diamonds_add", text="Diamonds", + layout.menu("VIEW3D_MT_mesh_diamonds_add", text="Diamonds", icon="PMARKER_SEL") layout.separator() layout.operator("mesh.add_beam", @@ -214,9 +214,9 @@ class INFO_MT_mesh_extras_add(Menu): text="Menger Sponge") -class INFO_MT_mesh_torus_add(Menu): +class VIEW3D_MT_mesh_torus_add(Menu): # Define the "Torus Objects" menu - bl_idname = "INFO_MT_mesh_torus_add" + bl_idname = "VIEW3D_MT_mesh_torus_add" bl_label = "Torus Objects" def draw(self, context): @@ -230,9 +230,9 @@ class INFO_MT_mesh_torus_add(Menu): text="Torus Knot") -class INFO_MT_mesh_pipe_joints_add(Menu): +class VIEW3D_MT_mesh_pipe_joints_add(Menu): # Define the "Pipe Joints" menu - bl_idname = "INFO_MT_mesh_pipe_joints_add" + bl_idname = "VIEW3D_MT_mesh_pipe_joints_add" bl_label = "Pipe Joints" def draw(self, context): @@ -355,15 +355,15 @@ def menu_func(self, context): lay_out.operator_context = 'INVOKE_REGION_WIN' lay_out.separator() - lay_out.menu("INFO_MT_mesh_vert_add", + lay_out.menu("VIEW3D_MT_mesh_vert_add", text="Single Vert", icon="LAYER_ACTIVE") lay_out.operator("mesh.primitive_round_cube_add", text="Round Cube", icon="MOD_SUBSURF") - lay_out.menu("INFO_MT_mesh_math_add", + lay_out.menu("VIEW3D_MT_mesh_math_add", text="Math Function", icon="PACKAGE") - lay_out.menu("INFO_MT_mesh_mech_add", + lay_out.menu("VIEW3D_MT_mesh_mech_add", text="Mechanical", icon="SCRIPTWIN") - lay_out.menu("INFO_MT_mesh_torus_add", + lay_out.menu("VIEW3D_MT_mesh_torus_add", text="Torus Objects", icon="MESH_TORUS") lay_out.separator() lay_out.operator("mesh.generate_geodesic_dome", @@ -371,7 +371,7 @@ def menu_func(self, context): lay_out.operator("discombobulate.ops", text="Discombobulator", icon="RETOPO") lay_out.separator() - lay_out.menu("INFO_MT_mesh_extras_add", + lay_out.menu("VIEW3D_MT_mesh_extras_add", text="Extras", icon="MESH_DATA") lay_out.separator() lay_out.operator("object.parent_to_empty", @@ -402,12 +402,12 @@ def register(): ) # Add "Extras" menu to the "Add Mesh" menu - bpy.types.INFO_MT_mesh_add.append(menu_func) + bpy.types.VIEW3D_MT_mesh_add.append(menu_func) def unregister(): # Remove "Extras" menu from the "Add Mesh" menu. - bpy.types.INFO_MT_mesh_add.remove(menu_func) + bpy.types.VIEW3D_MT_mesh_add.remove(menu_func) del bpy.types.Scene.discomb del bpy.types.Scene.error_message diff --git a/add_mesh_extra_objects/add_empty_as_parent.py b/add_mesh_extra_objects/add_empty_as_parent.py index bcaecf64..32d0d167 100644 --- a/add_mesh_extra_objects/add_empty_as_parent.py +++ b/add_mesh_extra_objects/add_empty_as_parent.py @@ -78,7 +78,7 @@ class P2E(Operator): bpy.ops.object.add(type='EMPTY', location=loc) context.object.name = self.nombre context.object.show_name = True - context.object.show_x_ray = True + context.object.show_in_front = True if self.grupo: bpy.ops.group.create(name=self.nombre) diff --git a/ant_landscape/__init__.py b/ant_landscape/__init__.py index 68dd2342..fd758e33 100644 --- a/ant_landscape/__init__.py +++ b/ant_landscape/__init__.py @@ -938,14 +938,14 @@ class AntLandscapePropertiesGroup(bpy.types.PropertyGroup): def register(): bpy.utils.register_module(__name__) - bpy.types.INFO_MT_mesh_add.append(menu_func_landscape) + bpy.types.VIEW3D_MT_mesh_add.append(menu_func_landscape) bpy.types.Object.ant_landscape = PointerProperty(type=AntLandscapePropertiesGroup, name="ANT_Landscape", description="Landscape properties") bpy.types.VIEW3D_MT_paint_weight.append(menu_func_eroder) def unregister(): bpy.utils.unregister_module(__name__) - bpy.types.INFO_MT_mesh_add.remove(menu_func_landscape) + bpy.types.VIEW3D_MT_mesh_add.remove(menu_func_landscape) bpy.types.VIEW3D_MT_paint_weight.remove(menu_func_eroder) diff --git a/archimesh/__init__.py b/archimesh/__init__.py index cb22e157..07049ff2 100644 --- a/archimesh/__init__.py +++ b/archimesh/__init__.py @@ -53,7 +53,7 @@ if "bpy" in locals(): importlib.reload(achm_kitchen_maker) importlib.reload(achm_shelves_maker) importlib.reload(achm_books_maker) - importlib.reload(achm_lamp_maker) + importlib.reload(achm_light_maker) importlib.reload(achm_curtain_maker) importlib.reload(achm_venetian_maker) importlib.reload(achm_main_panel) @@ -66,7 +66,7 @@ else: from . import achm_venetian_maker from . import achm_door_maker from . import achm_kitchen_maker - from . import achm_lamp_maker + from . import achm_light_maker from . import achm_main_panel from . import achm_roof_maker from . import achm_room_maker @@ -92,7 +92,7 @@ from bpy.types import ( AddonPreferences, Menu, Scene, - INFO_MT_mesh_add, + VIEW3D_MT_mesh_add, WindowManager, ) @@ -102,13 +102,13 @@ from bpy.types import ( class AchmInfoMtMeshDecorationAdd(Menu): - bl_idname = "INFO_MT_mesh_decoration_add" + bl_idname = "VIEW3D_MT_mesh_decoration_add" bl_label = "Decoration assets" # noinspection PyUnusedLocal def draw(self, context): self.layout.operator("mesh.archimesh_books", text="Add Books") - self.layout.operator("mesh.archimesh_lamp", text="Add Lamp") + self.layout.operator("mesh.archimesh_light", text="Add Lamp") self.layout.operator("mesh.archimesh_roller", text="Add Roller curtains") self.layout.operator("mesh.archimesh_venetian", text="Add Venetian blind") self.layout.operator("mesh.archimesh_japan", text="Add Japanese curtains") @@ -119,7 +119,7 @@ class AchmInfoMtMeshDecorationAdd(Menu): class AchmInfoMtMeshCustomMenuAdd(Menu): - bl_idname = "INFO_MT_mesh_custom_menu_add" + bl_idname = "VIEW3D_MT_mesh_custom_menu_add" bl_label = "Archimesh" # noinspection PyUnusedLocal @@ -134,7 +134,7 @@ class AchmInfoMtMeshCustomMenuAdd(Menu): self.layout.operator("mesh.archimesh_column", text="Add Column") self.layout.operator("mesh.archimesh_stairs", text="Add Stairs") self.layout.operator("mesh.archimesh_roof", text="Add Roof") - self.layout.menu("INFO_MT_mesh_decoration_add", text="Decoration props", icon="GROUP") + self.layout.menu("VIEW3D_MT_mesh_decoration_add", text="Decoration props", icon="GROUP") # -------------------------------------------------------------- # Register all operators and panels @@ -189,7 +189,7 @@ class Archi_Pref(AddonPreferences): # Define menu # noinspection PyUnusedLocal def AchmMenu_func(self, context): - self.layout.menu("INFO_MT_mesh_custom_menu_add", icon="GROUP") + self.layout.menu("VIEW3D_MT_mesh_custom_menu_add", icon="GROUP") def register(): @@ -210,7 +210,7 @@ def register(): bpy.utils.register_class(achm_kitchen_maker.AchmExportInventory) bpy.utils.register_class(achm_shelves_maker.AchmShelves) bpy.utils.register_class(achm_books_maker.AchmBooks) - bpy.utils.register_class(achm_lamp_maker.AchmLamp) + bpy.utils.register_class(achm_light_maker.AchmLamp) bpy.utils.register_class(achm_curtain_maker.AchmRoller) bpy.utils.register_class(achm_curtain_maker.AchmJapan) bpy.utils.register_class(achm_venetian_maker.AchmVenetian) @@ -222,7 +222,7 @@ def register(): bpy.utils.register_class(achm_window_panel.AchmWinPanel) bpy.utils.register_class(achm_window_panel.AchmWindowEditPanel) bpy.utils.register_class(Archi_Pref) - INFO_MT_mesh_add.append(AchmMenu_func) + VIEW3D_MT_mesh_add.append(AchmMenu_func) update_panel(None, bpy.context) # Define properties Scene.archimesh_select_only = BoolProperty( @@ -321,7 +321,7 @@ def unregister(): bpy.utils.unregister_class(achm_kitchen_maker.AchmExportInventory) bpy.utils.unregister_class(achm_shelves_maker.AchmShelves) bpy.utils.unregister_class(achm_books_maker.AchmBooks) - bpy.utils.unregister_class(achm_lamp_maker.AchmLamp) + bpy.utils.unregister_class(achm_light_maker.AchmLamp) bpy.utils.unregister_class(achm_curtain_maker.AchmRoller) bpy.utils.unregister_class(achm_curtain_maker.AchmJapan) bpy.utils.unregister_class(achm_venetian_maker.AchmVenetian) @@ -333,7 +333,7 @@ def unregister(): bpy.utils.unregister_class(achm_window_panel.AchmWinPanel) bpy.utils.unregister_class(achm_window_panel.AchmWindowEditPanel) bpy.utils.unregister_class(Archi_Pref) - INFO_MT_mesh_add.remove(AchmMenu_func) + VIEW3D_MT_mesh_add.remove(AchmMenu_func) # Remove properties del Scene.archimesh_select_only diff --git a/archimesh/achm_door_maker.py b/archimesh/achm_door_maker.py index 6d048bfd..4ef99373 100644 --- a/archimesh/achm_door_maker.py +++ b/archimesh/achm_door_maker.py @@ -233,7 +233,7 @@ def shape_children(mainobject, update=False): myctrl.location.x = 0 myctrl.location.y = -((mp.frame_thick * 3) / 2) myctrl.location.z = -gap - myctrl.draw_type = 'BOUNDS' + myctrl.display_type = 'BOUNDS' myctrl.hide = False myctrl.hide_render = True if bpy.context.scene.render.engine == 'CYCLES': @@ -256,7 +256,7 @@ def shape_children(mainobject, update=False): myctrlbase.location.x = 0 myctrlbase.location.y = -0.15 - (mp.frame_thick / 3) myctrlbase.location.z = -0.10 - myctrlbase.draw_type = 'BOUNDS' + myctrlbase.display_type = 'BOUNDS' myctrlbase.hide = False myctrlbase.hide_render = True if bpy.context.scene.render.engine == 'CYCLES': diff --git a/archimesh/achm_lamp_maker.py b/archimesh/achm_lamp_maker.py index a6b15435..67fbfc1e 100644 --- a/archimesh/achm_lamp_maker.py +++ b/archimesh/achm_lamp_maker.py @@ -130,7 +130,7 @@ def set_preset(self): # Lamps # ------------------------------------------------------------------ class AchmLamp(Operator): - bl_idname = "mesh.archimesh_lamp" + bl_idname = "mesh.archimesh_light" bl_label = "Lamp" bl_description = "Lamp Generator" bl_category = 'Archimesh' @@ -375,7 +375,7 @@ class AchmLamp(Operator): self.oldpreset = self.preset # Create lamp - create_lamp_mesh(self) + create_light_mesh(self) return {'FINISHED'} else: self.report({'WARNING'}, "Archimesh: Option only valid in Object mode") @@ -386,13 +386,13 @@ class AchmLamp(Operator): # Generate mesh data # All custom values are passed using self container (self.myvariable) # ------------------------------------------------------------------------------ -def create_lamp_mesh(self): +def create_light_mesh(self): # deactivate others for o in bpy.data.objects: if o.select is True: o.select = False bpy.ops.object.select_all(False) - generate_lamp(self) + generate_light(self) return @@ -401,13 +401,13 @@ def create_lamp_mesh(self): # Generate lamps # All custom values are passed using self container (self.myvariable) # ------------------------------------------------------------------------------ -def generate_lamp(self): +def generate_light(self): location = bpy.context.scene.cursor_location myloc = copy(location) # copy location to keep 3D cursor position # --------------------- # Lamp base # --------------------- - mydata = create_lamp_base("Lamp_base", self.base_height, + mydata = create_light_base("Lamp_base", self.base_height, myloc.x, myloc.y, myloc.z, self.base_segments, self.base_rings, [self.br01, self.br02, self.br03, self.br04, self.br05, self.br06, @@ -429,7 +429,7 @@ def generate_lamp(self): # --------------------- # Lampholder # --------------------- - myholder = create_lampholder("Lampholder", self.holder, + myholder = create_lightholder("Lampholder", self.holder, myloc.x, myloc.y, myloc.z, self.crt_mat) # refine @@ -444,7 +444,7 @@ def generate_lamp(self): # --------------------- # Lamp strings # --------------------- - mystrings = create_lampholder_strings("Lampstrings", self.holder, + mystrings = create_lightholder_strings("Lampstrings", self.holder, myloc.x, myloc.y, myloc.z, self.tr02, self.top_height, @@ -460,7 +460,7 @@ def generate_lamp(self): # --------------------- # Lampshade # --------------------- - mytop = create_lampshade("Lampshade", self.top_height, + mytop = create_lightshade("Lampshade", self.top_height, myloc.x, myloc.y, myloc.z, self.top_segments, self.tr01, self.tr02, @@ -517,7 +517,7 @@ def generate_lamp(self): # mat: Flag for creating materials # objcol: Color # ------------------------------------------------------------------------------ -def create_lamp_base(objname, height, px, py, pz, segments, rings, radios, ratios, subdivide, mat, objcol): +def create_light_base(objname, height, px, py, pz, segments, rings, radios, ratios, subdivide, mat, objcol): # Calculate heights h = height / (rings - 1) listheight = [] @@ -562,7 +562,7 @@ def create_lamp_base(objname, height, px, py, pz, segments, rings, radios, ratio # pZ: position Z axis # mat: Flag for creating materials # ------------------------------------------------------------------------------ -def create_lampholder(objname, height, px, py, pz, mat): +def create_lightholder(objname, height, px, py, pz, mat): mydata = create_cylinder_data(16, [0, height, height + 0.005, height + 0.008, height + 0.05], [0.005, 0.005, 0.010, 0.018, 0.018], False, False, False, 0, False) @@ -600,7 +600,7 @@ def create_lampholder(objname, height, px, py, pz, mat): # shadeh: height of lampshader # mat: Flag for creating materials # ------------------------------------------------------------------------------ -def create_lampholder_strings(objname, height, px, py, pz, radio, shadeh, mat): +def create_lightholder_strings(objname, height, px, py, pz, radio, shadeh, mat): mydata = create_cylinder_data(32, [height + 0.005, height + 0.005, height + 0.006, height + 0.006], [0.018, 0.025, 0.025, 0.018], False, False, False, 0, False) @@ -652,7 +652,7 @@ def create_lampholder_strings(objname, height, px, py, pz, radio, shadeh, mat): # opacity: opacity factor # mat: Flag for creating materials # ------------------------------------------------------------------------------ -def create_lampshade(objname, height, px, py, pz, segments, radio1, radio2, pleats, pleatsize, opacity, mat): +def create_lightshade(objname, height, px, py, pz, segments, radio1, radio2, pleats, pleatsize, opacity, mat): gap = 0.002 radios = [radio1 - gap, radio1 - gap, radio1, radio2, radio2 - gap, radio2 - gap] heights = [gap * 2, 0, 0, height, height, height - (gap * 2)] diff --git a/archimesh/achm_main_panel.py b/archimesh/achm_main_panel.py index 70312ac3..eb3d7748 100644 --- a/archimesh/achm_main_panel.py +++ b/archimesh/achm_main_panel.py @@ -462,10 +462,10 @@ class ArchimeshMainPanel(Panel): # Prop Buttons # ------------------------------ box = layout.box() - box.label("Props", icon='LAMP_DATA') + box.label("Props", icon='LIGHT_DATA') row = box.row() row.operator("mesh.archimesh_books") - row.operator("mesh.archimesh_lamp") + row.operator("mesh.archimesh_light") row = box.row() row.operator("mesh.archimesh_venetian") row.operator("mesh.archimesh_roller") diff --git a/archimesh/achm_window_maker.py b/archimesh/achm_window_maker.py index b7eb8235..1e43c792 100644 --- a/archimesh/achm_window_maker.py +++ b/archimesh/achm_window_maker.py @@ -216,7 +216,7 @@ def shape_mesh_and_create_children(mainobject, tmp_mesh, update=False): myctrl.location.x = 0 myctrl.location.y = -mp.depth * 3 / 2 myctrl.location.z = 0 - myctrl.draw_type = 'BOUNDS' + myctrl.display_type = 'BOUNDS' myctrl.hide = False myctrl.hide_render = True if bpy.context.scene.render.engine == 'CYCLES': diff --git a/archimesh/achm_window_panel.py b/archimesh/achm_window_panel.py index dbeed892..16c9209b 100644 --- a/archimesh/achm_window_panel.py +++ b/archimesh/achm_window_panel.py @@ -394,7 +394,7 @@ def do_ctrl_box(myobject): myctrl.location.x = 0 myctrl.location.y = 0 myctrl.location.z = 0 - myctrl.draw_type = 'WIRE' + myctrl.display_type = 'WIRE' myctrl.hide = False myctrl.hide_render = True if bpy.context.scene.render.engine == 'CYCLES': diff --git a/archipack/__init__.py b/archipack/__init__.py index 0f5d3a86..8b87585b 100644 --- a/archipack/__init__.py +++ b/archipack/__init__.py @@ -504,12 +504,12 @@ def register(): bpy.utils.register_class(Archipack_Pref) update_panel(None, bpy.context) bpy.utils.register_class(ARCHIPACK_MT_create) - bpy.types.INFO_MT_mesh_add.append(menu_func) + bpy.types.VIEW3D_MT_mesh_add.append(menu_func) def unregister(): global icons_collection - bpy.types.INFO_MT_mesh_add.remove(menu_func) + bpy.types.VIEW3D_MT_mesh_add.remove(menu_func) bpy.utils.unregister_class(ARCHIPACK_MT_create) bpy.utils.unregister_class(TOOLS_PT_Archipack_Tools) diff --git a/archipack/archipack_autoboolean.py b/archipack/archipack_autoboolean.py index c7e60305..10b8c5ce 100644 --- a/archipack/archipack_autoboolean.py +++ b/archipack/archipack_autoboolean.py @@ -105,7 +105,7 @@ class ArchipackBoolManager(): hole.lock_location = (True, True, True) hole.lock_rotation = (True, True, True) hole.lock_scale = (True, True, True) - hole.draw_type = 'WIRE' + hole.display_type = 'WIRE' hole.hide_render = True hole.hide_select = True hole.select = True diff --git a/archipack/archipack_floor.py b/archipack/archipack_floor.py index ed52fd8f..25d4db2f 100644 --- a/archipack/archipack_floor.py +++ b/archipack/archipack_floor.py @@ -337,7 +337,7 @@ class FloorGenerator(CutAblePolygon, CutAbleGenerator): segments=1, # d.bevel_res profile=0.5, vertex_only=False, - clamp_overlap=False, + clight_overlap=False, material=-1) bm.to_mesh(o.data) diff --git a/archipack/archipack_gl.py b/archipack/archipack_gl.py index a85a3080..8c475617 100644 --- a/archipack/archipack_gl.py +++ b/archipack/archipack_gl.py @@ -849,8 +849,7 @@ class Screen(): y_max = h - self.margin x_min = self.margin x_max = w - self.margin - if (system.use_region_overlap and - system.window_draw_method in {'TRIPLE_BUFFER', 'AUTOMATIC'}): + if system.use_region_overlap: area = context.area for r in area.regions: diff --git a/archipack/archipack_roof.py b/archipack/archipack_roof.py index 024dccb7..7d396d36 100644 --- a/archipack/archipack_roof.py +++ b/archipack/archipack_roof.py @@ -1868,7 +1868,7 @@ class RoofGenerator(CutAbleGenerator): segments=d.tile_bevel_segs, profile=0.5, vertex_only=False, - clamp_overlap=True, + clight_overlap=True, material=-1) if d.tile_solidify: diff --git a/archipack/archipack_thumbs.py b/archipack/archipack_thumbs.py index 8f652ab2..bfc9d55e 100644 --- a/archipack/archipack_thumbs.py +++ b/archipack/archipack_thumbs.py @@ -111,7 +111,7 @@ def generateThumb(context, cls, preset): p.data.materials.append(m) # add 3 lights - bpy.ops.object.lamp_add( + bpy.ops.object.light_add( type='POINT', radius=1, view_align=False, @@ -123,7 +123,7 @@ def generateThumb(context, cls, preset): emit = nodes["Emission"] emit.inputs[1].default_value = 2000.0 - bpy.ops.object.lamp_add( + bpy.ops.object.light_add( type='POINT', radius=1, view_align=False, @@ -137,7 +137,7 @@ def generateThumb(context, cls, preset): falloff.inputs[0].default_value = 5 tree.links.new(falloff.outputs[2], emit.inputs[1]) - bpy.ops.object.lamp_add( + bpy.ops.object.light_add( type='POINT', radius=1, view_align=False, diff --git a/archipack/archipack_wall2.py b/archipack/archipack_wall2.py index 5f464a02..1506e171 100644 --- a/archipack/archipack_wall2.py +++ b/archipack/archipack_wall2.py @@ -1672,7 +1672,7 @@ class ARCHIPACK_OT_wall2_throttle_update(Operator): m = o.modifiers.get("AutoBoolean") if m is not None: o.hide = False - # o.draw_type = 'TEXTURED' + # o.display_type = 'TEXTURED' # m.show_viewport = True return self.cancel(context) diff --git a/archipack/archipack_window.py b/archipack/archipack_window.py index 54d057e7..1bf349db 100644 --- a/archipack/archipack_window.py +++ b/archipack/archipack_window.py @@ -993,7 +993,7 @@ class archipack_window(ArchipackObject, Manipulable, PropertyGroup): def find_portal(self, o): for child in o.children: - if child.type == 'LAMP': + if child.type == 'LIGHT': return child return None @@ -1002,7 +1002,7 @@ class archipack_window(ArchipackObject, Manipulable, PropertyGroup): lamp = self.find_portal(o) if self.portal: if lamp is None: - bpy.ops.object.lamp_add(type='AREA') + bpy.ops.object.light_add(type='AREA') lamp = context.active_object lamp.name = "Portal" lamp.parent = o @@ -1025,7 +1025,7 @@ class archipack_window(ArchipackObject, Manipulable, PropertyGroup): d = lamp.data context.scene.objects.unlink(lamp) bpy.data.objects.remove(lamp) - bpy.data.lamps.remove(d) + bpy.data.lights.remove(d) context.scene.objects.active = o @@ -1658,7 +1658,7 @@ class ARCHIPACK_PT_window(Panel): box.prop(prop, 'hole_inside_mat') box.prop(prop, 'hole_outside_mat') - layout.prop(prop, 'portal', icon="LAMP_AREA") + layout.prop(prop, 'portal', icon="LIGHT_AREA") class ARCHIPACK_PT_window_panel(Panel): @@ -1751,11 +1751,11 @@ class ARCHIPACK_OT_window(ArchipackCreateTool, Operator): if archipack_window.filter(o): bpy.ops.archipack.disable_manipulate() for child in o.children: - if child.type == 'LAMP': + if child.type == 'LIGHT': d = child.data context.scene.objects.unlink(child) bpy.data.objects.remove(child) - bpy.data.lamps.remove(d) + bpy.data.lights.remove(d) elif 'archipack_hole' in child: context.scene.objects.unlink(child) bpy.data.objects.remove(child, do_unlink=True) diff --git a/archipack/bmesh_utils.py b/archipack/bmesh_utils.py index 3f402d1d..1157d9a3 100644 --- a/archipack/bmesh_utils.py +++ b/archipack/bmesh_utils.py @@ -216,7 +216,7 @@ class BmeshEdit(): segments=1, profile=0.5, vertex_only=False, - clamp_overlap=True, + clight_overlap=True, material=-1, use_selection=True): """ @@ -245,7 +245,7 @@ class BmeshEdit(): segments=segments, profile=profile, vertex_only=vertex_only, - clamp_overlap=clamp_overlap, + clight_overlap=clight_overlap, material=material) bm.to_mesh(o.data) diff --git a/blender_id/CHANGELOG.md b/blender_id/CHANGELOG.md index cf62a6e1..94b21376 100644 --- a/blender_id/CHANGELOG.md +++ b/blender_id/CHANGELOG.md @@ -1,5 +1,17 @@ # Blender ID Add-on Changelog +# Version 2.0 (in development) + +- Require Blender 2.80+. +- API change: `blender_id.get_subclient_user_id()` now returns `''` instead of `None` when the user + is not logged in. + + +# Version 1.5 (released 2018-07-03) + +- Support Blender 2.80. + + ## Version 1.4.1 (released 2017-12-15) - Improved error reporting when validating a token fails due to diff --git a/blender_id/README.md b/blender_id/README.md index 936e6e3e..8f73fbc7 100644 --- a/blender_id/README.md +++ b/blender_id/README.md @@ -13,6 +13,9 @@ Blender ID add-on version 1.2.0 removed some workarounds necessary for Blender 2.77a. As such, versions 1.1.x are the last versions compatible with Blender 2.77a, and 1.2.0 and newer require at least Blender 2.78. +Blender ID add-on version 2.0 is the first to support and require Blender 2.80+. + + Building & Bundling ------------------- diff --git a/blender_id/__init__.py b/blender_id/__init__.py index 73371945..e5d94715 100644 --- a/blender_id/__init__.py +++ b/blender_id/__init__.py @@ -14,15 +14,17 @@ # along with this program; if not, write to the Free Software Foundation, # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # +# Copyright (C) 2014-2018 Blender Foundation +# # ##### END GPL LICENSE BLOCK ##### # <pep8 compliant> bl_info = { 'name': 'Blender ID authentication', - 'author': 'Francesco Siddi, Inês Almeida and Sybren A. Stüvel', - 'version': (1, 4, 1), - 'blender': (2, 77, 0), + 'author': 'Sybren A. Stüvel, Francesco Siddi, and Inês Almeida', + 'version': (1, 9, 9), + 'blender': (2, 80, 0), 'location': 'Add-on preferences', 'description': 'Stores your Blender ID credentials for usage with other add-ons', @@ -117,11 +119,11 @@ def get_subclient_user_id(subclient_id: str) -> str: Requires that the user has been authenticated at the subclient using a call to create_subclient_token(...) - :returns: the subclient-local user ID, or None if not logged in. + :returns: the subclient-local user ID, or the empty string if not logged in. """ if not BlenderIdProfile.user_id: - return None + return '' return BlenderIdProfile.subclients[subclient_id]['subclient_user_id'] @@ -159,9 +161,9 @@ def token_expires() -> typing.Optional[datetime.datetime]: # Try parsing as different formats. A new Blender ID is coming, # which may change the format in which timestamps are sent. formats = [ - '%Y-%m-%dT%H:%M:%SZ', # ISO 8601 with Z-suffix - '%Y-%m-%dT%H:%M:%S.%fZ', # ISO 8601 with fractional seconds and Z-suffix - '%a, %d %b %Y %H:%M:%S GMT', # RFC 1123, used by old Blender ID + '%Y-%m-%dT%H:%M:%SZ', # ISO 8601 with Z-suffix + '%Y-%m-%dT%H:%M:%S.%fZ', # ISO 8601 with fractional seconds and Z-suffix + '%a, %d %b %Y %H:%M:%S GMT', # RFC 1123, used by old Blender ID ] for fmt in formats: try: @@ -177,22 +179,22 @@ def token_expires() -> typing.Optional[datetime.datetime]: class BlenderIdPreferences(AddonPreferences): bl_idname = __name__ - error_message = StringProperty( + error_message: StringProperty( name='Error Message', default='', options={'HIDDEN', 'SKIP_SAVE'} ) - ok_message = StringProperty( + ok_message: StringProperty( name='Message', default='', options={'HIDDEN', 'SKIP_SAVE'} ) - blender_id_username = StringProperty( + blender_id_username: StringProperty( name='E-mail address', default='', options={'HIDDEN', 'SKIP_SAVE'} ) - blender_id_password = StringProperty( + blender_id_password: StringProperty( name='Password', default='', options={'HIDDEN', 'SKIP_SAVE'}, @@ -209,10 +211,10 @@ class BlenderIdPreferences(AddonPreferences): if self.error_message: sub = layout.row() sub.alert = True # labels don't display in red :( - sub.label(self.error_message, icon='ERROR') + sub.label(text=self.error_message, icon='ERROR') if self.ok_message: sub = layout.row() - sub.label(self.ok_message, icon='FILE_TICK') + sub.label(text=self.ok_message, icon='FILE_TICK') active_profile = get_active_profile() if active_profile: @@ -238,15 +240,17 @@ class BlenderIdPreferences(AddonPreferences): exp_str = 'within seconds' if time_left.days < 14: - layout.label('You are logged in as %s.' % active_profile.username, + layout.label(text='You are logged in as %s.' % active_profile.username, icon='WORLD_DATA') layout.label(text='Your token will expire %s. Please log out and log in again ' - 'to refresh it.' % exp_str, icon='PREVIEW_RANGE') + 'to refresh it.' % exp_str, icon='PREVIEW_RANGE') else: - layout.label('You are logged in as %s. Your authentication token expires %s.' - % (active_profile.username, exp_str), icon='WORLD_DATA') + layout.label( + text='You are logged in as %s. Your authentication token expires %s.' + % (active_profile.username, exp_str), + icon='WORLD_DATA') - row = layout.row().split(0.8) + row = layout.row().split(factor=0.8) row.operator('blender_id.logout') row.operator('blender_id.validate') else: @@ -343,14 +347,20 @@ def register(): profiles.register() BlenderIdProfile.read_json() - bpy.utils.register_module(__name__) + bpy.utils.register_class(BlenderIdLogin) + bpy.utils.register_class(BlenderIdLogout) + bpy.utils.register_class(BlenderIdPreferences) + bpy.utils.register_class(BlenderIdValidate) preferences = bpy.context.user_preferences.addons[__name__].preferences preferences.reset_messages() def unregister(): - bpy.utils.unregister_module(__name__) + bpy.utils.unregister_class(BlenderIdLogin) + bpy.utils.unregister_class(BlenderIdLogout) + bpy.utils.unregister_class(BlenderIdPreferences) + bpy.utils.unregister_class(BlenderIdValidate) if __name__ == '__main__': diff --git a/bone_selection_sets.py b/bone_selection_sets.py index 686eb808..e91d5557 100644 --- a/bone_selection_sets.py +++ b/bone_selection_sets.py @@ -20,7 +20,7 @@ bl_info = { "name": "Bone Selection Sets", "author": "Inês Almeida, Sybren A. Stüvel, Antony Riakiotakis, Dan Eicher", "version": (2, 1, 1), - "blender": (2, 75, 0), + "blender": (2, 80, 0), "location": "Properties > Object Data (Armature) > Selection Sets", "description": "List of Bone sets for easy selection while animating", "warning": "", @@ -41,6 +41,7 @@ from bpy.props import ( StringProperty, IntProperty, EnumProperty, + BoolProperty, CollectionProperty, ) @@ -48,14 +49,15 @@ from bpy.props import ( # Data Structure ############################################################## # Note: bones are stored by name, this means that if the bone is renamed, -# there can be problems. However, bone renaming is unlikely during animation +# there can be problems. However, bone renaming is unlikely during animation. class SelectionEntry(PropertyGroup): - name = StringProperty(name="Bone Name") + name: StringProperty(name="Bone Name") class SelectionSet(PropertyGroup): - name = StringProperty(name="Set Name") - bone_ids = CollectionProperty(type=SelectionEntry) + name: StringProperty(name="Set Name") + bone_ids: CollectionProperty(type=SelectionEntry) + is_selected: BoolProperty(name="Is Selected") # UI Panel w/ UIList ########################################################## @@ -103,8 +105,8 @@ class POSE_PT_selection_sets(Panel): # add/remove/specials UI list Menu col = row.column(align=True) - col.operator("pose.selection_set_add", icon='ZOOMIN', text="") - col.operator("pose.selection_set_remove", icon='ZOOMOUT', text="") + col.operator("pose.selection_set_add", icon='ADD', text="") + col.operator("pose.selection_set_remove", icon='REMOVE', text="") col.menu("POSE_MT_selection_sets_specials", icon='DOWNARROW_HLT', text="") # move up/down arrows @@ -126,8 +128,11 @@ class POSE_PT_selection_sets(Panel): class POSE_UL_selection_set(UIList): - def draw_item(self, context, layout, data, set, icon, active_data, active_propname, index): - layout.prop(set, "name", text="", icon='GROUP_BONE', emboss=False) + def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index): + sel_set = item + layout.prop(item, "name", text="", icon='GROUP_BONE', emboss=False) + if self.layout_type in ('DEFAULT', 'COMPACT'): + layout.prop(item, "is_selected", text="") class POSE_MT_selection_set_create(Menu): @@ -139,7 +144,7 @@ class POSE_MT_selection_set_create(Menu): text="New Selection Set") -class POSE_MT_selection_sets(Menu): +class POSE_MT_selection_sets_select(Menu): bl_label = 'Select Selection Set' @classmethod @@ -157,6 +162,7 @@ class POSE_MT_selection_sets(Menu): # Operators ################################################################### class PluginOperator(Operator): + """Operator only available for objects of type armature in pose mode.""" @classmethod def poll(cls, context): return (context.object and @@ -165,6 +171,7 @@ class PluginOperator(Operator): class NeedSelSetPluginOperator(PluginOperator): + """Operator only available if the armature has a selected selection set.""" @classmethod def poll(cls, context): if not super().poll(context): @@ -187,8 +194,8 @@ class POSE_OT_selection_set_delete_all(PluginOperator): class POSE_OT_selection_set_remove_bones(PluginOperator): bl_idname = "pose.selection_set_remove_bones" - bl_label = "Remove Bones from Sets" - bl_description = "Removes the Active Bones from All Sets" + bl_label = "Remove Selected Bones from All Sets" + bl_description = "Removes the Selected Bones from All Sets" bl_options = {'UNDO', 'REGISTER'} def execute(self, context): @@ -210,14 +217,15 @@ class POSE_OT_selection_set_move(NeedSelSetPluginOperator): bl_description = "Move the active Selection Set up/down the list of sets" bl_options = {'UNDO', 'REGISTER'} - direction = EnumProperty( + direction: EnumProperty( name="Move Direction", description="Direction to move the active Selection Set: UP (default) or DOWN", items=[ ('UP', "Up", "", -1), ('DOWN', "Down", "", 1), ], - default='UP' + default='UP', + options={'HIDDEN'}, ) @classmethod @@ -334,10 +342,12 @@ class POSE_OT_selection_set_select(NeedSelSetPluginOperator): bl_description = "Add Selection Set bones to current selection" bl_options = {'UNDO', 'REGISTER'} - selection_set_index = IntProperty( + selection_set_index: IntProperty( name='Selection Set Index', default=-1, - description='Which Selection Set to select; -1 uses the active Selection Set') + description='Which Selection Set to select; -1 uses the active Selection Set', + options={'HIDDEN'}, + ) def execute(self, context): arm = context.object @@ -386,20 +396,20 @@ class POSE_OT_selection_set_add_and_assign(PluginOperator): class POSE_OT_selection_set_copy(NeedSelSetPluginOperator): bl_idname = "pose.selection_set_copy" - bl_label = "Copy Selection Set to Clipboard" - bl_description = "Converts the Selection Set to JSON and places it on the clipboard" + bl_label = "Copy Selection Set(s)" + bl_description = "Copies the selected Selection Set(s) to the clipboard" bl_options = {'UNDO', 'REGISTER'} def execute(self, context): context.window_manager.clipboard = to_json(context) - self.report({'INFO'}, 'Copied Selection Set to Clipboard') + self.report({'INFO'}, 'Copied Selection Set(s) to Clipboard') return {'FINISHED'} class POSE_OT_selection_set_paste(PluginOperator): bl_idname = "pose.selection_set_paste" - bl_label = "Paste Selection Set from Clipboard" - bl_description = "Adds a new Selection Set from copied JSON on the clipboard" + bl_label = "Paste Selection Set(s)" + bl_description = "Adds new Selection Set(s) from the Clipboard" bl_options = {'UNDO', 'REGISTER'} def execute(self, context): @@ -416,67 +426,51 @@ class POSE_OT_selection_set_paste(PluginOperator): return {'FINISHED'} -# Registry #################################################################### - -classes = ( - POSE_MT_selection_set_create, - POSE_MT_selection_sets_specials, - POSE_MT_selection_sets, - POSE_PT_selection_sets, - POSE_UL_selection_set, - SelectionEntry, - SelectionSet, - POSE_OT_selection_set_delete_all, - POSE_OT_selection_set_remove_bones, - POSE_OT_selection_set_move, - POSE_OT_selection_set_add, - POSE_OT_selection_set_remove, - POSE_OT_selection_set_assign, - POSE_OT_selection_set_unassign, - POSE_OT_selection_set_select, - POSE_OT_selection_set_deselect, - POSE_OT_selection_set_add_and_assign, - POSE_OT_selection_set_copy, - POSE_OT_selection_set_paste, -) - +# Helper Functions ############################################################ -def add_sss_button(self, context): - self.layout.menu('POSE_MT_selection_sets') +def menu_func_select_selection_set(self, context): + self.layout.menu('POSE_MT_selection_sets_select', text="Bone Selection Set") def to_json(context) -> str: - """Convert the active bone selection set of the current rig to JSON.""" + """Convert the selected Selection Sets of the current rig to JSON. + + Selected Sets are the active_selection_set determined by the UIList + plus any with the is_selected checkbox on.""" import json arm = context.object active_idx = arm.active_selection_set - sel_set = arm.selection_sets[active_idx] - return json.dumps({ - 'name': sel_set.name, - 'bones': [bone_id.name for bone_id in sel_set.bone_ids] - }) + json_obj = {} + for idx, sel_set in enumerate(context.object.selection_sets): + if idx == active_idx or sel_set.is_selected: + bones = [bone_id.name for bone_id in sel_set.bone_ids] + json_obj[sel_set.name] = bones + + return json.dumps(json_obj) def from_json(context, as_json: str): - """Add the single bone selection set from JSON to the current rig.""" + """Add the selection sets (one or more) from JSON to the current rig.""" import json - sel_set = json.loads(as_json) - - sel_sets = context.object.selection_sets - new_sel_set = sel_sets.add() - new_sel_set.name = uniqify(sel_set['name'], sel_sets.keys()) + json_obj = json.loads(as_json) + arm_sel_sets = context.object.selection_sets - for bone_name in sel_set['bones']: - bone_id = new_sel_set.bone_ids.add() - bone_id.name = bone_name + for name, bones in json_obj.items(): + new_sel_set = arm_sel_sets.add() + new_sel_set.name = uniqify(name, arm_sel_sets.keys()) + for bone_name in bones: + bone_id = new_sel_set.bone_ids.add() + bone_id.name = bone_name def uniqify(name: str, other_names: list) -> str: """Return a unique name with .xxx suffix if necessary. + Example usage: + >>> uniqify('hey', ['there']) 'hey' >>> uniqify('hey', ['hey.001', 'hey.005']) @@ -514,7 +508,32 @@ def uniqify(name: str, other_names: list) -> str: return "{}.{:03d}".format(name, min_index) -# store keymaps here to access after registration +# Registry #################################################################### + +classes = ( + POSE_MT_selection_set_create, + POSE_MT_selection_sets_specials, + POSE_MT_selection_sets_select, + POSE_PT_selection_sets, + POSE_UL_selection_set, + SelectionEntry, + SelectionSet, + POSE_OT_selection_set_delete_all, + POSE_OT_selection_set_remove_bones, + POSE_OT_selection_set_move, + POSE_OT_selection_set_add, + POSE_OT_selection_set_remove, + POSE_OT_selection_set_assign, + POSE_OT_selection_set_unassign, + POSE_OT_selection_set_select, + POSE_OT_selection_set_deselect, + POSE_OT_selection_set_add_and_assign, + POSE_OT_selection_set_copy, + POSE_OT_selection_set_paste, +) + + +# Store keymaps here to access after registration. addon_keymaps = [] @@ -522,6 +541,7 @@ def register(): for cls in classes: bpy.utils.register_class(cls) + # Add properties. bpy.types.Object.selection_sets = CollectionProperty( type=SelectionSet, name="Selection Sets", @@ -533,28 +553,34 @@ def register(): default=0 ) + # Add shortcuts to the keymap. wm = bpy.context.window_manager km = wm.keyconfigs.addon.keymaps.new(name='Pose') - kmi = km.keymap_items.new('wm.call_menu', 'W', 'PRESS', alt=True, shift=True) - kmi.properties.name = 'POSE_MT_selection_sets' + kmi.properties.name = 'POSE_MT_selection_sets_select' addon_keymaps.append((km, kmi)) - bpy.types.VIEW3D_MT_select_pose.append(add_sss_button) + # Add entries to menus. + bpy.types.VIEW3D_MT_select_pose.append(menu_func_select_selection_set) def unregister(): for cls in classes: bpy.utils.unregister_class(cls) + # Clear properties. del bpy.types.Object.selection_sets del bpy.types.Object.active_selection_set - # handle the keymap + # Clear shortcuts from the keymap. for km, kmi in addon_keymaps: km.keymap_items.remove(kmi) addon_keymaps.clear() + # Clear entries from menus. + bpy.types.VIEW3D_MT_select_pose.remove(menu_func_select_selection_set) + + if __name__ == "__main__": import doctest diff --git a/camera_dolly_crane_rigs.py b/camera_dolly_crane_rigs.py index c55b19e8..bd4b88bc 100644 --- a/camera_dolly_crane_rigs.py +++ b/camera_dolly_crane_rigs.py @@ -533,7 +533,7 @@ def build_dolly_rig(context): cam.data.name = "Dolly_Camera.000" cam_data_name = bpy.context.object.data.name - bpy.data.cameras[cam_data_name].draw_size = 1.0 + bpy.data.cameras[cam_data_name].display_size = 1.0 cam.rotation_euler[0] = 1.5708 # rotate the camera 90 degrees in x cam.location = (0.0, -2.0, 0.0) # move the camera to the correct position cam.parent = rig @@ -631,9 +631,9 @@ def build_crane_rig(context): ctrlAimChild.parent = ctrlAim # change display to BBone: it just looks nicer - bpy.context.object.data.draw_type = 'BBONE' + bpy.context.object.data.display_type = 'BBONE' # change display to wire for object - bpy.context.object.draw_type = 'WIRE' + bpy.context.object.display_type = 'WIRE' # jump into pose mode and change bones to euler bpy.ops.object.mode_set(mode='POSE') @@ -718,7 +718,7 @@ def build_crane_rig(context): cam.data.name = "Crane_Camera.000" cam_data_name = bpy.context.object.data.name - bpy.data.cameras[cam_data_name].draw_size = 1.0 + bpy.data.cameras[cam_data_name].display_size = 1.0 cam.rotation_euler[0] = 1.5708 # rotate the camera 90 degrees in x cam.location = (0.0, -2.0, 0.0) # move the camera to the correct position cam.parent = rig @@ -801,7 +801,7 @@ class DollyCameraUI(Panel): text="Make Active Camera", icon='CAMERA_DATA') col.prop(context.active_object, - 'show_x_ray', toggle=False, text='X Ray') + 'show_in_front', toggle=False, text='X Ray') col.prop(cam, "show_limits") col.prop(cam, "show_safe_areas") col.prop(cam, "show_passepartout") @@ -865,7 +865,7 @@ class CraneCameraUI(Panel): col.operator( "scene.make_camera_active", text="Make Active Camera", icon='CAMERA_DATA') col.prop( - context.active_object, 'show_x_ray', toggle=False, text='X Ray') + context.active_object, 'show_in_front', toggle=False, text='X Ray') col.prop(cam, "show_limits") col.prop(cam, "show_safe_areas") col.prop(cam, "show_passepartout") @@ -966,7 +966,7 @@ def register(): bpy.utils.register_class(MakeCameraActive) bpy.utils.register_class(AddMarkerBind) bpy.utils.register_class(AddDofEmpty) - bpy.types.INFO_MT_camera_add.append(add_dolly_crane_buttons) + bpy.types.VIEW3D_MT_camera_add.append(add_dolly_crane_buttons) def unregister(): @@ -977,7 +977,7 @@ def unregister(): bpy.utils.unregister_class(MakeCameraActive) bpy.utils.unregister_class(AddMarkerBind) bpy.utils.unregister_class(AddDofEmpty) - bpy.types.INFO_MT_camera_add.remove(add_dolly_crane_buttons) + bpy.types.VIEW3D_MT_camera_add.remove(add_dolly_crane_buttons) if __name__ == "__main__": diff --git a/camera_turnaround.py b/camera_turnaround.py index 6a6e710f..547c2834 100644 --- a/camera_turnaround.py +++ b/camera_turnaround.py @@ -96,7 +96,7 @@ class RunAction(Operator): context.user_preferences.edit.keyframe_new_interpolation_type = 'LINEAR' # create first frame myempty.rotation_euler = (0, 0, 0) - myempty.empty_draw_size = 0.1 + myempty.empty_display_size = 0.1 context.scene.frame_set(scene.frame_start) myempty.keyframe_insert(data_path='rotation_euler', frame=scene.frame_start) diff --git a/curve_simplify.py b/curve_simplify.py index b053a4b9..e14b2857 100644 --- a/curve_simplify.py +++ b/curve_simplify.py @@ -20,7 +20,7 @@ bl_info = { "name": "Simplify Curves", "author": "testscreenings", "version": (1, 0, 3), - "blender": (2, 75, 0), + "blender": (2, 80, 0), "location": "View3D > Add > Curve > Simplify Curves", "description": "Simplifies 3D Curve objects and animation F-Curves", "warning": "", @@ -35,16 +35,16 @@ This script simplifies Curve objects and animation F-Curves. import bpy from bpy.props import ( - BoolProperty, - EnumProperty, - FloatProperty, - IntProperty, - ) + BoolProperty, + EnumProperty, + FloatProperty, + IntProperty, +) from mathutils import Vector from math import ( - sin, - pow, - ) + sin, + pow, +) from bpy.types import Operator @@ -307,10 +307,11 @@ def main(context, obj, options, curve_dimension): # create new object and put into scene newCurve = bpy.data.objects.new("Simple_" + obj.name, curve) - scene.objects.link(newCurve) - newCurve.select = True + coll = context.view_layer.collections.active.collection + coll.objects.link(newCurve) + newCurve.select_set('SELECT') - scene.objects.active = newCurve + context.view_layer.objects.active = newCurve newCurve.matrix_world = obj.matrix_world # set bezierhandles to auto @@ -325,7 +326,7 @@ def getFcurveData(obj): for fc in obj.animation_data.action.fcurves: if fc.select: fcVerts = [vcVert.co.to_3d() - for vcVert in fc.keyframe_points.values()] + for vcVert in fc.keyframe_points.values()] fcurves.append(fcVerts) return fcurves @@ -396,38 +397,38 @@ class GRAPH_OT_simplify(Operator): opModes = [ ('DISTANCE', 'Distance', 'Distance-based simplification (Poly)'), ('CURVATURE', 'Curvature', 'Curvature-based simplification (RDP)')] - mode = EnumProperty( + mode: EnumProperty( name="Mode", description="Choose algorithm to use", items=opModes ) - k_thresh = FloatProperty( + k_thresh: FloatProperty( name="k", min=0, soft_min=0, default=0, precision=3, description="Threshold" ) - pointsNr = IntProperty( + pointsNr: IntProperty( name="n", min=5, soft_min=5, max=16, soft_max=9, default=5, description="Degree of curve to get averaged curvatures" ) - error = FloatProperty( + error: FloatProperty( name="Error", description="Maximum allowed distance error", min=0.0, soft_min=0.0, default=0, precision=3 ) - degreeOut = IntProperty( + degreeOut: IntProperty( name="Degree", min=3, soft_min=3, max=7, soft_max=7, default=5, description="Degree of new curve" ) - dis_error = FloatProperty( + dis_error: FloatProperty( name="Distance error", description="Maximum allowed distance error in Blender Units", min=0, soft_min=0, @@ -490,7 +491,7 @@ class CURVE_OT_simplify(Operator): ('DISTANCE', 'Distance', 'Distance-based simplification (Poly)'), ('CURVATURE', 'Curvature', 'Curvature-based simplification (RDP)') ] - mode = EnumProperty( + mode: EnumProperty( name="Mode", description="Choose algorithm to use", items=opModes @@ -501,42 +502,44 @@ class CURVE_OT_simplify(Operator): ('BEZIER', 'Bezier', 'BEZIER'), ('POLY', 'Poly', 'POLY') ] - output = EnumProperty( + output: EnumProperty( name="Output splines", description="Type of splines to output", items=SplineTypes ) - k_thresh = FloatProperty( + k_thresh: FloatProperty( name="k", min=0, soft_min=0, default=0, precision=3, description="Threshold" ) - pointsNr = IntProperty(name="n", + pointsNr: IntProperty( + name="n", min=5, soft_min=5, max=9, soft_max=9, default=5, description="Degree of curve to get averaged curvatures" ) - error = FloatProperty( + error: FloatProperty( name="Error", description="Maximum allowed distance error in Blender Units", min=0, soft_min=0, default=0.0, precision=3 ) - degreeOut = IntProperty(name="Degree", + degreeOut: IntProperty( + name="Degree", min=3, soft_min=3, max=7, soft_max=7, default=5, description="Degree of new curve" ) - dis_error = FloatProperty( + dis_error: FloatProperty( name="Distance error", description="Maximum allowed distance error in Blender Units", min=0, soft_min=0, default=0.0 ) - keepShort = BoolProperty( + keepShort: BoolProperty( name="Keep short splines", description="Keep short splines (less than 7 points)", default=True @@ -546,7 +549,7 @@ class CURVE_OT_simplify(Operator): layout = self.layout col = layout.column() - col.label("Distance Error:") + col.label(text="Distance Error:") col.prop(self, "error", expand=True) col.prop(self, "output", text="Output", icon="OUTLINER_OB_CURVE") if self.output == "NURBS": @@ -591,21 +594,30 @@ class CURVE_OT_simplify(Operator): # Register +classes = [ + GRAPH_OT_simplify, + CURVE_OT_simplify, +] + def register(): - bpy.utils.register_module(__name__) + from bpy.utils import register_class + for cls in classes: + register_class(cls) bpy.types.GRAPH_MT_channel.append(menu_func) bpy.types.DOPESHEET_MT_channel.append(menu_func) - bpy.types.INFO_MT_curve_add.append(menu) + bpy.types.VIEW3D_MT_curve_add.append(menu) def unregister(): + from bpy.utils import unregister_class + for cls in reversed(classes): + unregister_class(cls) + bpy.types.GRAPH_MT_channel.remove(menu_func) bpy.types.DOPESHEET_MT_channel.remove(menu_func) - bpy.types.INFO_MT_curve_add.remove(menu) - - bpy.utils.unregister_module(__name__) + bpy.types.VIEW3D_MT_curve_add.remove(menu) if __name__ == "__main__": diff --git a/depsgraph_debug.py b/depsgraph_debug.py index 438d4885..76f25290 100644 --- a/depsgraph_debug.py +++ b/depsgraph_debug.py @@ -27,7 +27,7 @@ bl_info = { "name": "Dependency Graph Debug", "author": "Sergey Sharybin", "version": (0, 1), - "blender": (2, 79, 0), + "blender": (2, 80, 0), "description": "Various dependency graph debugging tools", "warning": "", "wiki_url": "", @@ -48,12 +48,12 @@ def _get_depsgraph(context): # Save data from depsgraph to a specified file. class SCENE_OT_depsgraph_save_common: - filepath = StringProperty( - name="File Path", - description="Filepath used for saving the file", - maxlen=1024, - subtype='FILE_PATH', - ) + filepath: StringProperty( + name="File Path", + description="Filepath used for saving the file", + maxlen=1024, + subtype='FILE_PATH', + ) def _getExtension(self, context): return "" @@ -86,8 +86,10 @@ class SCENE_OT_depsgraph_save_common: pass -class SCENE_OT_depsgraph_relations_graphviz(Operator, - SCENE_OT_depsgraph_save_common): +class SCENE_OT_depsgraph_relations_graphviz( + Operator, + SCENE_OT_depsgraph_save_common, +): bl_idname = "scene.depsgraph_relations_graphviz" bl_label = "Save Depsgraph" bl_description = "Save current scene's dependency graph to a graphviz file" @@ -96,13 +98,16 @@ class SCENE_OT_depsgraph_relations_graphviz(Operator, return ".dot" def performSave(self, context, depsgraph): + import os basename, extension = os.path.splitext(self.filepath) - depsgraph.debug_relations_graphviz(self.filepath, absename + ".png") + depsgraph.debug_relations_graphviz(os.path.join(self.filepath, basename + ".dot")) return True -class SCENE_OT_depsgraph_stats_gnuplot(Operator, - SCENE_OT_depsgraph_save_common): +class SCENE_OT_depsgraph_stats_gnuplot( + Operator, + SCENE_OT_depsgraph_save_common, +): bl_idname = "scene.depsgraph_stats_gnuplot" bl_label = "Save Depsgraph Stats" bl_description = "Save current scene's evaluaiton stats to gnuplot file" diff --git a/development_api_navigator.py b/development_api_navigator.py index 5e0276cb..deae8443 100644 --- a/development_api_navigator.py +++ b/development_api_navigator.py @@ -514,7 +514,7 @@ class OBJECT_PT_api_navigator(ApiNavigator, Panel): elif iterable == 'b': box = self.layout.box() row = box.row() - row.label(text="Item Values", icon="OOPS") + row.label(text="Item Values", icon='OUTLINER') box = box.box() col = box.column(align=True) collection = list(current_module) diff --git a/development_icon_get.py b/development_icon_get.py index a7740c31..c8360e88 100644 --- a/development_icon_get.py +++ b/development_icon_get.py @@ -23,9 +23,9 @@ bl_info = { "name": "Icon Viewer", "description": "Click an icon to copy its name to the clipboard", "author": "roaoao", - "version": (1, 3, 2), - "blender": (2, 75, 0), - "location": "Spacebar > Icon Viewer, Text Editor > Properties", + "version": (1, 4, 0), + "blender": (2, 80, 0), + "location": "Search Menu > Icon Viewer, Text Editor > Properties", "wiki_url": "https://wiki.blender.org/index.php/Extensions:2.6" "/Py/Scripts/Development/Display_All_Icons", "category": "Development" @@ -33,6 +33,10 @@ bl_info = { import bpy import math +from bpy.props import ( + BoolProperty, + StringProperty, +) DPI = 72 POPUP_PADDING = 10 @@ -88,6 +92,9 @@ class Icons: not pr.show_brush_icons and "BRUSH_" in icon and \ icon != 'BRUSH_DATA' or \ not pr.show_matcap_icons and "MATCAP_" in icon or \ + not pr.show_event_icons and ( + "EVENT_" in icon or "MOUSE_" in icon + ) or \ not pr.show_colorset_icons and "COLORSET_" in icon: continue self._filtered_icons.append(icon) @@ -109,8 +116,8 @@ class Icons: else: filtered_icons = self.filtered_icons - column = layout.column(True) - row = column.row(True) + column = layout.column(align=True) + row = column.row(align=True) row.alignment = 'CENTER' selected_icon = self.selected_icon if self.is_popup else \ @@ -118,7 +125,7 @@ class Icons: col_idx = 0 for i, icon in enumerate(filtered_icons): p = row.operator( - IV_OT_icon_select.bl_idname, "", + IV_OT_icon_select.bl_idname, text="", icon=icon, emboss=icon == selected_icon) p.icon = icon p.force_copy_on_select = not self.is_popup @@ -129,16 +136,15 @@ class Icons: break col_idx = 0 if i < len(filtered_icons) - 1: - row = column.row(True) + row = column.row(align=True) row.alignment = 'CENTER' if col_idx != 0 and not icons and i >= num_cols: - sub = row.row(True) - sub.scale_x = num_cols - col_idx - sub.label("", icon='BLANK1') + for _ in range(num_cols - col_idx): + row.label(text="", icon='BLANK1') if not filtered_icons: - row.label("No icons were found") + row.label(text="No icons were found") class IV_Preferences(bpy.types.AddonPreferences): @@ -154,47 +160,51 @@ class IV_Preferences(bpy.types.AddonPreferences): def set_panel_filter(self, value): self.panel_icons.filter = value - panel_filter = bpy.props.StringProperty( + panel_filter: StringProperty( description="Filter", default="", get=lambda s: s.panel_icons.filter, set=set_panel_filter, options={'TEXTEDIT_UPDATE'}) - show_panel_icons = bpy.props.BoolProperty( + show_panel_icons: BoolProperty( name="Show Icons", description="Show icons", default=True) - show_history = bpy.props.BoolProperty( + show_history: BoolProperty( name="Show History", description="Show history", default=True) - show_brush_icons = bpy.props.BoolProperty( + show_brush_icons: BoolProperty( name="Show Brush Icons", description="Show brush icons", default=True, update=update_icons) - show_matcap_icons = bpy.props.BoolProperty( + show_matcap_icons: BoolProperty( name="Show Matcap Icons", description="Show matcap icons", default=True, update=update_icons) - show_colorset_icons = bpy.props.BoolProperty( + show_event_icons: BoolProperty( + name="Show Event Icons", + description="Show event icons", default=True, + update=update_icons) + show_colorset_icons: BoolProperty( name="Show Colorset Icons", description="Show colorset icons", default=True, update=update_icons) - copy_on_select = bpy.props.BoolProperty( + copy_on_select: BoolProperty( name="Copy Icon On Click", description="Copy icon on click", default=True) - close_on_select = bpy.props.BoolProperty( + close_on_select: BoolProperty( name="Close Popup On Click", description=( "Close the popup on click.\n" "Not supported by some windows (User Preferences, Render)" - ), + ), default=False) - auto_focus_filter = bpy.props.BoolProperty( + auto_focus_filter: BoolProperty( name="Auto Focus Input Field", description="Auto focus input field", default=True) - show_panel = bpy.props.BoolProperty( + show_panel: BoolProperty( name="Show Panel", description="Show the panel in the Text Editor", default=True) - show_header = bpy.props.BoolProperty( + show_header: BoolProperty( name="Show Header", description="Show the header in the Python Console", default=True) @@ -207,29 +217,30 @@ class IV_Preferences(bpy.types.AddonPreferences): row = layout.row() - col = row.column(True) - col.label("Icons:") + col = row.column(align=True) + col.label(text="Icons:") col.prop(self, "show_matcap_icons") col.prop(self, "show_brush_icons") col.prop(self, "show_colorset_icons") + col.prop(self, "show_event_icons") col.separator() col.prop(self, "show_history") - col = row.column(True) - col.label("Popup:") + col = row.column(align=True) + col.label(text="Popup:") col.prop(self, "auto_focus_filter") col.prop(self, "copy_on_select") if self.copy_on_select: col.prop(self, "close_on_select") - col = row.column(True) - col.label("Panel:") + col = row.column(align=True) + col.label(text="Panel:") col.prop(self, "show_panel") if self.show_panel: col.prop(self, "show_panel_icons") col.separator() - col.label("Header:") + col.label(text="Header:") col.prop(self, "show_header") @@ -253,12 +264,13 @@ class IV_PT_icons(bpy.types.Panel): def draw(self, context): pr = prefs() - row = self.layout.row(True) + row = self.layout.row(align=True) if pr.show_panel_icons: - row.prop(pr, "panel_filter", "", icon='VIEWZOOM') + row.prop(pr, "panel_filter", text="", icon='VIEWZOOM') else: row.operator(IV_OT_icons_show.bl_idname) - row.operator(IV_OT_panel_menu_call.bl_idname, "", icon='COLLAPSEMENU') + row.operator( + IV_OT_panel_menu_call.bl_idname, text="", icon='COLLAPSEMENU') _, y0 = context.region.view2d.region_to_view(0, 0) _, y1 = context.region.view2d.region_to_view(0, 10) @@ -271,11 +283,11 @@ class IV_PT_icons(bpy.types.Panel): col = None if HISTORY and pr.show_history: - col = self.layout.column(True) + col = self.layout.column(align=True) pr.panel_icons.draw(col.box(), num_cols, HISTORY) if pr.show_panel_icons: - col = col or self.layout.column(True) + col = col or self.layout.column(align=True) pr.panel_icons.draw(col.box(), num_cols) @classmethod @@ -313,9 +325,10 @@ class IV_OT_panel_menu_call(bpy.types.Operator): layout.prop(pr, "show_matcap_icons") layout.prop(pr, "show_brush_icons") layout.prop(pr, "show_colorset_icons") + layout.prop(pr, "show_event_icons") def execute(self, context): - context.window_manager.popup_menu(self.menu, "Icon Viewer") + context.window_manager.popup_menu(self.menu, title="Icon Viewer") return {'FINISHED'} @@ -325,8 +338,8 @@ class IV_OT_icon_select(bpy.types.Operator): bl_description = "Select the icon" bl_options = {'INTERNAL'} - icon = bpy.props.StringProperty() - force_copy_on_select = bpy.props.BoolProperty() + icon: StringProperty() + force_copy_on_select: BoolProperty() def execute(self, context): pr = prefs() @@ -362,17 +375,17 @@ class IV_OT_icons_show(bpy.types.Operator): if IV_OT_icons_show.instance: IV_OT_icons_show.instance.auto_focusable = False - filter_auto_focus = bpy.props.StringProperty( + filter_auto_focus: StringProperty( description="Filter", get=lambda s: prefs().popup_icons.filter, set=set_filter, options={'TEXTEDIT_UPDATE', 'SKIP_SAVE'}) - filter = bpy.props.StringProperty( + filter: StringProperty( description="Filter", get=lambda s: prefs().popup_icons.filter, set=set_filter, options={'TEXTEDIT_UPDATE'}) - selected_icon = bpy.props.StringProperty( + selected_icon: StringProperty( description="Selected Icon", get=lambda s: prefs().popup_icons.selected_icon, set=set_selected_icon) @@ -383,36 +396,38 @@ class IV_OT_icons_show(bpy.types.Operator): def draw_header(self, layout): pr = prefs() header = layout.box() - header = header.split(0.75) if self.selected_icon else header.row() - row = header.row(True) - row.prop(pr, "show_matcap_icons", "", icon='SMOOTH') - row.prop(pr, "show_brush_icons", "", icon='BRUSH_DATA') - row.prop(pr, "show_colorset_icons", "", icon='COLOR') + header = header.split(factor=0.75) if self.selected_icon else \ + header.row() + row = header.row(align=True) + row.prop(pr, "show_matcap_icons", text="", icon='SHADING_RENDERED') + row.prop(pr, "show_brush_icons", text="", icon='BRUSH_DATA') + row.prop(pr, "show_colorset_icons", text="", icon='COLOR') + row.prop(pr, "show_event_icons", text="", icon='HAND') row.separator() row.prop( - pr, "copy_on_select", "", + pr, "copy_on_select", text="", icon='BORDER_RECT', toggle=True) if pr.copy_on_select: - sub = row.row(True) + sub = row.row(align=True) if bpy.context.window.screen.name == "temp": sub.alert = True sub.prop( - pr, "close_on_select", "", + pr, "close_on_select", text="", icon='RESTRICT_SELECT_OFF', toggle=True) row.prop( - pr, "auto_focus_filter", "", + pr, "auto_focus_filter", text="", icon='OUTLINER_DATA_FONT', toggle=True) row.separator() if self.auto_focusable and pr.auto_focus_filter: - row.prop(self, "filter_auto_focus", "", icon='VIEWZOOM') + row.prop(self, "filter_auto_focus", text="", icon='VIEWZOOM') else: - row.prop(self, "filter", "", icon='VIEWZOOM') + row.prop(self, "filter", text="", icon='VIEWZOOM') if self.selected_icon: row = header.row() - row.prop(self, "selected_icon", "", icon=self.selected_icon) + row.prop(self, "selected_icon", text="", icon=self.selected_icon) def draw(self, context): pr = prefs() @@ -425,7 +440,7 @@ class IV_OT_icons_show(bpy.types.Operator): self.get_num_cols(len(pr.popup_icons.filtered_icons)), history_num_cols) - subcol = col.column(True) + subcol = col.column(align=True) if HISTORY and pr.show_history: pr.popup_icons.draw(subcol.box(), history_num_cols, HISTORY) @@ -468,18 +483,31 @@ class IV_OT_icons_show(bpy.types.Operator): ui_scale() * (num_cols * ICON_SIZE + POPUP_PADDING), context.window.width - WIN_PADDING) - return context.window_manager.invoke_props_dialog(self, self.width) + return context.window_manager.invoke_props_dialog( + self, width=self.width) + + +classes = ( + IV_PT_icons, + IV_HT_icons, + IV_OT_panel_menu_call, + IV_OT_icon_select, + IV_OT_icons_show, + IV_Preferences, +) def register(): if bpy.app.background: return - bpy.utils.register_module(__name__) + for cls in classes: + bpy.utils.register_class(cls) def unregister(): if bpy.app.background: return - bpy.utils.unregister_module(__name__) + for cls in classes: + bpy.utils.unregister_class(cls) diff --git a/game_engine_publishing.py b/game_engine_publishing.py deleted file mode 100644 index 495b0123..00000000 --- a/game_engine_publishing.py +++ /dev/null @@ -1,576 +0,0 @@ -# ##### BEGIN GPL LICENSE BLOCK ##### -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# ##### END GPL LICENSE BLOCK ##### - -import bpy -import os -import tempfile -import shutil -import tarfile -import time -import stat - - -bl_info = { - "name": "Game Engine Publishing", - "author": "Mitchell Stokes (Moguri), Oren Titane (Genome36)", - "version": (0, 1, 0), - "blender": (2, 75, 0), - "location": "Render Properties > Publishing Info", - "description": "Publish .blend file as game engine runtime, manage versions and platforms", - "warning": "", - "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.6/Py/Scripts/Game_Engine/Publishing", - "category": "Game Engine", -} - - -def WriteRuntime(player_path, output_path, asset_paths, copy_python, overwrite_lib, copy_dlls, make_archive, report=print): - import struct - - player_path = bpy.path.abspath(player_path) - ext = os.path.splitext(player_path)[-1].lower() - output_path = bpy.path.abspath(output_path) - output_dir = os.path.dirname(output_path) - if not os.path.exists(output_dir): - os.makedirs(output_dir) - - python_dir = os.path.join(os.path.dirname(player_path), - bpy.app.version_string.split()[0], - "python", - "lib") - - # Check the paths - if not os.path.isfile(player_path) and not(os.path.exists(player_path) and player_path.endswith('.app')): - report({'ERROR'}, "The player could not be found! Runtime not saved") - return - - # Check if we're bundling a .app - if player_path.lower().endswith('.app'): - # Python doesn't need to be copied for OS X since it's already inside blenderplayer.app - copy_python = False - - output_path = bpy.path.ensure_ext(output_path, '.app') - - if os.path.exists(output_path): - shutil.rmtree(output_path) - - shutil.copytree(player_path, output_path) - bpy.ops.wm.save_as_mainfile(filepath=os.path.join(output_path, 'Contents', 'Resources', 'game.blend'), - relative_remap=False, - compress=False, - copy=True, - ) - else: - # Enforce "exe" extension on Windows - if player_path.lower().endswith('.exe'): - output_path = bpy.path.ensure_ext(output_path, '.exe') - - # Get the player's binary and the offset for the blend - with open(player_path, "rb") as file: - player_d = file.read() - offset = file.tell() - - # Create a tmp blend file (Blenderplayer doesn't like compressed blends) - tempdir = tempfile.mkdtemp() - blend_path = os.path.join(tempdir, bpy.path.clean_name(output_path)) - bpy.ops.wm.save_as_mainfile(filepath=blend_path, - relative_remap=False, - compress=False, - copy=True, - ) - - # Get the blend data - with open(blend_path, "rb") as blend_file: - blend_d = blend_file.read() - - # Get rid of the tmp blend, we're done with it - os.remove(blend_path) - os.rmdir(tempdir) - - # Create a new file for the bundled runtime - with open(output_path, "wb") as output: - # Write the player and blend data to the new runtime - print("Writing runtime...", end=" ", flush=True) - output.write(player_d) - output.write(blend_d) - - # Store the offset (an int is 4 bytes, so we split it up into 4 bytes and save it) - output.write(struct.pack('BBBB', (offset >> 24) & 0xFF, - (offset >> 16) & 0xFF, - (offset >> 8) & 0xFF, - (offset >> 0) & 0xFF)) - - # Stuff for the runtime - output.write(b'BRUNTIME') - - print("done", flush=True) - - # Make sure the runtime is executable - os.chmod(output_path, 0o755) - - # Copy bundled Python - blender_dir = os.path.dirname(player_path) - - if copy_python: - print("Copying Python files...", end=" ", flush=True) - py_folder = os.path.join(bpy.app.version_string.split()[0], "python", "lib") - dst = os.path.join(output_dir, py_folder) - src = python_dir - - if os.path.exists(dst) and overwrite_lib: - shutil.rmtree(dst) - - if not os.path.exists(dst): - shutil.copytree(src, dst, ignore=lambda dir, contents: [i for i in contents if i == '__pycache__']) - print("done", flush=True) - else: - print("used existing Python folder", flush=True) - - # And DLLs if we're doing a Windows runtime) - if copy_dlls and ext == ".exe": - print("Copying DLLs...", end=" ", flush=True) - for file in [i for i in os.listdir(blender_dir) if i.lower().endswith('.dll')]: - src = os.path.join(blender_dir, file) - dst = os.path.join(output_dir, file) - shutil.copy2(src, dst) - - print("done", flush=True) - - # Copy assets - for ap in asset_paths: - src = bpy.path.abspath(ap.name) - dst = os.path.join(output_dir, ap.name[2:] if ap.name.startswith('//') else ap.name) - - if os.path.exists(src): - if os.path.isdir(src): - if ap.overwrite and os.path.exists(dst): - shutil.rmtree(dst) - elif not os.path.exists(dst): - shutil.copytree(src, dst) - else: - if ap.overwrite or not os.path.exists(dst): - shutil.copy2(src, dst) - else: - report({'ERROR'}, "Could not find asset path: '%s'" % src) - - # Make archive - if make_archive: - print("Making archive...", end=" ", flush=True) - - arctype = '' - if player_path.lower().endswith('.exe'): - arctype = 'zip' - elif player_path.lower().endswith('.app'): - arctype = 'zip' - else: # Linux - arctype = 'gztar' - - basedir = os.path.normpath(os.path.join(os.path.dirname(output_path), '..')) - afilename = os.path.join(basedir, os.path.basename(output_dir)) - - if arctype == 'gztar': - # Create the tarball ourselves instead of using shutil.make_archive - # so we can handle permission bits. - - # The runtimename needs to use forward slashes as a path separator - # since this is what tarinfo.name is using. - runtimename = os.path.relpath(output_path, basedir).replace('\\', '/') - - def _set_ex_perm(tarinfo): - if tarinfo.name == runtimename: - tarinfo.mode = 0o755 - return tarinfo - - with tarfile.open(afilename + '.tar.gz', 'w:gz') as tf: - tf.add(output_dir, os.path.relpath(output_dir, basedir), filter=_set_ex_perm) - elif arctype == 'zip': - shutil.make_archive(afilename, 'zip', output_dir) - else: - report({'ERROR'}, "Unknown archive type %s for runtime %s\n" % (arctype, player_path)) - - print("done", flush=True) - - -class PublishAllPlatforms(bpy.types.Operator): - bl_idname = "wm.publish_platforms" - bl_label = "Exports a runtime for each listed platform" - - def execute(self, context): - ps = context.scene.ge_publish_settings - - if ps.publish_default_platform: - print("Publishing default platform") - blender_bin_path = bpy.app.binary_path - blender_bin_dir = os.path.dirname(blender_bin_path) - ext = os.path.splitext(blender_bin_path)[-1].lower() - WriteRuntime(os.path.join(blender_bin_dir, 'blenderplayer' + ext), - os.path.join(ps.output_path, 'default', ps.runtime_name), - ps.asset_paths, - True, - True, - True, - ps.make_archive, - self.report - ) - else: - print("Skipping default platform") - - for platform in ps.platforms: - if platform.publish: - print("Publishing", platform.name) - WriteRuntime(platform.player_path, - os.path.join(ps.output_path, platform.name, ps.runtime_name), - ps.asset_paths, - True, - True, - True, - ps.make_archive, - self.report - ) - else: - print("Skipping", platform.name) - - return {'FINISHED'} - - -class RENDER_UL_assets(bpy.types.UIList): - bl_label = "Asset Paths Listing" - - def draw_item(self, context, layout, data, item, icon, active_data, active_propname): - layout.prop(item, "name", text="", emboss=False) - - -class RENDER_UL_platforms(bpy.types.UIList): - bl_label = "Platforms Listing" - - def draw_item(self, context, layout, data, item, icon, active_data, active_propname): - row = layout.row() - row.label(item.name) - row.prop(item, "publish", text="") - - -class RENDER_PT_publish(bpy.types.Panel): - bl_label = "Publishing Info" - bl_space_type = "PROPERTIES" - bl_region_type = "WINDOW" - bl_context = "render" - - @classmethod - def poll(cls, context): - scene = context.scene - return scene and (scene.render.engine == "BLENDER_GAME") - - def draw(self, context): - ps = context.scene.ge_publish_settings - layout = self.layout - - # config - layout.prop(ps, 'output_path') - layout.prop(ps, 'runtime_name') - layout.prop(ps, 'lib_path') - layout.prop(ps, 'make_archive') - - layout.separator() - - # assets list - layout.label("Asset Paths") - - # UI_UL_list - row = layout.row() - row.template_list("RENDER_UL_assets", "assets_list", ps, 'asset_paths', ps, 'asset_paths_active') - - # operators - col = row.column(align=True) - col.operator(PublishAddAssetPath.bl_idname, icon='ZOOMIN', text="") - col.operator(PublishRemoveAssetPath.bl_idname, icon='ZOOMOUT', text="") - - # indexing - if len(ps.asset_paths) > ps.asset_paths_active >= 0: - ap = ps.asset_paths[ps.asset_paths_active] - row = layout.row() - row.prop(ap, 'overwrite') - - layout.separator() - - # publishing list - row = layout.row(align=True) - row.label("Platforms") - row.prop(ps, 'publish_default_platform') - - # UI_UL_list - row = layout.row() - row.template_list("RENDER_UL_platforms", "platforms_list", ps, 'platforms', ps, 'platforms_active') - - # operators - col = row.column(align=True) - col.operator(PublishAddPlatform.bl_idname, icon='ZOOMIN', text="") - col.operator(PublishRemovePlatform.bl_idname, icon='ZOOMOUT', text="") - col.menu("PUBLISH_MT_platform_specials", icon='DOWNARROW_HLT', text="") - - # indexing - if len(ps.platforms) > ps.platforms_active >= 0: - platform = ps.platforms[ps.platforms_active] - layout.prop(platform, 'name') - layout.prop(platform, 'player_path') - - layout.operator(PublishAllPlatforms.bl_idname, 'Publish Platforms') - - -class PublishAutoPlatforms(bpy.types.Operator): - bl_idname = "scene.publish_auto_platforms" - bl_label = "Auto Add Platforms" - - def execute(self, context): - ps = context.scene.ge_publish_settings - - # verify lib folder - lib_path = bpy.path.abspath(ps.lib_path) - if not os.path.exists(lib_path): - self.report({'ERROR'}, "Could not add platforms, lib folder (%s) does not exist" % lib_path) - return {'CANCELLED'} - - for lib in [i for i in os.listdir(lib_path) if os.path.isdir(os.path.join(lib_path, i))]: - print("Found folder:", lib) - player_found = False - for root, dirs, files in os.walk(os.path.join(lib_path, lib)): - if "__MACOSX" in root: - continue - - for f in dirs + files: - if f.startswith("blenderplayer.app") or f.startswith("blenderplayer"): - a = ps.platforms.add() - if lib.startswith('blender-'): - # Clean up names for packages from blender.org - # example: blender-2.71-RC2-OSX_10.6-x86_64.zip => OSX_10.6-x86_64.zip - # We're pretty consistent on naming, so this should hold up. - a.name = '-'.join(lib.split('-')[3 if 'rc' in lib.lower() else 2:]) - else: - a.name = lib - a.player_path = bpy.path.relpath(os.path.join(root, f)) - player_found = True - break - - if player_found: - break - - return {'FINISHED'} - -# TODO This operator takes a long time to run, which is bad for UX. Could this instead be done as some sort of -# modal dialog? This could also allow users to select which platforms to download and give a better progress -# indicator. -class PublishDownloadPlatforms(bpy.types.Operator): - bl_idname = "scene.publish_download_platforms" - bl_label = "Download Platforms" - - def execute(self, context): - import html.parser - import urllib.request - - remote_platforms = [] - - ps = context.scene.ge_publish_settings - - # create lib folder if not already available - lib_path = bpy.path.abspath(ps.lib_path) - if not os.path.exists(lib_path): - os.makedirs(lib_path) - - print("Retrieving list of platforms from blender.org...", end=" ", flush=True) - - class AnchorParser(html.parser.HTMLParser): - def handle_starttag(self, tag, attrs): - if tag == 'a': - for key, value in attrs: - if key == 'href' and value.startswith('blender'): - remote_platforms.append(value) - - url = 'http://download.blender.org/release/Blender' + bpy.app.version_string.split()[0] - parser = AnchorParser() - data = urllib.request.urlopen(url).read() - parser.feed(str(data)) - - print("done", flush=True) - - print("Downloading files (this will take a while depending on your internet connection speed).", flush=True) - for i in remote_platforms: - src = '/'.join((url, i)) - dst = os.path.join(lib_path, i) - - dst_dir = '.'.join([i for i in dst.split('.') if i not in {'zip', 'tar', 'bz2'}]) - if not os.path.exists(dst) and not os.path.exists(dst.split('.')[0]): - print("Downloading " + src + "...", end=" ", flush=True) - urllib.request.urlretrieve(src, dst) - print("done", flush=True) - else: - print("Reusing existing file: " + dst, flush=True) - - print("Unpacking " + dst + "...", end=" ", flush=True) - if os.path.exists(dst_dir): - shutil.rmtree(dst_dir) - shutil.unpack_archive(dst, dst_dir) - print("done", flush=True) - - print("Creating platform from libs...", flush=True) - bpy.ops.scene.publish_auto_platforms() - return {'FINISHED'} - - -class PublishAddPlatform(bpy.types.Operator): - bl_idname = "scene.publish_add_platform" - bl_label = "Add Publish Platform" - - def execute(self, context): - a = context.scene.ge_publish_settings.platforms.add() - a.name = a.name - return {'FINISHED'} - - -class PublishRemovePlatform(bpy.types.Operator): - bl_idname = "scene.publish_remove_platform" - bl_label = "Remove Publish Platform" - - def execute(self, context): - ps = context.scene.ge_publish_settings - if ps.platforms_active < len(ps.platforms): - ps.platforms.remove(ps.platforms_active) - return {'FINISHED'} - return {'CANCELLED'} - - -# TODO maybe this should display a file browser? -class PublishAddAssetPath(bpy.types.Operator): - bl_idname = "scene.publish_add_assetpath" - bl_label = "Add Asset Path" - - def execute(self, context): - a = context.scene.ge_publish_settings.asset_paths.add() - a.name = a.name - return {'FINISHED'} - - -class PublishRemoveAssetPath(bpy.types.Operator): - bl_idname = "scene.publish_remove_assetpath" - bl_label = "Remove Asset Path" - - def execute(self, context): - ps = context.scene.ge_publish_settings - if ps.asset_paths_active < len(ps.asset_paths): - ps.asset_paths.remove(ps.asset_paths_active) - return {'FINISHED'} - return {'CANCELLED'} - - -class PUBLISH_MT_platform_specials(bpy.types.Menu): - bl_label = "Platform Specials" - - def draw(self, context): - layout = self.layout - layout.operator(PublishAutoPlatforms.bl_idname) - layout.operator(PublishDownloadPlatforms.bl_idname) - - -class PlatformSettings(bpy.types.PropertyGroup): - name = bpy.props.StringProperty( - name = "Platform Name", - description = "The name of the platform", - default = "Platform", - ) - - player_path = bpy.props.StringProperty( - name = "Player Path", - description = "The path to the Blenderplayer to use for this platform", - default = "//lib/platform/blenderplayer", - subtype = 'FILE_PATH', - ) - - publish = bpy.props.BoolProperty( - name = "Publish", - description = "Whether or not to publish to this platform", - default = True, - ) - - -class AssetPath(bpy.types.PropertyGroup): - # TODO This needs a way to be a FILE_PATH or a DIR_PATH - name = bpy.props.StringProperty( - name = "Asset Path", - description = "Path to the asset to be copied", - default = "//src", - subtype = 'FILE_PATH', - ) - - overwrite = bpy.props.BoolProperty( - name = "Overwrite Asset", - description = "Overwrite the asset if it already exists in the destination folder", - default = True, - ) - - -class PublishSettings(bpy.types.PropertyGroup): - output_path = bpy.props.StringProperty( - name = "Publish Output", - description = "Where to publish the game", - default = "//bin/", - subtype = 'DIR_PATH', - ) - - runtime_name = bpy.props.StringProperty( - name = "Runtime name", - description = "The filename for the created runtime", - default = "game", - ) - - lib_path = bpy.props.StringProperty( - name = "Library Path", - description = "Directory to search for platforms", - default = "//lib/", - subtype = 'DIR_PATH', - ) - - publish_default_platform = bpy.props.BoolProperty( - name = "Publish Default Platform", - description = "Whether or not to publish the default platform (the Blender install running this addon) when publishing platforms", - default = True, - ) - - - platforms = bpy.props.CollectionProperty(type=PlatformSettings, name="Platforms") - platforms_active = bpy.props.IntProperty() - - asset_paths = bpy.props.CollectionProperty(type=AssetPath, name="Asset Paths") - asset_paths_active = bpy.props.IntProperty() - - make_archive = bpy.props.BoolProperty( - name = "Make Archive", - description = "Create a zip archive of the published game", - default = True, - ) - - -def register(): - bpy.utils.register_module(__name__) - - bpy.types.Scene.ge_publish_settings = bpy.props.PointerProperty(type=PublishSettings) - - -def unregister(): - bpy.utils.unregister_module(__name__) - del bpy.types.Scene.ge_publish_settings - - -if __name__ == "__main__": - register() diff --git a/game_engine_save_as_runtime.py b/game_engine_save_as_runtime.py deleted file mode 100644 index 25e47d94..00000000 --- a/game_engine_save_as_runtime.py +++ /dev/null @@ -1,258 +0,0 @@ -# ##### BEGIN GPL LICENSE BLOCK ##### -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# ##### END GPL LICENSE BLOCK ##### - -bl_info = { - "name": "Save As Game Engine Runtime", - "author": "Mitchell Stokes (Moguri)", - "version": (0, 3, 1), - "blender": (2, 61, 0), - "location": "File > Export", - "description": "Bundle a .blend file with the Blenderplayer", - "warning": "", - "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.6/Py/" - "Scripts/Game_Engine/Save_As_Runtime", - "category": "Game Engine", -} - -import bpy -import os -import sys -import shutil -import tempfile - - -def CopyPythonLibs(dst, overwrite_lib, report=print): - import platform - - # use python module to find pytohn's libpath - src = os.path.dirname(platform.__file__) - - # dst points to lib/, but src points to current python's library path, eg: - # '/usr/lib/python3.2' vs '/usr/lib' - # append python's library dir name to destination, so only python's - # libraries would be copied - if os.name == 'posix': - dst = os.path.join(dst, os.path.basename(src)) - - if os.path.exists(src): - write = False - if os.path.exists(dst): - if overwrite_lib: - shutil.rmtree(dst) - write = True - else: - write = True - if write: - shutil.copytree(src, dst, ignore=lambda dir, contents: [i for i in contents if i == '__pycache__']) - else: - report({'WARNING'}, "Python not found in %r, skipping pythn copy" % src) - - -def WriteAppleRuntime(player_path, output_path, copy_python, overwrite_lib): - # Enforce the extension - if not output_path.endswith('.app'): - output_path += '.app' - - # Use the system's cp command to preserve some meta-data - os.system('cp -R "%s" "%s"' % (player_path, output_path)) - - bpy.ops.wm.save_as_mainfile(filepath=os.path.join(output_path, "Contents/Resources/game.blend"), - relative_remap=False, - compress=False, - copy=True, - ) - - # Python doesn't need to be copied for OS X since it's already inside blenderplayer.app - - -def WriteRuntime(player_path, output_path, copy_python, overwrite_lib, copy_dlls, report=print): - import struct - - # Check the paths - if not os.path.isfile(player_path) and not(os.path.exists(player_path) and player_path.endswith('.app')): - report({'ERROR'}, "The player could not be found! Runtime not saved") - return - - # Check if we're bundling a .app - if player_path.endswith('.app'): - WriteAppleRuntime(player_path, output_path, copy_python, overwrite_lib) - return - - # Enforce "exe" extension on Windows - if player_path.endswith('.exe') and not output_path.endswith('.exe'): - output_path += '.exe' - - # Get the player's binary and the offset for the blend - file = open(player_path, 'rb') - player_d = file.read() - offset = file.tell() - file.close() - - # Create a tmp blend file (Blenderplayer doesn't like compressed blends) - tempdir = tempfile.mkdtemp() - blend_path = os.path.join(tempdir, bpy.path.clean_name(output_path)) - bpy.ops.wm.save_as_mainfile(filepath=blend_path, - relative_remap=False, - compress=False, - copy=True, - ) - - # Get the blend data - blend_file = open(blend_path, 'rb') - blend_d = blend_file.read() - blend_file.close() - - # Get rid of the tmp blend, we're done with it - os.remove(blend_path) - os.rmdir(tempdir) - - # Create a new file for the bundled runtime - output = open(output_path, 'wb') - - # Write the player and blend data to the new runtime - print("Writing runtime...", end=" ") - output.write(player_d) - output.write(blend_d) - - # Store the offset (an int is 4 bytes, so we split it up into 4 bytes and save it) - output.write(struct.pack('B', (offset>>24)&0xFF)) - output.write(struct.pack('B', (offset>>16)&0xFF)) - output.write(struct.pack('B', (offset>>8)&0xFF)) - output.write(struct.pack('B', (offset>>0)&0xFF)) - - # Stuff for the runtime - output.write(b'BRUNTIME') - output.close() - - print("done") - - # Make the runtime executable on Linux - if os.name == 'posix': - os.chmod(output_path, 0o755) - - # Copy bundled Python - blender_dir = os.path.dirname(bpy.app.binary_path) - runtime_dir = os.path.dirname(output_path) - - if copy_python: - print("Copying Python files...", end=" ") - py_folder = os.path.join(bpy.app.version_string.split()[0], "python", "lib") - dst = os.path.join(runtime_dir, py_folder) - CopyPythonLibs(dst, overwrite_lib, report) - print("done") - - # And DLLs - if copy_dlls: - print("Copying DLLs...", end=" ") - for file in [i for i in os.listdir(blender_dir) if i.lower().endswith('.dll')]: - src = os.path.join(blender_dir, file) - dst = os.path.join(runtime_dir, file) - shutil.copy2(src, dst) - - print("done") - -from bpy.props import * - - -class SaveAsRuntime(bpy.types.Operator): - bl_idname = "wm.save_as_runtime" - bl_label = "Save As Game Engine Runtime" - bl_options = {'REGISTER'} - - if sys.platform == 'darwin': - # XXX, this line looks suspicious, could be done better? - blender_bin_dir = '/' + os.path.join(*bpy.app.binary_path.split('/')[0:-4]) - ext = '.app' - else: - blender_bin_path = bpy.app.binary_path - blender_bin_dir = os.path.dirname(blender_bin_path) - ext = os.path.splitext(blender_bin_path)[-1].lower() - - default_player_path = os.path.join(blender_bin_dir, 'blenderplayer' + ext) - player_path = StringProperty( - name="Player Path", - description="The path to the player to use", - default=default_player_path, - subtype='FILE_PATH', - ) - filepath = StringProperty( - subtype='FILE_PATH', - ) - copy_python = BoolProperty( - name="Copy Python", - description="Copy bundle Python with the runtime", - default=True, - ) - overwrite_lib = BoolProperty( - name="Overwrite 'lib' folder", - description="Overwrites the lib folder (if one exists) with the bundled Python lib folder", - default=False, - ) - - # Only Windows has dlls to copy - if ext == '.exe': - copy_dlls = BoolProperty( - name="Copy DLLs", - description="Copy all needed DLLs with the runtime", - default=True, - ) - else: - copy_dlls = False - - def execute(self, context): - import time - start_time = time.clock() - print("Saving runtime to %r" % self.filepath) - WriteRuntime(self.player_path, - self.filepath, - self.copy_python, - self.overwrite_lib, - self.copy_dlls, - self.report, - ) - print("Finished in %.4fs" % (time.clock()-start_time)) - return {'FINISHED'} - - def invoke(self, context, event): - if not self.filepath: - ext = '.app' if sys.platform == 'darwin' else os.path.splitext(bpy.app.binary_path)[-1] - self.filepath = bpy.path.ensure_ext(bpy.data.filepath, ext) - - wm = context.window_manager - wm.fileselect_add(self) - return {'RUNNING_MODAL'} - - -def menu_func(self, context): - self.layout.operator(SaveAsRuntime.bl_idname) - - -def register(): - bpy.utils.register_module(__name__) - - bpy.types.INFO_MT_file_export.append(menu_func) - - -def unregister(): - bpy.utils.unregister_module(__name__) - - bpy.types.INFO_MT_file_export.remove(menu_func) - - -if __name__ == "__main__": - register() diff --git a/io_anim_acclaim/__init__.py b/io_anim_acclaim/__init__.py index 620c1fc4..7cada817 100644 --- a/io_anim_acclaim/__init__.py +++ b/io_anim_acclaim/__init__.py @@ -189,7 +189,7 @@ class StructureBuilder(DataStructure): self.armature = self.object.data self.object.name = self.name self.armature.name = self.name - self.armature.draw_type = 'STICK' + self.armature.display_type = 'STICK' self.object['source_file_path'] = self.file_path self.object['source_scale'] = self.user_def_scale self.object['MhxArmature'] = 'Daz' @@ -530,16 +530,16 @@ def menu_func_me(self, context): def register(): bpy.utils.register_module(__name__) - bpy.types.INFO_MT_file_import.append(menu_func_s) - bpy.types.INFO_MT_file_import.append(menu_func_mi) - bpy.types.INFO_MT_file_export.append(menu_func_me) + bpy.types.TOPBAR_MT_file_import.append(menu_func_s) + bpy.types.TOPBAR_MT_file_import.append(menu_func_mi) + bpy.types.TOPBAR_MT_file_export.append(menu_func_me) def unregister(): bpy.utils.unregister_module(__name__) - bpy.types.INFO_MT_file_import.remove(menu_func_s) - bpy.types.INFO_MT_file_import.remove(menu_func_mi) - bpy.types.INFO_MT_file_export.remove(menu_func_me) + bpy.types.TOPBAR_MT_file_import.remove(menu_func_s) + bpy.types.TOPBAR_MT_file_import.remove(menu_func_mi) + bpy.types.TOPBAR_MT_file_export.remove(menu_func_me) if __name__ == "__main__": diff --git a/io_anim_bvh/__init__.py b/io_anim_bvh/__init__.py index 4a4983ff..dd9c2037 100644 --- a/io_anim_bvh/__init__.py +++ b/io_anim_bvh/__init__.py @@ -22,7 +22,7 @@ bl_info = { "name": "BioVision Motion Capture (BVH) format", "author": "Campbell Barton", "version": (1, 0, 0), - "blender": (2, 74, 0), + "blender": (2, 80, 0), "location": "File > Import-Export", "description": "Import-Export BVH from armature objects", "warning": "", @@ -52,24 +52,22 @@ from bpy.props import ( from bpy_extras.io_utils import ( ImportHelper, ExportHelper, - orientation_helper_factory, + orientation_helper, axis_conversion, ) -ImportBVHOrientationHelper = orientation_helper_factory("ImportBVHOrientationHelper", axis_forward='-Z', axis_up='Y') - - -class ImportBVH(bpy.types.Operator, ImportHelper, ImportBVHOrientationHelper): +@orientation_helper(axis_forward='-Z', axis_up='Y') +class ImportBVH(bpy.types.Operator, ImportHelper): """Load a BVH motion capture file""" bl_idname = "import_anim.bvh" bl_label = "Import BVH" bl_options = {'REGISTER', 'UNDO'} filename_ext = ".bvh" - filter_glob = StringProperty(default="*.bvh", options={'HIDDEN'}) + filter_glob: StringProperty(default="*.bvh", options={'HIDDEN'}) - target = EnumProperty( + target: EnumProperty( items=( ('ARMATURE', "Armature", ""), ('OBJECT', "Object", ""), @@ -78,20 +76,19 @@ class ImportBVH(bpy.types.Operator, ImportHelper, ImportBVHOrientationHelper): description="Import target type", default='ARMATURE', ) - - global_scale = FloatProperty( + global_scale: FloatProperty( name="Scale", description="Scale the BVH by this value", min=0.0001, max=1000000.0, soft_min=0.001, soft_max=100.0, default=1.0, ) - frame_start = IntProperty( + frame_start: IntProperty( name="Start Frame", description="Starting frame for the animation", default=1, ) - use_fps_scale = BoolProperty( + use_fps_scale: BoolProperty( name="Scale FPS", description=( "Scale the framerate from the BVH to the current scenes, " @@ -99,25 +96,25 @@ class ImportBVH(bpy.types.Operator, ImportHelper, ImportBVHOrientationHelper): ), default=False, ) - update_scene_fps = BoolProperty( + update_scene_fps: BoolProperty( name="Update Scene FPS", description=( "Set the scene framerate to that of the BVH file (note that this " "nullifies the 'Scale FPS' option, as the scale will be 1:1)" ), - default=False + default=False, ) - update_scene_duration = BoolProperty( + update_scene_duration: BoolProperty( name="Update Scene Duration", description="Extend the scene's duration to the BVH duration (never shortens the scene)", default=False, ) - use_cyclic = BoolProperty( + use_cyclic: BoolProperty( name="Loop", description="Loop the animation playback", default=False, ) - rotate_mode = EnumProperty( + rotate_mode: EnumProperty( name="Rotation", description="Rotation conversion", items=( @@ -143,7 +140,6 @@ class ImportBVH(bpy.types.Operator, ImportHelper, ImportBVHOrientationHelper): "filter_glob", ) ) - global_matrix = axis_conversion( from_forward=self.axis_forward, from_up=self.axis_up, @@ -161,29 +157,29 @@ class ExportBVH(bpy.types.Operator, ExportHelper): bl_label = "Export BVH" filename_ext = ".bvh" - filter_glob = StringProperty( + filter_glob: StringProperty( default="*.bvh", options={'HIDDEN'}, ) - global_scale = FloatProperty( + global_scale: FloatProperty( name="Scale", description="Scale the BVH by this value", min=0.0001, max=1000000.0, soft_min=0.001, soft_max=100.0, default=1.0, ) - frame_start = IntProperty( + frame_start: IntProperty( name="Start Frame", description="Starting frame to export", default=0, ) - frame_end = IntProperty( + frame_end: IntProperty( name="End Frame", description="End frame to export", default=0, ) - rotate_mode = EnumProperty( + rotate_mode: EnumProperty( name="Rotation", description="Rotation conversion", items=( @@ -198,7 +194,7 @@ class ExportBVH(bpy.types.Operator, ExportHelper): ), default='NATIVE', ) - root_transform_only = BoolProperty( + root_transform_only: BoolProperty( name="Root Translation Only", description="Only write out translation channels for the root bone", default=False, @@ -220,7 +216,14 @@ class ExportBVH(bpy.types.Operator, ExportHelper): self.frame_start = context.scene.frame_start self.frame_end = context.scene.frame_end - keywords = self.as_keywords(ignore=("check_existing", "filter_glob")) + keywords = self.as_keywords( + ignore=( + "axis_forward", + "axis_up", + "check_existing", + "filter_glob", + ) + ) from . import export_bvh return export_bvh.save(context, **keywords) @@ -234,19 +237,25 @@ def menu_func_export(self, context): self.layout.operator(ExportBVH.bl_idname, text="Motion Capture (.bvh)") +classes = ( + ImportBVH, + ExportBVH +) + def register(): - bpy.utils.register_module(__name__) + for cls in classes: + bpy.utils.register_class(cls) - bpy.types.INFO_MT_file_import.append(menu_func_import) - bpy.types.INFO_MT_file_export.append(menu_func_export) + bpy.types.TOPBAR_MT_file_import.append(menu_func_import) + bpy.types.TOPBAR_MT_file_export.append(menu_func_export) def unregister(): - bpy.utils.unregister_module(__name__) - - bpy.types.INFO_MT_file_import.remove(menu_func_import) - bpy.types.INFO_MT_file_export.remove(menu_func_export) + for cls in classes: + bpy.utils.unregister_class(cls) + bpy.types.TOPBAR_MT_file_import.remove(menu_func_import) + bpy.types.TOPBAR_MT_file_export.remove(menu_func_export) if __name__ == "__main__": register() diff --git a/io_anim_bvh/export_bvh.py b/io_anim_bvh/export_bvh.py index 6a0c210f..a8b589df 100644 --- a/io_anim_bvh/export_bvh.py +++ b/io_anim_bvh/export_bvh.py @@ -255,12 +255,12 @@ def write_armature( itrans = Matrix.Translation(-dbone.rest_bone.head_local) if dbone.parent: - mat_final = dbone.parent.rest_arm_mat * dbone.parent.pose_imat * dbone.pose_mat * dbone.rest_arm_imat - mat_final = itrans * mat_final * trans + mat_final = dbone.parent.rest_arm_mat @ dbone.parent.pose_imat @ dbone.pose_mat @ dbone.rest_arm_imat + mat_final = itrans @ mat_final @ trans loc = mat_final.to_translation() + (dbone.rest_bone.head_local - dbone.parent.rest_bone.head_local) else: - mat_final = dbone.pose_mat * dbone.rest_arm_imat - mat_final = itrans * mat_final * trans + mat_final = dbone.pose_mat @ dbone.rest_arm_imat + mat_final = itrans @ mat_final @ trans loc = mat_final.to_translation() + dbone.rest_bone.head # keep eulers compatible, no jumping on interpolation. diff --git a/io_anim_bvh/import_bvh.py b/io_anim_bvh/import_bvh.py index 1f3c93fe..0a9e4b30 100644 --- a/io_anim_bvh/import_bvh.py +++ b/io_anim_bvh/import_bvh.py @@ -348,19 +348,19 @@ def bvh_node_dict2objects(context, bvh_name, bvh_nodes, rotate_mode='NATIVE', fr scene = context.scene for obj in scene.objects: - obj.select = False + obj.select_set("DESELECT") objects = [] def add_ob(name): obj = bpy.data.objects.new(name, None) - scene.objects.link(obj) + context.collection.objects.link(obj) objects.append(obj) - obj.select = True + obj.select_set("SELECT") # nicer drawing. - obj.empty_draw_type = 'CUBE' - obj.empty_draw_size = 0.1 + obj.empty_display_type = 'CUBE' + obj.empty_display_size = 0.1 return obj @@ -422,15 +422,15 @@ def bvh_node_dict2armature( # Add the new armature, scene = context.scene for obj in scene.objects: - obj.select = False + obj.select_set("DESELECT") arm_data = bpy.data.armatures.new(bvh_name) arm_ob = bpy.data.objects.new(bvh_name, arm_data) - scene.objects.link(arm_ob) + context.collection.objects.link(arm_ob) - arm_ob.select = True - scene.objects.active = arm_ob + arm_ob.select_set("SELECT") + context.view_layer.objects.active = arm_ob bpy.ops.object.mode_set(mode='OBJECT', toggle=False) bpy.ops.object.mode_set(mode='EDIT', toggle=False) @@ -580,7 +580,7 @@ def bvh_node_dict2armature( bone_translate_matrix = Matrix.Translation( Vector(bvh_loc) - bvh_node.rest_head_local) - location[frame_i] = (bone_rest_matrix_inv * + location[frame_i] = (bone_rest_matrix_inv @ bone_translate_matrix).to_translation() # For each location x, y, z. @@ -617,8 +617,8 @@ def bvh_node_dict2armature( euler = Euler(bvh_rot, bvh_node.rot_order_str[::-1]) bone_rotation_matrix = euler.to_matrix().to_4x4() bone_rotation_matrix = ( - bone_rest_matrix_inv * - bone_rotation_matrix * + bone_rest_matrix_inv @ + bone_rotation_matrix @ bone_rest_matrix ) diff --git a/io_anim_c3d/__init__.py b/io_anim_c3d/__init__.py index 2c9cd0d6..e14fcaec 100644 --- a/io_anim_c3d/__init__.py +++ b/io_anim_c3d/__init__.py @@ -272,7 +272,7 @@ class C3DImporter(bpy.types.Operator): unames[name] = o.name bpy.ops.transform.resize(value=empty_size) o.show_name = self.properties.show_names - o.show_x_ray = self.properties.x_ray + o.show_in_front = self.properties.x_ray for name in unames.values(): bpy.context.scene.objects[name].select = True return unames @@ -291,7 +291,7 @@ class C3DImporter(bpy.types.Operator): arm = bpy.context.active_object arm.name = os.path.basename(self.properties.filepath) arm.data.show_names = self.properties.show_names - arm.show_x_ray = self.properties.x_ray + arm.show_in_front = self.properties.x_ray for idx, ml in enumerate(ms.markerLabels): name = self.properties.prefix + ml bpy.ops.armature.select_all(action='DESELECT') @@ -354,12 +354,12 @@ def menu_func(self, context): def register(): bpy.utils.register_module(__name__) - bpy.types.INFO_MT_file_import.append(menu_func) + bpy.types.TOPBAR_MT_file_import.append(menu_func) def unregister(): bpy.utils.unregister_module(__name__) - bpy.types.INFO_MT_file_import.remove(menu_func) + bpy.types.TOPBAR_MT_file_import.remove(menu_func) if __name__ == "__main__": diff --git a/io_anim_camera.py b/io_anim_camera.py index 20cb5395..b382a32d 100644 --- a/io_anim_camera.py +++ b/io_anim_camera.py @@ -22,7 +22,7 @@ bl_info = { "name": "Export Camera Animation", "author": "Campbell Barton", "version": (0, 1), - "blender": (2, 57, 0), + "blender": (2, 80, 0), "location": "File > Export > Cameras & Markers (.py)", "description": "Export Cameras & Markers (.py)", "warning": "", @@ -45,7 +45,7 @@ def write_cameras(context, filepath, frame_start, frame_end, only_selected=False 'dof_distance', 'clip_start', 'clip_end', - 'draw_size', + 'display_size', ) obj_attrs = ( @@ -59,7 +59,7 @@ def write_cameras(context, filepath, frame_start, frame_end, only_selected=False cameras = [] for obj in scene.objects: - if only_selected and not obj.select: + if only_selected and not obj.select_get(): continue if obj.type != 'CAMERA': continue @@ -84,7 +84,7 @@ def write_cameras(context, filepath, frame_start, frame_end, only_selected=False for attr in obj_attrs: fw("obj.%s = %s\n" % (attr, repr(getattr(obj, attr)))) - fw("scene.objects.link(obj)\n") + fw("bpy.context.collection.objects.link(obj)\n") fw("cameras[%r] = obj\n" % obj.name) fw("\n") @@ -134,15 +134,15 @@ class CameraExporter(bpy.types.Operator, ExportHelper): bl_label = "Export Camera & Markers" filename_ext = ".py" - filter_glob = StringProperty(default="*.py", options={'HIDDEN'}) + filter_glob: StringProperty(default="*.py", options={'HIDDEN'}) - frame_start = IntProperty(name="Start Frame", + frame_start: IntProperty(name="Start Frame", description="Start frame for export", default=1, min=1, max=300000) - frame_end = IntProperty(name="End Frame", + frame_end: IntProperty(name="End Frame", description="End frame for export", default=250, min=1, max=300000) - only_selected = BoolProperty(name="Only Selected", + only_selected: BoolProperty(name="Only Selected", default=True) def execute(self, context): @@ -165,15 +165,13 @@ def menu_export(self, context): def register(): - bpy.utils.register_module(__name__) - - bpy.types.INFO_MT_file_export.append(menu_export) + bpy.utils.register_class(CameraExporter) + bpy.types.TOPBAR_MT_file_export.append(menu_export) def unregister(): - bpy.utils.unregister_module(__name__) - - bpy.types.INFO_MT_file_export.remove(menu_export) + bpy.utils.unregister_class(CameraExporter) + bpy.types.TOPBAR_MT_file_export.remove(menu_export) if __name__ == "__main__": diff --git a/io_anim_nuke_chan/__init__.py b/io_anim_nuke_chan/__init__.py index b3102329..9266c439 100644 --- a/io_anim_nuke_chan/__init__.py +++ b/io_anim_nuke_chan/__init__.py @@ -143,15 +143,15 @@ def menu_func_export(self, context): def register(): bpy.utils.register_class(ImportChan) bpy.utils.register_class(ExportChan) - bpy.types.INFO_MT_file_import.append(menu_func_import) - bpy.types.INFO_MT_file_export.append(menu_func_export) + bpy.types.TOPBAR_MT_file_import.append(menu_func_import) + bpy.types.TOPBAR_MT_file_export.append(menu_func_export) def unregister(): bpy.utils.unregister_class(ImportChan) bpy.utils.unregister_class(ExportChan) - bpy.types.INFO_MT_file_import.remove(menu_func_import) - bpy.types.INFO_MT_file_export.remove(menu_func_export) + bpy.types.TOPBAR_MT_file_import.remove(menu_func_import) + bpy.types.TOPBAR_MT_file_export.remove(menu_func_export) if __name__ == "__main__": diff --git a/io_blend_utils/__init__.py b/io_blend_utils/__init__.py index d44d4754..9d102102 100644 --- a/io_blend_utils/__init__.py +++ b/io_blend_utils/__init__.py @@ -135,14 +135,14 @@ def register(): for cls in classes: bpy.utils.register_class(cls) - bpy.types.INFO_MT_file_external_data.append(menu_func) + bpy.types.TOPBAR_MT_file_external_data.append(menu_func) def unregister(): for cls in classes: bpy.utils.unregister_class(cls) - bpy.types.INFO_MT_file_external_data.remove(menu_func) + bpy.types.TOPBAR_MT_file_external_data.remove(menu_func) if __name__ == "__main__": diff --git a/io_coat3D/__init__.py b/io_coat3D/__init__.py index b5539ede..751e56f7 100644 --- a/io_coat3D/__init__.py +++ b/io_coat3D/__init__.py @@ -19,8 +19,8 @@ bl_info = { "name": "3D-Coat Applink", "author": "Kalle-Samuli Riihikoski (haikalle)", - "version": (3, 5, 22), - "blender": (2, 59, 0), + "version": (5, 0, 00), + "blender": (2, 80, 0), "location": "Scene > 3D-Coat Applink", "description": "Transfer data between 3D-Coat/Blender", "warning": "", @@ -35,10 +35,16 @@ if "bpy" in locals(): importlib.reload(coat) importlib.reload(tex) else: - from . import coat from . import tex +from io_coat3D import tex +import os +import ntpath +import re + +import time import bpy +import subprocess from bpy.types import PropertyGroup from bpy.props import ( BoolProperty, @@ -49,244 +55,1175 @@ from bpy.props import ( ) +bpy.coat3D = dict() +bpy.coat3D['active_coat'] = '' +bpy.coat3D['status'] = 0 + +def folder_size(path): + + tosi = True + while tosi: + list_of_files = [] + for file in os.listdir(path): + list_of_files.append(path + os.sep + file) + + if len(list_of_files) >= 400: + oldest_file = min(list_of_files, key=os.path.getctime) + os.remove(os.path.abspath(oldest_file)) + else: + tosi = False + +def set_exchange_folder(): + platform = os.sys.platform + coat3D = bpy.context.scene.coat3D + Blender_export = "" + + if(platform == 'win32'): + exchange = os.path.expanduser("~") + os.sep + 'Documents' + os.sep + '3D-CoatV4' + os.sep +'Exchange' + if not(os.path.isdir(exchange)): + exchange = os.path.expanduser("~") + os.sep + 'Documents' + os.sep + '3D-CoatV3' + os.sep +'Exchange' + else: + exchange = os.path.expanduser("~") + os.sep + '3D-CoatV4' + os.sep + 'Exchange' + if not(os.path.isdir(exchange)): + exchange = os.path.expanduser("~") + os.sep + '3D-CoatV3' + os.sep + 'Exchange' + if(not(os.path.isdir(exchange))): + exchange = coat3D.exchangedir + + if(os.path.isdir(exchange)): + bpy.coat3D['status'] = 1 + if(platform == 'win32'): + exchange_path = os.path.expanduser("~") + os.sep + 'Documents' + os.sep + '3DC2Blender' + os.sep + 'Exchange_folder.txt' + applink_folder = os.path.expanduser("~") + os.sep + 'Documents' + os.sep + '3DC2Blender' + if(not(os.path.isdir(applink_folder))): + os.makedirs(applink_folder) + else: + exchange_path = os.path.expanduser("~") + os.sep + 'Documents' + os.sep + '3DC2Blender' + os.sep + 'Exchange_folder.txt' + applink_folder = os.path.expanduser("~") + os.sep + 'Documents' + os.sep + '3DC2Blender' + if(not(os.path.isdir(applink_folder))): + os.makedirs(applink_folder) + file = open(exchange_path, "w") + file.write("%s"%(coat3D.exchangedir)) + file.close() + + else: + if(platform == 'win32'): + exchange_path = os.path.expanduser("~") + os.sep + 'Documents' + os.sep + '3DC2Blender' + os.sep + 'Exchange_folder.txt' + else: + exchange_path = os.path.expanduser("~") + os.sep + '3DC2Blender' + os.sep + 'Exchange_folder.txt' + if(os.path.isfile(exchange_path)): + ex_path ='' + + ex_pathh = open(exchange_path) + for line in ex_pathh: + ex_path = line + break + ex_pathh.close() + + if(os.path.isdir(ex_path) and ex_path.rfind('Exchange') >= 0): + exchange = ex_path + bpy.coat3D['status'] = 1 + else: + bpy.coat3D['status'] = 0 + else: + bpy.coat3D['status'] = 0 + if(bpy.coat3D['status'] == 1): + Blender_folder = ("%s%sBlender"%(exchange,os.sep)) + Blender_export = Blender_folder + path3b_now = exchange + path3b_now += ('last_saved_3b_file.txt') + Blender_export += ('%sexport.txt'%(os.sep)) + + if(not(os.path.isdir(Blender_folder))): + os.makedirs(Blender_folder) + Blender_folder = os.path.join(Blender_folder,"run.txt") + file = open(Blender_folder, "w") + file.close() + return exchange + +def set_working_folders(): + platform = os.sys.platform + coat3D = bpy.context.scene.coat3D + if(platform == 'win32'): + folder_objects = os.path.expanduser("~") + os.sep + 'Documents' + os.sep + '3DC2Blender' + os.sep + 'ApplinkObjects' + if(not(os.path.isdir(folder_objects))): + os.makedirs(folder_objects) + else: + folder_objects = os.path.expanduser("~") + os.sep + '3DC2Blender' + os.sep + 'ApplinkObjects' + if(not(os.path.isdir(folder_objects))): + os.makedirs(folder_objects) + + return folder_objects + +def make_texture_list(texturefolder): + texturefolder += ('%stextures.txt'%(os.sep)) + texturelist = [] + + if (os.path.isfile(texturefolder)): + texturefile = open(texturefolder) + index = 0 + for line in texturefile: + if line != '' and index == 0: + line = line.rstrip('\n') + objekti = line + index += 1 + elif index == 1: + line = line.rstrip('\n') + material = line + index += 1 + elif index == 2: + line = line.rstrip('\n') + type = line + index += 1 + elif index == 3: + line = line.rstrip('\n') + address = line + texturelist.append([objekti,material,type,address]) + index = 0 + texturefile.close() + return texturelist + + +''' +#Updating objects MESH part ( Mesh, Vertex Groups, Vertex Colors ) +''' + +def updatemesh(objekti, proxy): + + + #TO DO VERTEX GROUPS, gives an error with this code. + + if(objekti.vertex_groups.keys() != []): + bpy.ops.object.select_all(action='DESELECT') + proxy.select_set('SELECT') + objekti.select_set('SELECT') + bpy.ops.object.vertex_group_copy_to_selected() + bpy.ops.object.select_all(action='DESELECT') + + # UV Set Copy + + proxy.select_set('SELECT') + objekti.select_set('SELECT') + + if len(objekti.data.uv_layers) > 1: + obj_uv_index = objekti.data.uv_layers.active_index + index = 0 + for uv_layer in objekti.data.uv_layers: + if (uv_layer != objekti.data.uv_layers[0]): + proxy.data.uv_layers.new(uv_layer.name) + proxy.data.uv_layers.active_index = index + objekti.data.uv_layers.active_index = index + bpy.ops.object.join_uvs() + index += 1 + proxy.data.uv_layers.active_index = obj_uv_index + + bpy.ops.object.select_all(action='DESELECT') + + #Mesh Copy + + proxy.select_set('SELECT') + obj_data = objekti.data.id_data + objekti.data = proxy.data.id_data + objekti.data.id_data.name = obj_data.name + if (bpy.data.meshes[obj_data.name].users == 0): + bpy.data.meshes.remove(obj_data) + + + +class SCENE_PT_Main(bpy.types.Panel): + bl_label = "3D-Coat Applink" + bl_space_type = "VIEW_3D" + bl_region_type = "TOOLS" + bl_context = "objectmode" + bl_options = {'DEFAULT_CLOSED'} + + def draw(self, context): + layout = self.layout + coat = bpy.coat3D + coat3D = bpy.context.scene.coat3D + if(bpy.context.active_object): + coa = bpy.context.active_object.coat3D + + if(coat['status'] == 0): + row = layout.row() + row.label(text="Applink didn't find your 3d-Coat/Excahnge folder.") + row = layout.row() + row.label("Please select it before using Applink.") + row = layout.row() + row.prop(coat3D,"exchangedir",text="") + row = layout.row() + row.operator("update_exchange_folder.pilgway_3d_coat", text="Apply folder") + + else: + #Here you add your GUI + row = layout.row() + row.prop(coat3D,"type",text = "") + row = layout.row() + colL = row.column() + colR = row.column() + + colR.operator("export_applink.pilgway_3d_coat", text="Transfer") + colL.operator("import_applink.pilgway_3d_coat", text="Update") + + +def running(): + n=0# number of instances of the program running + prog=[line.split() for line in subprocess.check_output("tasklist").splitlines()] + [prog.pop(e) for e in [0,1,2]] #useless + for task in prog: + if str(task[0]) == "b'3D-CoatDX64C.exe'" or str(task[0]) == "b'3D-CoatGL64C.exe'": + n+=1 + break + if n>0: + return True + else: + return False + +class SCENE_OT_folder(bpy.types.Operator): + bl_idname = "update_exchange_folder.pilgway_3d_coat" + bl_label = "Export your custom property" + bl_description = "Export your custom property" + bl_options = {'UNDO'} + + def invoke(self, context, event): + coat3D = bpy.context.scene.coat3D + + if(os.path.isdir(coat3D.exchangedir)): + coat3D.exchange_found = True + else: + coat3D.exchange_found = False + + return {'FINISHED'} + +class SCENE_OT_opencoat(bpy.types.Operator): + bl_idname = "open_3dcoat.pilgway_3d_coat" + bl_label = "Export your custom property" + bl_description = "Export your custom property" + bl_options = {'UNDO'} + + def invoke(self, context, event): + coat3D = bpy.context.selected_objects[0].coat3D.applink_3b_path + platform = os.sys.platform + prog_path = os.environ['PROGRAMFILES'] + if (platform == 'win32'): + index = 0 + for file in os.listdir(prog_path): + if index == 0: + if file.startswith('3D-Coat-V4'): + modi = os.path.getmtime(prog_path + os.sep + file) + active_3dcoat = prog_path + os.sep + file + index += 1 + else: + if file.startswith('3D-Coat-V4'): + if(os.path.getmtime(prog_path + os.sep + file) > modi): + modi = os.path.getmtime(prog_path + os.sep + file) + active_3dcoat = prog_path + os.sep + file + + if running() == False: + + os.popen('"' + active_3dcoat + os.sep + '3D-CoatDX64C.exe' '" ' + coat3D) + else: + importfile = bpy.context.scene.coat3D.exchangedir + importfile += ('%simport.txt' % (os.sep)) + file = open(importfile, "w") + file.write("%s" % (coat3D)) + file.write("\n%s" % (coat3D)) + file.write("\n[3B]") + file.close() + + ''' + If not Windows Os it will only write import.txt. Auto run 3d-coat.exe is disabled. + ''' + + else: + importfile = bpy.context.scene.coat3D.exchangedir + importfile += ('%simport.txt' % (os.sep)) + file = open(importfile, "w") + file.write("%s" % (coat3D)) + file.write("\n%s" % (coat3D)) + file.write("\n[3B]") + file.close() + + + + return {'FINISHED'} + +class SCENE_OT_export(bpy.types.Operator): + bl_idname = "export_applink.pilgway_3d_coat" + bl_label = "Export your custom property" + bl_description = "Export your custom property" + bl_options = {'UNDO'} + + def invoke(self, context, event): + + for mesh in bpy.data.meshes: + if (mesh.users == 0 and mesh.coat3D.name == '3DC'): + bpy.data.meshes.remove(mesh) + + for material in bpy.data.materials: + if (material.users == 1 and material.coat3D.name == '3DC'): + bpy.data.materials.remove(material) + + export_ok = False + coat3D = bpy.context.scene.coat3D + + if (bpy.context.selected_objects == []): + return {'FINISHED'} + else: + for objec in bpy.context.selected_objects: + if objec.type == 'MESH': + export_ok = True + if (export_ok == False): + return {'FINISHED'} + + activeobj = bpy.context.active_object.name + checkname = '' + coa = bpy.context.active_object.coat3D + coat3D.exchangedir = set_exchange_folder() + + if (not os.path.isdir(coat3D.exchangedir)): + coat3D.exchange_found = False + return {'FINISHED'} + + + folder_objects = set_working_folders() + folder_size(folder_objects) + + importfile = coat3D.exchangedir + texturefile = coat3D.exchangedir + importfile += ('%simport.txt'%(os.sep)) + texturefile += ('%stextures.txt'%(os.sep)) + + looking = True + object_index = 0 + + while(looking == True): + checkname = folder_objects + os.sep + activeobj + checkname = ("%s%.2d.fbx"%(checkname,object_index)) + if(os.path.isfile(checkname)): + object_index += 1 + else: + looking = False + coa.applink_name = ("%s%.2d"%(activeobj,object_index)) + coa.applink_address = checkname + + matindex = 0 + for objekti in bpy.context.selected_objects: + if(objekti.material_slots.keys() == []): + newmat = bpy.data.materials.new('Material') + newmat.use_nodes = True + objekti.data.materials.append(newmat) + matindex += 1 + + for objekti in bpy.context.selected_objects: + objekti.coat3D.applink_scale = objekti.scale + + bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY') + #bpy.ops.object.transforms_to_deltas(mode='SCALE') + + if(coat3D.type == 'ppp' or coat3D.type == 'mv' or coat3D.type == 'ptex'): + bpy.ops.export_scene.fbx(filepath=coa.applink_address, use_selection=True, use_mesh_modifiers=False, axis_forward='X', axis_up='Y') + else: + bpy.ops.export_scene.fbx(filepath=coa.applink_address, use_selection=True, use_mesh_modifiers=False, axis_up='Z', axis_forward='Y') + + + file = open(importfile, "w") + file.write("%s"%(checkname)) + file.write("\n%s"%(checkname)) + file.write("\n[%s]"%(coat3D.type)) + file.close() + group_index = -1.0 + + for objekti in bpy.context.selected_objects: + nimi = '' + for koko in bpy.context.selected_objects: + nimi += koko.data.name + ':::' + objekti.coat3D.applink_group = nimi + objekti.coat3D.applink_address = coa.applink_address + objekti.coat3D.obj_mat = '' + objekti.coat3D.applink_name = coa.applink_name + objekti.coat3D.applink_firsttime = True + objekti.coat3D.objecttime = str(os.path.getmtime(objekti.coat3D.applink_address)) + objekti.data.coat3D.name = '3DC' + + if(objekti.material_slots.keys() != []): + for material in objekti.material_slots: + if material.material.use_nodes == True: + for node in material.material.node_tree.nodes: + if(node.name.startswith('3DC_') == True): + material.material.node_tree.nodes.remove(node) + + return {'FINISHED'} + +class SCENE_OT_import(bpy.types.Operator): + bl_idname = "import_applink.pilgway_3d_coat" + bl_label = "import your custom property" + bl_description = "import your custom property" + bl_options = {'UNDO'} + + def invoke(self, context, event): + + for mesh in bpy.data.meshes: + if(mesh.users == 0 and mesh.coat3D.name == '3DC'): + bpy.data.meshes.remove(mesh) + + for material in bpy.data.materials: + img_list = [] + if (material.users == 1 and material.coat3D.name == '3DC'): + if material.use_nodes == True: + for node in material.node_tree.nodes: + if node.type == 'TEX_IMAGE' and node.name.startswith('3DC'): + img_list.append(node.image) + if img_list != []: + for del_img in img_list: + bpy.data.images.remove(del_img) + + bpy.data.materials.remove(material) + + coat3D = bpy.context.scene.coat3D + coat = bpy.coat3D + coat3D.exchangedir = set_exchange_folder() + + + texturelist = make_texture_list(coat3D.exchangedir) + for texturepath in texturelist: + for image in bpy.data.images: + if(image.filepath == texturepath[3] and image.users == 0): + bpy.data.images.remove(image) + + Blender_folder = ("%s%sBlender"%(coat3D.exchangedir,os.sep)) + Blender_export = Blender_folder + path3b_now = coat3D.exchangedir + path3b_now += ('last_saved_3b_file.txt') + Blender_export += ('%sexport.txt'%(os.sep)) + new_applink_address = 'False' + new_object = False + if(os.path.isfile(Blender_export)): + obj_pathh = open(Blender_export) + new_object = True + for line in obj_pathh: + new_applink_address = line + break + obj_pathh.close() + + for scene_objects in bpy.context.collection.objects: + if(scene_objects.type == 'MESH'): + if(scene_objects.coat3D.applink_address == new_applink_address): + new_object = False + + exportfile = coat3D.exchangedir + exportfile += ('%sBlender' % (os.sep)) + exportfile += ('%sexport.txt' % (os.sep)) + if (os.path.isfile(exportfile)): + os.remove(exportfile) + + if(new_object == False): + + ''' + #Blender -> 3DC -> Blender workflow + #First check if objects needs to be imported, if imported it will then delete extra mat and objs. + ''' + + old_materials = bpy.data.materials.keys() + old_objects = bpy.data.objects.keys() + old_images = bpy.data.images.keys() + image_list = [] + object_list = [] + import_list = [] + mesh_del_list = [] + for objekti in bpy.context.scene.collection.all_objects: + if (objekti.type == 'MESH'): + object_list.append(objekti.name) + obj_coat = objekti.coat3D + if(obj_coat.applink_address != ''): + if (obj_coat.objecttime != str(os.path.getmtime(obj_coat.applink_address))): + obj_coat.dime = objekti.dimensions + obj_coat.import_mesh = True + obj_coat.objecttime = str(os.path.getmtime(obj_coat.applink_address)) + if(obj_coat.applink_address not in import_list): + import_list.append(obj_coat.applink_address) + print('image:', bpy.data.images) + if(import_list): + for list in import_list: + bpy.ops.import_scene.fbx(filepath=list, global_scale = 1,axis_forward='X') + + bpy.ops.object.select_all(action='DESELECT') + + new_materials = bpy.data.materials.keys() + new_objects = bpy.data.objects.keys() + new_images = bpy.data.images.keys() + + + diff_mat = [i for i in new_materials if i not in old_materials] + diff_objects = [i for i in new_objects if i not in old_objects] + + for mark_mesh in diff_objects: + bpy.data.objects[mark_mesh].data.coat3D.name = '3DC' + for c_index in diff_mat: + bpy.data.materials.remove(bpy.data.materials[c_index]) + '''The main Applink Object Loop''' + + for oname in object_list: + objekti = bpy.data.objects[oname] + if(objekti.coat3D.import_mesh and coat3D.importmesh == True): + objekti.coat3D.import_mesh = False + objekti.select_set('SELECT') + + new_name = objekti.data.name + name_boxs = new_name.split('.') + if len(name_boxs) > 1: + if len(name_boxs[-1]) == 3: + luku = int(name_boxs[-1]) + luku +=1 + uusi_nimi = ("%s.%.3d" % (new_name[:-4], luku)) + find_name = uusi_nimi + else: + find_name = objekti.data.name + tosi = True + luku = 1 + find_name = ("%s.%.3d" % (objekti.data.name, luku)) + loyty = False + while tosi: + for obj in bpy.data.meshes: + if (obj.name == find_name): + loyty = True + break + if(loyty == True): + luku += 1 + find_name = ("%s.%.3d" % (objekti.data.name, luku)) + loyty = False + else: + find_name = ("%s.%.3d" % (objekti.data.name, luku-1)) + tosi = False + + for proxy_objects in diff_objects: + if (bpy.data.objects[proxy_objects].data.name == find_name): + obj_proxy = bpy.data.objects[proxy_objects] + break + + exportfile = coat3D.exchangedir + path3b_n = coat3D.exchangedir + path3b_n += ('last_saved_3b_file.txt') + exportfile += ('%sBlender' % (os.sep)) + exportfile += ('%sexport.txt'%(os.sep)) + if(os.path.isfile(exportfile)): + export_file = open(exportfile) + for line in export_file: + if line.rfind('.3b'): + coat['active_coat'] = line + export_file.close() + os.remove(exportfile) + + obj_names = objekti.coat3D.applink_group + obj_list = obj_names.split(':::') + applinks = [] + mat_list = [] + obj_list.pop() + + use_smooth = objekti.data.polygons[0].use_smooth + + if(objekti.material_slots): + act_mat = objekti.active_material + for obj_mat in objekti.material_slots: + mat_list.append(obj_mat.material) + + bpy.ops.object.select_all(action='DESELECT') + obj_proxy.select_set('SELECT') + + bpy.ops.object.select_all(action='TOGGLE') + + if objekti.coat3D.applink_firsttime == True: + objekti.scale = (objekti.scale[0]/objekti.coat3D.applink_scale[0],objekti.scale[1]/objekti.coat3D.applink_scale[1],objekti.scale[2]/objekti.coat3D.applink_scale[2]) + bpy.ops.object.transforms_to_deltas(mode='SCALE') + objekti.rotation_euler = (0,0,0) + objekti.scale = (0.01,0.01,0.01) + objekti.coat3D.applink_firsttime = False + + if(coat3D.importlevel): + obj_proxy.select = True + obj_proxy.modifiers.new(name='temp',type='MULTIRES') + objekti.select = True + bpy.ops.object.multires_reshape(modifier=multires_name) + bpy.ops.object.select_all(action='TOGGLE') + multires_on = False + else: + updatemesh(objekti,obj_proxy) + + #tärkee että saadaan oikein käännettyä objekt + + objekti.select_set('SELECT') + bpy.ops.object.origin_set(type='GEOMETRY_ORIGIN') + + objekti.data.materials.pop() + for mat in mat_list: + objekti.data.materials.append(mat) + + if (use_smooth): + for data_mesh in objekti.data.polygons: + data_mesh.use_smooth = True + + bpy.ops.object.select_all(action='DESELECT') + + if(os.path.isfile(path3b_n)): + path3b_fil = open(path3b_n) + for lin in path3b_fil: + objekti.coat3D.applink_3b_path = lin + head, tail = os.path.split(objekti.coat3D.applink_3b_path) + objekti.coat3D.applink_3b_just_name = tail + path3b_fil.close() + os.remove(path3b_n) + + if(coat3D.importmesh and not(os.path.isfile(objekti.coat3D.applink_address))): + coat3D.importmesh = False + + objekti.select_set('SELECT') + if(coat3D.importtextures): + is_new = False + print('matlist: ', mat_list) + print('objekti: ', objekti) + print('is_new: ', is_new) + tex.matlab(objekti,mat_list,texturelist,is_new) + objekti.select_set('DESELECT') + else: + mat_list = [] + + if (objekti.material_slots): + for obj_mat in objekti.material_slots: + mat_list.append(obj_mat.material) + + if (coat3D.importtextures): + is_new = False + print('matlist: ',mat_list) + print('objekti: ', objekti) + print('is_new: ', is_new) + tex.matlab(objekti,mat_list,texturelist, is_new) + objekti.select_set('DESELECT') + + + bpy.ops.object.select_all(action='DESELECT') + if(import_list): + for del_obj in diff_objects: + bpy.context.collection.all_objects[del_obj].select_set('SELECT') + bpy.ops.object.delete() + + + + else: + + ''' + 3DC -> Blender workflow + ''' + + for old_obj in bpy.context.collection.objects: + old_obj.coat3D.applink_old = True + + coat3D = bpy.context.scene.coat3D + scene = context.scene + Blender_folder = ("%s%sBlender"%(coat3D.exchangedir,os.sep)) + Blender_export = Blender_folder + path3b_now = coat3D.exchangedir + os.sep + path3b_now += ('last_saved_3b_file.txt') + Blender_export += ('%sexport.txt'%(os.sep)) + mat_list = [] + nimi = '' + osoite_3b = '' + if (os.path.isfile(path3b_now)): + path3b_fil = open(path3b_now) + for lin in path3b_fil: + osoite_3b = lin + path3b_fil.close() + head, tail = os.path.split(osoite_3b) + just_3b_name = tail + os.remove(path3b_now) + + old_materials = bpy.data.materials.keys() + old_objects = bpy.data.objects.keys() + + bpy.ops.import_scene.fbx(filepath=new_applink_address) + + new_materials = bpy.data.materials.keys() + new_objects = bpy.data.objects.keys() + + diff_mat = [i for i in new_materials if i not in old_materials] + diff_objects = [i for i in new_objects if i not in old_objects] + + for mark_mesh in diff_mat: + bpy.data.materials[mark_mesh].coat3D.name = '3DC' + bpy.data.materials[mark_mesh].use_fake_user = True + laskuri = 0 + for c_index in diff_objects: + bpy.data.objects[c_index].data.coat3D.name = '3DC' + bpy.data.objects[c_index].material_slots[0].material = bpy.data.materials[diff_mat[laskuri]] + laskuri += 1 + + bpy.ops.object.select_all(action='DESELECT') + for new_obj in bpy.context.collection.objects: + + if(new_obj.coat3D.applink_old == False): + nimi += new_obj.data.name + ':::' + new_obj.select_set('SELECT') + #bpy.ops.object.origin_set(type='GEOMETRY_ORIGIN') + new_obj.rotation_euler = (0, 0, 0) + new_obj.scale = (1, 1, 1) + new_obj.coat3D.applink_firsttime = False + new_obj.select_set('DESELECT') + new_obj.coat3D.applink_address = new_applink_address + new_obj.coat3D.objecttime = str(os.path.getmtime(new_obj.coat3D.applink_address)) + splittext = ntpath.basename(new_applink_address) + new_obj.coat3D.applink_name = splittext.split('.')[0] + new_obj.coat3D.applink_export = True + if(osoite_3b != ''): + new_obj.coat3D.applink_3b_path = osoite_3b + new_obj.coat3D.applink_3b_just_name = just_3b_name + + mat_list.append(new_obj.material_slots[0].material) + is_new = True + tex.matlab(mat_list, new_obj, bpy.context.scene, is_new) + + for new_obj in bpy.context.collection.objects: + if(new_obj.coat3D.applink_old == False): + new_obj.coat3D.applink_group = nimi + new_obj.coat3D.applink_old = True + + bpy.ops.object.select_all(action='SELECT') + bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY') + bpy.ops.object.select_all(action='DESELECT') + if (os.path.isfile(Blender_export)): + os.remove(Blender_export) + for material in bpy.data.materials: + if material.use_nodes == True: + for node in material.node_tree.nodes: + if (node.name).startswith('3DC'): + node.location = node.location + + return {'FINISHED'} + +from bpy import * +from mathutils import Vector, Matrix + +class ObjectButtonsPanel(): + bl_space_type = 'PROPERTIES' + bl_region_type = 'WINDOW' + bl_context = "object" + +class SCENE_PT_Settings(ObjectButtonsPanel,bpy.types.Panel): + bl_label = "3D-Coat Applink Settings" + bl_space_type = "PROPERTIES" + bl_region_type = "WINDOW" + bl_context = "scene" + + def draw(self, context): + pass + +class SCENE_PT_Settings_Update(ObjectButtonsPanel, bpy.types.Panel): + bl_label = "Update" + bl_parent_id = "SCENE_PT_Settings" + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'} + + def draw(self, context): + layout = self.layout + layout.use_property_split = False + coat3D = bpy.context.scene.coat3D + + rd = context.scene.render + + layout.active = True + + flow = layout.grid_flow(row_major=True, columns=0, even_columns=False, even_rows=False, align=True) + + col = flow.column() + col.prop(coat3D, "importmesh", text="Update Mesh") + col = flow.column() + col.prop(coat3D, "createnodes", text="Create Extra Nodes") + col = flow.column() + col.prop(coat3D, "importtextures", text="Update Textures") + col = flow.column() + col.prop(coat3D, "creategroup", text="Group Nodes") + +class SCENE_PT_Settings_Folders(ObjectButtonsPanel, bpy.types.Panel): + bl_label = "Folders" + bl_parent_id = "SCENE_PT_Settings" + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'} + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + coat3D = bpy.context.scene.coat3D + + rd = context.scene.render + + layout.active = True + + flow = layout.grid_flow(row_major=True, columns=0, even_columns=False, even_rows=False, align=True) + + col = flow.column() + col.prop(coat3D, "exchangedir", text="Exchange folder") + + col = flow.column() + col.prop(coat3D, "coat3D_exe", text="3D-Coat.exe") + +# 3D-Coat Dynamic Menu +class VIEW3D_MT_Coat_Dynamic_Menu(bpy.types.Menu): + bl_label = "3D-Coat Applink Menu" + + def draw(self, context): + layout = self.layout + + layout.operator_context = 'INVOKE_REGION_WIN' + + ob = context + if ob.mode == 'OBJECT': + if(len(context.selected_objects) > 0): + layout.operator("import_applink.pilgway_3d_coat", text="Update Scene") + layout.separator() + + layout.operator("export_applink.pilgway_3d_coat", text="Copy selected object(s) into 3D-Coat") + layout.separator() + if(context.selected_objects[0].coat3D.applink_3b_path != ''): + layout.operator("open_3dcoat.pilgway_3d_coat", text="Open " +context.selected_objects[0].coat3D.applink_3b_just_name) + layout.separator() + + else: + layout.operator("import_applink.pilgway_3d_coat", text="Update Scene") + layout.separator() + +class VIEW3D_MT_ImportMenu(bpy.types.Menu): + bl_label = "Import Settings" + + def draw(self, context): + layout = self.layout + coat3D = bpy.context.scene.coat3D + settings = context.tool_settings + layout.operator_context = 'INVOKE_REGION_WIN' + layout.prop(coat3D,"importmesh") + layout.prop(coat3D,"importmod") + layout.prop(coat3D,"smooth_on") + layout.prop(coat3D,"importtextures") + +class VIEW3D_MT_ExportMenu(bpy.types.Menu): + bl_label = "Export Settings" + + def draw(self, context): + layout = self.layout + coat3D = bpy.context.scene.coat3D + settings = context.tool_settings + + layout.operator_context = 'INVOKE_REGION_WIN' + layout.operator("view3d.copybuffer", icon="COPY_ID") + + layout.prop(coat3D,"exportover") + if(coat3D.exportover): + layout.prop(coat3D,"exportmod") + +class VIEW3D_MT_ExtraMenu(bpy.types.Menu): + bl_label = "Extra" + + def draw(self, context): + layout = self.layout + coat3D = bpy.context.scene.coat3D + settings = context.tool_settings + layout.operator_context = 'INVOKE_REGION_WIN' + + layout.operator("import_applink.pilgway_3d_deltex",text="Delete all Textures") + layout.separator() + +class ObjectCoat3D(PropertyGroup): + objpath: StringProperty( + name="Object_Path" + ) + obj_mat: StringProperty( + name="Object_Path", + default='' + ) + applink_address: StringProperty( + name="Object_Applink_address" + ) + applink_3b_path: StringProperty( + name="Object_3B_Path" + ) + applink_name: StringProperty( + name="Applink object name" + ) + applink_3b_just_name: StringProperty( + name="Applink object name" + ) + applink_group: StringProperty( + name="Applink group" + ) + applink_firsttime: BoolProperty( + name="FirstTime", + description="FirstTime", + default=True + ) + import_mesh: BoolProperty( + name="ImportMesh", + description="ImportMesh", + default=False + ) + applink_old: BoolProperty( + name="OldObject", + description="Old Object", + default=False + ) + applink_export: BoolProperty( + name="FirstTime", + description="Object is from 3d-ocat", + default=False + ) + objecttime: StringProperty( + name="ObjectTime", + subtype="FILE_PATH" + ) + path3b: StringProperty( + name="3B Path", + subtype="FILE_PATH" + ) + dime: FloatVectorProperty( + name="dime", + description="Dimension" + ) + applink_scale: FloatVectorProperty( + name="Scale", + description="Scale" + ) + +class SceneCoat3D(PropertyGroup): + defaultfolder: StringProperty( + name="FilePath", + subtype="DIR_PATH", + ) + coat3D_exe: StringProperty( + name="FilePath", + subtype="DIR_PATH", + ) + cursor_loc: FloatVectorProperty( + name="Cursor_loc", + description="location" + ) + exchangedir: StringProperty( + name="FilePath", + subtype="DIR_PATH" + ) + exchangefolder: StringProperty( + name="FilePath", + subtype="DIR_PATH" + ) + wasactive: StringProperty( + name="Pass active object", + ) + import_box: BoolProperty( + name="Import window", + description="Allows to skip import dialog", + default=True + ) + exchange_found: BoolProperty( + name="Exchange Found", + description="Alert if Exchange folder is not found", + default=True + ) + export_box: BoolProperty( + name="Export window", + description="Allows to skip export dialog", + default=True + ) + export_color: BoolProperty( + name="Export color", + description="Export color texture", + default=True + ) + export_spec: BoolProperty( + name="Export specular", + description="Export specular texture", + default=True + ) + export_normal: BoolProperty( + name="Export Normal", + description="Export normal texture", + default=True + ) + export_disp: BoolProperty( + name="Export Displacement", + description="Export displacement texture", + default=True + ) + export_position: BoolProperty( + name="Export Source Position", + description="Export source position", + default=True + ) + export_zero_layer: BoolProperty( + name="Export from Layer 0", + description="Export mesh from Layer 0", + default=True + ) + export_coarse: BoolProperty( + name="Export Coarse", + description="Export Coarse", + default=True + ) + exportfile: BoolProperty( + name="No Import File", + description="Add Modifiers and export", + default=False + ) + importmod: BoolProperty( + name="Remove Modifiers", + description="Import and add modifiers", + default=False + ) + exportmod: BoolProperty( + name="Modifiers", + description="Export modifiers", + default=False + ) + export_pos: BoolProperty( + name="Remember Position", + description="Remember position", + default=True + ) + importtextures: BoolProperty( + name="Bring Textures", + description="Import Textures", + default=True + ) + createnodes: BoolProperty( + name="Bring Textures", + description="Import Textures", + default=True + ) + creategroup: BoolProperty( + name="Bring Textures", + description="Import Textures", + default=True + ) + importlevel: BoolProperty( + name="Multires. Level", + description="Bring Specific Multires Level", + default=False + ) + exportover: BoolProperty( + name="Export Obj", + description="Import Textures", + default=False + ) + importmesh: BoolProperty( + name="Mesh", + description="Import Mesh", + default=True + ) + + # copy location + + loca: FloatVectorProperty( + name="location", + description="Location", + subtype="XYZ", + default=(0.0, 0.0, 0.0) + ) + rota: FloatVectorProperty( + name="location", + description="Location", + subtype="EULER", + default=(0.0, 0.0, 0.0) + ) + scal: FloatVectorProperty( + name="location", + description="Location", + subtype="XYZ", + default=(0.0, 0.0, 0.0) + ) + dime: FloatVectorProperty( + name="dimension", + description="Dimension", + subtype="XYZ", + default=(0.0, 0.0, 0.0) + ) + type: EnumProperty( + name="Export Type", + description="Different Export Types", + items=(("ppp", "Per-Pixel Painting", ""), + ("mv", "Microvertex Painting", ""), + ("ptex", "Ptex Painting", ""), + ("uv", "UV-Mapping", ""), + ("ref", "Reference Mesh", ""), + ("retopo", "Retopo mesh as new layer", ""), + ("vox", "Mesh As Voxel Object", ""), + ("alpha", "Mesh As New Pen Alpha", ""), + ("prim", "Mesh As Voxel Primitive", ""), + ("curv", "Mesh As a Curve Profile", ""), + ("autopo", "Mesh For Auto-retopology", ""), + ), + default="ppp" + ) +class MeshCoat3D(PropertyGroup): + applink_address: StringProperty( + name="ApplinkAddress", + subtype="APPLINK_ADDRESS", + ) +class MaterialCoat3D(PropertyGroup): + name: StringProperty( + name="ApplinkAddress", + subtype="APPLINK_ADDRESS", + ) + +classes = ( + #ObjectButtonsPanel, + SCENE_PT_Main, + SCENE_PT_Settings, + SCENE_PT_Settings_Update, + SCENE_PT_Settings_Folders, + SCENE_OT_folder, + SCENE_OT_opencoat, + SCENE_OT_export, + SCENE_OT_import, + VIEW3D_MT_Coat_Dynamic_Menu, + #VIEW3D_MT_ImportMenu, + #VIEW3D_MT_ExportMenu, + #VIEW3D_MT_ExtraMenu, + ObjectCoat3D, + SceneCoat3D, + MeshCoat3D, + MaterialCoat3D, + ) + def register(): bpy.coat3D = dict() bpy.coat3D['active_coat'] = '' - bpy.coat3D['status'] = 0 + bpy.coat3D['status'] = 1 bpy.coat3D['kuva'] = 1 - class ObjectCoat3D(PropertyGroup): - objpath = StringProperty( - name="Object_Path" - ) - applink_name = StringProperty( - name="Object_Applink_name" - ) - coatpath = StringProperty( - name="Coat_Path" - ) - objectdir = StringProperty( - name="ObjectPath", - subtype="FILE_PATH" - ) - objecttime = StringProperty( - name="ObjectTime", - subtype="FILE_PATH" - ) - texturefolder = StringProperty( - name="Texture folder:", - subtype="DIR_PATH" - ) - path3b = StringProperty( - name="3B Path", - subtype="FILE_PATH" - ) - export_on = BoolProperty( - name="Export_On", - description="Add Modifiers and export", - default=False - ) - dime = FloatVectorProperty( - name="dime", - description="Dimension" - ) - loc = FloatVectorProperty( - name="Location", - description="Location" - ) - rot = FloatVectorProperty( - name="Rotation", - description="Rotation", - subtype='EULER' - ) - sca = FloatVectorProperty( - name="Scale", - description="Scale" - ) - - class SceneCoat3D(PropertyGroup): - defaultfolder = StringProperty( - name="FilePath", - subtype="DIR_PATH", - ) - cursor_loc = FloatVectorProperty( - name="Cursor_loc", - description="location" - ) - exchangedir = StringProperty( - name="FilePath", - subtype="DIR_PATH" - ) - exchangefolder = StringProperty( - name="FilePath", - subtype="DIR_PATH" - ) - wasactive = StringProperty( - name="Pass active object", - ) - import_box = BoolProperty( - name="Import window", - description="Allows to skip import dialog", - default=True - ) - exchange_found = BoolProperty( - name="Exchange Found", - description="Alert if Exchange folder is not found", - default=True - ) - export_box = BoolProperty( - name="Export window", - description="Allows to skip export dialog", - default=True - ) - export_color = BoolProperty( - name="Export color", - description="Export color texture", - default=True - ) - export_spec = BoolProperty( - name="Export specular", - description="Export specular texture", - default=True - ) - export_normal = BoolProperty( - name="Export Normal", - description="Export normal texture", - default=True - ) - export_disp = BoolProperty( - name="Export Displacement", - description="Export displacement texture", - default=True - ) - export_position = BoolProperty( - name="Export Source Position", - description="Export source position", - default=True - ) - export_zero_layer = BoolProperty( - name="Export from Layer 0", - description="Export mesh from Layer 0", - default=True - ) - export_coarse = BoolProperty( - name="Export Coarse", - description="Export Coarse", - default=True - ) - exportfile = BoolProperty( - name="No Import File", - description="Add Modifiers and export", - default=False - ) - importmod = BoolProperty( - name="Remove Modifiers", - description="Import and add modifiers", - default=False - ) - exportmod = BoolProperty( - name="Modifiers", - description="Export modifiers", - default=False - ) - export_pos = BoolProperty( - name="Remember Position", - description="Remember position", - default=True - ) - importtextures = BoolProperty( - name="Bring Textures", - description="Import Textures", - default=True - ) - importlevel = BoolProperty( - name="Multires. Level", - description="Bring Specific Multires Level", - default=False - ) - exportover = BoolProperty( - name="Export Obj", - description="Import Textures", - default=False - ) - importmesh = BoolProperty( - name="Mesh", - description="Import Mesh", - default=True - ) - - # copy location - cursor = FloatVectorProperty( - name="Cursor", - description="Location", - subtype="XYZ", - default=(0.0, 0.0, 0.0) - ) - loca = FloatVectorProperty( - name="location", - description="Location", - subtype="XYZ", - default=(0.0, 0.0, 0.0) - ) - rota = FloatVectorProperty( - name="location", - description="Location", - subtype="EULER", - default=(0.0, 0.0, 0.0) - ) - scal = FloatVectorProperty( - name="location", - description="Location", - subtype="XYZ", - default=(0.0, 0.0, 0.0) - ) - dime = FloatVectorProperty( - name="dimension", - description="Dimension", - subtype="XYZ", - default=(0.0, 0.0, 0.0) - ) - type = EnumProperty( - name="Export Type", - description="Different Export Types", - items=(("ppp", "Per-Pixel Painting", ""), - ("mv", "Microvertex Painting", ""), - ("ptex", "Ptex Painting", ""), - ("uv", "UV-Mapping", ""), - ("ref", "Reference Mesh", ""), - ("retopo", "Retopo mesh as new layer", ""), - ("vox", "Mesh As Voxel Object", ""), - ("alpha", "Mesh As New Pen Alpha", ""), - ("prim", "Mesh As Voxel Primitive", ""), - ("curv", "Mesh As a Curve Profile", ""), - ("autopo", "Mesh For Auto-retopology", ""), - ), - default="ppp" - ) - - bpy.utils.register_module(__name__) - - bpy.types.Object.coat3D = PointerProperty( - name="Applink Variables", - type=ObjectCoat3D, - description="Applink variables" - ) - bpy.types.Scene.coat3D = PointerProperty( - name="Applink Variables", - type=SceneCoat3D, - description="Applink variables" - ) + from bpy.utils import register_class + for cls in classes: + register_class(cls) + + bpy.types.Object.coat3D = PointerProperty(type=ObjectCoat3D) + bpy.types.Scene.coat3D = PointerProperty(type=SceneCoat3D) + bpy.types.Mesh.coat3D = PointerProperty(type=MeshCoat3D) + bpy.types.Material.coat3D = PointerProperty(type=MaterialCoat3D) + + kc = bpy.context.window_manager.keyconfigs.addon + if kc: + km = kc.keymaps.new(name="Object Mode") + kmi = km.keymap_items.new('wm.call_menu', 'Q', 'PRESS') + kmi.properties.name = "VIEW3D_MT_Coat_Dynamic_Menu" def unregister(): + import bpy + from bpy.utils import unregister_class del bpy.types.Object.coat3D del bpy.types.Scene.coat3D + del bpy.types.Mesh.coat3D del bpy.coat3D - bpy.utils.unregister_module(__name__) - + kc = bpy.context.window_manager.keyconfigs.addon + if kc: + km = kc.keymaps.get('Object Mode') + for kmi in km.keymap_items: + if kmi.idname == 'wm.call_menu': + if kmi.properties.name == "VIEW3D_MT_Coat_Dynamic_Menu": + km.keymap_items.remove(kmi) -if __name__ == "__main__": - register() + for cls in reversed(classes): + unregister_class(cls) diff --git a/io_coat3D/coat.py b/io_coat3D/coat.py deleted file mode 100644 index fc3cb747..00000000 --- a/io_coat3D/coat.py +++ /dev/null @@ -1,626 +0,0 @@ -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# ***** END GPL LICENCE BLOCK ***** - -import bpy -from bpy.props import * -from io_coat3D import tex -import os - - -bpy.coat3D = dict() -bpy.coat3D['active_coat'] = '' -bpy.coat3D['status'] = 0 -def set_exchange_folder(): - platform = os.sys.platform - coat3D = bpy.context.scene.coat3D - Blender_export = "" - - if(platform == 'win32'): - exchange = os.path.expanduser("~") + os.sep + 'Documents' + os.sep + '3D-CoatV4' + os.sep +'Exchange' - if not(os.path.isdir(exchange)): - exchange = os.path.expanduser("~") + os.sep + 'Documents' + os.sep + '3D-CoatV3' + os.sep +'Exchange' - else: - exchange = os.path.expanduser("~") + os.sep + '3D-CoatV4' + os.sep + 'Exchange' - if not(os.path.isdir(exchange)): - exchange = os.path.expanduser("~") + os.sep + '3D-CoatV3' + os.sep + 'Exchange' - if(not(os.path.isdir(exchange))): - exchange = coat3D.exchangedir - - if(os.path.isdir(exchange)): - bpy.coat3D['status'] = 1 - if(platform == 'win32'): - exchange_path = os.path.expanduser("~") + os.sep + 'Documents' + os.sep + '3DC2Blender' + os.sep + 'Exchange_folder.txt' - applink_folder = os.path.expanduser("~") + os.sep + 'Documents' + os.sep + '3DC2Blender' - if(not(os.path.isdir(applink_folder))): - os.makedirs(applink_folder) - else: - exchange_path = os.path.expanduser("~") + os.sep + 'Documents' + os.sep + '3DC2Blender' + os.sep + 'Exchange_folder.txt' - applink_folder = os.path.expanduser("~") + os.sep + 'Documents' + os.sep + '3DC2Blender' - if(not(os.path.isdir(applink_folder))): - os.makedirs(applink_folder) - file = open(exchange_path, "w") - file.write("%s"%(coat3D.exchangedir)) - file.close() - - else: - if(platform == 'win32'): - exchange_path = os.path.expanduser("~") + os.sep + 'Documents' + os.sep + '3DC2Blender' + os.sep + 'Exchange_folder.txt' - else: - exchange_path = os.path.expanduser("~") + os.sep + '3DC2Blender' + os.sep + 'Exchange_folder.txt' - if(os.path.isfile(exchange_path)): - ex_path ='' - - ex_pathh = open(exchange_path) - for line in ex_pathh: - ex_path = line - break - ex_pathh.close() - - if(os.path.isdir(ex_path) and ex_path.rfind('Exchange') >= 0): - exchange = ex_path - bpy.coat3D['status'] = 1 - else: - bpy.coat3D['status'] = 0 - else: - bpy.coat3D['status'] = 0 - if(bpy.coat3D['status'] == 1): - Blender_folder = ("%s%sBlender"%(exchange,os.sep)) - Blender_export = Blender_folder - path3b_now = exchange - path3b_now += ('last_saved_3b_file.txt') - Blender_export += ('%sexport.txt'%(os.sep)) - - if(not(os.path.isdir(Blender_folder))): - os.makedirs(Blender_folder) - Blender_folder = os.path.join(Blender_folder,"run.txt") - file = open(Blender_folder, "w") - file.close() - return exchange - -def set_working_folders(): - platform = os.sys.platform - coat3D = bpy.context.scene.coat3D - if(platform == 'win32'): - folder_objects = os.path.expanduser("~") + os.sep + 'Documents' + os.sep + '3DC2Blender' + os.sep + 'Objects' - folder_textures = os.path.expanduser("~") + os.sep + 'Documents' + os.sep + '3DC2Blender' + os.sep + 'Textures' + os.sep - if(not(os.path.isdir(folder_objects))): - os.makedirs(folder_objects) - if(not(os.path.isdir(folder_textures))): - os.makedirs(folder_textures) - else: - folder_objects = os.path.expanduser("~") + os.sep + '3DC2Blender' + os.sep + 'Objects' - folder_textures = os.path.expanduser("~") + os.sep + '3DC2Blender' + os.sep + 'Textures' + os.sep - if(not(os.path.isdir(folder_objects))): - os.makedirs(folder_objects) - if(not(os.path.isdir(folder_textures))): - os.makedirs(folder_textures) - - - return folder_objects,folder_textures - -class ObjectButtonsPanel(): - bl_space_type = 'PROPERTIES' - bl_region_type = 'WINDOW' - bl_context = "object" - -class SCENE_PT_Main(ObjectButtonsPanel,bpy.types.Panel): - bl_label = "3D-Coat Applink" - bl_space_type = "PROPERTIES" - bl_region_type = "WINDOW" - bl_context = "scene" - - def draw(self, context): - layout = self.layout - scene = context.scene - me = context.scene.objects - mat_list = [] - import_no = 0 - coat = bpy.coat3D - coat3D = bpy.context.scene.coat3D - if(bpy.context.scene.objects.active): - coa = bpy.context.scene.objects.active.coat3D - - - if(bpy.coat3D['status'] == 0 and not(os.path.isdir(coat3D.exchangedir))): - bpy.coat3D['active_coat'] = set_exchange_folder() - row = layout.row() - row.label(text="Applink didn't find your 3d-Coat/Excahnge folder.") - row = layout.row() - row.label("Please select it before using Applink.") - row = layout.row() - row.prop(coat3D,"exchangedir",text="") - - else: - - - #Here you add your GUI - row = layout.row() - row.prop(coat3D,"type",text = "") - row = layout.row() - colL = row.column() - colR = row.column() - - colR.operator("export_applink.pilgway_3d_coat", text="Transfer") - - colL.operator("import_applink.pilgway_3d_coat", text="Update") - - - - - - - - - - -class SCENE_OT_export(bpy.types.Operator): - bl_idname = "export_applink.pilgway_3d_coat" - bl_label = "Export your custom property" - bl_description = "Export your custom property" - bl_options = {'UNDO'} - - def invoke(self, context, event): - checkname = '' - coat3D = bpy.context.scene.coat3D - scene = context.scene - activeobj = bpy.context.active_object.name - obj = scene.objects[activeobj] - coa = bpy.context.scene.objects.active.coat3D - coat3D.exchangedir = set_exchange_folder() - export_ok = False - - folder_objects,folder_textures = set_working_folders() - - if(coat3D.exchange_found == False): - return {'FINISHED'} - - if(bpy.context.selected_objects == []): - return {'FINISHED'} - else: - for objec in bpy.context.selected_objects: - if objec.type == 'MESH': - export_ok = True - if(export_ok == False): - return {'FINISHED'} - - importfile = coat3D.exchangedir - texturefile = coat3D.exchangedir - importfile += ('%simport.txt'%(os.sep)) - texturefile += ('%stextures.txt'%(os.sep)) - - looking = True - object_index = 0 - if(coa.applink_name and os.path.isfile(coa.applink_name)): - checkname = coa.applink_name - - else: - while(looking == True): - checkname = folder_objects + os.sep + activeobj - checkname = ("%s%.2d.obj"%(checkname,object_index)) - if(os.path.isfile(checkname)): - object_index += 1 - else: - looking = False - coa.applink_name = checkname - - - coat3D.cursor_loc = obj.location - coat3D.cursor_orginal = bpy.context.scene.cursor_location - - - - coa.loc = obj.location - coa.rot = obj.rotation_euler - coa.sca = obj.scale - coa.dime = obj.dimensions - - obj.location = (0,0,0) - obj.rotation_euler = (0,0,0) - bpy.ops.object.transform_apply(scale=True) - - bpy.ops.export_scene.obj(filepath=coa.applink_name,use_selection=True, - use_mesh_modifiers=False,use_blen_objects=True, use_materials = True, - keep_vertex_order = True,axis_forward='-Z',axis_up='Y') - - obj.location = coa.loc - obj.rotation_euler = coa.rot - - - bpy.context.scene.cursor_location = coat3D.cursor_loc - bpy.context.scene.cursor_location = coat3D.cursor_orginal - - file = open(importfile, "w") - file.write("%s"%(checkname)) - file.write("\n%s"%(checkname)) - file.write("\n[%s]"%(coat3D.type)) - file.write("\n[TexOutput:%s]"%(folder_textures)) - file.close() - - coa.objecttime = str(os.path.getmtime(coa.applink_name)) - - - - return {'FINISHED'} - -class SCENE_OT_import(bpy.types.Operator): - bl_idname = "import_applink.pilgway_3d_coat" - bl_label = "import your custom property" - bl_description = "import your custom property" - bl_options = {'UNDO'} - - def invoke(self, context, event): - scene = context.scene - coat3D = bpy.context.scene.coat3D - coat = bpy.coat3D - test = bpy.context.selected_objects - act_first = bpy.context.scene.objects.active - bpy.context.scene.game_settings.material_mode = 'GLSL' - coat3D.exchangedir = set_exchange_folder() - - folder_objects,folder_textures = set_working_folders() - - Blender_folder = ("%s%sBlender"%(coat3D.exchangedir,os.sep)) - Blender_export = Blender_folder - path3b_now = coat3D.exchangedir - path3b_now += ('last_saved_3b_file.txt') - Blender_export += ('%sexport.txt'%(os.sep)) - new_applink_name = 'False' - new_object = False - if(os.path.isfile(Blender_export)): - obj_pathh = open(Blender_export) - new_object = True - for line in obj_pathh: - new_applink_name = line - break - obj_pathh.close() - - for scene_objects in bpy.context.scene.objects: - if(scene_objects.type == 'MESH'): - if(scene_objects.coat3D.applink_name == new_applink_name): - new_object = False - - for act_name in test: - coa = act_name.coat3D - path_object = coa.applink_name - if act_name.type == 'MESH' and os.path.isfile(path_object): - multires_on = False - activeobj = act_name.name - mat_list = [] - scene.objects[activeobj].select = True - objekti = scene.objects[activeobj] - coat3D.loca = objekti.location - coat3D.rota = objekti.rotation_euler - coat3D.dime = objekti.scale - - - - #See if there is multres modifier. - for modifiers in objekti.modifiers: - if modifiers.type == 'MULTIRES' and (modifiers.total_levels > 0): - if(not(coat3D.importlevel)): - bpy.ops.object.multires_external_pack() - multires = coat3D.exchangedir - multires += ('%stemp.btx'%(os.sep)) - bpy.ops.object.multires_external_save(filepath=multires) - #bpy.ops.object.multires_external_pack() - multires_on = True - multires_name = modifiers.name - break - - exportfile = coat3D.exchangedir - path3b_n = coat3D.exchangedir - path3b_n += ('last_saved_3b_file.txt') - exportfile += ('%sexport.txt'%(os.sep)) - if(os.path.isfile(exportfile)): - export_file = open(exportfile) - for line in export_file: - if line.rfind('.3b'): - objekti.coat3D.coatpath = line - coat['active_coat'] = line - export_file.close() - os.remove(exportfile) - - if(len(objekti.material_slots) == 0): - delete_material = False - else: - delete_material = True - - - if(not(objekti.active_material) and objekti.material_slots): - act_mat_index = objekti.active_material_index - materials_old = bpy.data.materials.keys() - bpy.ops.material.new() - materials_new = bpy.data.materials.keys() - new_ma = list(set(materials_new).difference(set(materials_old))) - new_mat = new_ma[0] - ki = bpy.data.materials[new_mat] - objekti.material_slots[act_mat_index].material = ki - - - - if(os.path.isfile(path_object) and (coa.objecttime != str(os.path.getmtime(path_object)))): - - if(objekti.material_slots): - act_mat_index = objekti.active_material_index - for obj_mat in objekti.material_slots: - mat_list.append(obj_mat.material) - - coa.dime = objekti.dimensions - coa.objecttime = str(os.path.getmtime(path_object)) - mtl = coa.applink_name - mtl = mtl.replace('.obj','.mtl') - if(os.path.isfile(mtl)): - os.remove(mtl) - - bpy.ops.import_scene.obj(filepath=path_object,axis_forward='-Z',axis_up='Y',use_image_search=False) - obj_proxy = scene.objects[0] - bpy.ops.object.select_all(action='TOGGLE') - obj_proxy.select = True - - - bpy.ops.object.transform_apply(rotation=True) - proxy_mat = obj_proxy.material_slots[0].material - if(delete_material): - while(list(obj_proxy.data.materials) != []): - proxy_mat = obj_proxy.material_slots[0].material - obj_proxy.data.materials.pop(0,1) - proxy_mat.user_clear() - bpy.data.materials.remove(proxy_mat) - bpy.ops.object.select_all(action='TOGGLE') - - if(coat3D.importlevel): - obj_proxy.select = True - obj_proxy.modifiers.new(name='temp',type='MULTIRES') - objekti.select = True - bpy.ops.object.multires_reshape(modifier=multires_name) - bpy.ops.object.select_all(action='TOGGLE') - multires_on = False - else: - - scene.objects.active = obj_proxy - - obj_data = objekti.data.id_data - objekti.data = obj_proxy.data.id_data - if(bpy.data.meshes[obj_data.name].users == 0): - objekti.data.id_data.name = obj_data.name - bpy.data.meshes.remove(obj_data) - - - obj_proxy.select = True - bpy.ops.object.delete() - objekti.select = True - objekti.scale = coat3D.dime - - bpy.context.scene.objects.active = objekti - - if(os.path.isfile(path3b_n)): - path3b_fil = open(path3b_n) - for lin in path3b_fil: - objekti.coat3D.path3b = lin - path3b_fil.close() - os.remove(path3b_n) - - if(coat3D.importmesh and not(os.path.isfile(path_object))): - coat3D.importmesh = False - - if(mat_list and coat3D.importmesh): - for mat_one in mat_list: - objekti.data.materials.append(mat_one) - objekti.active_material_index = act_mat_index - - if(mat_list): - for obj_mate in objekti.material_slots: - if(hasattr(obj_mate.material,'texture_slots')): - for tex_slot in obj_mate.material.texture_slots: - if(hasattr(tex_slot,'texture')): - if(tex_slot.texture.type == 'IMAGE'): - if tex_slot.texture.image is not None: - tex_slot.texture.image.reload() - - - if(coat3D.importtextures): - export = '' - tex.gettex(mat_list,objekti,scene,export) - - if(multires_on): - temp_file = coat3D.exchangedir - temp_file += ('%stemp2.btx'%(os.sep)) - if(objekti.modifiers[multires_name].levels == 0): - objekti.modifiers[multires_name].levels = 1 - bpy.ops.object.multires_external_save(filepath=temp_file) - objekti.modifiers[multires_name].filepath = multires - objekti.modifiers[multires_name].levels = 0 - - else: - bpy.ops.object.multires_external_save(filepath=temp_file) - objekti.modifiers[multires_name].filepath = multires - #bpy.ops.object.multires_external_pack() - bpy.ops.object.shade_smooth() - - - for act_name in test: - act_name.select = True - bpy.context.scene.objects.active = act_first - - if(new_object == True): - coat3D = bpy.context.scene.coat3D - scene = context.scene - - Blender_folder = ("%s%sBlender"%(coat3D.exchangedir,os.sep)) - Blender_export = Blender_folder - path3b_now = coat3D.exchangedir - path3b_now += ('last_saved_3b_file.txt') - Blender_export += ('%sexport.txt'%(os.sep)) - - - mat_list = [] - obj_path ='' - - - export = new_applink_name - mod_time = os.path.getmtime(new_applink_name) - mtl_list = new_applink_name.replace('.obj','.mtl') - if(os.path.isfile(mtl_list)): - os.remove(mtl_list) - - bpy.ops.import_scene.obj(filepath=new_applink_name,axis_forward='-Z',axis_up='Y') - bpy.ops.object.transform_apply(rotation=True) - new_obj = scene.objects[0] - new_obj.coat3D.applink_name = obj_path - scene.objects[0].coat3D.applink_name = export #objectdir muutettava - - os.remove(Blender_export) - - bpy.context.scene.objects.active = new_obj - - bpy.ops.object.shade_smooth() - - Blender_tex = ("%s%stextures.txt"%(coat3D.exchangedir,os.sep)) - mat_list.append(new_obj.material_slots[0].material) - tex.gettex(mat_list, new_obj, scene,export) - - return {'FINISHED'} - - - -from bpy import * -from mathutils import Vector, Matrix - -# 3D-Coat Dynamic Menu -class VIEW3D_MT_Coat_Dynamic_Menu(bpy.types.Menu): - bl_label = "3D-Coat Applink Menu" - - def draw(self, context): - layout = self.layout - settings = context.tool_settings - layout.operator_context = 'INVOKE_REGION_WIN' - coat3D = bpy.context.scene.coat3D - Blender_folder = ("%s%sBlender"%(coat3D.exchangedir,os.sep)) - Blender_export = Blender_folder - Blender_export += ('%sexport.txt'%(os.sep)) - - ob = context - if ob.mode == 'OBJECT': - if(bpy.context.selected_objects): - for ind_obj in bpy.context.selected_objects: - if(ind_obj.type == 'MESH'): - layout.active = True - break - layout.active = False - - if(layout.active == True): - - layout.operator("import_applink.pilgway_3d_coat", text="Import") - layout.separator() - - layout.operator("export_applink.pilgway_3d_coat", text="Export") - layout.separator() - - layout.menu("VIEW3D_MT_ImportMenu") - layout.separator() - - layout.menu("VIEW3D_MT_ExportMenu") - layout.separator() - - layout.menu("VIEW3D_MT_ExtraMenu") - layout.separator() - - if(len(bpy.context.selected_objects) == 1): - if(os.path.isfile(bpy.context.selected_objects[0].coat3D.path3b)): - layout.operator("import_applink.pilgway_3d_coat_3b", text="Load 3b") - layout.separator() - - if(os.path.isfile(Blender_export)): - - layout.operator("import3b_applink.pilgway_3d_coat", text="Bring from 3D-Coat") - layout.separator() - else: - if(os.path.isfile(Blender_export)): - layout.active = True - - layout.operator("import3b_applink.pilgway_3d_coat", text="Bring from 3D-Coat") - layout.separator() - else: - if(os.path.isfile(Blender_export)): - - - layout.operator("import3b_applink.pilgway_3d_coat", text="Bring from 3D-Coat") - layout.separator() - -class VIEW3D_MT_ImportMenu(bpy.types.Menu): - bl_label = "Import Settings" - - def draw(self, context): - layout = self.layout - coat3D = bpy.context.scene.coat3D - settings = context.tool_settings - layout.operator_context = 'INVOKE_REGION_WIN' - layout.prop(coat3D,"importmesh") - layout.prop(coat3D,"importmod") - layout.prop(coat3D,"smooth_on") - layout.prop(coat3D,"importtextures") - -class VIEW3D_MT_ExportMenu(bpy.types.Menu): - bl_label = "Export Settings" - - def draw(self, context): - layout = self.layout - coat3D = bpy.context.scene.coat3D - settings = context.tool_settings - layout.operator_context = 'INVOKE_REGION_WIN' - layout.prop(coat3D,"exportover") - if(coat3D.exportover): - layout.prop(coat3D,"exportmod") - -class VIEW3D_MT_ExtraMenu(bpy.types.Menu): - bl_label = "Extra" - - def draw(self, context): - layout = self.layout - coat3D = bpy.context.scene.coat3D - settings = context.tool_settings - layout.operator_context = 'INVOKE_REGION_WIN' - - layout.operator("import_applink.pilgway_3d_deltex",text="Delete all Textures") - layout.separator() - -def register(): - bpy.utils.register_module(__name__) - - kc = bpy.context.window_manager.keyconfigs.addon - if kc: - km = kc.keymaps.new(name='3D View', space_type='VIEW_3D') - kmi = km.keymap_items.new('wm.call_menu2', 'Q', 'PRESS') - kmi.properties.name = "VIEW3D_MT_Coat_Dynamic_Menu" - -def unregister(): - bpy.utils.unregister_module(__name__) - - kc = bpy.context.window_manager.keyconfigs.addon - if kc: - km = kc.keymapskeymaps['3D View'] - for kmi in km.keymap_items: - if kmi.idname == '': - if kmi.properties.name == "VIEW3D_MT_Coat_Dynamic_Menu": - km.keymap_items.remove(kmi) - break - - -if __name__ == "__main__": - register() diff --git a/io_coat3D/tex.py b/io_coat3D/tex.py index f532177c..c9feec95 100644 --- a/io_coat3D/tex.py +++ b/io_coat3D/tex.py @@ -19,8 +19,9 @@ import bpy import os - +import re def find_index(objekti): + luku = 0 for tex in objekti.active_material.texture_slots: if(not(hasattr(tex,'texture'))): @@ -28,308 +29,256 @@ def find_index(objekti): luku = luku +1 return luku -def gettex(mat_list, objekti, scene,export): - - coat3D = bpy.context.scene.coat3D - coa = objekti.coat3D - - if(bpy.context.scene.render.engine == 'VRAY_RENDER' or bpy.context.scene.render.engine == 'VRAY_RENDER_PREVIEW'): - vray = True - else: - vray = False +def RemoveFbxNodes(objekti): + Node_Tree = objekti.active_material.node_tree + for node in Node_Tree.nodes: + if node.type != 'OUTPUT_MATERIAL': + Node_Tree.nodes.remove(node) + else: + output = node + output.location = 340,400 + Prin_mat = Node_Tree.nodes.new(type="ShaderNodeBsdfPrincipled") + Prin_mat.location = 13, 375 - take_color = 0 - take_spec = 0 - take_normal = 0 - take_disp = 0 + Node_Tree.links.new(Prin_mat.outputs[0], output.inputs[0]) - bring_color = 1 - bring_spec = 1 - bring_normal = 1 - bring_disp = 1 +def readtexturefolder(mat_list,texturelist,is_new): #read textures from texture file texcoat = {} texcoat['color'] = [] - texcoat['specular'] = [] + texcoat['metalness'] = [] + texcoat['rough'] = [] texcoat['nmap'] = [] texcoat['disp'] = [] - texu = [] - - if(export): - objekti.coat3D.objpath = export - nimi = os.path.split(export)[1] - osoite = os.path.dirname(export) + os.sep #pitaa ehka muuttaa - for mate in objekti.material_slots: - for tex_slot in mate.material.texture_slots: - if(hasattr(tex_slot,'texture')): - if(tex_slot.texture.type == 'IMAGE'): - if tex_slot.texture.image is not None: - tex_slot.texture.image.reload() - else: - if(os.sys.platform == 'win32'): - osoite = os.path.expanduser("~") + os.sep + 'Documents' + os.sep + '3DC2Blender' + os.sep + 'Textures' + os.sep - else: - osoite = os.path.expanduser("~") + os.sep + '3DC2Blender' + os.sep + 'Textures' + os.sep - ki = os.path.split(coa.applink_name)[1] - ko = os.path.splitext(ki)[0] - just_nimi = ko + '_' - just_nimi_len = len(just_nimi) - print('terve:' + coa.applink_name) - - if(len(objekti.material_slots) != 0): - for obj_tex in objekti.active_material.texture_slots: - if(hasattr(obj_tex,'texture')): - if(obj_tex.texture.type == 'IMAGE'): - if(obj_tex.use_map_color_diffuse): - bring_color = 0; - if(obj_tex.use_map_specular): - bring_spec = 0; - if(obj_tex.use_map_normal): - bring_normal = 0; - if(obj_tex.use_map_displacement): - bring_disp = 0; - - files = os.listdir(osoite) - for i in files: - tui = i[:just_nimi_len] - if(tui == just_nimi): - texu.append(i) - - for yy in texu: - minimi = (yy.rfind('_'))+1 - maksimi = (yy.rfind('.')) - tex_name = yy[minimi:maksimi] - koko = '' - koko += osoite - koko += yy - texcoat[tex_name].append(koko) - - if((texcoat['color'] or texcoat['nmap'] or texcoat['disp'] or texcoat['specular']) and (len(objekti.material_slots)) == 0): - materials_old = bpy.data.materials.keys() - bpy.ops.material.new() - materials_new = bpy.data.materials.keys() - new_ma = list(set(materials_new).difference(set(materials_old))) - new_mat = new_ma[0] - ki = bpy.data.materials[new_mat] - objekti.data.materials.append(ki) - - if(bring_color == 1 and texcoat['color']): - index = find_index(objekti) - tex = bpy.ops.Texture - objekti.active_material.texture_slots.create(index) - total_mat = len(objekti.active_material.texture_slots.items()) - useold = '' - - for seekco in bpy.data.textures: - if((seekco.name[:5] == 'Color') and (seekco.users_material == ())): - useold = seekco - - - if(useold == ''): - - textures_old = bpy.data.textures.keys() - bpy.data.textures.new('Color',type='IMAGE') - textures_new = bpy.data.textures.keys() - name_te = list(set(textures_new).difference(set(textures_old))) - name_tex = name_te[0] - - bpy.ops.image.new(name=name_tex) - bpy.data.images[name_tex].filepath = texcoat['color'][0] - bpy.data.images[name_tex].source = 'FILE' - - objekti.active_material.texture_slots[index].texture = bpy.data.textures[name_tex] - objekti.active_material.texture_slots[index].texture.image = bpy.data.images[name_tex] - - if(objekti.data.uv_textures.active): - objekti.active_material.texture_slots[index].texture_coords = 'UV' - objekti.active_material.texture_slots[index].uv_layer = objekti.data.uv_textures.active.name - - objekti.active_material.texture_slots[index].texture.image.reload() - - - elif(useold != ''): - - objekti.active_material.texture_slots[index].texture = useold - objekti.active_material.texture_slots[index].texture.image = bpy.data.images[useold.name] - objekti.active_material.texture_slots[index].texture.image.filepath = texcoat['color'][0] - if(objekti.data.uv_textures.active): - objekti.active_material.texture_slots[index].texture_coords = 'UV' - objekti.active_material.texture_slots[index].uv_layer = objekti.data.uv_textures.active.name - - - if(bring_normal == 1 and texcoat['nmap']): - index = find_index(objekti) - tex = bpy.ops.Texture - objekti.active_material.texture_slots.create(index) - total_mat = len(objekti.active_material.texture_slots.items()) - useold = '' - - for seekco in bpy.data.textures: - if((seekco.name[:6] == 'Normal') and (seekco.users_material == ())): - useold = seekco - - if(useold == ''): - - textures_old = bpy.data.textures.keys() - bpy.data.textures.new('Normal',type='IMAGE') - textures_new = bpy.data.textures.keys() - name_te = list(set(textures_new).difference(set(textures_old))) - name_tex = name_te[0] - - bpy.ops.image.new(name=name_tex) - bpy.data.images[name_tex].filepath = texcoat['nmap'][0] - bpy.data.images[name_tex].source = 'FILE' - - objekti.active_material.texture_slots[index].texture = bpy.data.textures[name_tex] - objekti.active_material.texture_slots[index].texture.image = bpy.data.images[name_tex] - - if(objekti.data.uv_textures.active): - objekti.active_material.texture_slots[index].texture_coords = 'UV' - objekti.active_material.texture_slots[index].uv_layer = objekti.data.uv_textures.active.name - - objekti.active_material.texture_slots[index].use_map_color_diffuse = False - objekti.active_material.texture_slots[index].use_map_normal = True - - objekti.active_material.texture_slots[index].texture.image.reload() - if(vray): - bpy.data.textures[name_tex].vray_slot.BRDFBump.map_type = 'TANGENT' - - else: - bpy.data.textures[name_tex].use_normal_map = True - objekti.active_material.texture_slots[index].normal_map_space = 'TANGENT' - objekti.active_material.texture_slots[index].normal_factor = 1 - + texcoat['emissive'] = [] + + + for texture_info in texturelist: + if texture_info[0] == mat_list[0].name: + if texture_info[2] == 'color' or texture_info[2] == 'diffuse': + texcoat['color'].append(texture_info[3]) + if texture_info[2] == 'metalness' or texture_info[2] == 'reflection': + texcoat['metalness'].append(texture_info[3]) + if texture_info[2] == 'rough' or texture_info[2] == 'roughness': + texcoat['rough'].append(texture_info[3]) + if texture_info[2] == 'nmap' or texture_info[2] == 'normal_map': + texcoat['nmap'].append(texture_info[3]) + if texture_info[2] == 'emissive': + texcoat['emissive'].append(texture_info[3]) + + createnodes(mat_list, texcoat) + +def checkmaterial(mat_list, objekti): #check how many materials object has + mat_list = [] + + for obj_mate in objekti.material_slots: + if(obj_mate.material.use_nodes == False): + obj_mate.material.use_nodes = True + +def createnodes(mat_list,texcoat): #luo nodes palikat ja linkittaa tekstuurit niihin + bring_color = True #naiden tarkoitus on tsekata onko tarvetta luoda uusi node vai riittaako paivitys + bring_metalness = True + bring_roughness = True + bring_normal = True + bring_disp = True - - elif(useold != ''): - - objekti.active_material.texture_slots[index].texture = useold - objekti.active_material.texture_slots[index].texture.image = bpy.data.images[useold.name] - objekti.active_material.texture_slots[index].texture.image.filepath = texcoat['nmap'][0] - if(objekti.data.uv_textures.active): - objekti.active_material.texture_slots[index].texture_coords = 'UV' - objekti.active_material.texture_slots[index].uv_layer = objekti.data.uv_textures.active.name - objekti.active_material.texture_slots[index].use_map_color_diffuse = False - objekti.active_material.texture_slots[index].use_map_normal = True - objekti.active_material.texture_slots[index].normal_factor = 1 - - - if(bring_spec == 1 and texcoat['specular']): - - index = find_index(objekti) - - objekti.active_material.texture_slots.create(index) - useold = '' - - for seekco in bpy.data.textures: - if((seekco.name[:8] == 'Specular') and (seekco.users_material == ())): - useold = seekco - - if(useold == ''): - - textures_old = bpy.data.textures.keys() - bpy.data.textures.new('Specular',type='IMAGE') - textures_new = bpy.data.textures.keys() - name_te = list(set(textures_new).difference(set(textures_old))) - name_tex = name_te[0] - - bpy.ops.image.new(name=name_tex) - bpy.data.images[name_tex].filepath = texcoat['specular'][0] - bpy.data.images[name_tex].source = 'FILE' - - objekti.active_material.texture_slots[index].texture = bpy.data.textures[name_tex] - objekti.active_material.texture_slots[index].texture.image = bpy.data.images[name_tex] - - if(objekti.data.uv_textures.active): - objekti.active_material.texture_slots[index].texture_coords = 'UV' - objekti.active_material.texture_slots[index].uv_layer = objekti.data.uv_textures.active.name - - objekti.active_material.texture_slots[index].use_map_color_diffuse = False - objekti.active_material.texture_slots[index].use_map_specular = True - - objekti.active_material.texture_slots[index].texture.image.reload() - - - elif(useold != ''): - - objekti.active_material.texture_slots[index].texture = useold - objekti.active_material.texture_slots[index].texture.image = bpy.data.images[useold.name] - objekti.active_material.texture_slots[index].texture.image.filepath = texcoat['specular'][0] - if(objekti.data.uv_textures.active): - objekti.active_material.texture_slots[index].texture_coords = 'UV' - objekti.active_material.texture_slots[index].uv_layer = objekti.data.uv_textures.active.name - objekti.active_material.texture_slots[index].use_map_color_diffuse = False - objekti.active_material.texture_slots[index].use_map_specular = True - - if(bring_disp == 1 and texcoat['disp']): - - index = find_index(objekti) - - - objekti.active_material.texture_slots.create(index) - useold = '' - - for seekco in bpy.data.textures: - if((seekco.name[:12] == 'Displacement') and (seekco.users_material == ())): - useold = seekco - - if useold == "": - - textures_old = bpy.data.textures.keys() - bpy.data.textures.new('Displacement',type='IMAGE') - textures_new = bpy.data.textures.keys() - name_te = list(set(textures_new).difference(set(textures_old))) - name_tex = name_te[0] - - bpy.ops.image.new(name=name_tex) - bpy.data.images[name_tex].filepath = texcoat['disp'][0] - bpy.data.images[name_tex].source = 'FILE' - - objekti.active_material.texture_slots[index].texture = bpy.data.textures[name_tex] - objekti.active_material.texture_slots[index].texture.image = bpy.data.images[name_tex] - - if(objekti.data.uv_textures.active): - objekti.active_material.texture_slots[index].texture_coords = 'UV' - objekti.active_material.texture_slots[index].uv_layer = objekti.data.uv_textures.active.name - - objekti.active_material.texture_slots[index].use_map_color_diffuse = False - objekti.active_material.texture_slots[index].use_map_displacement = True - - objekti.active_material.texture_slots[index].texture.image.reload() - - - elif(useold != ''): - - objekti.active_material.texture_slots[index].texture = useold - objekti.active_material.texture_slots[index].texture.image = bpy.data.images[useold.name] - objekti.active_material.texture_slots[index].texture.image.filepath = texcoat['disp'][0] - if(objekti.data.uv_textures.active): - objekti.active_material.texture_slots[index].texture_coords = 'UV' - objekti.active_material.texture_slots[index].uv_layer = objekti.data.uv_textures.active.name - objekti.active_material.texture_slots[index].use_map_color_diffuse = False - objekti.active_material.texture_slots[index].use_map_displacement = True - - if(vray): - objekti.active_material.texture_slots[index].texture.use_interpolation = False - objekti.active_material.texture_slots[index].displacement_factor = 0.05 + coat3D = bpy.context.scene.coat3D + coatMat = mat_list[0] + + if(coatMat.use_nodes == False): + coatMat.use_nodes = True + act_material = coatMat.node_tree + main_material = coatMat.node_tree + applink_group_node = False + + #ensimmaiseksi kaydaan kaikki image nodet lapi ja tarkistetaan onko nimi 3DC alkunen jos on niin reload + print('texcoat:',texcoat) + for node in act_material.nodes: + if(node.name == '3DC_Applink' and node.type == 'GROUP'): + applink_group_node = True + act_material = node.node_tree + break + for node in act_material.nodes: + if(node.type == 'TEX_IMAGE'): + if(node.name == '3DC_color'): + bring_color = False + node.image.reload() + elif(node.name == '3DC_metalness'): + bring_metalness = False + node.image.reload() + elif(node.name == '3DC_roughness'): + bring_roughness = False + node.image.reload() + elif(node.name == '3DC_normal'): + bring_normal = False + node.image.reload() + + #seuraavaksi lahdemme rakentamaan node tree. Lahdetaan Material Outputista rakentaa + if(applink_group_node == False and coat3D.creategroup): + group_tree = bpy.data.node_groups.new('3DC_Applink', 'ShaderNodeTree') + applink_tree = act_material.nodes.new('ShaderNodeGroup') + applink_tree.name = '3DC_Applink' + applink_tree.node_tree = group_tree + applink_tree.location = -400, 300 + act_material = group_tree + notegroup = act_material.nodes.new('NodeGroupOutput') + + main_mat = main_material.nodes['Material Output'] + if(main_mat.inputs['Surface'].is_linked == True): + glue_mat = main_mat.inputs['Surface'].links[0].from_node + if(glue_mat.inputs.find('Base Color') == -1): + input_color = glue_mat.inputs.find('Color') else: - disp_modi = '' - for seek_modi in objekti.modifiers: - if(seek_modi.type == 'DISPLACE'): - disp_modi = seek_modi - break - if(disp_modi): - disp_modi.texture = objekti.active_material.texture_slots[index].texture - if(objekti.data.uv_textures.active): - disp_modi.texture_coords = 'UV' - disp_modi.uv_layer = objekti.data.uv_textures.active.name + input_color = glue_mat.inputs.find('Base Color') + input_index = 0 + #Color + if(bring_color == True and texcoat['color'] != []): + print('image:', bpy.data.images) + node = act_material.nodes.new('ShaderNodeTexImage') + node.name = '3DC_color' + if (texcoat['color']): + sameimage = False + for image in bpy.data.images: + if(image.filepath == texcoat['color'][0]): + sameimage = True + imagename = image + break + + if sameimage == True: + node.image = imagename + else: + node.image = bpy.data.images.load(texcoat['color'][0]) + if(coat3D.createnodes): + curvenode = act_material.nodes.new('ShaderNodeRGBCurve') + curvenode.name = '3DC_RGBCurve' + huenode = act_material.nodes.new('ShaderNodeHueSaturation') + huenode.name = '3DC_HueSaturation' + act_material.links.new(huenode.outputs[0], glue_mat.inputs[input_color]) + act_material.links.new(curvenode.outputs[0], huenode.inputs[4]) + act_material.links.new(node.outputs[0], curvenode.inputs[1]) + node.location = -990, 530 + curvenode.location = -660, 480 + huenode.location = -337, 335 + if(coat3D.creategroup): + act_material.links.new(huenode.outputs[0], notegroup.inputs[input_index]) + group_tree.outputs[input_index].name = 'Color' + main_material.links.new(applink_tree.outputs[input_index], glue_mat.inputs[input_color]) + input_index += 1 + else: + if (coat3D.creategroup): + node.location = -400, 400 + act_material.links.new(node.outputs[0], notegroup.inputs[input_index]) + if (input_color != -1): + main_material.links.new(applink_tree.outputs[input_index], glue_mat.inputs[input_color]) + input_index += 1 + + else: + node.location = -400,400 + if (input_color != -1): + act_material.links.new(node.outputs[0], glue_mat.inputs[input_color]) + #Metalness + if(bring_metalness == True and texcoat['metalness'] != []): + node = act_material.nodes.new('ShaderNodeTexImage') + node.name='3DC_metalness' + input_color = glue_mat.inputs.find('Metallic') + if(texcoat['metalness']): + node.image = bpy.data.images.load(texcoat['metalness'][0]) + node.color_space = 'NONE' + if (coat3D.createnodes): + curvenode = act_material.nodes.new('ShaderNodeRGBCurve') + curvenode.name = '3DC_RGBCurve' + huenode = act_material.nodes.new('ShaderNodeHueSaturation') + huenode.name = '3DC_HueSaturation' + act_material.links.new(huenode.outputs[0], glue_mat.inputs[input_color]) + act_material.links.new(curvenode.outputs[0], huenode.inputs[4]) + act_material.links.new(node.outputs[0], curvenode.inputs[1]) + node.location = -994, 119 + curvenode.location = -668, 113 + huenode.location = -345, 118 + if (coat3D.creategroup): + act_material.links.new(huenode.outputs[0], notegroup.inputs[input_index]) + group_tree.outputs[input_index].name = 'Metalness' + main_material.links.new(applink_tree.outputs[input_index], glue_mat.inputs[input_color]) + input_index += 1 + else: + if (coat3D.creategroup): + node.location = -830, 160 + act_material.links.new(node.outputs[0], notegroup.inputs[input_index]) + if (input_color != -1): + main_material.links.new(applink_tree.outputs[input_index], glue_mat.inputs[input_color]) + input_index += 1 + else: + node.location = -830, 160 + if (input_color != -1): + act_material.links.new(node.outputs[0], glue_mat.inputs[input_color]) + + #Roughness + if(bring_roughness == True and texcoat['rough'] != []): + node = act_material.nodes.new('ShaderNodeTexImage') + node.name='3DC_roughness' + input_color = glue_mat.inputs.find('Roughness') + if(texcoat['rough']): + node.image = bpy.data.images.load(texcoat['rough'][0]) + node.color_space = 'NONE' + if (coat3D.createnodes): + curvenode = act_material.nodes.new('ShaderNodeRGBCurve') + curvenode.name = '3DC_RGBCurve' + huenode = act_material.nodes.new('ShaderNodeHueSaturation') + huenode.name = '3DC_HueSaturation' + act_material.links.new(huenode.outputs[0], glue_mat.inputs[input_color]) + act_material.links.new(curvenode.outputs[0], huenode.inputs[4]) + act_material.links.new(node.outputs[0], curvenode.inputs[1]) + node.location = -1000, -276 + curvenode.location = -670, -245 + huenode.location = -340, -100 + if (coat3D.creategroup): + act_material.links.new(huenode.outputs[0], notegroup.inputs[input_index]) + group_tree.outputs[input_index].name = 'Roughness' + main_material.links.new(applink_tree.outputs[input_index], glue_mat.inputs[input_color]) + input_index += 1 else: - objekti.modifiers.new('Displace',type='DISPLACE') - objekti.modifiers['Displace'].texture = objekti.active_material.texture_slots[index].texture - if(objekti.data.uv_textures.active): - objekti.modifiers['Displace'].texture_coords = 'UV' - objekti.modifiers['Displace'].uv_layer = objekti.data.uv_textures.active.name + if (coat3D.creategroup): + node.location = -550, 0 + act_material.links.new(node.outputs[0], notegroup.inputs[input_index]) + if (input_color != -1): + main_material.links.new(applink_tree.outputs[input_index], glue_mat.inputs[input_color]) + input_index += 1 + else: + node.location = -550, 0 + if (input_color != -1): + act_material.links.new(node.outputs[0], glue_mat.inputs[input_color]) + + #Normal map + if(bring_normal == True and texcoat['nmap'] != []): + node = act_material.nodes.new('ShaderNodeTexImage') + normal_node = act_material.nodes.new('ShaderNodeNormalMap') + node.location = -600,-670 + normal_node.location = -300,-300 + node.name='3DC_normal' + normal_node.name='3DC_normalnode' + if(texcoat['nmap']): + node.image = bpy.data.images.load(texcoat['nmap'][0]) + node.color_space = 'NONE' + input_color = glue_mat.inputs.find('Normal') + act_material.links.new(node.outputs[0], normal_node.inputs[1]) + act_material.links.new(normal_node.outputs[0], glue_mat.inputs[input_color]) + if (coat3D.creategroup): + act_material.links.new(normal_node.outputs[0], notegroup.inputs[input_index]) + main_material.links.new(applink_tree.outputs[input_index], glue_mat.inputs[input_color]) + input_index += 1 + + + +def matlab(objekti,mat_list,texturelist,is_new): + + ''' FBX Materials: remove all nodes and create princibles node''' + if(is_new): + RemoveFbxNodes(objekti) + + '''Main Loop for Texture Update''' + #checkmaterial(mat_list, objekti) + readtexturefolder(mat_list,texturelist,is_new) return('FINISHED') diff --git a/io_convert_image_to_mesh_img/__init__.py b/io_convert_image_to_mesh_img/__init__.py index 1e5bdddf..a884fb90 100644 --- a/io_convert_image_to_mesh_img/__init__.py +++ b/io_convert_image_to_mesh_img/__init__.py @@ -51,12 +51,12 @@ def menu_import(self, context): def register(): bpy.utils.register_module(__name__) - bpy.types.INFO_MT_file_import.append(menu_import) + bpy.types.TOPBAR_MT_file_import.append(menu_import) def unregister(): bpy.utils.unregister_module(__name__) - bpy.types.INFO_MT_file_import.remove(menu_import) + bpy.types.TOPBAR_MT_file_import.remove(menu_import) if __name__ == '__main__': diff --git a/io_curve_svg/__init__.py b/io_curve_svg/__init__.py index 188e9189..c8a9988d 100644 --- a/io_curve_svg/__init__.py +++ b/io_curve_svg/__init__.py @@ -21,8 +21,7 @@ bl_info = { "name": "Scalable Vector Graphics (SVG) 1.1 format", "author": "JM Soler, Sergey Sharybin", - "version": (1, 0, 0), - "blender": (2, 57, 0), + "blender": (2, 80, 0), "location": "File > Import > Scalable Vector Graphics (.svg)", "description": "Import SVG as curves", "warning": "", @@ -53,13 +52,12 @@ class ImportSVG(bpy.types.Operator, ImportHelper): bl_options = {'UNDO'} filename_ext = ".svg" - filter_glob = StringProperty(default="*.svg", options={'HIDDEN'}) + filter_glob: StringProperty(default="*.svg", options={'HIDDEN'}) def execute(self, context): from . import import_svg - return import_svg.load(self, context, - **self.as_keywords(ignore=("filter_glob",))) + return import_svg.load(self, context, filepath=self.filepath) def menu_func_import(self, context): @@ -68,15 +66,15 @@ def menu_func_import(self, context): def register(): - bpy.utils.register_module(__name__) + bpy.utils.register_class(ImportSVG) - bpy.types.INFO_MT_file_import.append(menu_func_import) + bpy.types.TOPBAR_MT_file_import.append(menu_func_import) def unregister(): - bpy.utils.unregister_module(__name__) + bpy.utils.unregister_class(ImportSVG) - bpy.types.INFO_MT_file_import.remove(menu_func_import) + bpy.types.TOPBAR_MT_file_import.remove(menu_func_import) # NOTES # - blender version is hardcoded diff --git a/io_curve_svg/import_svg.py b/io_curve_svg/import_svg.py index 00c90dc6..1a8c2f65 100644 --- a/io_curve_svg/import_svg.py +++ b/io_curve_svg/import_svg.py @@ -118,14 +118,15 @@ def SVGParseFloat(s, i=0): return token, i -def SVGCreateCurve(): +def SVGCreateCurve(context): """ Create new curve object to hold splines in """ cu = bpy.data.curves.new("Curve", 'CURVE') obj = bpy.data.objects.new("Curve", cu) - bpy.context.scene.objects.link(obj) + + context['collection'].objects.link(obj) return obj @@ -213,8 +214,8 @@ def SVGMatrixFromNode(node, context): m = Matrix.Translation(Vector((x, y, 0.0))) if has_user_coordinate: if rect[0] != 0 and rect[1] != 0: - m = m * Matrix.Scale(w / rect[0], 4, Vector((1.0, 0.0, 0.0))) - m = m * Matrix.Scale(h / rect[1], 4, Vector((0.0, 1.0, 0.0))) + m = m @ Matrix.Scale(w / rect[0], 4, Vector((1.0, 0.0, 0.0))) + m = m @ Matrix.Scale(h / rect[1], 4, Vector((0.0, 1.0, 0.0))) if node.getAttribute('viewBox'): viewBox = node.getAttribute('viewBox').replace(',', ' ').split() @@ -237,11 +238,11 @@ def SVGMatrixFromNode(node, context): tx = (w - vw * scale) / 2 ty = (h - vh * scale) / 2 - m = m * Matrix.Translation(Vector((tx, ty, 0.0))) + m = m @ Matrix.Translation(Vector((tx, ty, 0.0))) - m = m * Matrix.Translation(Vector((-vx, -vy, 0.0))) - m = m * Matrix.Scale(scale, 4, Vector((1.0, 0.0, 0.0))) - m = m * Matrix.Scale(scale, 4, Vector((0.0, 1.0, 0.0))) + m = m @ Matrix.Translation(Vector((-vx, -vy, 0.0))) + m = m @ Matrix.Scale(scale, 4, Vector((1.0, 0.0, 0.0))) + m = m @ Matrix.Scale(scale, 4, Vector((0.0, 1.0, 0.0))) return m @@ -263,7 +264,7 @@ def SVGParseTransform(transform): if proc is None: raise Exception('Unknown trasnform function: ' + func) - m = m * proc(params) + m = m @ proc(params) return m @@ -304,7 +305,6 @@ def SVGGetMaterial(color, context): mat = bpy.data.materials.new(name='SVGMat') mat.diffuse_color = diffuse_color - mat.diffuse_intensity = 1.0 materials[color] = mat @@ -350,8 +350,8 @@ def SVGTransformScale(params): m = Matrix() - m = m * Matrix.Scale(sx, 4, Vector((1.0, 0.0, 0.0))) - m = m * Matrix.Scale(sy, 4, Vector((0.0, 1.0, 0.0))) + m = m @ Matrix.Scale(sx, 4, Vector((1.0, 0.0, 0.0))) + m = m @ Matrix.Scale(sy, 4, Vector((0.0, 1.0, 0.0))) return m @@ -395,7 +395,7 @@ def SVGTransformRotate(params): tm = Matrix.Translation(Vector((cx, cy, 0.0))) rm = Matrix.Rotation(ang, 4, Vector((0.0, 0.0, 1.0))) - return tm * rm * tm.inverted() + return tm @ rm @ tm.inverted() SVGTransforms = {'translate': SVGTransformTranslate, 'scale': SVGTransformScale, @@ -1030,7 +1030,7 @@ class SVGGeometry: """ self._context['transform'].append(matrix) - self._context['matrix'] = self._context['matrix'] * matrix + self._context['matrix'] = self._context['matrix'] @ matrix def _popMatrix(self): """ @@ -1038,7 +1038,7 @@ class SVGGeometry: """ matrix = self._context['transform'].pop() - self._context['matrix'] = self._context['matrix'] * matrix.inverted() + self._context['matrix'] = self._context['matrix'] @ matrix.inverted() def _pushStyle(self, style): """ @@ -1063,7 +1063,7 @@ class SVGGeometry: v = Vector((point[0], point[1], 0.0)) - return self._context['matrix'] * v + return self._context['matrix'] @ v def getNodeMatrix(self): """ @@ -1211,7 +1211,7 @@ class SVGGeometryPATH(SVGGeometry): Create real geometries """ - ob = SVGCreateCurve() + ob = SVGCreateCurve(self._context) cu = ob.data if self._node.getAttribute('id'): @@ -1234,7 +1234,7 @@ class SVGGeometryPATH(SVGGeometry): act_spline = cu.splines[-1] act_spline.use_cyclic_u = spline['closed'] else: - act_spline.bezier_points.add() + act_spline.bezier_points.add(1) bezt = act_spline.bezier_points[-1] bezt.co = co @@ -1378,7 +1378,7 @@ class SVGGeometryRECT(SVGGeometry): co = self._transformCoord(coord) if not firstTime: - spline.bezier_points.add() + spline.bezier_points.add(1) bezt = spline.bezier_points[-1] bezt.co = co @@ -1429,7 +1429,7 @@ class SVGGeometryRECT(SVGGeometry): radius = (rx, ry) # Geometry creation - ob = SVGCreateCurve() + ob = SVGCreateCurve(self._context) cu = ob.data if self._styles['useFill']: @@ -1539,7 +1539,7 @@ class SVGGeometryELLIPSE(SVGGeometry): return # Create circle - ob = SVGCreateCurve() + ob = SVGCreateCurve(self._context) cu = ob.data if self._node.getAttribute('id'): @@ -1578,7 +1578,7 @@ class SVGGeometryELLIPSE(SVGGeometry): spline = cu.splines[-1] spline.use_cyclic_u = True else: - spline.bezier_points.add() + spline.bezier_points.add(1) bezt = spline.bezier_points[-1] bezt.co = co @@ -1656,7 +1656,7 @@ class SVGGeometryLINE(SVGGeometry): y2 = SVGParseCoord(self._y2, crect[1]) # Create cline - ob = SVGCreateCurve() + ob = SVGCreateCurve(self._context) cu = ob.data coords = [(x1, y1), (x2, y2)] @@ -1670,7 +1670,7 @@ class SVGGeometryLINE(SVGGeometry): spline = cu.splines[-1] spline.use_cyclic_u = True else: - spline.bezier_points.add() + spline.bezier_points.add(1) bezt = spline.bezier_points[-1] bezt.co = co @@ -1727,7 +1727,7 @@ class SVGGeometryPOLY(SVGGeometry): Create real geometries """ - ob = SVGCreateCurve() + ob = SVGCreateCurve(self._context) cu = ob.data if self._closed and self._styles['useFill']: @@ -1746,7 +1746,7 @@ class SVGGeometryPOLY(SVGGeometry): spline = cu.splines[-1] spline.use_cyclic_u = self._closed else: - spline.bezier_points.add() + spline.bezier_points.add(1) bezt = spline.bezier_points[-1] bezt.co = co @@ -1798,7 +1798,7 @@ class SVGGeometrySVG(SVGGeometryContainer): if self._node.getAttribute('inkscape:version'): raw_height = self._node.getAttribute('height') document_height = SVGParseCoord(raw_height, 1.0) - matrix = matrix * Matrix.Translation([0.0, -document_height , 0.0]) + matrix = matrix @ matrix.Translation([0.0, -document_height , 0.0]) self._pushMatrix(matrix) self._pushRect(rect) @@ -1824,16 +1824,22 @@ class SVGLoader(SVGGeometryContainer): return None - def __init__(self, filepath, do_colormanage): + def __init__(self, context, filepath, do_colormanage): """ Initialize SVG loader """ + import os + + svg_name = os.path.basename(filepath) + scene = context.scene + collection = bpy.data.collections.new(name=svg_name) + scene.collection.children.link(collection) node = xml.dom.minidom.parse(filepath) m = Matrix() - m = m * Matrix.Scale(1.0 / 90.0 * 0.3048 / 12.0, 4, Vector((1.0, 0.0, 0.0))) - m = m * Matrix.Scale(-1.0 / 90.0 * 0.3048 / 12.0, 4, Vector((0.0, 1.0, 0.0))) + m = m @ Matrix.Scale(1.0 / 90.0 * 0.3048 / 12.0, 4, Vector((1.0, 0.0, 0.0))) + m = m @ Matrix.Scale(-1.0 / 90.0 * 0.3048 / 12.0, 4, Vector((0.0, 1.0, 0.0))) rect = (0, 0) @@ -1845,7 +1851,8 @@ class SVGLoader(SVGGeometryContainer): 'materials': {}, 'styles': [None], 'style': None, - 'do_colormanage': do_colormanage} + 'do_colormanage': do_colormanage, + 'collection': collection} super().__init__(node, self._context) @@ -1882,7 +1889,7 @@ def parseAbstractNode(node, context): return None -def load_svg(filepath, do_colormanage): +def load_svg(context, filepath, do_colormanage): """ Load specified SVG file """ @@ -1890,7 +1897,7 @@ def load_svg(filepath, do_colormanage): if bpy.ops.object.mode_set.poll(): bpy.ops.object.mode_set(mode='OBJECT') - loader = SVGLoader(filepath, do_colormanage) + loader = SVGLoader(context, filepath, do_colormanage) loader.parse() loader.createGeom(False) @@ -1901,7 +1908,7 @@ def load(operator, context, filepath=""): # non SVG files can give useful messages. do_colormanage = context.scene.display_settings.display_device != 'NONE' try: - load_svg(filepath, do_colormanage) + load_svg(context, filepath, do_colormanage) except (xml.parsers.expat.ExpatError, UnicodeEncodeError) as e: import traceback traceback.print_exc() diff --git a/io_export_after_effects.py b/io_export_after_effects.py index bb7ec73c..d682497d 100644 --- a/io_export_after_effects.py +++ b/io_export_after_effects.py @@ -110,7 +110,7 @@ def get_selected(context): # not ready yet. is_plane(object) returns False in all cases. This is temporary solids.append([ob, convert_name(ob.name)]) - elif ob.type == 'LAMP': + elif ob.type == 'LIGHT': lights.append([ob, ob.data.type + convert_name(ob.name)]) # Type of lamp added to name else: @@ -768,12 +768,12 @@ def menu_func(self, context): def register(): bpy.utils.register_class(ExportJsx) - bpy.types.INFO_MT_file_export.append(menu_func) + bpy.types.TOPBAR_MT_file_export.append(menu_func) def unregister(): bpy.utils.unregister_class(ExportJsx) - bpy.types.INFO_MT_file_export.remove(menu_func) + bpy.types.TOPBAR_MT_file_export.remove(menu_func) if __name__ == "__main__": register() diff --git a/io_export_dxf/__init__.py b/io_export_dxf/__init__.py index 254ffdae..41fd79e6 100644 --- a/io_export_dxf/__init__.py +++ b/io_export_dxf/__init__.py @@ -45,7 +45,7 @@ classes = ( ) def register(): - bpy.types.INFO_MT_file_export.append(menu_func) + bpy.types.TOPBAR_MT_file_export.append(menu_func) from bpy.utils import register_class for cls in classes: @@ -53,7 +53,7 @@ def register(): def unregister(): - bpy.types.INFO_MT_file_export.remove(menu_func) + bpy.types.TOPBAR_MT_file_export.remove(menu_func) from bpy.utils import unregister_class for cls in reversed(classes): diff --git a/io_export_dxf/export_dxf.py b/io_export_dxf/export_dxf.py index df0dcddc..934ae90e 100644 --- a/io_export_dxf/export_dxf.py +++ b/io_export_dxf/export_dxf.py @@ -27,7 +27,7 @@ if DEBUG: from .model.migiusModel import MigiusDXFLibDrawing -SUPPORTED_TYPES = ('MESH')#,'CURVE','EMPTY','TEXT','CAMERA','LAMP') +SUPPORTED_TYPES = ('MESH')#,'CURVE','EMPTY','TEXT','CAMERA','LIGHT') def exportDXF(context, filePath, settings): """ @@ -277,8 +277,8 @@ def _exportItem(ctx, o, mw, drawing, settings): elif (o.type == 'CAMERA') and settings['camera_as']: from .primitive_exporters.camera_exporter import CameraDXFExporter e = CameraDXFExporter(settings) - elif (o.type == 'LAMP') and settings['lamp_as']: - from .primitive_exporters.lamp_exporter import LampDXFExporter + elif (o.type == 'LIGHT') and settings['light_as']: + from .primitive_exporters.light_exporter import LampDXFExporter e = LampDXFExporter(settings) return e.export(ctx, drawing, o, mx, mx_n, color=ecolor, layer=elayer, lineType=eltype) diff --git a/io_export_dxf/operator.py b/io_export_dxf/operator.py index e419608f..7e2dd7a7 100644 --- a/io_export_dxf/operator.py +++ b/io_export_dxf/operator.py @@ -160,10 +160,10 @@ class DXFExporter(bpy.types.Operator): # ('VIEW', 'VIEW', ''), # ('POINT', 'POINT', '') # ) -# lamp_asItems = ( +# light_asItems = ( # ('NO', 'Do not export', ''), # ('..BLOCK', '..BLOCK', ''), -# ('..A_LAMP', '..A_LAMP', ''), +# ('..A_LIGHT', '..A_LIGHT', ''), # ('POINT', 'POINT', '') # ) # --------- CONTROL PROPERTIES -------------------------------------------- @@ -207,9 +207,9 @@ class DXFExporter(bpy.types.Operator): # camera_as = EnumProperty( name="Export camera As:", default='NO', # description="Select representation of a camera", # items=camera_asItems) -# lamp_as = EnumProperty( name="Export lamp As:", default='NO', +# light_as = EnumProperty( name="Export lamp As:", default='NO', # description="Select representation of a lamp", -# items=lamp_asItems) +# items=light_asItems) # ---------------------------------------------------------- entitylayer_from = EnumProperty(name="Entity Layer", default="obj.data.name", description="Entity LAYER assigned to?", @@ -265,7 +265,7 @@ class DXFExporter(bpy.types.Operator): # 'group_as' : self._checkNO(self.group_as), # 'proxy_as' : self._checkNO(self.proxy_as), # 'camera_as' : self._checkNO(self.camera_as), -# 'lamp_as' : self._checkNO(self.lamp_as), +# 'light_as' : self._checkNO(self.light_as), 'entitylayer_from' : self.entitylayer_from, 'entitycolor_from' : self.entitycolor_from, diff --git a/io_export_dxf/primitive_exporters/lamp_exporter.py b/io_export_dxf/primitive_exporters/lamp_exporter.py index c67eb032..849f0984 100644 --- a/io_export_dxf/primitive_exporters/lamp_exporter.py +++ b/io_export_dxf/primitive_exporters/lamp_exporter.py @@ -13,7 +13,7 @@ def exportLamp(ob, mx, mw, **common): [p] = toGlobalOrigin([p]) entities = [] - c = lamp_as_list[GUI_A['lamp_as'].val] + c = light_as_list[GUI_A['light_as'].val] if c=="POINT": # export as POINT dxfPOINT = DXF.Point(points=[p],**common) entities.append(dxfPOINT) diff --git a/io_export_paper_model.py b/io_export_paper_model.py index 38444b37..0906eb33 100644 --- a/io_export_paper_model.py +++ b/io_export_paper_model.py @@ -2238,8 +2238,8 @@ class ExportPaperModel(bpy.types.Operator): row = layout.row(align=True) row.menu("VIEW3D_MT_paper_model_presets", text=bpy.types.VIEW3D_MT_paper_model_presets.bl_label) - row.operator("export_mesh.paper_model_preset_add", text="", icon='ZOOMIN') - row.operator("export_mesh.paper_model_preset_add", text="", icon='ZOOMOUT').remove_active = True + row.operator("export_mesh.paper_model_preset_add", text="", icon='ADD') + row.operator("export_mesh.paper_model_preset_add", text="", icon='REMOVE').remove_active = True # a little hack: this prints out something like "Scale: 1: 72" layout.prop(self.properties, "scale", text="Scale: 1") @@ -2582,12 +2582,12 @@ def register(): bpy.types.Mesh.paper_island_index = bpy.props.IntProperty( name="Island List Index", default=-1, min=-1, max=100, options={'SKIP_SAVE'}) - bpy.types.INFO_MT_file_export.append(menu_func) + bpy.types.TOPBAR_MT_file_export.append(menu_func) def unregister(): bpy.utils.unregister_module(__name__) - bpy.types.INFO_MT_file_export.remove(menu_func) + bpy.types.TOPBAR_MT_file_export.remove(menu_func) if display_islands.handle: bpy.types.SpaceView3D.draw_handler_remove(display_islands.handle, 'WINDOW') display_islands.handle = None diff --git a/io_export_pc2.py b/io_export_pc2.py index 752df5c4..7384e21e 100644 --- a/io_export_pc2.py +++ b/io_export_pc2.py @@ -19,8 +19,8 @@ bl_info = { "name": "Export Pointcache Format(.pc2)", "author": "Florian Meyer (tstscr)", - "version": (1, 1, 1), - "blender": (2, 71, 0), + "version": (1, 1, 2), + "blender": (2, 80, 0), "location": "File > Export > Pointcache (.pc2)", "description": "Export mesh Pointcache data (.pc2)", "warning": "", @@ -50,9 +50,11 @@ import time import math import struct + def get_sampled_frames(start, end, sampling): return [math.modf(start + x * sampling) for x in range(int((end - start) / sampling) + 1)] + def do_export(context, props, filepath): mat_x90 = mathutils.Matrix.Rotation(-math.pi/2, 4, 'X') ob = context.active_object @@ -61,13 +63,13 @@ def do_export(context, props, filepath): end = props.range_end sampling = float(props.sampling) apply_modifiers = props.apply_modifiers - me = ob.to_mesh(sc, apply_modifiers, 'PREVIEW') + me = ob.to_mesh(context.depsgraph, apply_modifiers) vertCount = len(me.vertices) sampletimes = get_sampled_frames(start, end, sampling) sampleCount = len(sampletimes) # Create the header - headerFormat='<12siiffi' + headerFormat = '<12siiffi' headerStr = struct.pack(headerFormat, b'POINTCACHE2\0', 1, vertCount, start, sampling, sampleCount) @@ -75,8 +77,9 @@ def do_export(context, props, filepath): file.write(headerStr) for frame in sampletimes: - sc.frame_set(int(frame[1]), frame[0]) # stupid modf() gives decimal part first! - me = ob.to_mesh(sc, apply_modifiers, 'PREVIEW') + # stupid modf() gives decimal part first! + sc.frame_set(int(frame[1]), subframe=frame[0]) + me = ob.to_mesh(context.depsgraph, apply_modifiers) if len(me.vertices) != vertCount: bpy.data.meshes.remove(me, do_unlink=True) @@ -97,19 +100,18 @@ def do_export(context, props, filepath): for v in me.vertices: thisVertex = struct.pack('<fff', float(v.co[0]), - float(v.co[1]), - float(v.co[2])) + float(v.co[1]), + float(v.co[2])) file.write(thisVertex) bpy.data.meshes.remove(me, do_unlink=True) - file.flush() file.close() return True -###### EXPORT OPERATOR ####### +# EXPORT OPERATOR class Export_pc2(bpy.types.Operator, ExportHelper): """Export the active Object as a .pc2 Pointcache file""" bl_idname = "export_shape.pc2" @@ -117,50 +119,51 @@ class Export_pc2(bpy.types.Operator, ExportHelper): filename_ext = ".pc2" - rot_x90 = BoolProperty(name="Convert to Y-up", - description="Rotate 90 degrees around X to convert to y-up", - default=True, - ) - world_space = BoolProperty(name="Export into Worldspace", - description="Transform the Vertexcoordinates into Worldspace", - default=False, - ) - apply_modifiers = BoolProperty(name="Apply Modifiers", - description="Applies the Modifiers", - default=True, - ) - range_start = IntProperty(name='Start Frame', - description='First frame to use for Export', - default=1, - ) - range_end = IntProperty(name='End Frame', - description='Last frame to use for Export', - default=250, - ) - sampling = EnumProperty(name='Sampling', - description='Sampling --> frames per sample (0.1 yields 10 samples per frame)', - items=(('0.01', '0.01', ''), - ('0.05', '0.05', ''), - ('0.1', '0.1', ''), - ('0.2', '0.2', ''), - ('0.25', '0.25', ''), - ('0.5', '0.5', ''), - ('1', '1', ''), - ('2', '2', ''), - ('3', '3', ''), - ('4', '4', ''), - ('5', '5', ''), - ('10', '10', ''), - ), - default='1', - ) + rot_x90: BoolProperty( + name="Convert to Y-up", + description="Rotate 90 degrees around X to convert to y-up", + default=True,) + world_space: BoolProperty( + name="Export into Worldspace", + description="Transform the Vertexcoordinates into Worldspace", + default=False,) + apply_modifiers: BoolProperty( + name="Apply Modifiers", + description="Applies the Modifiers", + default=True,) + range_start: IntProperty( + name='Start Frame', + description='First frame to use for Export', + default=1,) + range_end: IntProperty( + name='End Frame', + description='Last frame to use for Export', + default=250,) + sampling: EnumProperty( + name='Sampling', + description='Sampling --> frames per sample (0.1 yields 10 samples per frame)', + items=(('0.01', '0.01', ''), + ('0.05', '0.05', ''), + ('0.1', '0.1', ''), + ('0.2', '0.2', ''), + ('0.25', '0.25', ''), + ('0.5', '0.5', ''), + ('1', '1', ''), + ('2', '2', ''), + ('3', '3', ''), + ('4', '4', ''), + ('5', '5', ''), + ('10', '10', ''), + ), + default='1', + ) @classmethod def poll(cls, context): obj = context.active_object return ( - obj is not None and - obj.type in {'MESH', 'CURVE', 'SURFACE', 'FONT'} + obj is not None + and obj.type in {'MESH', 'CURVE', 'SURFACE', 'FONT'} ) def execute(self, context): @@ -173,7 +176,8 @@ class Export_pc2(bpy.types.Operator, ExportHelper): exported = do_export(context, props, filepath) if exported: - print('finished export in %s seconds' %((time.time() - start_time))) + print('finished export in %s seconds' % + ((time.time() - start_time))) print(filepath) return {'FINISHED'} @@ -183,7 +187,7 @@ class Export_pc2(bpy.types.Operator, ExportHelper): if True: # File selector - wm.fileselect_add(self) # will run self.execute() + wm.fileselect_add(self) # will run self.execute() return {'RUNNING_MODAL'} elif True: # search the enum @@ -196,23 +200,29 @@ class Export_pc2(bpy.types.Operator, ExportHelper): return self.execute(context) -### REGISTER ### - -def menu_func(self, context): +def menu_func_export_button(self, context): self.layout.operator(Export_pc2.bl_idname, text="Pointcache (.pc2)") +classes = [ + Export_pc2, +] + + def register(): - bpy.utils.register_module(__name__) + for cls in classes: + bpy.utils.register_class(cls) + + bpy.types.TOPBAR_MT_file_export.append(menu_func_export_button) + #bpy.types.VIEW3D_PT_tools_objectmode.prepend(menu_func_export_button) - bpy.types.INFO_MT_file_export.append(menu_func) - #bpy.types.VIEW3D_PT_tools_objectmode.prepend(menu_func) def unregister(): - bpy.utils.unregister_module(__name__) + bpy.types.TOPBAR_MT_file_export.remove(menu_func_export_button) + #bpy.types.VIEW3D_PT_tools_objectmode.remove(menu_func_export_button) + for cls in classes: + bpy.utils.unregister_class(cls) - bpy.types.INFO_MT_file_export.remove(menu_func) - #bpy.types.VIEW3D_PT_tools_objectmode.remove(menu_func) if __name__ == "__main__": register() diff --git a/io_export_unreal_psk_psa.py b/io_export_unreal_psk_psa.py index 6179470c..40840e90 100644 --- a/io_export_unreal_psk_psa.py +++ b/io_export_unreal_psk_psa.py @@ -1201,8 +1201,8 @@ def parse_mesh(mesh, psk): # does with the mesh Y coordinates. this is otherwise known as MAGIC-2 uv[1] = 1.0 - uv[1] - # clamp UV coords if udk_option_clamp_uv is True - if bpy.context.scene.udk_option_clamp_uv: + # clamp UV coords if udk_option_clight_uv is True + if bpy.context.scene.udk_option_clight_uv: if (uv[0] > 1): uv[0] = 1 if (uv[0] < 0): @@ -2422,7 +2422,7 @@ class Panel_UDKExport(Panel): object_name = context.active_object.name row10 = layout.row() row10.prop(context.scene, "udk_option_smoothing_groups") - row10.prop(context.scene, "udk_option_clamp_uv") + row10.prop(context.scene, "udk_option_clight_uv") row10.prop(context.scene, "udk_option_verbose") row = layout.row() @@ -2792,7 +2792,7 @@ class ExportUDKAnimData(Operator): scene = context.scene layout.prop(scene, "udk_option_smoothing_groups") - layout.prop(scene, "udk_option_clamp_uv") + layout.prop(scene, "udk_option_clight_uv") layout.prop(scene, "udk_option_verbose") layout.prop(scene, "udk_option_filename_src") layout.prop(scene, "udk_option_export") @@ -2865,7 +2865,7 @@ class PskAddonPreferences(AddonPreferences): def register(): bpy.utils.register_module(__name__) - bpy.types.INFO_MT_file_export.append(menu_func) + bpy.types.TOPBAR_MT_file_export.append(menu_func) update_panel(None, bpy.context) # Added by [MGVS] @@ -2888,7 +2888,7 @@ def register(): description="Boolean for exporting psa format (Animation Data)", default=True ) - bpy.types.Scene.udk_option_clamp_uv = BoolProperty( + bpy.types.Scene.udk_option_clight_uv = BoolProperty( name="Clamp UV", description="True is to limit Clamp UV co-ordinates to [0-1]. False is unrestricted (x,y)", default=False @@ -2972,12 +2972,12 @@ def register(): def unregister(): bpy.utils.unregister_module(__name__) - bpy.types.INFO_MT_file_export.remove(menu_func) + bpy.types.TOPBAR_MT_file_export.remove(menu_func) del bpy.types.Scene.udk_option_filename_src del bpy.types.Scene.udk_option_export_psk del bpy.types.Scene.udk_option_export_psa - del bpy.types.Scene.udk_option_clamp_uv + del bpy.types.Scene.udk_option_clight_uv del bpy.types.Scene.udk_copy_merge del bpy.types.Scene.udk_option_export del bpy.types.Scene.udk_option_verbose diff --git a/io_import_dxf/__init__.py b/io_import_dxf/__init__.py index d768d624..46e84fd5 100644 --- a/io_import_dxf/__init__.py +++ b/io_import_dxf/__init__.py @@ -559,12 +559,12 @@ def menu_func(self, context): def register(): bpy.utils.register_module(__name__) - bpy.types.INFO_MT_file_import.append(menu_func) + bpy.types.TOPBAR_MT_file_import.append(menu_func) def unregister(): bpy.utils.unregister_module(__name__) - bpy.types.INFO_MT_file_import.remove(menu_func) + bpy.types.TOPBAR_MT_file_import.remove(menu_func) if __name__ == "__main__": diff --git a/io_import_dxf/dxfimport/do.py b/io_import_dxf/dxfimport/do.py index 7ac4c392..be79908c 100644 --- a/io_import_dxf/dxfimport/do.py +++ b/io_import_dxf/dxfimport/do.py @@ -738,7 +738,7 @@ class Do: if self.import_light: type_map = ["NONE", "SUN", "POINT", "SPOT"] layer = self.dwg.layers[en.layer] - lamp = bpy.data.lamps.new(en.name, type_map[en.light_type]) + lamp = bpy.data.lights.new(en.name, type_map[en.light_type]) if en.color != 256: aci = en.color else: @@ -1005,7 +1005,7 @@ class Do: bpy.context.screen.scene = scene o = bbox.copy() - # o.empty_draw_size = 0.3 + # o.empty_display_size = 0.3 o.dupli_type = "GROUP" o.dupli_group = block_group group.objects.link(o) diff --git a/io_import_gimp_image_to_scene.py b/io_import_gimp_image_to_scene.py index 6ff1d66f..94d496e3 100644 --- a/io_import_gimp_image_to_scene.py +++ b/io_import_gimp_image_to_scene.py @@ -619,7 +619,7 @@ class GIMPImageToScene(bpy.types.Operator): if self.OpacityMode == 'COMPO' and self.SetupCompo == False: box.label('Tip: Enable Node Compositing', icon='INFO') box.prop(self, 'AlphaMode', icon='IMAGE_RGB_ALPHA') - box.prop(self, 'ShadelessMats', icon='SOLID') + box.prop(self, 'ShadelessMats', icon='SHADING_SOLID') box.prop(self, 'LayerOffset') box.prop(self, 'LayerScale') @@ -680,13 +680,13 @@ def menu_func(self, context): def register(): bpy.utils.register_module(__name__) - bpy.types.INFO_MT_file_import.append(menu_func) + bpy.types.TOPBAR_MT_file_import.append(menu_func) def unregister(): bpy.utils.unregister_module(__name__) - bpy.types.INFO_MT_file_import.remove(menu_func) + bpy.types.TOPBAR_MT_file_import.remove(menu_func) if __name__ == "__main__": diff --git a/io_import_images_as_planes.py b/io_import_images_as_planes.py index 1f32bc5f..e0c71426 100644 --- a/io_import_images_as_planes.py +++ b/io_import_images_as_planes.py @@ -21,8 +21,8 @@ bl_info = { "name": "Import Images as Planes", "author": "Florian Meyer (tstscr), mont29, matali, Ted Schundler (SpkyElctrc)", - "version": (3, 1, 1), - "blender": (2, 78, 0), + "version": (3, 2, 0), + "blender": (2, 80, 0), "location": "File > Import > Images as Planes or Add > Mesh > Images as Planes", "description": "Imports images and creates planes with the appropriate aspect ratio. " "The images are mapped to the planes.", @@ -179,7 +179,6 @@ def load_images(filenames, directory, force_reload=False, frame_start=1, find_se frames = image.frame_duration elif frames > 1: # Not movie, but multiple frames -> image sequence - image.use_animation = True image.source = 'SEQUENCE' yield ImageSpec(image, size, frame_start, offset - 1, frames) @@ -200,11 +199,10 @@ def offset_planes(planes, gap, axis): prior = planes[0] offset = Vector() for current in planes[1:]: - - local_offset = abs((prior.dimensions + current.dimensions) * axis) / 2.0 + gap + local_offset = abs((prior.dimensions + current.dimensions).dot(axis)) / 2.0 + gap offset += local_offset * axis - current.location = current.matrix_world * offset + current.location = current.matrix_world @ offset prior = current @@ -242,7 +240,7 @@ def compute_camera_size(context, center, fill_mode, aspect): def center_in_camera(scene, camera, obj, axis=(1, 1)): - """Center object along specified axiis of the camera""" + """Center object along specified axis of the camera""" camera_matrix_col = camera.matrix_world.col location = obj.location @@ -250,11 +248,11 @@ def center_in_camera(scene, camera, obj, axis=(1, 1)): delta = camera_matrix_col[3].xyz - location # How far off center we are along the camera's local X - camera_x_mag = delta * camera_matrix_col[0].xyz * axis[0] + camera_x_mag = delta.dot(camera_matrix_col[0].xyz) * axis[0] # How far off center we are along the camera's local Y - camera_y_mag = delta * camera_matrix_col[1].xyz * axis[1] + camera_y_mag = delta.dot(camera_matrix_col[1].xyz) * axis[1] - # Now offet only along camera local axiis + # Now offset only along camera local axis offset = camera_matrix_col[0].xyz * camera_x_mag + \ camera_matrix_col[1].xyz * camera_y_mag @@ -262,7 +260,7 @@ def center_in_camera(scene, camera, obj, axis=(1, 1)): # ----------------------------------------------------------------------------- -# Cycles utils +# Cycles/Eevee utils def get_input_nodes(node, links): """Get nodes that are a inputs to the given node""" @@ -327,7 +325,7 @@ def clean_node_tree(node_tree): def get_shadeless_node(dest_node_tree): - """Return a "shadless" cycles node, creating a node group if nonexistent""" + """Return a "shadless" cycles/eevee node, creating a node group if nonexistent""" try: node_tree = bpy.data.node_groups['IAP_SHADELESS'] @@ -474,7 +472,7 @@ def find_plane_corner(object_name, x, y, axis, camera=None, *args, **kwargs): v = plane.dimensions.copy() v.x *= x / scale.x v.y *= y / scale.y - v = plane.matrix_world * v + v = plane.matrix_world @ v camera_vertex = world_to_camera_view( bpy.context.scene, camera, v) @@ -614,22 +612,22 @@ class IMPORT_IMAGE_OT_to_plane(Operator, AddObjectHelper): # ---------------------- # File dialog properties - files = CollectionProperty(type=bpy.types.OperatorFileListElement, options={'HIDDEN', 'SKIP_SAVE'}) + files: CollectionProperty(type=bpy.types.OperatorFileListElement, options={'HIDDEN', 'SKIP_SAVE'}) - directory = StringProperty(maxlen=1024, subtype='FILE_PATH', options={'HIDDEN', 'SKIP_SAVE'}) + directory: StringProperty(maxlen=1024, subtype='FILE_PATH', options={'HIDDEN', 'SKIP_SAVE'}) - filter_image = BoolProperty(default=True, options={'HIDDEN', 'SKIP_SAVE'}) - filter_movie = BoolProperty(default=True, options={'HIDDEN', 'SKIP_SAVE'}) - filter_folder = BoolProperty(default=True, options={'HIDDEN', 'SKIP_SAVE'}) + filter_image: BoolProperty(default=True, options={'HIDDEN', 'SKIP_SAVE'}) + filter_movie: BoolProperty(default=True, options={'HIDDEN', 'SKIP_SAVE'}) + filter_folder: BoolProperty(default=True, options={'HIDDEN', 'SKIP_SAVE'}) # ---------------------- # Properties - Importing - force_reload = BoolProperty( + force_reload: BoolProperty( name="Force Reload", default=False, description="Force reloading of the image if already opened elsewhere in Blender" ) - image_sequence = BoolProperty( + image_sequence: BoolProperty( name="Animate Image Sequences", default=False, description="Import sequentially numbered images as an animated " "image sequence instead of separate planes" @@ -646,7 +644,7 @@ class IMPORT_IMAGE_OT_to_plane(Operator, AddObjectHelper): 'Z-': Vector(( 0, 0, -1)), } - offset = BoolProperty(name="Offset Planes", default=True, description="Offset Planes From Each Other") + offset: BoolProperty(name="Offset Planes", default=True, description="Offset Planes From Each Other") OFFSET_MODES = ( ('X+', "X+", "Side by Side to the Left"), @@ -656,12 +654,12 @@ class IMPORT_IMAGE_OT_to_plane(Operator, AddObjectHelper): ('Y-', "Y-", "Side by Side, Upward"), ('Z-', "Z-", "Stacked Below"), ) - offset_axis = EnumProperty( + offset_axis: EnumProperty( name="Orientation", default='X+', items=OFFSET_MODES, description="How planes are oriented relative to each others' local axis" ) - offset_amount = FloatProperty( + offset_amount: FloatProperty( name="Offset", soft_min=0, default=0.1, description="Space between planes", subtype='DISTANCE', unit='LENGTH' ) @@ -676,14 +674,14 @@ class IMPORT_IMAGE_OT_to_plane(Operator, AddObjectHelper): ('CAM', "Face Camera", "Facing Camera"), ('CAM_AX', "Main Axis", "Facing the Camera's dominant axis"), ) - align_axis = EnumProperty( + align_axis: EnumProperty( name="Align", default='CAM_AX', items=AXIS_MODES, description="How to align the planes" ) # prev_align_axis is used only by update_size_model - prev_align_axis = EnumProperty( + prev_align_axis: EnumProperty( items=AXIS_MODES + (('NONE', '', ''),), default='NONE', options={'HIDDEN', 'SKIP_SAVE'}) - align_track = BoolProperty( + align_track: BoolProperty( name="Track Camera", default=False, description="Always face the camera" ) @@ -707,7 +705,7 @@ class IMPORT_IMAGE_OT_to_plane(Operator, AddObjectHelper): ('DPI', "Dpi", "Use definition of the image as dots per inch"), ('DPBU', "Dots/BU", "Use definition of the image as dots per Blender Unit"), ) - size_mode = EnumProperty( + size_mode: EnumProperty( name="Size Mode", default='ABSOLUTE', items=SIZE_MODES, update=update_size_mode, description="How the size of the plane is computed") @@ -716,13 +714,13 @@ class IMPORT_IMAGE_OT_to_plane(Operator, AddObjectHelper): ('FILL', "Fill", "Fill camera frame, spilling outside the frame"), ('FIT', "Fit", "Fit entire image within the camera frame"), ) - fill_mode = EnumProperty(name="Scale", default='FILL', items=FILL_MODES, + fill_mode: EnumProperty(name="Scale", default='FILL', items=FILL_MODES, description="How large in the camera frame is the plane") - height = FloatProperty(name="Height", description="Height of the created plane", + height: FloatProperty(name="Height", description="Height of the created plane", default=1.0, min=0.001, soft_min=0.001, subtype='DISTANCE', unit='LENGTH') - factor = FloatProperty(name="Definition", min=1.0, default=600.0, + factor: FloatProperty(name="Definition", min=1.0, default=600.0, description="Number of pixels per inch or Blender Unit") # ------------------------------ @@ -732,40 +730,37 @@ class IMPORT_IMAGE_OT_to_plane(Operator, AddObjectHelper): ('SHADELESS', "Shadeless", "Only visible to camera and reflections."), ('EMISSION', "Emit", "Emission Shader"), ) - shader = EnumProperty(name="Shader", items=SHADERS, default='DIFFUSE', description="Node shader to use") + shader: EnumProperty(name="Shader", items=SHADERS, default='DIFFUSE', description="Node shader to use") - emit_strength = FloatProperty( + emit_strength: FloatProperty( name="Strength", min=0.0, default=1.0, soft_max=10.0, step=100, description="Brightness of Emission Texture") - overwrite_material = BoolProperty( + overwrite_material: BoolProperty( name="Overwrite Material", default=True, description="Overwrite existing Material (based on material name)") - compositing_nodes = BoolProperty( + compositing_nodes: BoolProperty( name="Setup Corner Pin", default=False, description="Build Compositor Nodes to reference this image " "without re-rendering") # ------------------ # Properties - Image - use_transparency = BoolProperty( + use_transparency: BoolProperty( name="Use Alpha", default=True, description="Use alphachannel for transparency") t = bpy.types.Image.bl_rna.properties["alpha_mode"] alpha_mode_items = tuple((e.identifier, e.name, e.description) for e in t.enum_items) - alpha_mode = EnumProperty( + alpha_mode: EnumProperty( name=t.name, items=alpha_mode_items, default=t.default, description=t.description) - t = bpy.types.Image.bl_rna.properties["use_fields"] - use_fields = BoolProperty(name=t.name, default=False, description=t.description) - t = bpy.types.ImageUser.bl_rna.properties["use_auto_refresh"] - use_auto_refresh = BoolProperty(name=t.name, default=True, description=t.description) + use_auto_refresh: BoolProperty(name=t.name, default=True, description=t.description) - relative = BoolProperty(name="Relative Paths", default=True, description="Use relative file paths") + relative: BoolProperty(name="Relative Paths", default=True, description="Use relative file paths") # ------- # Draw UI @@ -798,7 +793,7 @@ class IMPORT_IMAGE_OT_to_plane(Operator, AddObjectHelper): box.prop(self, "emit_strength") engine = context.scene.render.engine - if engine not in ('CYCLES', 'BLENDER_RENDER'): + if engine not in ('CYCLES', 'BLENDER_EEVEE', 'BLENDER_OPENGL'): box.label(text="%s is not supported" % engine, icon='ERROR') box.prop(self, "overwrite_material") @@ -809,7 +804,6 @@ class IMPORT_IMAGE_OT_to_plane(Operator, AddObjectHelper): sub = row.row() sub.active = self.use_transparency sub.prop(self, "alpha_mode", text="") - box.prop(self, "use_fields") box.prop(self, "use_auto_refresh") def draw_spatial_config(self, context): @@ -857,9 +851,13 @@ class IMPORT_IMAGE_OT_to_plane(Operator, AddObjectHelper): # Core functionality def invoke(self, context, event): engine = context.scene.render.engine - if engine not in ('CYCLES', 'BLENDER_RENDER', 'BLENDER_GAME'): - # Use default blender texture, but acknowledge things may not work - self.report({'WARNING'}, "Cannot generate materials for unknown %s render engine" % engine) + if engine not in {'CYCLES', 'BLENDER_EEVEE'}: + if engine not in {'BLENDER_OPENGL'}: + self.report({'ERROR'}, "Cannot generate materials for unknown %s render engine" % engine) + return {'CANCELLED'} + else: + self.report({'WARNING'}, + "Generating Cycles/EEVEE compatible material, but won't be visible with %s engine" % engine) # Open file browser context.window_manager.fileselect_add(self) @@ -910,7 +908,7 @@ class IMPORT_IMAGE_OT_to_plane(Operator, AddObjectHelper): # setup new selection for plane in planes: - plane.select = True + plane.select_set('SELECT') # all done! self.report({'INFO'}, "Added {} Image Plane(s)".format(len(planes))) @@ -923,22 +921,14 @@ class IMPORT_IMAGE_OT_to_plane(Operator, AddObjectHelper): # Configure material engine = context.scene.render.engine - if engine == 'CYCLES': + if engine in {'CYCLES', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}: material = self.create_cycles_material(context, img_spec) - else: - tex = self.create_image_textures(context, img_spec) - material = self.create_material_for_texture(tex) - - # Game Engine Material Settings - material.game_settings.use_backface_culling = False - material.game_settings.alpha_blend = 'ALPHA' # Create and position plane object plane = self.create_image_plane(context, material.name, img_spec) # Assign Material plane.data.materials.append(material) - plane.data.uv_textures[0].data[0].image = img_spec.image # If applicable, setup Corner Pin node if self.compositing_nodes: @@ -949,7 +939,6 @@ class IMPORT_IMAGE_OT_to_plane(Operator, AddObjectHelper): def apply_image_options(self, image): image.use_alpha = self.use_transparency image.alpha_mode = self.alpha_mode - image.use_fields = self.use_fields if self.relative: try: # can't always find the relative path (between drive letters on windows) @@ -971,48 +960,6 @@ class IMPORT_IMAGE_OT_to_plane(Operator, AddObjectHelper): texture.extension = 'CLIP' # Default of "Repeat" can cause artifacts - # ------------------------------------------------------------------------- - # Blender Internal Material - def create_image_textures(self, context, img_spec): - image = img_spec.image - fn_full = os.path.normpath(bpy.path.abspath(image.filepath)) - - # look for texture referencing this file - for texture in bpy.data.textures: - if texture.type == 'IMAGE': - tex_img = texture.image - if (tex_img is not None) and (tex_img.library is None): - fn_tex_full = os.path.normpath(bpy.path.abspath(tex_img.filepath)) - if fn_full == fn_tex_full: - if self.overwrite_material: - self.apply_texture_options(texture, img_spec) - return texture - - # if no texture is found: create one - name_compat = bpy.path.display_name_from_filepath(image.filepath) - texture = bpy.data.textures.new(name=name_compat, type='IMAGE') - texture.image = image - self.apply_texture_options(texture, img_spec) - return texture - - def create_material_for_texture(self, texture): - # look for material with the needed texture - for material in bpy.data.materials: - slot = material.texture_slots[0] - if slot and slot.texture == texture: - if self.overwrite_material: - self.apply_material_options(material, slot) - return material - - # if no material found: create one - name_compat = bpy.path.display_name_from_filepath(texture.image.filepath) - material = bpy.data.materials.new(name=name_compat) - slot = material.texture_slots.add() - slot.texture = texture - slot.texture_coords = 'UV' - self.apply_material_options(material, slot) - return material - def apply_material_options(self, material, slot): shader = self.shader @@ -1034,7 +981,7 @@ class IMPORT_IMAGE_OT_to_plane(Operator, AddObjectHelper): material.emit = self.emit_strength if shader == 'EMISSION' else 0.0 # ------------------------------------------------------------------------- - # Cycles + # Cycles/Eevee def create_cycles_texnode(self, context, node_tree, img_spec): tex_image = node_tree.nodes.new('ShaderNodeTexImage') tex_image.image = img_spec.image @@ -1092,14 +1039,13 @@ class IMPORT_IMAGE_OT_to_plane(Operator, AddObjectHelper): # Create new mesh bpy.ops.mesh.primitive_plane_add('INVOKE_REGION_WIN') - plane = context.scene.objects.active + plane = context.active_object # Why does mesh.primitive_plane_add leave the object in edit mode??? if plane.mode is not 'OBJECT': bpy.ops.object.mode_set(mode='OBJECT') plane.dimensions = width, height, 0.0 plane.data.name = plane.name = name bpy.ops.object.transform_apply(scale=True) - plane.data.uv_textures.new() # If sizing for camera, also insert into the camera's field of view if self.size_mode == 'CAMERA': @@ -1148,7 +1094,7 @@ class IMPORT_IMAGE_OT_to_plane(Operator, AddObjectHelper): camera = context.scene.camera if (camera): # Find the axis that best corresponds to the camera's view direction - axis = camera.matrix_world * \ + axis = camera.matrix_world @ \ Vector((0, 0, 1)) - camera.matrix_world.col[3].xyz # pick the axis with the greatest magnitude mag = max(map(abs, axis)) @@ -1213,16 +1159,16 @@ def register(): for cls in classes: bpy.utils.register_class(cls) - bpy.types.INFO_MT_file_import.append(import_images_button) - bpy.types.INFO_MT_mesh_add.append(import_images_button) + bpy.types.TOPBAR_MT_file_import.append(import_images_button) + bpy.types.VIEW3D_MT_mesh_add.append(import_images_button) bpy.app.handlers.load_post.append(register_driver) register_driver() def unregister(): - bpy.types.INFO_MT_file_import.remove(import_images_button) - bpy.types.INFO_MT_mesh_add.remove(import_images_button) + bpy.types.TOPBAR_MT_file_import.remove(import_images_button) + bpy.types.VIEW3D_MT_mesh_add.remove(import_images_button) # This will only exist if drivers are active if check_drivers in bpy.app.handlers.scene_update_post: diff --git a/io_import_scene_lwo.py b/io_import_scene_lwo.py index 3cfe207c..be5f55aa 100644 --- a/io_import_scene_lwo.py +++ b/io_import_scene_lwo.py @@ -1251,13 +1251,13 @@ def menu_func(self, context): def register(): bpy.utils.register_module(__name__) - bpy.types.INFO_MT_file_import.append(menu_func) + bpy.types.TOPBAR_MT_file_import.append(menu_func) def unregister(): bpy.utils.unregister_module(__name__) - bpy.types.INFO_MT_file_import.remove(menu_func) + bpy.types.TOPBAR_MT_file_import.remove(menu_func) if __name__ == "__main__": register() diff --git a/io_import_scene_unreal_psa_psk.py b/io_import_scene_unreal_psa_psk.py index 5fb0c8f6..461cd05d 100644 --- a/io_import_scene_unreal_psa_psk.py +++ b/io_import_scene_unreal_psa_psk.py @@ -1275,11 +1275,11 @@ def menu_func(self, context): def register(): bpy.utils.register_module(__name__) - bpy.types.INFO_MT_file_import.append(menu_func) + bpy.types.TOPBAR_MT_file_import.append(menu_func) def unregister(): bpy.utils.unregister_module(__name__) - bpy.types.INFO_MT_file_import.remove(menu_func) + bpy.types.TOPBAR_MT_file_import.remove(menu_func) if __name__ == "__main__": register() diff --git a/io_mesh_pdb/__init__.py b/io_mesh_pdb/__init__.py index 1355d73b..4e731cf5 100644 --- a/io_mesh_pdb/__init__.py +++ b/io_mesh_pdb/__init__.py @@ -82,7 +82,7 @@ class ImportPDB(Operator, ImportHelper): use_camera = BoolProperty( name="Camera", default=False, description="Do you need a camera?") - use_lamp = BoolProperty( + use_light = BoolProperty( name="Lamp", default=False, description = "Do you need a lamp?") ball = EnumProperty( @@ -162,7 +162,7 @@ class ImportPDB(Operator, ImportHelper): layout = self.layout row = layout.row() row.prop(self, "use_camera") - row.prop(self, "use_lamp") + row.prop(self, "use_light") row = layout.row() row.prop(self, "use_center") # Balls @@ -256,7 +256,7 @@ class ImportPDB(Operator, ImportHelper): self.sticks_radius, self.use_center, self.use_camera, - self.use_lamp, + self.use_light, filepath_pdb) return {'FINISHED'} @@ -301,13 +301,13 @@ def menu_func_export(self, context): def register(): bpy.utils.register_module(__name__) - bpy.types.INFO_MT_file_import.append(menu_func_import) - bpy.types.INFO_MT_file_export.append(menu_func_export) + bpy.types.TOPBAR_MT_file_import.append(menu_func_import) + bpy.types.TOPBAR_MT_file_export.append(menu_func_export) def unregister(): bpy.utils.unregister_module(__name__) - bpy.types.INFO_MT_file_import.remove(menu_func_import) - bpy.types.INFO_MT_file_export.remove(menu_func_export) + bpy.types.TOPBAR_MT_file_import.remove(menu_func_import) + bpy.types.TOPBAR_MT_file_export.remove(menu_func_export) if __name__ == "__main__": diff --git a/io_mesh_pdb/import_pdb.py b/io_mesh_pdb/import_pdb.py index a7067692..8256d108 100644 --- a/io_mesh_pdb/import_pdb.py +++ b/io_mesh_pdb/import_pdb.py @@ -536,7 +536,7 @@ def build_stick(radius, length, sectors): # Function, which puts a camera and light source into the 3D scene def camera_light_source(use_camera, - use_lamp, + use_light, object_center_vec, object_size): @@ -592,27 +592,27 @@ def camera_light_source(use_camera, release_confirm=False) # Here a lamp is put into the scene, if chosen. - if use_lamp == True: + if use_light == True: # This is the distance from the object measured in terms of % # of the camera distance. It is set onto 50% (1/2) distance. - lamp_dl = sqrt(object_size) * 15 * 0.5 + light_dl = sqrt(object_size) * 15 * 0.5 # This is a factor to which extend the lamp shall go to the right # (from the camera point of view). - lamp_dy_right = lamp_dl * (3.0/4.0) + light_dy_right = light_dl * (3.0/4.0) # Create x, y and z for the lamp. - object_lamp_vec = Vector((lamp_dl,lamp_dy_right,lamp_dl)) - lamp_xyz_vec = object_center_vec + object_lamp_vec + object_light_vec = Vector((light_dl,light_dy_right,light_dl)) + light_xyz_vec = object_center_vec + object_light_vec # Create the lamp current_layers=bpy.context.scene.layers - lamp_data = bpy.data.lamps.new(name="A_lamp", type="POINT") - lamp_data.distance = 500.0 - lamp_data.energy = 3.0 - lamp_data.shadow_method = 'RAY_SHADOW' - lamp = bpy.data.objects.new("A_lamp", lamp_data) - lamp.location = lamp_xyz_vec + light_data = bpy.data.lights.new(name="A_light", type="POINT") + light_data.distance = 500.0 + light_data.energy = 3.0 + light_data.shadow_method = 'RAY_SHADOW' + lamp = bpy.data.objects.new("A_light", light_data) + lamp.location = light_xyz_vec lamp.layers = current_layers bpy.context.scene.objects.link(lamp) @@ -1145,7 +1145,7 @@ def import_pdb(Ball_type, Stick_diameter, put_to_center, use_camera, - use_lamp, + use_light, filepath_pdb): @@ -1376,7 +1376,7 @@ def import_pdb(Ball_type, # CAMERA and LIGHT SOURCES camera_light_source(use_camera, - use_lamp, + use_light, object_center_vec, object_size) diff --git a/io_mesh_ply/__init__.py b/io_mesh_ply/__init__.py index 6764dcb4..30051796 100644 --- a/io_mesh_ply/__init__.py +++ b/io_mesh_ply/__init__.py @@ -22,7 +22,7 @@ bl_info = { "name": "Stanford PLY format", "author": "Bruce Merry, Campbell Barton", "version": (1, 0, 0), - "blender": (2, 74, 0), + "blender": (2, 80, 0), "location": "File > Import-Export", "description": "Import-Export PLY mesh data with UV's and vertex colors", "warning": "", @@ -56,29 +56,26 @@ from bpy.props import ( from bpy_extras.io_utils import ( ImportHelper, ExportHelper, - orientation_helper_factory, axis_conversion, + orientation_helper ) -IOPLYOrientationHelper = orientation_helper_factory("IOPLYOrientationHelper", axis_forward='Y', axis_up='Z') - - class ImportPLY(bpy.types.Operator, ImportHelper): """Load a PLY geometry file""" bl_idname = "import_mesh.ply" bl_label = "Import PLY" bl_options = {'UNDO'} - files = CollectionProperty(name="File Path", + files: CollectionProperty(name="File Path", description="File path used for importing " "the PLY file", type=bpy.types.OperatorFileListElement) - directory = StringProperty() + directory: StringProperty() filename_ext = ".ply" - filter_glob = StringProperty(default="*.ply", options={'HIDDEN'}) + filter_glob: StringProperty(default="*.ply", options={'HIDDEN'}) def execute(self, context): paths = [os.path.join(self.directory, name.name) @@ -94,21 +91,22 @@ class ImportPLY(bpy.types.Operator, ImportHelper): return {'FINISHED'} -class ExportPLY(bpy.types.Operator, ExportHelper, IOPLYOrientationHelper): +@orientation_helper(axis_forward='Y', axis_up='Z') +class ExportPLY(bpy.types.Operator, ExportHelper): """Export a single object as a Stanford PLY with normals, """ \ """colors and texture coordinates""" bl_idname = "export_mesh.ply" bl_label = "Export PLY" filename_ext = ".ply" - filter_glob = StringProperty(default="*.ply", options={'HIDDEN'}) + filter_glob: StringProperty(default="*.ply", options={'HIDDEN'}) - use_mesh_modifiers = BoolProperty( + use_mesh_modifiers: BoolProperty( name="Apply Modifiers", description="Apply Modifiers to the exported mesh", default=True, ) - use_normals = BoolProperty( + use_normals: BoolProperty( name="Normals", description="Export Normals for smooth and " "hard shaded faces " @@ -116,18 +114,18 @@ class ExportPLY(bpy.types.Operator, ExportHelper, IOPLYOrientationHelper): "as individual faces)", default=True, ) - use_uv_coords = BoolProperty( + use_uv_coords: BoolProperty( name="UVs", description="Export the active UV layer", default=True, ) - use_colors = BoolProperty( + use_colors: BoolProperty( name="Vertex Colors", description="Export the active vertex color layer", default=True, ) - global_scale = FloatProperty( + global_scale: FloatProperty( name="Scale", min=0.01, max=1000.0, default=1.0, @@ -150,7 +148,7 @@ class ExportPLY(bpy.types.Operator, ExportHelper, IOPLYOrientationHelper): )) global_matrix = axis_conversion(to_forward=self.axis_forward, to_up=self.axis_up, - ).to_4x4() * Matrix.Scale(self.global_scale, 4) + ).to_4x4() @ Matrix.Scale(self.global_scale, 4) keywords["global_matrix"] = global_matrix filepath = self.filepath @@ -191,16 +189,16 @@ def register(): for cls in classes: bpy.utils.register_class(cls) - bpy.types.INFO_MT_file_import.append(menu_func_import) - bpy.types.INFO_MT_file_export.append(menu_func_export) + bpy.types.TOPBAR_MT_file_import.append(menu_func_import) + bpy.types.TOPBAR_MT_file_export.append(menu_func_export) def unregister(): for cls in classes: bpy.utils.unregister_class(cls) - bpy.types.INFO_MT_file_import.remove(menu_func_import) - bpy.types.INFO_MT_file_export.remove(menu_func_export) + bpy.types.TOPBAR_MT_file_import.remove(menu_func_import) + bpy.types.TOPBAR_MT_file_export.remove(menu_func_export) if __name__ == "__main__": register() diff --git a/io_mesh_ply/export_ply.py b/io_mesh_ply/export_ply.py index 8de5d674..b50b6544 100644 --- a/io_mesh_ply/export_ply.py +++ b/io_mesh_ply/export_ply.py @@ -44,12 +44,12 @@ def save_mesh(filepath, file = open(filepath, "w", encoding="utf8", newline="\n") fw = file.write - # Be sure tessface & co are available! - if not mesh.tessfaces and mesh.polygons: - mesh.calc_tessface() + # Be sure tessellated loop trianlges are available! + if not mesh.loop_triangles and mesh.polygons: + mesh.calc_loop_triangles() - has_uv = bool(mesh.tessface_uv_textures) - has_vcol = bool(mesh.tessface_vertex_colors) + has_uv = bool(mesh.uv_layers) + has_vcol = bool(mesh.vertex_colors) if not has_uv: use_uv_coords = False @@ -62,7 +62,7 @@ def save_mesh(filepath, has_vcol = False if has_uv: - active_uv_layer = mesh.tessface_uv_textures.active + active_uv_layer = mesh.uv_layers.active if not active_uv_layer: use_uv_coords = False has_uv = False @@ -70,7 +70,7 @@ def save_mesh(filepath, active_uv_layer = active_uv_layer.data if has_vcol: - active_col_layer = mesh.tessface_vertex_colors.active + active_col_layer = mesh.vertex_colors.active if not active_col_layer: use_colors = False has_vcol = False @@ -84,9 +84,9 @@ def save_mesh(filepath, ply_verts = [] # list of dictionaries # vdict = {} # (index, normal, uv) -> new index vdict = [{} for i in range(len(mesh_verts))] - ply_faces = [[] for f in range(len(mesh.tessfaces))] + ply_faces = [[] for f in range(len(mesh.loop_triangles))] vert_count = 0 - for i, f in enumerate(mesh.tessfaces): + for i, f in enumerate(mesh.loop_triangles): smooth = not use_normals or f.use_smooth if not smooth: @@ -94,16 +94,12 @@ def save_mesh(filepath, normal_key = rvec3d(normal) if has_uv: - uv = active_uv_layer[i] - uv = uv.uv1, uv.uv2, uv.uv3, uv.uv4 + uv = [active_uv_layer[l].uv[:] for l in f.loops] if has_vcol: - col = active_col_layer[i] - col = col.color1[:], col.color2[:], col.color3[:], col.color4[:] - - f_verts = f.vertices + col = [active_col_layer[l].color[:] for l in f.loops] pf = ply_faces[i] - for j, vidx in enumerate(f_verts): + for j, vidx in enumerate(f.vertices): v = mesh_verts[vidx] if smooth: @@ -119,6 +115,7 @@ def save_mesh(filepath, color = (int(color[0] * 255.0), int(color[1] * 255.0), int(color[2] * 255.0), + 255 ) key = normal_key, uvcoord_key, color @@ -157,7 +154,7 @@ def save_mesh(filepath, "property uchar blue\n" "property uchar alpha\n") - fw("element face %d\n" % len(mesh.tessfaces)) + fw("element face %d\n" % len(mesh.loop_triangles)) fw("property list uchar uint vertex_indices\n") fw("end_header\n") @@ -193,7 +190,6 @@ def save(operator, global_matrix=None ): - scene = context.scene obj = context.active_object if global_matrix is None: @@ -204,14 +200,15 @@ def save(operator, bpy.ops.object.mode_set(mode='OBJECT') if use_mesh_modifiers and obj.modifiers: - mesh = obj.to_mesh(scene, True, 'PREVIEW') + mesh = obj.to_mesh(context.depsgraph, True) + else: mesh = obj.data.copy() if not mesh: raise Exception("Error, could not get mesh data from active object") - mesh.transform(global_matrix * obj.matrix_world) + mesh.transform(global_matrix @ obj.matrix_world) if use_normals: mesh.calc_normals() @@ -221,7 +218,6 @@ def save(operator, use_colors=use_colors, ) - if use_mesh_modifiers: - bpy.data.meshes.remove(mesh) + bpy.data.meshes.remove(mesh) return ret diff --git a/io_mesh_ply/import_ply.py b/io_mesh_ply/import_ply.py index 86fc2e1b..f05e1caa 100644 --- a/io_mesh_ply/import_ply.py +++ b/io_mesh_ply/import_ply.py @@ -176,6 +176,7 @@ def read(filepath): else: texture = tokens[2] continue + elif tokens[0] == b'obj_info': continue elif tokens[0] == b'format': @@ -222,9 +223,9 @@ import bpy def load_ply_mesh(filepath, ply_name): from bpy_extras.io_utils import unpack_face_list - # from bpy_extras.image_utils import load_image # UNUSED obj_spec, obj, texture = read(filepath) + # XXX28: use texture if obj is None: print('Invalid file') return @@ -262,9 +263,9 @@ def load_ply_mesh(filepath, ply_name): def add_face(vertices, indices, uvindices, colindices): mesh_faces.append(indices) if uvindices: - mesh_uvs.append([(vertices[index][uvindices[0]], vertices[index][uvindices[1]]) for index in indices]) + mesh_uvs.extend([(vertices[index][uvindices[0]], vertices[index][uvindices[1]]) for index in indices]) if colindices: - mesh_colors.append([(vertices[index][colindices[0]] * colmultiply[0], + mesh_colors.extend([(vertices[index][colindices[0]] * colmultiply[0], vertices[index][colindices[1]] * colmultiply[1], vertices[index][colindices[2]] * colmultiply[2], vertices[index][colindices[3]] * colmultiply[3], @@ -316,41 +317,45 @@ def load_ply_mesh(filepath, ply_name): mesh.edges.foreach_set("vertices", [a for e in obj[b'edge'] for a in (e[eindex1], e[eindex2])]) if mesh_faces: - mesh.tessfaces.add(len(mesh_faces)) - mesh.tessfaces.foreach_set("vertices_raw", unpack_face_list(mesh_faces)) - - if uvindices or colindices: - if uvindices: - uvlay = mesh.tessface_uv_textures.new() - if colindices: - vcol_lay = mesh.tessface_vertex_colors.new() - - if uvindices: - for i, f in enumerate(uvlay.data): - ply_uv = mesh_uvs[i] - for j, uv in enumerate(f.uv): - uv[0], uv[1] = ply_uv[j] - - if colindices: - for i, f in enumerate(vcol_lay.data): - # XXX, colors dont come in right, needs further investigation. - ply_col = mesh_colors[i] - if len(ply_col) == 4: - f_col = f.color1, f.color2, f.color3, f.color4 - else: - f_col = f.color1, f.color2, f.color3 + loops_vert_idx = [] + faces_loop_start = [] + faces_loop_total = [] + lidx = 0 + for f in mesh_faces: + nbr_vidx = len(f) + loops_vert_idx.extend(f) + faces_loop_start.append(lidx) + faces_loop_total.append(nbr_vidx) + lidx += nbr_vidx + + mesh.loops.add(len(loops_vert_idx)) + mesh.polygons.add(len(mesh_faces)) + + mesh.loops.foreach_set("vertex_index", loops_vert_idx) + mesh.polygons.foreach_set("loop_start", faces_loop_start) + mesh.polygons.foreach_set("loop_total", faces_loop_total) + + if uvindices: + uv_layer = mesh.uv_layers.new() + for i, uv in enumerate(uv_layer.data): + uv.uv = mesh_uvs[i] - for j, col in enumerate(f_col): - col[0] = ply_col[j][0] - col[1] = ply_col[j][1] - col[2] = ply_col[j][2] - col[3] = ply_col[j][3] + if colindices: + vcol_lay = mesh.vertex_colors.new() + + for i, col in enumerate(vcol_lay.data): + col.color[0] = mesh_colors[i][0] + col.color[1] = mesh_colors[i][1] + col.color[2] = mesh_colors[i][2] + col.color[3] = mesh_colors[i][3] - mesh.validate() mesh.update() + mesh.validate() if texture and uvindices: - + pass + # XXX28: add support for using texture. + ''' import os import sys from bpy_extras.image_utils import load_image @@ -375,6 +380,7 @@ def load_ply_mesh(filepath, ply_name): mesh.materials.append(material) for face in mesh.uv_textures[0].data: face.image = image + ''' return mesh @@ -389,12 +395,10 @@ def load_ply(filepath): if not mesh: return {'CANCELLED'} - scn = bpy.context.scene - obj = bpy.data.objects.new(ply_name, mesh) - scn.objects.link(obj) - scn.objects.active = obj - obj.select = True + bpy.context.collection.objects.link(obj) + bpy.context.view_layer.objects.active = obj + obj.select_set("SELECT") print('\nSuccessfully imported %r in %.3f sec' % (filepath, time.time() - t)) return {'FINISHED'} diff --git a/io_mesh_raw/__init__.py b/io_mesh_raw/__init__.py index 69640932..5ad4c6f5 100644 --- a/io_mesh_raw/__init__.py +++ b/io_mesh_raw/__init__.py @@ -107,15 +107,15 @@ def menu_export(self, context): def register(): bpy.utils.register_module(__name__) - bpy.types.INFO_MT_file_import.append(menu_import) - bpy.types.INFO_MT_file_export.append(menu_export) + bpy.types.TOPBAR_MT_file_import.append(menu_import) + bpy.types.TOPBAR_MT_file_export.append(menu_export) def unregister(): bpy.utils.unregister_module(__name__) - bpy.types.INFO_MT_file_import.remove(menu_import) - bpy.types.INFO_MT_file_export.remove(menu_export) + bpy.types.TOPBAR_MT_file_import.remove(menu_import) + bpy.types.TOPBAR_MT_file_export.remove(menu_export) if __name__ == "__main__": register() diff --git a/io_mesh_stl/__init__.py b/io_mesh_stl/__init__.py index fc8bced2..6859627c 100644 --- a/io_mesh_stl/__init__.py +++ b/io_mesh_stl/__init__.py @@ -22,7 +22,7 @@ bl_info = { "name": "STL format", "author": "Guillaume Bouchard (Guillaum)", "version": (1, 1, 2), - "blender": (2, 74, 0), + "blender": (2, 80, 0), "location": "File > Import-Export > Stl", "description": "Import-Export STL files", "warning": "", @@ -67,7 +67,7 @@ from bpy.props import ( from bpy_extras.io_utils import ( ImportHelper, ExportHelper, - orientation_helper_factory, + orientation_helper, axis_conversion, ) from bpy.types import ( @@ -76,10 +76,8 @@ from bpy.types import ( ) -IOSTLOrientationHelper = orientation_helper_factory("IOSTLOrientationHelper", axis_forward='Y', axis_up='Z') - - -class ImportSTL(Operator, ImportHelper, IOSTLOrientationHelper): +@orientation_helper(axis_forward='Y', axis_up='Z') +class ImportSTL(Operator, ImportHelper): """Load STL triangle mesh data""" bl_idname = "import_mesh.stl" bl_label = "Import STL" @@ -87,32 +85,32 @@ class ImportSTL(Operator, ImportHelper, IOSTLOrientationHelper): filename_ext = ".stl" - filter_glob = StringProperty( + filter_glob: StringProperty( default="*.stl", options={'HIDDEN'}, ) - files = CollectionProperty( + files: CollectionProperty( name="File Path", type=OperatorFileListElement, ) - directory = StringProperty( + directory: StringProperty( subtype='DIR_PATH', ) - global_scale = FloatProperty( + global_scale: FloatProperty( name="Scale", soft_min=0.001, soft_max=1000.0, min=1e-6, max=1e6, default=1.0, ) - use_scene_unit = BoolProperty( + use_scene_unit: BoolProperty( name="Scene Unit", description="Apply current scene's unit (as defined by unit scale) to imported data", default=False, ) - use_facet_normal = BoolProperty( + use_facet_normal: BoolProperty( name="Facet Normals", description="Use (import) facet normals (note that this will still give flat shading)", default=False, @@ -135,7 +133,7 @@ class ImportSTL(Operator, ImportHelper, IOSTLOrientationHelper): global_matrix = axis_conversion(from_forward=self.axis_forward, from_up=self.axis_up, - ).to_4x4() * Matrix.Scale(global_scale, 4) + ).to_4x4() @ Matrix.Scale(global_scale, 4) if not paths: paths.append(self.filepath) @@ -155,41 +153,42 @@ class ImportSTL(Operator, ImportHelper, IOSTLOrientationHelper): return {'FINISHED'} -class ExportSTL(Operator, ExportHelper, IOSTLOrientationHelper): +@orientation_helper(axis_forward='Y', axis_up='Z') +class ExportSTL(Operator, ExportHelper): """Save STL triangle mesh data from the active object""" bl_idname = "export_mesh.stl" bl_label = "Export STL" filename_ext = ".stl" - filter_glob = StringProperty(default="*.stl", options={'HIDDEN'}) + filter_glob: StringProperty(default="*.stl", options={'HIDDEN'}) - use_selection = BoolProperty( + use_selection: BoolProperty( name="Selection Only", description="Export selected objects only", default=False, ) - global_scale = FloatProperty( + global_scale: FloatProperty( name="Scale", min=0.01, max=1000.0, default=1.0, ) - use_scene_unit = BoolProperty( + use_scene_unit: BoolProperty( name="Scene Unit", description="Apply current scene's unit (as defined by unit scale) to exported data", default=False, ) - ascii = BoolProperty( + ascii: BoolProperty( name="Ascii", description="Save the file in ASCII file format", default=False, ) - use_mesh_modifiers = BoolProperty( + use_mesh_modifiers: BoolProperty( name="Apply Modifiers", description="Apply the modifiers before saving", default=True, ) - batch_mode = EnumProperty( + batch_mode: EnumProperty( name="Batch Mode", items=(('OFF', "Off", "All data in one file"), ('OBJECT', "Object", "Each object as a file"), @@ -228,7 +227,7 @@ class ExportSTL(Operator, ExportHelper, IOSTLOrientationHelper): global_matrix = axis_conversion(to_forward=self.axis_forward, to_up=self.axis_up, - ).to_4x4() * Matrix.Scale(global_scale, 4) + ).to_4x4() @ Matrix.Scale(global_scale, 4) if self.batch_mode == 'OFF': faces = itertools.chain.from_iterable( @@ -252,22 +251,28 @@ def menu_import(self, context): def menu_export(self, context): - default_path = os.path.splitext(bpy.data.filepath)[0] + ".stl" self.layout.operator(ExportSTL.bl_idname, text="Stl (.stl)") +classes = ( + ImportSTL, + ExportSTL +) + def register(): - bpy.utils.register_module(__name__) + for cls in classes: + bpy.utils.register_class(cls) - bpy.types.INFO_MT_file_import.append(menu_import) - bpy.types.INFO_MT_file_export.append(menu_export) + bpy.types.TOPBAR_MT_file_import.append(menu_import) + bpy.types.TOPBAR_MT_file_export.append(menu_export) def unregister(): - bpy.utils.unregister_module(__name__) + for cls in classes: + bpy.utils.unregister_class(cls) - bpy.types.INFO_MT_file_import.remove(menu_import) - bpy.types.INFO_MT_file_export.remove(menu_export) + bpy.types.TOPBAR_MT_file_import.remove(menu_import) + bpy.types.TOPBAR_MT_file_export.remove(menu_export) if __name__ == "__main__": diff --git a/io_mesh_stl/blender_utils.py b/io_mesh_stl/blender_utils.py index 864335ab..ee5cb098 100644 --- a/io_mesh_stl/blender_utils.py +++ b/io_mesh_stl/blender_utils.py @@ -57,15 +57,13 @@ def create_and_link_mesh(name, faces, face_nors, points, global_matrix): mesh.update() - scene = bpy.context.scene - obj = bpy.data.objects.new(name, mesh) - scene.objects.link(obj) - scene.objects.active = obj - obj.select = True + bpy.context.collection.objects.link(obj) + bpy.context.view_layer.objects.active = obj + obj.select_set("SELECT") -def faces_from_mesh(ob, global_matrix, use_mesh_modifiers=False, triangulate=True): +def faces_from_mesh(ob, global_matrix, use_mesh_modifiers=False): """ From an object, return a generator over a list of faces. @@ -84,34 +82,19 @@ def faces_from_mesh(ob, global_matrix, use_mesh_modifiers=False, triangulate=Tru # get the modifiers try: - mesh = ob.to_mesh(bpy.context.scene, use_mesh_modifiers, "PREVIEW") + mesh = ob.to_mesh(bpy.context.depsgraph, use_mesh_modifiers) except RuntimeError: raise StopIteration - mat = global_matrix * ob.matrix_world + mat = global_matrix @ ob.matrix_world mesh.transform(mat) if mat.is_negative: mesh.flip_normals() - mesh.calc_tessface() - - if triangulate: - # From a list of faces, return the face triangulated if needed. - def iter_face_index(): - for face in mesh.tessfaces: - vertices = face.vertices[:] - if len(vertices) == 4: - yield vertices[0], vertices[1], vertices[2] - yield vertices[2], vertices[3], vertices[0] - else: - yield vertices - else: - def iter_face_index(): - for face in mesh.tessfaces: - yield face.vertices[:] + mesh.calc_loop_triangles() vertices = mesh.vertices - for indexes in iter_face_index(): - yield [vertices[index].co.copy() for index in indexes] + for tri in mesh.loop_triangles: + yield [vertices[index].co.copy() for index in tri.vertices] bpy.data.meshes.remove(mesh) diff --git a/io_mesh_uv_layout/__init__.py b/io_mesh_uv_layout/__init__.py index 30dff949..bd2c97bd 100644 --- a/io_mesh_uv_layout/__init__.py +++ b/io_mesh_uv_layout/__init__.py @@ -22,7 +22,7 @@ bl_info = { "name": "UV Layout", "author": "Campbell Barton, Matt Ebb", "version": (1, 1, 1), - "blender": (2, 75, 0), + "blender": (2, 80, 0), "location": "Image-Window > UVs > Export UV Layout", "description": "Export the UV layout as a 2D graphic", "warning": "", @@ -43,15 +43,16 @@ if "bpy" in locals(): if "export_uv_svg" in locals(): importlib.reload(export_uv_svg) +import os import bpy from bpy.props import ( - StringProperty, - BoolProperty, - EnumProperty, - IntVectorProperty, - FloatProperty, - ) + StringProperty, + BoolProperty, + EnumProperty, + IntVectorProperty, + FloatProperty, +) class ExportUVLayout(bpy.types.Operator): @@ -61,172 +62,171 @@ class ExportUVLayout(bpy.types.Operator): bl_label = "Export UV Layout" bl_options = {'REGISTER', 'UNDO'} - filepath = StringProperty( - subtype='FILE_PATH', - ) - check_existing = BoolProperty( - name="Check Existing", - description="Check and warn on overwriting existing files", - default=True, - options={'HIDDEN'}, - ) - export_all = BoolProperty( - name="All UVs", - description="Export all UVs in this mesh (not just visible ones)", - default=False, - ) - modified = BoolProperty( - name="Modified", - description="Exports UVs from the modified mesh", - default=False, - ) - mode = EnumProperty( - items=(('SVG', "Scalable Vector Graphic (.svg)", - "Export the UV layout to a vector SVG file"), - ('EPS', "Encapsulate PostScript (.eps)", - "Export the UV layout to a vector EPS file"), - ('PNG', "PNG Image (.png)", - "Export the UV layout to a bitmap image"), - ), - name="Format", - description="File format to export the UV layout to", - default='PNG', - ) - size = IntVectorProperty( - size=2, - default=(1024, 1024), - min=8, max=32768, - description="Dimensions of the exported file", - ) - opacity = FloatProperty( - name="Fill Opacity", - min=0.0, max=1.0, - default=0.25, - description="Set amount of opacity for exported UV layout" - ) - tessellated = BoolProperty( - name="Tessellated UVs", - description="Export tessellated UVs instead of polygons ones", - default=False, - options={'HIDDEN'}, # As not working currently :/ - ) + filepath: StringProperty( + subtype='FILE_PATH', + ) + export_all: BoolProperty( + name="All UVs", + description="Export all UVs in this mesh (not just visible ones)", + default=False, + ) + modified: BoolProperty( + name="Modified", + description="Exports UVs from the modified mesh", + default=False, + ) + mode: EnumProperty( + items=( + ('SVG', "Scalable Vector Graphic (.svg)", + "Export the UV layout to a vector SVG file"), + ('EPS', "Encapsulate PostScript (.eps)", + "Export the UV layout to a vector EPS file"), + ('PNG', "PNG Image (.png)", + "Export the UV layout to a bitmap image"), + ), + name="Format", + description="File format to export the UV layout to", + default='PNG', + ) + size: IntVectorProperty( + size=2, + default=(1024, 1024), + min=8, max=32768, + description="Dimensions of the exported file", + ) + opacity: FloatProperty( + name="Fill Opacity", + min=0.0, max=1.0, + default=0.25, + description="Set amount of opacity for exported UV layout", + ) @classmethod def poll(cls, context): obj = context.active_object - return (obj and obj.type == 'MESH' and obj.data.uv_textures) + return obj is not None and obj.type == 'MESH' and obj.data.uv_layers - def _space_image(self, context): - space_data = context.space_data - if isinstance(space_data, bpy.types.SpaceImageEditor): - return space_data - else: - return None - - def _image_size(self, context, default_width=1024, default_height=1024): - # fallback if not in image context. - image_width, image_height = default_width, default_height + def invoke(self, context, event): + self.size = self.get_image_size(context) + self.filepath = self.get_default_file_name(context) + "." + self.mode.lower() + context.window_manager.fileselect_add(self) + return {'RUNNING_MODAL'} - space_data = self._space_image(context) - if space_data: - image = space_data.image - if image: - width, height = tuple(context.space_data.image.size) - # in case no data is found. - if width and height: - image_width, image_height = width, height + def get_default_file_name(self, context): + AMOUNT = 3 + objects = list(self.iter_objects_to_export(context)) + name = " ".join(sorted([obj.name for obj in objects[:AMOUNT]])) + if len(objects) > AMOUNT: + name += " and more" + return name - return image_width, image_height + def check(self, context): + if any(self.filepath.endswith(ext) for ext in (".png", ".eps", ".svg")): + self.filepath = self.filepath[:-4] - def _face_uv_iter(self, context, mesh, tessellated): - uv_layer = mesh.uv_layers.active.data - polys = mesh.polygons - - if not self.export_all: - uv_tex = mesh.uv_textures.active.data - local_image = Ellipsis - - if context.tool_settings.show_uv_local_view: - space_data = self._space_image(context) - if space_data: - local_image = space_data.image - - for i, p in enumerate(polys): - # context checks - if polys[i].select and local_image in {Ellipsis, - uv_tex[i].image}: - start = p.loop_start - end = start + p.loop_total - uvs = tuple((uv.uv[0], uv.uv[1]) - for uv in uv_layer[start:end]) - - # just write what we see. - yield (i, uvs) - else: - # all, simple - for i, p in enumerate(polys): - start = p.loop_start - end = start + p.loop_total - uvs = tuple((uv.uv[0], uv.uv[1]) for uv in uv_layer[start:end]) - yield (i, uvs) + ext = "." + self.mode.lower() + self.filepath = bpy.path.ensure_ext(self.filepath, ext) + return True def execute(self, context): - obj = context.active_object is_editmode = (obj.mode == 'EDIT') if is_editmode: bpy.ops.object.mode_set(mode='OBJECT', toggle=False) - mode = self.mode - filepath = self.filepath - filepath = bpy.path.ensure_ext(filepath, "." + mode.lower()) - file = open(filepath, "w") - fw = file.write - - if mode == 'EPS': - from . import export_uv_eps - func = export_uv_eps.write - elif mode == 'PNG': - from . import export_uv_png - func = export_uv_png.write - elif mode == 'SVG': - from . import export_uv_svg - func = export_uv_svg.write + filepath = bpy.path.ensure_ext(filepath, "." + self.mode.lower()) + meshes = list(self.iter_meshes_to_export(context)) + polygon_data = list(self.iter_polygon_data_to_draw(context, meshes)) + different_colors = set(color for _, color in polygon_data) if self.modified: - mesh = obj.to_mesh(context.scene, True, 'PREVIEW') - else: - mesh = obj.data + self.free_meshes(meshes) - func(fw, mesh, self.size[0], self.size[1], self.opacity, - lambda: self._face_uv_iter(context, mesh, self.tessellated)) - - if self.modified: - bpy.data.meshes.remove(mesh) + export = self.get_exporter() + export(filepath, polygon_data, different_colors, self.size[0], self.size[1], self.opacity) if is_editmode: bpy.ops.object.mode_set(mode='EDIT', toggle=False) - file.close() - return {'FINISHED'} - def check(self, context): - filepath = bpy.path.ensure_ext(self.filepath, "." + self.mode.lower()) - if filepath != self.filepath: - self.filepath = filepath - return True - else: - return False + def iter_meshes_to_export(self, context): + for obj in self.iter_objects_to_export(context): + if self.modified: + yield obj.to_mesh(context.depsgraph, apply_modifiers=True) + else: + yield obj.data + + @staticmethod + def iter_objects_to_export(context): + for obj in context.selected_objects: + if obj.type != 'MESH': + continue + mesh = obj.data + if mesh.uv_layers.active is None: + continue + yield obj - def invoke(self, context, event): - import os - self.size = self._image_size(context) - self.filepath = os.path.splitext(bpy.data.filepath)[0] - wm = context.window_manager - wm.fileselect_add(self) - return {'RUNNING_MODAL'} + @staticmethod + def free_meshes(meshes): + for mesh in meshes: + bpy.data.meshes.remove(mesh) + + @staticmethod + def currently_image_image_editor(context): + return isinstance(context.space_data, bpy.types.SpaceImageEditor) + + def get_currently_opened_image(self, context): + if not self.currently_image_image_editor(context): + return None + return context.space_data.image + + def get_image_size(self, context): + # fallback if not in image context + image_width = self.size[0] + image_height = self.size[1] + + # get size of "active" image if some exist + image = self.get_currently_opened_image(context) + if image is not None: + width, height = image.size + if width and height: + image_width = width + image_height = height + + return image_width, image_height + + def iter_polygon_data_to_draw(self, context, meshes): + for mesh in meshes: + uv_layer = mesh.uv_layers.active.data + for polygon in mesh.polygons: + if self.export_all or polygon.select: + start = polygon.loop_start + end = start + polygon.loop_total + uvs = tuple(tuple(uv.uv) for uv in uv_layer[start:end]) + yield (uvs, self.get_polygon_color(mesh, polygon)) + + @staticmethod + def get_polygon_color(mesh, polygon, default=(0.8, 0.8, 0.8)): + if polygon.material_index < len(mesh.materials): + material = mesh.materials[polygon.material_index] + if material is not None: + return tuple(material.diffuse_color) + return default + + def get_exporter(self): + if self.mode == 'PNG': + from . import export_uv_png + return export_uv_png.export + elif self.mode == 'EPS': + from . import export_uv_eps + return export_uv_eps.export + elif self.mode == 'SVG': + from . import export_uv_svg + return export_uv_svg.export + else: + assert False def menu_func(self, context): @@ -234,13 +234,14 @@ def menu_func(self, context): def register(): - bpy.utils.register_module(__name__) + bpy.utils.register_class(ExportUVLayout) bpy.types.IMAGE_MT_uvs.append(menu_func) def unregister(): - bpy.utils.unregister_module(__name__) + bpy.utils.unregister_class(ExportUVLayout) bpy.types.IMAGE_MT_uvs.remove(menu_func) + if __name__ == "__main__": register() diff --git a/io_mesh_uv_layout/export_uv_eps.py b/io_mesh_uv_layout/export_uv_eps.py index a15dc266..3280cefa 100644 --- a/io_mesh_uv_layout/export_uv_eps.py +++ b/io_mesh_uv_layout/export_uv_eps.py @@ -21,66 +21,72 @@ import bpy -def write(fw, mesh, image_width, image_height, opacity, face_iter_func): - fw("%!PS-Adobe-3.0 EPSF-3.0\n") - fw("%%%%Creator: Blender %s\n" % bpy.app.version_string) - fw("%%Pages: 1\n") - fw("%%Orientation: Portrait\n") - fw("%%%%BoundingBox: 0 0 %d %d\n" % (image_width, image_height)) - fw("%%%%HiResBoundingBox: 0.0 0.0 %.4f %.4f\n" % - (image_width, image_height)) - fw("%%EndComments\n") - fw("%%Page: 1 1\n") - fw("0 0 translate\n") - fw("1.0 1.0 scale\n") - fw("0 0 0 setrgbcolor\n") - fw("[] 0 setdash\n") - fw("1 setlinewidth\n") - fw("1 setlinejoin\n") - fw("1 setlinecap\n") - - polys = mesh.polygons +def export(filepath, face_data, colors, width, height, opacity): + with open(filepath, "w") as file: + for text in get_file_parts(face_data, colors, width, height, opacity): + file.write(text) +def get_file_parts(face_data, colors, width, height, opacity): + yield from header(width, height) if opacity > 0.0: - for i, mat in enumerate(mesh.materials if mesh.materials else [None]): - fw("/DRAW_%d {" % i) - fw("gsave\n") - if mat: - color = tuple((1.0 - ((1.0 - c) * opacity)) - for c in mat.diffuse_color) - else: - color = 1.0, 1.0, 1.0 - fw("%.3g %.3g %.3g setrgbcolor\n" % color) - fw("fill\n") - fw("grestore\n") - fw("0 setgray\n") - fw("} def\n") + name_by_color = {} + yield from prepare_colors(colors, name_by_color) + yield from draw_colored_polygons(face_data, name_by_color, width, height) + yield from draw_lines(face_data, width, height) + yield from footer() + + +def header(width, height): + yield "%!PS-Adobe-3.0 EPSF-3.0\n" + yield f"%%Creator: Blender {bpy.app.version_string}\n" + yield "%%Pages: 1\n" + yield "%%Orientation: Portrait\n" + yield f"%%BoundingBox: 0 0 {width} {height}\n" + yield f"%%HiResBoundingBox: 0.0 0.0 {width:.4f} {height:.4f}\n" + yield "%%EndComments\n" + yield "%%Page: 1 1\n" + yield "0 0 translate\n" + yield "1.0 1.0 scale\n" + yield "0 0 0 setrgbcolor\n" + yield "[] 0 setdash\n" + yield "1 setlinewidth\n" + yield "1 setlinejoin\n" + yield "1 setlinecap\n" + +def prepare_colors(colors, out_name_by_color): + for i, color in enumerate(colors): + name = f"COLOR_{i}" + yield "/%s {" % name + out_name_by_color[color] = name - # fill - for i, uvs in face_iter_func(): - fw("newpath\n") - for j, uv in enumerate(uvs): - uv_scale = (uv[0] * image_width, uv[1] * image_height) - if j == 0: - fw("%.5f %.5f moveto\n" % uv_scale) - else: - fw("%.5f %.5f lineto\n" % uv_scale) + yield "gsave\n" + yield "%.3g %.3g %.3g setrgbcolor\n" % color + yield "fill\n" + yield "grestore\n" + yield "0 setgray\n" + yield "} def\n" - fw("closepath\n") - fw("DRAW_%d\n" % polys[i].material_index) +def draw_colored_polygons(face_data, name_by_color, width, height): + for uvs, color in face_data: + yield from draw_polygon_path(uvs, width, height) + yield "closepath\n" + yield "%s\n" % name_by_color[color] - # stroke only - for i, uvs in face_iter_func(): - fw("newpath\n") - for j, uv in enumerate(uvs): - uv_scale = (uv[0] * image_width, uv[1] * image_height) - if j == 0: - fw("%.5f %.5f moveto\n" % uv_scale) - else: - fw("%.5f %.5f lineto\n" % uv_scale) +def draw_lines(face_data, width, height): + for uvs, _ in face_data: + yield from draw_polygon_path(uvs, width, height) + yield "closepath\n" + yield "stroke\n" - fw("closepath\n") - fw("stroke\n") +def draw_polygon_path(uvs, width, height): + yield "newpath\n" + for j, uv in enumerate(uvs): + uv_scale = (uv[0] * width, uv[1] * height) + if j == 0: + yield "%.5f %.5f moveto\n" % uv_scale + else: + yield "%.5f %.5f lineto\n" % uv_scale - fw("showpage\n") - fw("%%EOF\n") +def footer(): + yield "showpage\n" + yield "%%EOF\n"
\ No newline at end of file diff --git a/io_mesh_uv_layout/export_uv_png.py b/io_mesh_uv_layout/export_uv_png.py index b556c982..f23d516c 100644 --- a/io_mesh_uv_layout/export_uv_png.py +++ b/io_mesh_uv_layout/export_uv_png.py @@ -20,132 +20,134 @@ import bpy +# maybe we could also just use the svg exporter, import it again +# and render it. Unfortunately the svg importer does not work atm. +def export(filepath, face_data, colors, width, height, opacity): + aspect = width / height + + # curves for lines + lines = curve_from_uvs(face_data, aspect, 1 / min(width, height)) + lines_object = bpy.data.objects.new("temp_lines_object", lines) + black_material = make_colored_material((0, 0, 0)) + lines.materials.append(black_material) + + # background mesh + background_mesh = background_mesh_from_uvs(face_data, colors, aspect, opacity) + background_object = bpy.data.objects.new("temp_background_object", background_mesh) + background_object.location = (0, 0, -1) + + # camera + camera = bpy.data.cameras.new("temp_camera") + camera_object = bpy.data.objects.new("temp_camera_object", camera) + camera.type = "ORTHO" + camera.ortho_scale = max(1, aspect) + camera_object.location = (aspect / 2, 0.5, 1) + camera_object.rotation_euler = (0, 0, 0) + + # scene + scene = bpy.data.scenes.new("temp_scene") + scene.render.engine = "BLENDER_EEVEE" + scene.render.resolution_x = width + scene.render.resolution_y = height + scene.render.image_settings.color_mode = "RGBA" + scene.render.alpha_mode = "TRANSPARENT" + scene.render.filepath = filepath -def write(fw, mesh_source, image_width, image_height, opacity, face_iter_func): - filepath = fw.__self__.name - fw.__self__.close() - - material_solids = [bpy.data.materials.new("uv_temp_solid") - for i in range(max(1, len(mesh_source.materials)))] - - material_wire = bpy.data.materials.new("uv_temp_wire") - - scene = bpy.data.scenes.new("uv_temp") - mesh = bpy.data.meshes.new("uv_temp") - for mat_solid in material_solids: - mesh.materials.append(mat_solid) + # Link everything to the scene + scene.collection.objects.link(lines_object) + scene.collection.objects.link(camera_object) + scene.collection.objects.link(background_object) + scene.camera = camera_object + + # Render + override = {"scene" : scene} + bpy.ops.render.render(override, write_still=True) + + # Cleanup + bpy.data.objects.remove(lines_object) + bpy.data.objects.remove(camera_object) + bpy.data.objects.remove(background_object) + + for material in background_mesh.materials: + bpy.data.materials.remove(material) + bpy.data.meshes.remove(background_mesh) + + bpy.data.cameras.remove(camera) + bpy.data.curves.remove(lines) + bpy.data.materials.remove(black_material) + bpy.data.scenes.remove(scene) + +def curve_from_uvs(face_data, aspect, thickness): + lines = bpy.data.curves.new("temp_curve", "CURVE") + lines.fill_mode = "BOTH" + lines.bevel_depth = thickness + lines.offset = -thickness / 2 + lines.dimensions = "3D" + + for uvs, _ in face_data: + for i in range(len(uvs)): + start = uvs[i] + end = uvs[(i+1) % len(uvs)] + + spline = lines.splines.new("POLY") + # one point is already there + spline.points.add(1) + points = spline.points + + points[0].co.x = start[0] * aspect + points[0].co.y = start[1] + + points[1].co.x = end[0] * aspect + points[1].co.y = end[1] + + return lines + +def background_mesh_from_uvs(face_data, colors, aspect, opacity): + mesh = bpy.data.meshes.new("temp_background") + + vertices = [] + polygons = [] + for uvs, _ in face_data: + polygon = [] + for uv in uvs: + polygon.append(len(vertices)) + vertices.append((uv[0] * aspect, uv[1], 0)) + polygons.append(tuple(polygon)) - polys_source = mesh_source.polygons + mesh.from_pydata(vertices, [], polygons) - # get unique UV's in case there are many overlapping - # which slow down filling. - face_hash = {(uvs, polys_source[i].material_index) - for i, uvs in face_iter_func()} + materials, material_index_by_color = make_polygon_background_materials(colors, opacity) + for material in materials: + mesh.materials.append(material) - # now set the faces coords and locations - # build mesh data - mesh_new_vertices = [] - mesh_new_materials = [] - mesh_new_polys_startloop = [] - mesh_new_polys_totloop = [] - mesh_new_loops_vertices = [] + for generated_polygon, (_, color) in zip(mesh.polygons, face_data): + generated_polygon.material_index = material_index_by_color[color] - current_vert = 0 + mesh.update() + mesh.validate() - for uvs, mat_idx in face_hash: - num_verts = len(uvs) - dummy = (0.0,) * num_verts - for uv in uvs: - mesh_new_vertices += (uv[0], uv[1], 0.0) - mesh_new_polys_startloop.append(current_vert) - mesh_new_polys_totloop.append(num_verts) - mesh_new_loops_vertices += range(current_vert, - current_vert + num_verts) - mesh_new_materials.append(mat_idx) - current_vert += num_verts - - mesh.vertices.add(current_vert) - mesh.loops.add(current_vert) - mesh.polygons.add(len(mesh_new_polys_startloop)) - - mesh.vertices.foreach_set("co", mesh_new_vertices) - mesh.loops.foreach_set("vertex_index", mesh_new_loops_vertices) - mesh.polygons.foreach_set("loop_start", mesh_new_polys_startloop) - mesh.polygons.foreach_set("loop_total", mesh_new_polys_totloop) - mesh.polygons.foreach_set("material_index", mesh_new_materials) - - mesh.update(calc_edges=True) - - obj_solid = bpy.data.objects.new("uv_temp_solid", mesh) - obj_wire = bpy.data.objects.new("uv_temp_wire", mesh) - base_solid = scene.objects.link(obj_solid) - base_wire = scene.objects.link(obj_wire) - base_solid.layers[0] = True - base_wire.layers[0] = True - - # place behind the wire - obj_solid.location = 0, 0, -1 - - obj_wire.material_slots[0].link = 'OBJECT' - obj_wire.material_slots[0].material = material_wire - - # setup the camera - cam = bpy.data.cameras.new("uv_temp") - cam.type = 'ORTHO' - cam.ortho_scale = 1.0 - obj_cam = bpy.data.objects.new("uv_temp_cam", cam) - obj_cam.location = 0.5, 0.5, 1.0 - scene.objects.link(obj_cam) - scene.camera = obj_cam - - # setup materials - for i, mat_solid in enumerate(material_solids): - if mesh_source.materials and mesh_source.materials[i]: - mat_solid.diffuse_color = mesh_source.materials[i].diffuse_color - - mat_solid.use_shadeless = True - mat_solid.use_transparency = True - mat_solid.alpha = opacity - - material_wire.type = 'WIRE' - material_wire.use_shadeless = True - material_wire.diffuse_color = 0, 0, 0 - material_wire.use_transparency = True - - # scene render settings - scene.render.use_raytrace = False - scene.render.alpha_mode = 'TRANSPARENT' - scene.render.image_settings.color_mode = 'RGBA' - - scene.render.resolution_x = image_width - scene.render.resolution_y = image_height - scene.render.resolution_percentage = 100 - - if image_width > image_height: - scene.render.pixel_aspect_y = image_width / image_height - elif image_width < image_height: - scene.render.pixel_aspect_x = image_height / image_width - - scene.frame_start = 1 - scene.frame_end = 1 - - scene.render.image_settings.file_format = 'PNG' - scene.render.filepath = filepath + return mesh - scene.update() +def make_polygon_background_materials(colors, opacity=1): + materials = [] + material_index_by_color = {} + for i, color in enumerate(colors): + material = make_colored_material(color, opacity) + materials.append(material) + material_index_by_color[color] = i + return materials, material_index_by_color - data_context = {"blend_data": bpy.context.blend_data, "scene": scene} - bpy.ops.render.render(data_context, write_still=True) +def make_colored_material(color, opacity=1): + material = bpy.data.materials.new("temp_material") + material.use_nodes = True + material.blend_method = "BLEND" + tree = material.node_tree + tree.nodes.clear() - # cleanup - bpy.data.scenes.remove(scene, do_unlink=True) - bpy.data.objects.remove(obj_cam, do_unlink=True) - bpy.data.objects.remove(obj_solid, do_unlink=True) - bpy.data.objects.remove(obj_wire, do_unlink=True) + output_node = tree.nodes.new("ShaderNodeOutputMaterial") + emission_node = tree.nodes.new("ShaderNodeEmission") - bpy.data.cameras.remove(cam, do_unlink=True) - bpy.data.meshes.remove(mesh, do_unlink=True) + emission_node.inputs["Color"].default_value = [color[0], color[1], color[2], opacity] + tree.links.new(emission_node.outputs["Emission"], output_node.inputs["Surface"]) - bpy.data.materials.remove(material_wire, do_unlink=True) - for mat_solid in material_solids: - bpy.data.materials.remove(mat_solid, do_unlink=True) + return material diff --git a/io_mesh_uv_layout/export_uv_svg.py b/io_mesh_uv_layout/export_uv_svg.py index 764f0d34..d00f9402 100644 --- a/io_mesh_uv_layout/export_uv_svg.py +++ b/io_mesh_uv_layout/export_uv_svg.py @@ -19,50 +19,46 @@ # <pep8-80 compliant> import bpy +from os.path import basename +from xml.sax.saxutils import escape +def export(filepath, face_data, colors, width, height, opacity): + with open(filepath, "w") as file: + for text in get_file_parts(face_data, colors, width, height, opacity): + file.write(text) -def write(fw, mesh, image_width, image_height, opacity, face_iter_func): - # for making an XML compatible string - from xml.sax.saxutils import escape - from os.path import basename +def get_file_parts(face_data, colors, width, height, opacity): + yield from header(width, height) + yield from draw_polygons(face_data, width, height, opacity) + yield from footer() - fw('<?xml version="1.0" standalone="no"?>\n') - fw('<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" \n') - fw(' "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n') - fw('<svg width="%d" height="%d" viewBox="0 0 %d %d"\n' % - (image_width, image_height, image_width, image_height)) - fw(' xmlns="http://www.w3.org/2000/svg" version="1.1">\n') - desc = ("%r, %s, (Blender %s)" % - (basename(bpy.data.filepath), mesh.name, bpy.app.version_string)) - fw('<desc>%s</desc>\n' % escape(desc)) +def header(width, height): + yield '<?xml version="1.0" standalone="no"?>\n' + yield '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" \n' + yield ' "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n' + yield f'<svg width="{width}" height="{height}" viewBox="0 0 {width} {height}"\n' + yield ' xmlns="http://www.w3.org/2000/svg" version="1.1">\n' + desc = f"{basename(bpy.data.filepath)}, (Blender {bpy.app.version_string})" + yield f'<desc>{escape(desc)}</desc>\n' - # svg colors - fill_settings = [] - fill_default = 'fill="grey"' - for mat in mesh.materials if mesh.materials else [None]: - if mat: - fill_settings.append('fill="rgb(%d, %d, %d)"' % - tuple(int(c * 255) - for c in mat.diffuse_color)) - else: - fill_settings.append(fill_default) +def draw_polygons(face_data, width, height, opacity): + for uvs, color in face_data: + fill = f'fill="{get_color_string(color)}"' - polys = mesh.polygons - for i, uvs in face_iter_func(): - try: # rare cases material index is invalid. - fill = fill_settings[polys[i].material_index] - except IndexError: - fill = fill_default + yield '<polygon stroke="black" stroke-width="1"' + yield f' {fill} fill-opacity="{opacity:.2g}"' - fw('<polygon stroke="black" stroke-width="1"') - if opacity > 0.0: - fw(' %s fill-opacity="%.2g"' % (fill, opacity)) + yield ' points="' - fw(' points="') - - for j, uv in enumerate(uvs): + for uv in uvs: x, y = uv[0], 1.0 - uv[1] - fw('%.3f,%.3f ' % (x * image_width, y * image_height)) - fw('" />\n') - fw('\n') - fw('</svg>\n') + yield f'{x*width:.3f},{y*height:.3f} ' + yield '" />\n' + +def get_color_string(color): + r, g, b = color + return f"rgb({round(r*255)}, {round(g*255)}, {round(b*255)})" + +def footer(): + yield '\n' + yield '</svg>\n'
\ No newline at end of file diff --git a/io_online_sketchfab/__init__.py b/io_online_sketchfab/__init__.py index ba73bd19..2205f497 100644 --- a/io_online_sketchfab/__init__.py +++ b/io_online_sketchfab/__init__.py @@ -247,7 +247,7 @@ class ExportSketchfab(Operator): with open(SKETCHFAB_EXPORT_DATA_FILE, 'w') as s: json.dump({ "models": props.models, - "lamps": props.lamps, + "lights": props.lights, }, s) subprocess.check_call([ @@ -311,7 +311,7 @@ class VIEW3D_PT_sketchfab(Panel): layout.label("Export:") col = layout.box().column(align=True) col.prop(props, "models") - col.prop(props, "lamps") + col.prop(props, "lights") layout.label("Model info:") col = layout.box().column(align=True) diff --git a/io_online_sketchfab/pack_for_export.py b/io_online_sketchfab/pack_for_export.py index 587c94c2..972735c8 100644 --- a/io_online_sketchfab/pack_for_export.py +++ b/io_online_sketchfab/pack_for_export.py @@ -87,12 +87,12 @@ def prepare_assets(export_settings): images.add(image) if ((export_settings['models'] == 'SELECTION' and ob.type == 'MESH') or - (export_settings['lamps'] == 'SELECTION' and ob.type == 'LAMP')): + (export_settings['lamps'] == 'SELECTION' and ob.type == 'LIGHT')): if not ob.select and not ob.hide: ob.hide = True hidden.add(ob) - elif export_settings['lamps'] == 'NONE' and ob.type == 'LAMP': + elif export_settings['lamps'] == 'NONE' and ob.type == 'LIGHT': if not ob.hide: ob.hide = True hidden.add(ob) diff --git a/io_scene_3ds/__init__.py b/io_scene_3ds/__init__.py index 9236c07e..4daa4c29 100644 --- a/io_scene_3ds/__init__.py +++ b/io_scene_3ds/__init__.py @@ -50,15 +50,13 @@ from bpy.props import ( from bpy_extras.io_utils import ( ImportHelper, ExportHelper, - orientation_helper_factory, + orientation_helper, axis_conversion, ) -IO3DSOrientationHelper = orientation_helper_factory("IO3DSOrientationHelper", axis_forward='Y', axis_up='Z') - - -class Import3DS(bpy.types.Operator, ImportHelper, IO3DSOrientationHelper): +@orientation_helper(axis_forward='Y', axis_up='Z') +class Import3DS(bpy.types.Operator, ImportHelper): """Import from 3DS file format (.3ds)""" bl_idname = "import_scene.autodesk_3ds" bl_label = 'Import 3DS' @@ -104,7 +102,8 @@ class Import3DS(bpy.types.Operator, ImportHelper, IO3DSOrientationHelper): return import_3ds.load(self, context, **keywords) -class Export3DS(bpy.types.Operator, ExportHelper, IO3DSOrientationHelper): +@orientation_helper(axis_forward='Y', axis_up='Z') +class Export3DS(bpy.types.Operator, ExportHelper): """Export to 3DS file format (.3ds)""" bl_idname = "export_scene.autodesk_3ds" bl_label = 'Export 3DS' @@ -149,15 +148,15 @@ def menu_func_import(self, context): def register(): bpy.utils.register_module(__name__) - bpy.types.INFO_MT_file_import.append(menu_func_import) - bpy.types.INFO_MT_file_export.append(menu_func_export) + bpy.types.TOPBAR_MT_file_import.append(menu_func_import) + bpy.types.TOPBAR_MT_file_export.append(menu_func_export) def unregister(): bpy.utils.unregister_module(__name__) - bpy.types.INFO_MT_file_import.remove(menu_func_import) - bpy.types.INFO_MT_file_export.remove(menu_func_export) + bpy.types.TOPBAR_MT_file_import.remove(menu_func_import) + bpy.types.TOPBAR_MT_file_export.remove(menu_func_export) # NOTES: # why add 1 extra vertex? and remove it when done? - diff --git a/io_scene_3ds/import_3ds.py b/io_scene_3ds/import_3ds.py index 862fe2a7..cf17edcd 100644 --- a/io_scene_3ds/import_3ds.py +++ b/io_scene_3ds/import_3ds.py @@ -83,27 +83,27 @@ MAT_24BIT_COLOR = 0x0011 # color defined as 3 bytes #>------ sub defines of OBJECT OBJECT_MESH = 0x4100 # This lets us know that we are reading a new object -OBJECT_LAMP = 0x4600 # This lets un know we are reading a light object -OBJECT_LAMP_SPOT = 0x4610 # The light is a spotloght. -OBJECT_LAMP_OFF = 0x4620 # The light off. -OBJECT_LAMP_ATTENUATE = 0x4625 -OBJECT_LAMP_RAYSHADE = 0x4627 -OBJECT_LAMP_SHADOWED = 0x4630 -OBJECT_LAMP_LOCAL_SHADOW = 0x4640 -OBJECT_LAMP_LOCAL_SHADOW2 = 0x4641 -OBJECT_LAMP_SEE_CONE = 0x4650 -OBJECT_LAMP_SPOT_RECTANGULAR = 0x4651 -OBJECT_LAMP_SPOT_OVERSHOOT = 0x4652 -OBJECT_LAMP_SPOT_PROJECTOR = 0x4653 -OBJECT_LAMP_EXCLUDE = 0x4654 -OBJECT_LAMP_RANGE = 0x4655 -OBJECT_LAMP_ROLL = 0x4656 -OBJECT_LAMP_SPOT_ASPECT = 0x4657 -OBJECT_LAMP_RAY_BIAS = 0x4658 -OBJECT_LAMP_INNER_RANGE = 0x4659 -OBJECT_LAMP_OUTER_RANGE = 0x465A -OBJECT_LAMP_MULTIPLIER = 0x465B -OBJECT_LAMP_AMBIENT_LIGHT = 0x4680 +OBJECT_LIGHT = 0x4600 # This lets un know we are reading a light object +OBJECT_LIGHT_SPOT = 0x4610 # The light is a spotloght. +OBJECT_LIGHT_OFF = 0x4620 # The light off. +OBJECT_LIGHT_ATTENUATE = 0x4625 +OBJECT_LIGHT_RAYSHADE = 0x4627 +OBJECT_LIGHT_SHADOWED = 0x4630 +OBJECT_LIGHT_LOCAL_SHADOW = 0x4640 +OBJECT_LIGHT_LOCAL_SHADOW2 = 0x4641 +OBJECT_LIGHT_SEE_CONE = 0x4650 +OBJECT_LIGHT_SPOT_RECTANGULAR = 0x4651 +OBJECT_LIGHT_SPOT_OVERSHOOT = 0x4652 +OBJECT_LIGHT_SPOT_PROJECTOR = 0x4653 +OBJECT_LIGHT_EXCLUDE = 0x4654 +OBJECT_LIGHT_RANGE = 0x4655 +OBJECT_LIGHT_ROLL = 0x4656 +OBJECT_LIGHT_SPOT_ASPECT = 0x4657 +OBJECT_LIGHT_RAY_BIAS = 0x4658 +OBJECT_LIGHT_INNER_RANGE = 0x4659 +OBJECT_LIGHT_OUTER_RANGE = 0x465A +OBJECT_LIGHT_MULTIPLIER = 0x465B +OBJECT_LIGHT_AMBIENT_LIGHT = 0x4680 OBJECT_CAMERA = 0x4700 # This lets un know we are reading a camera object @@ -596,7 +596,7 @@ def process_next_chunk(file, previous_chunk, importedObjects, IMAGE_SEARCH): new_chunk.bytes_read += temp_chunk.bytes_read - elif new_chunk.ID == OBJECT_LAMP: # Basic lamp support. + elif new_chunk.ID == OBJECT_LIGHT: # Basic lamp support. temp_data = file.read(STRUCT_SIZE_3FLOAT) @@ -604,7 +604,7 @@ def process_next_chunk(file, previous_chunk, importedObjects, IMAGE_SEARCH): new_chunk.bytes_read += STRUCT_SIZE_3FLOAT # no lamp in dict that would be confusing - contextLamp[1] = bpy.data.lamps.new("Lamp", 'POINT') + contextLamp[1] = bpy.data.lights.new("Lamp", 'POINT') contextLamp[0] = ob = bpy.data.objects.new("Lamp", contextLamp[1]) SCN.objects.link(ob) @@ -946,8 +946,8 @@ def load_3ds(filepath, axis_min = [1000000000] * 3 axis_max = [-1000000000] * 3 - global_clamp_size = IMPORT_CONSTRAIN_BOUNDS - if global_clamp_size != 0.0: + global_clight_size = IMPORT_CONSTRAIN_BOUNDS + if global_clight_size != 0.0: # Get all object bounds for ob in importedObjects: for v in ob.bound_box: @@ -963,7 +963,7 @@ def load_3ds(filepath, axis_max[2] - axis_min[2]) scale = 1.0 - while global_clamp_size < max_axis * scale: + while global_clight_size < max_axis * scale: scale = scale / 10.0 scale_mat = mathutils.Matrix.Scale(scale, 4) diff --git a/io_scene_fbx/__init__.py b/io_scene_fbx/__init__.py index fddeda6c..490a2ff6 100644 --- a/io_scene_fbx/__init__.py +++ b/io_scene_fbx/__init__.py @@ -21,8 +21,8 @@ bl_info = { "name": "FBX format", "author": "Campbell Barton, Bastien Montagne, Jens Restemeier", - "version": (3, 10, 0), - "blender": (2, 79, 1), + "version": (4, 12, 1), + "blender": (2, 80, 0), "location": "File > Import-Export", "description": "FBX IO meshes, UV's, vertex colors, materials, textures, cameras, lamps and actions", "warning": "", @@ -52,27 +52,25 @@ from bpy.props import ( from bpy_extras.io_utils import ( ImportHelper, ExportHelper, - orientation_helper_factory, + orientation_helper, path_reference_mode, axis_conversion, ) -IOFBXOrientationHelper = orientation_helper_factory("IOFBXOrientationHelper", axis_forward='-Z', axis_up='Y') - - -class ImportFBX(bpy.types.Operator, ImportHelper, IOFBXOrientationHelper): +@orientation_helper(axis_forward='-Z', axis_up='Y') +class ImportFBX(bpy.types.Operator, ImportHelper): """Load a FBX file""" bl_idname = "import_scene.fbx" bl_label = "Import FBX" bl_options = {'UNDO', 'PRESET'} - directory = StringProperty() + directory: StringProperty() filename_ext = ".fbx" - filter_glob = StringProperty(default="*.fbx", options={'HIDDEN'}) + filter_glob: StringProperty(default="*.fbx", options={'HIDDEN'}) - ui_tab = EnumProperty( + ui_tab: EnumProperty( items=(('MAIN', "Main", "Main basic settings"), ('ARMATURE', "Armatures", "Armature-related settings"), ), @@ -80,17 +78,17 @@ class ImportFBX(bpy.types.Operator, ImportHelper, IOFBXOrientationHelper): description="Import options categories", ) - use_manual_orientation = BoolProperty( + use_manual_orientation: BoolProperty( name="Manual Orientation", description="Specify orientation and scale, instead of using embedded data in FBX file", default=False, ) - global_scale = FloatProperty( + global_scale: FloatProperty( name="Scale", min=0.001, max=1000.0, default=1.0, ) - bake_space_transform = BoolProperty( + bake_space_transform: BoolProperty( name="!EXPERIMENTAL! Apply Transform", description="Bake space transform into object data, avoids getting unwanted rotations to objects when " "target space is not aligned with Blender's space " @@ -98,69 +96,69 @@ class ImportFBX(bpy.types.Operator, ImportHelper, IOFBXOrientationHelper): default=False, ) - use_custom_normals = BoolProperty( + use_custom_normals: BoolProperty( name="Import Normals", description="Import custom normals, if available (otherwise Blender will recompute them)", default=True, ) - use_image_search = BoolProperty( + use_image_search: BoolProperty( name="Image Search", description="Search subdirs for any associated images (WARNING: may be slow)", default=True, ) - use_alpha_decals = BoolProperty( + use_alpha_decals: BoolProperty( name="Alpha Decals", description="Treat materials with alpha as decals (no shadow casting)", default=False, ) - decal_offset = FloatProperty( + decal_offset: FloatProperty( name="Decal Offset", description="Displace geometry of alpha meshes", min=0.0, max=1.0, default=0.0, ) - use_anim = BoolProperty( + use_anim: BoolProperty( name="Import Animation", description="Import FBX animation", default=True, ) - anim_offset = FloatProperty( + anim_offset: FloatProperty( name="Animation Offset", description="Offset to apply to animation during import, in frames", default=1.0, ) - use_custom_props = BoolProperty( + use_custom_props: BoolProperty( name="Import User Properties", description="Import user properties as custom properties", default=True, ) - use_custom_props_enum_as_string = BoolProperty( + use_custom_props_enum_as_string: BoolProperty( name="Import Enums As Strings", description="Store enumeration values as strings", default=True, ) - ignore_leaf_bones = BoolProperty( + ignore_leaf_bones: BoolProperty( name="Ignore Leaf Bones", description="Ignore the last bone at the end of each chain (used to mark the length of the previous bone)", default=False, ) - force_connect_children = BoolProperty( + force_connect_children: BoolProperty( name="Force Connect Children", description="Force connection of children bones to their parent, even if their computed head/tail " "positions do not match (can be useful with pure-joints-type armatures)", default=False, ) - automatic_bone_orientation = BoolProperty( + automatic_bone_orientation: BoolProperty( name="Automatic Bone Orientation", description="Try to align the major bone axis with the bone children", default=False, ) - primary_bone_axis = EnumProperty( + primary_bone_axis: EnumProperty( name="Primary Bone Axis", items=(('X', "X Axis", ""), ('Y', "Y Axis", ""), @@ -171,7 +169,7 @@ class ImportFBX(bpy.types.Operator, ImportHelper, IOFBXOrientationHelper): ), default='Y', ) - secondary_bone_axis = EnumProperty( + secondary_bone_axis: EnumProperty( name="Secondary Bone Axis", items=(('X', "X Axis", ""), ('Y', "Y Axis", ""), @@ -183,7 +181,7 @@ class ImportFBX(bpy.types.Operator, ImportHelper, IOFBXOrientationHelper): default='X', ) - use_prepost_rot = BoolProperty( + use_prepost_rot: BoolProperty( name="Use Pre/Post Rotation", description="Use pre/post rotation from FBX transform (you may have to disable that in some cases)", default=True, @@ -228,25 +226,25 @@ class ImportFBX(bpy.types.Operator, ImportHelper, IOFBXOrientationHelper): def execute(self, context): keywords = self.as_keywords(ignore=("filter_glob", "directory", "ui_tab")) - keywords["use_cycles"] = (context.scene.render.engine == 'CYCLES') from . import import_fbx return import_fbx.load(self, context, **keywords) -class ExportFBX(bpy.types.Operator, ExportHelper, IOFBXOrientationHelper): +@orientation_helper(axis_forward='-Z', axis_up='Y') +class ExportFBX(bpy.types.Operator, ExportHelper): """Write a FBX file""" bl_idname = "export_scene.fbx" bl_label = "Export FBX" bl_options = {'UNDO', 'PRESET'} filename_ext = ".fbx" - filter_glob = StringProperty(default="*.fbx", options={'HIDDEN'}) + filter_glob: StringProperty(default="*.fbx", options={'HIDDEN'}) # List of operator properties, the attributes will be assigned # to the class instance from the operator settings before calling. - ui_tab = EnumProperty( + ui_tab: EnumProperty( items=(('MAIN', "Main", "Main basic settings"), ('GEOMETRY', "Geometries", "Geometry-related settings"), ('ARMATURE', "Armatures", "Armature-related settings"), @@ -256,24 +254,24 @@ class ExportFBX(bpy.types.Operator, ExportHelper, IOFBXOrientationHelper): description="Export options categories", ) - use_selection = BoolProperty( + use_selection: BoolProperty( name="Selected Objects", description="Export selected objects on visible layers", default=False, ) - global_scale = FloatProperty( + global_scale: FloatProperty( name="Scale", description="Scale all data (Some importers do not support scaled armatures!)", min=0.001, max=1000.0, soft_min=0.01, soft_max=1000.0, default=1.0, ) - apply_unit_scale = BoolProperty( + apply_unit_scale: BoolProperty( name="Apply Unit", description="Take into account current Blender units settings (if unset, raw Blender Units values are used as-is)", default=True, ) - apply_scale_options = EnumProperty( + apply_scale_options: EnumProperty( items=(('FBX_SCALE_NONE', "All Local", "Apply custom scaling and units scaling to each object transformation, FBX scale remains at 1.0"), ('FBX_SCALE_UNITS', "FBX Units Scale", @@ -288,7 +286,7 @@ class ExportFBX(bpy.types.Operator, ExportHelper, IOFBXOrientationHelper): "(Blender uses FBX scale to detect units on import, " "but many other applications do not handle the same way)", ) - bake_space_transform = BoolProperty( + bake_space_transform: BoolProperty( name="!EXPERIMENTAL! Apply Transform", description="Bake space transform into object data, avoids getting unwanted rotations to objects when " "target space is not aligned with Blender's space " @@ -296,32 +294,32 @@ class ExportFBX(bpy.types.Operator, ExportHelper, IOFBXOrientationHelper): default=False, ) - object_types = EnumProperty( + object_types: EnumProperty( name="Object Types", options={'ENUM_FLAG'}, items=(('EMPTY', "Empty", ""), ('CAMERA', "Camera", ""), - ('LAMP', "Lamp", ""), + ('LIGHT', "Lamp", ""), ('ARMATURE', "Armature", "WARNING: not supported in dupli/group instances"), ('MESH', "Mesh", ""), ('OTHER', "Other", "Other geometry types, like curve, metaball, etc. (converted to meshes)"), ), description="Which kind of object to export", - default={'EMPTY', 'CAMERA', 'LAMP', 'ARMATURE', 'MESH', 'OTHER'}, + default={'EMPTY', 'CAMERA', 'LIGHT', 'ARMATURE', 'MESH', 'OTHER'}, ) - use_mesh_modifiers = BoolProperty( + use_mesh_modifiers: BoolProperty( name="Apply Modifiers", description="Apply modifiers to mesh objects (except Armature ones) - " "WARNING: prevents exporting shape keys", default=True, ) - use_mesh_modifiers_render = BoolProperty( + use_mesh_modifiers_render: BoolProperty( name="Use Modifiers Render Setting", description="Use render settings when applying modifiers to mesh objects", default=True, ) - mesh_smooth_type = EnumProperty( + mesh_smooth_type: EnumProperty( name="Smoothing", items=(('OFF', "Normals Only", "Export only normals instead of writing edge or face smoothing data"), ('FACE', "Face", "Write face smoothing"), @@ -331,29 +329,29 @@ class ExportFBX(bpy.types.Operator, ExportHelper, IOFBXOrientationHelper): "(prefer 'Normals Only' option if your target importer understand split normals)", default='OFF', ) - use_mesh_edges = BoolProperty( + use_mesh_edges: BoolProperty( name="Loose Edges", description="Export loose edges (as two-vertices polygons)", default=False, ) - use_tspace = BoolProperty( + use_tspace: BoolProperty( name="Tangent Space", description="Add binormal and tangent vectors, together with normal they form the tangent space " "(will only work correctly with tris/quads only meshes!)", default=False, ) - use_custom_props = BoolProperty( + use_custom_props: BoolProperty( name="Custom Properties", description="Export custom properties", default=False, ) - add_leaf_bones = BoolProperty( + add_leaf_bones: BoolProperty( name="Add Leaf Bones", description="Append a final bone to the end of each chain to specify last bone length " "(use this when you intend to edit the armature from exported data)", default=True # False for commit! ) - primary_bone_axis = EnumProperty( + primary_bone_axis: EnumProperty( name="Primary Bone Axis", items=(('X', "X Axis", ""), ('Y', "Y Axis", ""), @@ -364,7 +362,7 @@ class ExportFBX(bpy.types.Operator, ExportHelper, IOFBXOrientationHelper): ), default='Y', ) - secondary_bone_axis = EnumProperty( + secondary_bone_axis: EnumProperty( name="Secondary Bone Axis", items=(('X', "X Axis", ""), ('Y', "Y Axis", ""), @@ -375,12 +373,12 @@ class ExportFBX(bpy.types.Operator, ExportHelper, IOFBXOrientationHelper): ), default='X', ) - use_armature_deform_only = BoolProperty( + use_armature_deform_only: BoolProperty( name="Only Deform Bones", description="Only write deforming bones (and non-deforming ones when they have deforming children)", default=False, ) - armature_nodetype = EnumProperty( + armature_nodetype: EnumProperty( name="Armature FBXNode Type", items=(('NULL', "Null", "'Null' FBX node, similar to Blender's Empty (default)"), ('ROOT', "Root", "'Root' FBX node, supposed to be the root of chains of bones..."), @@ -391,68 +389,68 @@ class ExportFBX(bpy.types.Operator, ExportHelper, IOFBXOrientationHelper): "perfectly in Blender...)", default='NULL', ) - bake_anim = BoolProperty( + bake_anim: BoolProperty( name="Baked Animation", description="Export baked keyframe animation", default=True, ) - bake_anim_use_all_bones = BoolProperty( + bake_anim_use_all_bones: BoolProperty( name="Key All Bones", description="Force exporting at least one key of animation for all bones " "(needed with some target applications, like UE4)", default=True, ) - bake_anim_use_nla_strips = BoolProperty( + bake_anim_use_nla_strips: BoolProperty( name="NLA Strips", description="Export each non-muted NLA strip as a separated FBX's AnimStack, if any, " "instead of global scene animation", default=True, ) - bake_anim_use_all_actions = BoolProperty( + bake_anim_use_all_actions: BoolProperty( name="All Actions", description="Export each action as a separated FBX's AnimStack, instead of global scene animation " "(note that animated objects will get all actions compatible with them, " "others will get no animation at all)", default=True, ) - bake_anim_force_startend_keying = BoolProperty( + bake_anim_force_startend_keying: BoolProperty( name="Force Start/End Keying", description="Always add a keyframe at start and end of actions for animated channels", default=True, ) - bake_anim_step = FloatProperty( + bake_anim_step: FloatProperty( name="Sampling Rate", description="How often to evaluate animated values (in frames)", min=0.01, max=100.0, soft_min=0.1, soft_max=10.0, default=1.0, ) - bake_anim_simplify_factor = FloatProperty( + bake_anim_simplify_factor: FloatProperty( name="Simplify", description="How much to simplify baked values (0.0 to disable, the higher the more simplified)", min=0.0, max=100.0, # No simplification to up to 10% of current magnitude tolerance. soft_min=0.0, soft_max=10.0, default=1.0, # default: min slope: 0.005, max frame step: 10. ) - path_mode = path_reference_mode - embed_textures = BoolProperty( + path_mode: path_reference_mode + embed_textures: BoolProperty( name="Embed Textures", description="Embed textures in FBX binary file (only for \"Copy\" path mode!)", default=False, ) - batch_mode = EnumProperty( + batch_mode: EnumProperty( name="Batch Mode", items=(('OFF', "Off", "Active scene to file"), ('SCENE', "Scene", "Each scene as a file"), ('GROUP', "Group", "Each group as a file"), ), ) - use_batch_own_dir = BoolProperty( + use_batch_own_dir: BoolProperty( name="Batch Own Dir", description="Create a dir for each exported file", default=True, ) - use_metadata = BoolProperty( + use_metadata: BoolProperty( name="Use Metadata", default=True, options={'HIDDEN'}, @@ -559,13 +557,13 @@ def register(): for cls in classes: bpy.utils.register_class(cls) - bpy.types.INFO_MT_file_import.append(menu_func_import) - bpy.types.INFO_MT_file_export.append(menu_func_export) + bpy.types.TOPBAR_MT_file_import.append(menu_func_import) + bpy.types.TOPBAR_MT_file_export.append(menu_func_export) def unregister(): - bpy.types.INFO_MT_file_import.remove(menu_func_import) - bpy.types.INFO_MT_file_export.remove(menu_func_export) + bpy.types.TOPBAR_MT_file_import.remove(menu_func_import) + bpy.types.TOPBAR_MT_file_export.remove(menu_func_export) for cls in classes: bpy.utils.unregister_class(cls) diff --git a/io_scene_fbx/export_fbx_bin.py b/io_scene_fbx/export_fbx_bin.py index e82ceadd..f6c53272 100644 --- a/io_scene_fbx/export_fbx_bin.py +++ b/io_scene_fbx/export_fbx_bin.py @@ -27,7 +27,6 @@ import math import os import time -from collections import OrderedDict from itertools import zip_longest, chain if "bpy" in locals(): @@ -41,6 +40,7 @@ if "bpy" in locals(): import bpy import bpy_extras +from bpy_extras import node_shader_utils from mathutils import Vector, Matrix from . import encode_bin, data_types, fbx_utils @@ -75,6 +75,7 @@ from .fbx_utils import ( get_blender_bindpose_key, get_blender_armature_skin_key, get_blender_bone_cluster_key, get_blender_anim_id_base, get_blender_anim_stack_key, get_blender_anim_layer_key, get_blender_anim_curve_node_key, get_blender_anim_curve_key, + get_blender_nodetexture_key, # FBX element data. elem_empty, elem_data_single_bool, elem_data_single_int16, elem_data_single_int32, elem_data_single_int64, @@ -110,7 +111,7 @@ convert_rad_to_deg_iter = units_convertor_iter("radian", "degree") # TODO: check all those "default" values, they should match Blender's default as much as possible, I guess? def fbx_template_def_globalsettings(scene, settings, override_defaults=None, nbr_users=0): - props = OrderedDict() + props = {} if override_defaults is not None: props.update(override_defaults) return FBXTemplate(b"GlobalSettings", b"", props, nbr_users, [False]) @@ -118,91 +119,91 @@ def fbx_template_def_globalsettings(scene, settings, override_defaults=None, nbr def fbx_template_def_model(scene, settings, override_defaults=None, nbr_users=0): gscale = settings.global_scale - props = OrderedDict(( - # Name, Value, Type, Animatable - (b"QuaternionInterpolate", (0, "p_enum", False)), # 0 = no quat interpolation. - (b"RotationOffset", ((0.0, 0.0, 0.0), "p_vector_3d", False)), - (b"RotationPivot", ((0.0, 0.0, 0.0), "p_vector_3d", False)), - (b"ScalingOffset", ((0.0, 0.0, 0.0), "p_vector_3d", False)), - (b"ScalingPivot", ((0.0, 0.0, 0.0), "p_vector_3d", False)), - (b"TranslationActive", (False, "p_bool", False)), - (b"TranslationMin", ((0.0, 0.0, 0.0), "p_vector_3d", False)), - (b"TranslationMax", ((0.0, 0.0, 0.0), "p_vector_3d", False)), - (b"TranslationMinX", (False, "p_bool", False)), - (b"TranslationMinY", (False, "p_bool", False)), - (b"TranslationMinZ", (False, "p_bool", False)), - (b"TranslationMaxX", (False, "p_bool", False)), - (b"TranslationMaxY", (False, "p_bool", False)), - (b"TranslationMaxZ", (False, "p_bool", False)), - (b"RotationOrder", (0, "p_enum", False)), # we always use 'XYZ' order. - (b"RotationSpaceForLimitOnly", (False, "p_bool", False)), - (b"RotationStiffnessX", (0.0, "p_double", False)), - (b"RotationStiffnessY", (0.0, "p_double", False)), - (b"RotationStiffnessZ", (0.0, "p_double", False)), - (b"AxisLen", (10.0, "p_double", False)), - (b"PreRotation", ((0.0, 0.0, 0.0), "p_vector_3d", False)), - (b"PostRotation", ((0.0, 0.0, 0.0), "p_vector_3d", False)), - (b"RotationActive", (False, "p_bool", False)), - (b"RotationMin", ((0.0, 0.0, 0.0), "p_vector_3d", False)), - (b"RotationMax", ((0.0, 0.0, 0.0), "p_vector_3d", False)), - (b"RotationMinX", (False, "p_bool", False)), - (b"RotationMinY", (False, "p_bool", False)), - (b"RotationMinZ", (False, "p_bool", False)), - (b"RotationMaxX", (False, "p_bool", False)), - (b"RotationMaxY", (False, "p_bool", False)), - (b"RotationMaxZ", (False, "p_bool", False)), - (b"InheritType", (0, "p_enum", False)), # RrSs - (b"ScalingActive", (False, "p_bool", False)), - (b"ScalingMin", ((0.0, 0.0, 0.0), "p_vector_3d", False)), - (b"ScalingMax", ((1.0, 1.0, 1.0), "p_vector_3d", False)), - (b"ScalingMinX", (False, "p_bool", False)), - (b"ScalingMinY", (False, "p_bool", False)), - (b"ScalingMinZ", (False, "p_bool", False)), - (b"ScalingMaxX", (False, "p_bool", False)), - (b"ScalingMaxY", (False, "p_bool", False)), - (b"ScalingMaxZ", (False, "p_bool", False)), - (b"GeometricTranslation", ((0.0, 0.0, 0.0), "p_vector_3d", False)), - (b"GeometricRotation", ((0.0, 0.0, 0.0), "p_vector_3d", False)), - (b"GeometricScaling", ((1.0, 1.0, 1.0), "p_vector_3d", False)), - (b"MinDampRangeX", (0.0, "p_double", False)), - (b"MinDampRangeY", (0.0, "p_double", False)), - (b"MinDampRangeZ", (0.0, "p_double", False)), - (b"MaxDampRangeX", (0.0, "p_double", False)), - (b"MaxDampRangeY", (0.0, "p_double", False)), - (b"MaxDampRangeZ", (0.0, "p_double", False)), - (b"MinDampStrengthX", (0.0, "p_double", False)), - (b"MinDampStrengthY", (0.0, "p_double", False)), - (b"MinDampStrengthZ", (0.0, "p_double", False)), - (b"MaxDampStrengthX", (0.0, "p_double", False)), - (b"MaxDampStrengthY", (0.0, "p_double", False)), - (b"MaxDampStrengthZ", (0.0, "p_double", False)), - (b"PreferedAngleX", (0.0, "p_double", False)), - (b"PreferedAngleY", (0.0, "p_double", False)), - (b"PreferedAngleZ", (0.0, "p_double", False)), - (b"LookAtProperty", (None, "p_object", False)), - (b"UpVectorProperty", (None, "p_object", False)), - (b"Show", (True, "p_bool", False)), - (b"NegativePercentShapeSupport", (True, "p_bool", False)), - (b"DefaultAttributeIndex", (-1, "p_integer", False)), - (b"Freeze", (False, "p_bool", False)), - (b"LODBox", (False, "p_bool", False)), - (b"Lcl Translation", ((0.0, 0.0, 0.0), "p_lcl_translation", True)), - (b"Lcl Rotation", ((0.0, 0.0, 0.0), "p_lcl_rotation", True)), - (b"Lcl Scaling", ((1.0, 1.0, 1.0), "p_lcl_scaling", True)), - (b"Visibility", (1.0, "p_visibility", True)), - (b"Visibility Inheritance", (1, "p_visibility_inheritance", False)), - )) + props = { + # Name, Value, Type, Animatable + b"QuaternionInterpolate": (0, "p_enum", False), # 0 = no quat interpolation. + b"RotationOffset": ((0.0, 0.0, 0.0), "p_vector_3d", False), + b"RotationPivot": ((0.0, 0.0, 0.0), "p_vector_3d", False), + b"ScalingOffset": ((0.0, 0.0, 0.0), "p_vector_3d", False), + b"ScalingPivot": ((0.0, 0.0, 0.0), "p_vector_3d", False), + b"TranslationActive": (False, "p_bool", False), + b"TranslationMin": ((0.0, 0.0, 0.0), "p_vector_3d", False), + b"TranslationMax": ((0.0, 0.0, 0.0), "p_vector_3d", False), + b"TranslationMinX": (False, "p_bool", False), + b"TranslationMinY": (False, "p_bool", False), + b"TranslationMinZ": (False, "p_bool", False), + b"TranslationMaxX": (False, "p_bool", False), + b"TranslationMaxY": (False, "p_bool", False), + b"TranslationMaxZ": (False, "p_bool", False), + b"RotationOrder": (0, "p_enum", False), # we always use 'XYZ' order. + b"RotationSpaceForLimitOnly": (False, "p_bool", False), + b"RotationStiffnessX": (0.0, "p_double", False), + b"RotationStiffnessY": (0.0, "p_double", False), + b"RotationStiffnessZ": (0.0, "p_double", False), + b"AxisLen": (10.0, "p_double", False), + b"PreRotation": ((0.0, 0.0, 0.0), "p_vector_3d", False), + b"PostRotation": ((0.0, 0.0, 0.0), "p_vector_3d", False), + b"RotationActive": (False, "p_bool", False), + b"RotationMin": ((0.0, 0.0, 0.0), "p_vector_3d", False), + b"RotationMax": ((0.0, 0.0, 0.0), "p_vector_3d", False), + b"RotationMinX": (False, "p_bool", False), + b"RotationMinY": (False, "p_bool", False), + b"RotationMinZ": (False, "p_bool", False), + b"RotationMaxX": (False, "p_bool", False), + b"RotationMaxY": (False, "p_bool", False), + b"RotationMaxZ": (False, "p_bool", False), + b"InheritType": (0, "p_enum", False), # RrSs + b"ScalingActive": (False, "p_bool", False), + b"ScalingMin": ((0.0, 0.0, 0.0), "p_vector_3d", False), + b"ScalingMax": ((1.0, 1.0, 1.0), "p_vector_3d", False), + b"ScalingMinX": (False, "p_bool", False), + b"ScalingMinY": (False, "p_bool", False), + b"ScalingMinZ": (False, "p_bool", False), + b"ScalingMaxX": (False, "p_bool", False), + b"ScalingMaxY": (False, "p_bool", False), + b"ScalingMaxZ": (False, "p_bool", False), + b"GeometricTranslation": ((0.0, 0.0, 0.0), "p_vector_3d", False), + b"GeometricRotation": ((0.0, 0.0, 0.0), "p_vector_3d", False), + b"GeometricScaling": ((1.0, 1.0, 1.0), "p_vector_3d", False), + b"MinDampRangeX": (0.0, "p_double", False), + b"MinDampRangeY": (0.0, "p_double", False), + b"MinDampRangeZ": (0.0, "p_double", False), + b"MaxDampRangeX": (0.0, "p_double", False), + b"MaxDampRangeY": (0.0, "p_double", False), + b"MaxDampRangeZ": (0.0, "p_double", False), + b"MinDampStrengthX": (0.0, "p_double", False), + b"MinDampStrengthY": (0.0, "p_double", False), + b"MinDampStrengthZ": (0.0, "p_double", False), + b"MaxDampStrengthX": (0.0, "p_double", False), + b"MaxDampStrengthY": (0.0, "p_double", False), + b"MaxDampStrengthZ": (0.0, "p_double", False), + b"PreferedAngleX": (0.0, "p_double", False), + b"PreferedAngleY": (0.0, "p_double", False), + b"PreferedAngleZ": (0.0, "p_double", False), + b"LookAtProperty": (None, "p_object", False), + b"UpVectorProperty": (None, "p_object", False), + b"Show": (True, "p_bool", False), + b"NegativePercentShapeSupport": (True, "p_bool", False), + b"DefaultAttributeIndex": (-1, "p_integer", False), + b"Freeze": (False, "p_bool", False), + b"LODBox": (False, "p_bool", False), + b"Lcl Translation": ((0.0, 0.0, 0.0), "p_lcl_translation", True), + b"Lcl Rotation": ((0.0, 0.0, 0.0), "p_lcl_rotation", True), + b"Lcl Scaling": ((1.0, 1.0, 1.0), "p_lcl_scaling", True), + b"Visibility": (1.0, "p_visibility", True), + b"Visibility Inheritance": (1, "p_visibility_inheritance", False), + } if override_defaults is not None: props.update(override_defaults) return FBXTemplate(b"Model", b"FbxNode", props, nbr_users, [False]) def fbx_template_def_null(scene, settings, override_defaults=None, nbr_users=0): - props = OrderedDict(( - (b"Color", ((0.8, 0.8, 0.8), "p_color_rgb", False)), - (b"Size", (100.0, "p_double", False)), - (b"Look", (1, "p_enum", False)), # Cross (0 is None, i.e. invisible?). - )) + props = { + b"Color": ((0.8, 0.8, 0.8), "p_color_rgb", False), + b"Size": (100.0, "p_double", False), + b"Look": (1, "p_enum", False), # Cross (0 is None, i.e. invisible?). + } if override_defaults is not None: props.update(override_defaults) return FBXTemplate(b"NodeAttribute", b"FbxNull", props, nbr_users, [False]) @@ -210,17 +211,17 @@ def fbx_template_def_null(scene, settings, override_defaults=None, nbr_users=0): def fbx_template_def_light(scene, settings, override_defaults=None, nbr_users=0): gscale = settings.global_scale - props = OrderedDict(( - (b"LightType", (0, "p_enum", False)), # Point light. - (b"CastLight", (True, "p_bool", False)), - (b"Color", ((1.0, 1.0, 1.0), "p_color", True)), - (b"Intensity", (100.0, "p_number", True)), # Times 100 compared to Blender values... - (b"DecayType", (2, "p_enum", False)), # Quadratic. - (b"DecayStart", (30.0 * gscale, "p_double", False)), - (b"CastShadows", (True, "p_bool", False)), - (b"ShadowColor", ((0.0, 0.0, 0.0), "p_color", True)), - (b"AreaLightShape", (0, "p_enum", False)), # Rectangle. - )) + props = { + b"LightType": (0, "p_enum", False), # Point light. + b"CastLight": (True, "p_bool", False), + b"Color": ((1.0, 1.0, 1.0), "p_color", True), + b"Intensity": (100.0, "p_number", True), # Times 100 compared to Blender values... + b"DecayType": (2, "p_enum", False), # Quadratic. + b"DecayStart": (30.0 * gscale, "p_double", False), + b"CastShadows": (True, "p_bool", False), + b"ShadowColor": ((0.0, 0.0, 0.0), "p_color", True), + b"AreaLightShape": (0, "p_enum", False), # Rectangle. + } if override_defaults is not None: props.update(override_defaults) return FBXTemplate(b"NodeAttribute", b"FbxLight", props, nbr_users, [False]) @@ -228,137 +229,137 @@ def fbx_template_def_light(scene, settings, override_defaults=None, nbr_users=0) def fbx_template_def_camera(scene, settings, override_defaults=None, nbr_users=0): r = scene.render - props = OrderedDict(( - (b"Color", ((0.8, 0.8, 0.8), "p_color_rgb", False)), - (b"Position", ((0.0, 0.0, -50.0), "p_vector", True)), - (b"UpVector", ((0.0, 1.0, 0.0), "p_vector", True)), - (b"InterestPosition", ((0.0, 0.0, 0.0), "p_vector", True)), - (b"Roll", (0.0, "p_roll", True)), - (b"OpticalCenterX", (0.0, "p_opticalcenterx", True)), - (b"OpticalCenterY", (0.0, "p_opticalcentery", True)), - (b"BackgroundColor", ((0.63, 0.63, 0.63), "p_color", True)), - (b"TurnTable", (0.0, "p_number", True)), - (b"DisplayTurnTableIcon", (False, "p_bool", False)), - (b"UseMotionBlur", (False, "p_bool", False)), - (b"UseRealTimeMotionBlur", (True, "p_bool", False)), - (b"Motion Blur Intensity", (1.0, "p_number", True)), - (b"AspectRatioMode", (0, "p_enum", False)), # WindowSize. - (b"AspectWidth", (320.0, "p_double", False)), - (b"AspectHeight", (200.0, "p_double", False)), - (b"PixelAspectRatio", (1.0, "p_double", False)), - (b"FilmOffsetX", (0.0, "p_number", True)), - (b"FilmOffsetY", (0.0, "p_number", True)), - (b"FilmWidth", (0.816, "p_double", False)), - (b"FilmHeight", (0.612, "p_double", False)), - (b"FilmAspectRatio", (1.3333333333333333, "p_double", False)), - (b"FilmSqueezeRatio", (1.0, "p_double", False)), - (b"FilmFormatIndex", (0, "p_enum", False)), # Assuming this is ApertureFormat, 0 = custom. - (b"PreScale", (1.0, "p_number", True)), - (b"FilmTranslateX", (0.0, "p_number", True)), - (b"FilmTranslateY", (0.0, "p_number", True)), - (b"FilmRollPivotX", (0.0, "p_number", True)), - (b"FilmRollPivotY", (0.0, "p_number", True)), - (b"FilmRollValue", (0.0, "p_number", True)), - (b"FilmRollOrder", (0, "p_enum", False)), # 0 = rotate first (default). - (b"ApertureMode", (2, "p_enum", False)), # 2 = Vertical. - (b"GateFit", (0, "p_enum", False)), # 0 = no resolution gate fit. - (b"FieldOfView", (25.114999771118164, "p_fov", True)), - (b"FieldOfViewX", (40.0, "p_fov_x", True)), - (b"FieldOfViewY", (40.0, "p_fov_y", True)), - (b"FocalLength", (34.89327621672628, "p_number", True)), - (b"CameraFormat", (0, "p_enum", False)), # Custom camera format. - (b"UseFrameColor", (False, "p_bool", False)), - (b"FrameColor", ((0.3, 0.3, 0.3), "p_color_rgb", False)), - (b"ShowName", (True, "p_bool", False)), - (b"ShowInfoOnMoving", (True, "p_bool", False)), - (b"ShowGrid", (True, "p_bool", False)), - (b"ShowOpticalCenter", (False, "p_bool", False)), - (b"ShowAzimut", (True, "p_bool", False)), - (b"ShowTimeCode", (False, "p_bool", False)), - (b"ShowAudio", (False, "p_bool", False)), - (b"AudioColor", ((0.0, 1.0, 0.0), "p_vector_3d", False)), # Yep, vector3d, not corlorgb… :cry: - (b"NearPlane", (10.0, "p_double", False)), - (b"FarPlane", (4000.0, "p_double", False)), - (b"AutoComputeClipPanes", (False, "p_bool", False)), - (b"ViewCameraToLookAt", (True, "p_bool", False)), - (b"ViewFrustumNearFarPlane", (False, "p_bool", False)), - (b"ViewFrustumBackPlaneMode", (2, "p_enum", False)), # 2 = show back plane if texture added. - (b"BackPlaneDistance", (4000.0, "p_number", True)), - (b"BackPlaneDistanceMode", (1, "p_enum", False)), # 1 = relative to camera. - (b"ViewFrustumFrontPlaneMode", (2, "p_enum", False)), # 2 = show front plane if texture added. - (b"FrontPlaneDistance", (10.0, "p_number", True)), - (b"FrontPlaneDistanceMode", (1, "p_enum", False)), # 1 = relative to camera. - (b"LockMode", (False, "p_bool", False)), - (b"LockInterestNavigation", (False, "p_bool", False)), + props = { + b"Color": ((0.8, 0.8, 0.8), "p_color_rgb", False), + b"Position": ((0.0, 0.0, -50.0), "p_vector", True), + b"UpVector": ((0.0, 1.0, 0.0), "p_vector", True), + b"InterestPosition": ((0.0, 0.0, 0.0), "p_vector", True), + b"Roll": (0.0, "p_roll", True), + b"OpticalCenterX": (0.0, "p_opticalcenterx", True), + b"OpticalCenterY": (0.0, "p_opticalcentery", True), + b"BackgroundColor": ((0.63, 0.63, 0.63), "p_color", True), + b"TurnTable": (0.0, "p_number", True), + b"DisplayTurnTableIcon": (False, "p_bool", False), + b"UseMotionBlur": (False, "p_bool", False), + b"UseRealTimeMotionBlur": (True, "p_bool", False), + b"Motion Blur Intensity": (1.0, "p_number", True), + b"AspectRatioMode": (0, "p_enum", False), # WindowSize. + b"AspectWidth": (320.0, "p_double", False), + b"AspectHeight": (200.0, "p_double", False), + b"PixelAspectRatio": (1.0, "p_double", False), + b"FilmOffsetX": (0.0, "p_number", True), + b"FilmOffsetY": (0.0, "p_number", True), + b"FilmWidth": (0.816, "p_double", False), + b"FilmHeight": (0.612, "p_double", False), + b"FilmAspectRatio": (1.3333333333333333, "p_double", False), + b"FilmSqueezeRatio": (1.0, "p_double", False), + b"FilmFormatIndex": (0, "p_enum", False), # Assuming this is ApertureFormat, 0 = custom. + b"PreScale": (1.0, "p_number", True), + b"FilmTranslateX": (0.0, "p_number", True), + b"FilmTranslateY": (0.0, "p_number", True), + b"FilmRollPivotX": (0.0, "p_number", True), + b"FilmRollPivotY": (0.0, "p_number", True), + b"FilmRollValue": (0.0, "p_number", True), + b"FilmRollOrder": (0, "p_enum", False), # 0 = rotate first (default). + b"ApertureMode": (2, "p_enum", False), # 2 = Vertical. + b"GateFit": (0, "p_enum", False), # 0 = no resolution gate fit. + b"FieldOfView": (25.114999771118164, "p_fov", True), + b"FieldOfViewX": (40.0, "p_fov_x", True), + b"FieldOfViewY": (40.0, "p_fov_y", True), + b"FocalLength": (34.89327621672628, "p_number", True), + b"CameraFormat": (0, "p_enum", False), # Custom camera format. + b"UseFrameColor": (False, "p_bool", False), + b"FrameColor": ((0.3, 0.3, 0.3), "p_color_rgb", False), + b"ShowName": (True, "p_bool", False), + b"ShowInfoOnMoving": (True, "p_bool", False), + b"ShowGrid": (True, "p_bool", False), + b"ShowOpticalCenter": (False, "p_bool", False), + b"ShowAzimut": (True, "p_bool", False), + b"ShowTimeCode": (False, "p_bool", False), + b"ShowAudio": (False, "p_bool", False), + b"AudioColor": ((0.0, 1.0, 0.0), "p_vector_3d", False), # Yep, vector3d, not corlorgb… :cry: + b"NearPlane": (10.0, "p_double", False), + b"FarPlane": (4000.0, "p_double", False), + b"AutoComputeClipPanes": (False, "p_bool", False), + b"ViewCameraToLookAt": (True, "p_bool", False), + b"ViewFrustumNearFarPlane": (False, "p_bool", False), + b"ViewFrustumBackPlaneMode": (2, "p_enum", False), # 2 = show back plane if texture added. + b"BackPlaneDistance": (4000.0, "p_number", True), + b"BackPlaneDistanceMode": (1, "p_enum", False), # 1 = relative to camera. + b"ViewFrustumFrontPlaneMode": (2, "p_enum", False), # 2 = show front plane if texture added. + b"FrontPlaneDistance": (10.0, "p_number", True), + b"FrontPlaneDistanceMode": (1, "p_enum", False), # 1 = relative to camera. + b"LockMode": (False, "p_bool", False), + b"LockInterestNavigation": (False, "p_bool", False), # BackPlate... properties **arggggg!** - (b"FitImage", (False, "p_bool", False)), - (b"Crop", (False, "p_bool", False)), - (b"Center", (True, "p_bool", False)), - (b"KeepRatio", (True, "p_bool", False)), + b"FitImage": (False, "p_bool", False), + b"Crop": (False, "p_bool", False), + b"Center": (True, "p_bool", False), + b"KeepRatio": (True, "p_bool", False), # End of BackPlate... - (b"BackgroundAlphaTreshold", (0.5, "p_double", False)), - (b"ShowBackplate", (True, "p_bool", False)), - (b"BackPlaneOffsetX", (0.0, "p_number", True)), - (b"BackPlaneOffsetY", (0.0, "p_number", True)), - (b"BackPlaneRotation", (0.0, "p_number", True)), - (b"BackPlaneScaleX", (1.0, "p_number", True)), - (b"BackPlaneScaleY", (1.0, "p_number", True)), - (b"Background Texture", (None, "p_object", False)), - (b"FrontPlateFitImage", (True, "p_bool", False)), - (b"FrontPlateCrop", (False, "p_bool", False)), - (b"FrontPlateCenter", (True, "p_bool", False)), - (b"FrontPlateKeepRatio", (True, "p_bool", False)), - (b"Foreground Opacity", (1.0, "p_double", False)), - (b"ShowFrontplate", (True, "p_bool", False)), - (b"FrontPlaneOffsetX", (0.0, "p_number", True)), - (b"FrontPlaneOffsetY", (0.0, "p_number", True)), - (b"FrontPlaneRotation", (0.0, "p_number", True)), - (b"FrontPlaneScaleX", (1.0, "p_number", True)), - (b"FrontPlaneScaleY", (1.0, "p_number", True)), - (b"Foreground Texture", (None, "p_object", False)), - (b"DisplaySafeArea", (False, "p_bool", False)), - (b"DisplaySafeAreaOnRender", (False, "p_bool", False)), - (b"SafeAreaDisplayStyle", (1, "p_enum", False)), # 1 = rounded corners. - (b"SafeAreaAspectRatio", (1.3333333333333333, "p_double", False)), - (b"Use2DMagnifierZoom", (False, "p_bool", False)), - (b"2D Magnifier Zoom", (100.0, "p_number", True)), - (b"2D Magnifier X", (50.0, "p_number", True)), - (b"2D Magnifier Y", (50.0, "p_number", True)), - (b"CameraProjectionType", (0, "p_enum", False)), # 0 = perspective, 1 = orthogonal. - (b"OrthoZoom", (1.0, "p_double", False)), - (b"UseRealTimeDOFAndAA", (False, "p_bool", False)), - (b"UseDepthOfField", (False, "p_bool", False)), - (b"FocusSource", (0, "p_enum", False)), # 0 = camera interest, 1 = distance from camera interest. - (b"FocusAngle", (3.5, "p_double", False)), # ??? - (b"FocusDistance", (200.0, "p_double", False)), - (b"UseAntialiasing", (False, "p_bool", False)), - (b"AntialiasingIntensity", (0.77777, "p_double", False)), - (b"AntialiasingMethod", (0, "p_enum", False)), # 0 = oversampling, 1 = hardware. - (b"UseAccumulationBuffer", (False, "p_bool", False)), - (b"FrameSamplingCount", (7, "p_integer", False)), - (b"FrameSamplingType", (1, "p_enum", False)), # 0 = uniform, 1 = stochastic. - )) + b"BackgroundAlphaTreshold": (0.5, "p_double", False), + b"ShowBackplate": (True, "p_bool", False), + b"BackPlaneOffsetX": (0.0, "p_number", True), + b"BackPlaneOffsetY": (0.0, "p_number", True), + b"BackPlaneRotation": (0.0, "p_number", True), + b"BackPlaneScaleX": (1.0, "p_number", True), + b"BackPlaneScaleY": (1.0, "p_number", True), + b"Background Texture": (None, "p_object", False), + b"FrontPlateFitImage": (True, "p_bool", False), + b"FrontPlateCrop": (False, "p_bool", False), + b"FrontPlateCenter": (True, "p_bool", False), + b"FrontPlateKeepRatio": (True, "p_bool", False), + b"Foreground Opacity": (1.0, "p_double", False), + b"ShowFrontplate": (True, "p_bool", False), + b"FrontPlaneOffsetX": (0.0, "p_number", True), + b"FrontPlaneOffsetY": (0.0, "p_number", True), + b"FrontPlaneRotation": (0.0, "p_number", True), + b"FrontPlaneScaleX": (1.0, "p_number", True), + b"FrontPlaneScaleY": (1.0, "p_number", True), + b"Foreground Texture": (None, "p_object", False), + b"DisplaySafeArea": (False, "p_bool", False), + b"DisplaySafeAreaOnRender": (False, "p_bool", False), + b"SafeAreaDisplayStyle": (1, "p_enum", False), # 1 = rounded corners. + b"SafeAreaAspectRatio": (1.3333333333333333, "p_double", False), + b"Use2DMagnifierZoom": (False, "p_bool", False), + b"2D Magnifier Zoom": (100.0, "p_number", True), + b"2D Magnifier X": (50.0, "p_number", True), + b"2D Magnifier Y": (50.0, "p_number", True), + b"CameraProjectionType": (0, "p_enum", False), # 0 = perspective, 1 = orthogonal. + b"OrthoZoom": (1.0, "p_double", False), + b"UseRealTimeDOFAndAA": (False, "p_bool", False), + b"UseDepthOfField": (False, "p_bool", False), + b"FocusSource": (0, "p_enum", False), # 0 = camera interest, 1 = distance from camera interest. + b"FocusAngle": (3.5, "p_double", False), # ??? + b"FocusDistance": (200.0, "p_double", False), + b"UseAntialiasing": (False, "p_bool", False), + b"AntialiasingIntensity": (0.77777, "p_double", False), + b"AntialiasingMethod": (0, "p_enum", False), # 0 = oversampling, 1 = hardware. + b"UseAccumulationBuffer": (False, "p_bool", False), + b"FrameSamplingCount": (7, "p_integer", False), + b"FrameSamplingType": (1, "p_enum", False), # 0 = uniform, 1 = stochastic. + } if override_defaults is not None: props.update(override_defaults) return FBXTemplate(b"NodeAttribute", b"FbxCamera", props, nbr_users, [False]) def fbx_template_def_bone(scene, settings, override_defaults=None, nbr_users=0): - props = OrderedDict() + props = {} if override_defaults is not None: props.update(override_defaults) return FBXTemplate(b"NodeAttribute", b"LimbNode", props, nbr_users, [False]) def fbx_template_def_geometry(scene, settings, override_defaults=None, nbr_users=0): - props = OrderedDict(( - (b"Color", ((0.8, 0.8, 0.8), "p_color_rgb", False)), - (b"BBoxMin", ((0.0, 0.0, 0.0), "p_vector_3d", False)), - (b"BBoxMax", ((0.0, 0.0, 0.0), "p_vector_3d", False)), - (b"Primary Visibility", (True, "p_bool", False)), - (b"Casts Shadows", (True, "p_bool", False)), - (b"Receive Shadows", (True, "p_bool", False)), - )) + props = { + b"Color": ((0.8, 0.8, 0.8), "p_color_rgb", False), + b"BBoxMin": ((0.0, 0.0, 0.0), "p_vector_3d", False), + b"BBoxMax": ((0.0, 0.0, 0.0), "p_vector_3d", False), + b"Primary Visibility": (True, "p_bool", False), + b"Casts Shadows": (True, "p_bool", False), + b"Receive Shadows": (True, "p_bool", False), + } if override_defaults is not None: props.update(override_defaults) return FBXTemplate(b"Geometry", b"FbxMesh", props, nbr_users, [False]) @@ -366,37 +367,37 @@ def fbx_template_def_geometry(scene, settings, override_defaults=None, nbr_users def fbx_template_def_material(scene, settings, override_defaults=None, nbr_users=0): # WIP... - props = OrderedDict(( - (b"ShadingModel", ("Phong", "p_string", False)), - (b"MultiLayer", (False, "p_bool", False)), + props = { + b"ShadingModel": ("Phong", "p_string", False), + b"MultiLayer": (False, "p_bool", False), # Lambert-specific. - (b"EmissiveColor", ((0.0, 0.0, 0.0), "p_color", True)), - (b"EmissiveFactor", (1.0, "p_number", True)), - (b"AmbientColor", ((0.2, 0.2, 0.2), "p_color", True)), - (b"AmbientFactor", (1.0, "p_number", True)), - (b"DiffuseColor", ((0.8, 0.8, 0.8), "p_color", True)), - (b"DiffuseFactor", (1.0, "p_number", True)), - (b"TransparentColor", ((0.0, 0.0, 0.0), "p_color", True)), - (b"TransparencyFactor", (0.0, "p_number", True)), - (b"Opacity", (1.0, "p_number", True)), - (b"NormalMap", ((0.0, 0.0, 0.0), "p_vector_3d", False)), - (b"Bump", ((0.0, 0.0, 0.0), "p_vector_3d", False)), - (b"BumpFactor", (1.0, "p_double", False)), - (b"DisplacementColor", ((0.0, 0.0, 0.0), "p_color_rgb", False)), - (b"DisplacementFactor", (1.0, "p_double", False)), - (b"VectorDisplacementColor", ((0.0, 0.0, 0.0), "p_color_rgb", False)), - (b"VectorDisplacementFactor", (1.0, "p_double", False)), + b"EmissiveColor": ((0.0, 0.0, 0.0), "p_color", True), + b"EmissiveFactor": (1.0, "p_number", True), + b"AmbientColor": ((0.2, 0.2, 0.2), "p_color", True), + b"AmbientFactor": (1.0, "p_number", True), + b"DiffuseColor": ((0.8, 0.8, 0.8), "p_color", True), + b"DiffuseFactor": (1.0, "p_number", True), + b"TransparentColor": ((0.0, 0.0, 0.0), "p_color", True), + b"TransparencyFactor": (0.0, "p_number", True), + b"Opacity": (1.0, "p_number", True), + b"NormalMap": ((0.0, 0.0, 0.0), "p_vector_3d", False), + b"Bump": ((0.0, 0.0, 0.0), "p_vector_3d", False), + b"BumpFactor": (1.0, "p_double", False), + b"DisplacementColor": ((0.0, 0.0, 0.0), "p_color_rgb", False), + b"DisplacementFactor": (1.0, "p_double", False), + b"VectorDisplacementColor": ((0.0, 0.0, 0.0), "p_color_rgb", False), + b"VectorDisplacementFactor": (1.0, "p_double", False), # Phong-specific. - (b"SpecularColor", ((0.2, 0.2, 0.2), "p_color", True)), - (b"SpecularFactor", (1.0, "p_number", True)), + b"SpecularColor": ((0.2, 0.2, 0.2), "p_color", True), + b"SpecularFactor": (1.0, "p_number", True), # Not sure about the name, importer uses this (but ShininessExponent for tex prop name!) # And in fbx exported by sdk, you have one in template, the other in actual material!!! :/ # For now, using both. - (b"Shininess", (20.0, "p_number", True)), - (b"ShininessExponent", (20.0, "p_number", True)), - (b"ReflectionColor", ((0.0, 0.0, 0.0), "p_color", True)), - (b"ReflectionFactor", (1.0, "p_number", True)), - )) + b"Shininess": (20.0, "p_number", True), + b"ShininessExponent": (20.0, "p_number", True), + b"ReflectionColor": ((0.0, 0.0, 0.0), "p_color", True), + b"ReflectionFactor": (1.0, "p_number", True), + } if override_defaults is not None: props.update(override_defaults) return FBXTemplate(b"Material", b"FbxSurfacePhong", props, nbr_users, [False]) @@ -405,26 +406,26 @@ def fbx_template_def_material(scene, settings, override_defaults=None, nbr_users def fbx_template_def_texture_file(scene, settings, override_defaults=None, nbr_users=0): # WIP... # XXX Not sure about all names! - props = OrderedDict(( - (b"TextureTypeUse", (0, "p_enum", False)), # Standard. - (b"AlphaSource", (2, "p_enum", False)), # Black (i.e. texture's alpha), XXX name guessed!. - (b"Texture alpha", (1.0, "p_double", False)), - (b"PremultiplyAlpha", (True, "p_bool", False)), - (b"CurrentTextureBlendMode", (1, "p_enum", False)), # Additive... - (b"CurrentMappingType", (0, "p_enum", False)), # UV. - (b"UVSet", ("default", "p_string", False)), # UVMap name. - (b"WrapModeU", (0, "p_enum", False)), # Repeat. - (b"WrapModeV", (0, "p_enum", False)), # Repeat. - (b"UVSwap", (False, "p_bool", False)), - (b"Translation", ((0.0, 0.0, 0.0), "p_vector_3d", False)), - (b"Rotation", ((0.0, 0.0, 0.0), "p_vector_3d", False)), - (b"Scaling", ((1.0, 1.0, 1.0), "p_vector_3d", False)), - (b"TextureRotationPivot", ((0.0, 0.0, 0.0), "p_vector_3d", False)), - (b"TextureScalingPivot", ((0.0, 0.0, 0.0), "p_vector_3d", False)), + props = { + b"TextureTypeUse": (0, "p_enum", False), # Standard. + b"AlphaSource": (2, "p_enum", False), # Black (i.e. texture's alpha), XXX name guessed!. + b"Texture alpha": (1.0, "p_double", False), + b"PremultiplyAlpha": (True, "p_bool", False), + b"CurrentTextureBlendMode": (1, "p_enum", False), # Additive... + b"CurrentMappingType": (0, "p_enum", False), # UV. + b"UVSet": ("default", "p_string", False), # UVMap name. + b"WrapModeU": (0, "p_enum", False), # Repeat. + b"WrapModeV": (0, "p_enum", False), # Repeat. + b"UVSwap": (False, "p_bool", False), + b"Translation": ((0.0, 0.0, 0.0), "p_vector_3d", False), + b"Rotation": ((0.0, 0.0, 0.0), "p_vector_3d", False), + b"Scaling": ((1.0, 1.0, 1.0), "p_vector_3d", False), + b"TextureRotationPivot": ((0.0, 0.0, 0.0), "p_vector_3d", False), + b"TextureScalingPivot": ((0.0, 0.0, 0.0), "p_vector_3d", False), # Not sure about those two... - (b"UseMaterial", (False, "p_bool", False)), - (b"UseMipMap", (False, "p_bool", False)), - )) + b"UseMaterial": (False, "p_bool", False), + b"UseMipMap": (False, "p_bool", False), + } if override_defaults is not None: props.update(override_defaults) return FBXTemplate(b"Texture", b"FbxFileTexture", props, nbr_users, [False]) @@ -432,86 +433,86 @@ def fbx_template_def_texture_file(scene, settings, override_defaults=None, nbr_u def fbx_template_def_video(scene, settings, override_defaults=None, nbr_users=0): # WIP... - props = OrderedDict(( + props = { # All pictures. - (b"Width", (0, "p_integer", False)), - (b"Height", (0, "p_integer", False)), - (b"Path", ("", "p_string_url", False)), - (b"AccessMode", (0, "p_enum", False)), # Disk (0=Disk, 1=Mem, 2=DiskAsync). + b"Width": (0, "p_integer", False), + b"Height": (0, "p_integer", False), + b"Path": ("", "p_string_url", False), + b"AccessMode": (0, "p_enum", False), # Disk (0=Disk, 1=Mem, 2=DiskAsync). # All videos. - (b"StartFrame", (0, "p_integer", False)), - (b"StopFrame", (0, "p_integer", False)), - (b"Offset", (0, "p_timestamp", False)), - (b"PlaySpeed", (0.0, "p_double", False)), - (b"FreeRunning", (False, "p_bool", False)), - (b"Loop", (False, "p_bool", False)), - (b"InterlaceMode", (0, "p_enum", False)), # None, i.e. progressive. + b"StartFrame": (0, "p_integer", False), + b"StopFrame": (0, "p_integer", False), + b"Offset": (0, "p_timestamp", False), + b"PlaySpeed": (0.0, "p_double", False), + b"FreeRunning": (False, "p_bool", False), + b"Loop": (False, "p_bool", False), + b"InterlaceMode": (0, "p_enum", False), # None, i.e. progressive. # Image sequences. - (b"ImageSequence", (False, "p_bool", False)), - (b"ImageSequenceOffset", (0, "p_integer", False)), - (b"FrameRate", (0.0, "p_double", False)), - (b"LastFrame", (0, "p_integer", False)), - )) + b"ImageSequence": (False, "p_bool", False), + b"ImageSequenceOffset": (0, "p_integer", False), + b"FrameRate": (0.0, "p_double", False), + b"LastFrame": (0, "p_integer", False), + } if override_defaults is not None: props.update(override_defaults) return FBXTemplate(b"Video", b"FbxVideo", props, nbr_users, [False]) def fbx_template_def_pose(scene, settings, override_defaults=None, nbr_users=0): - props = OrderedDict() + props = {} if override_defaults is not None: props.update(override_defaults) return FBXTemplate(b"Pose", b"", props, nbr_users, [False]) def fbx_template_def_deformer(scene, settings, override_defaults=None, nbr_users=0): - props = OrderedDict() + props = {} if override_defaults is not None: props.update(override_defaults) return FBXTemplate(b"Deformer", b"", props, nbr_users, [False]) def fbx_template_def_animstack(scene, settings, override_defaults=None, nbr_users=0): - props = OrderedDict(( - (b"Description", ("", "p_string", False)), - (b"LocalStart", (0, "p_timestamp", False)), - (b"LocalStop", (0, "p_timestamp", False)), - (b"ReferenceStart", (0, "p_timestamp", False)), - (b"ReferenceStop", (0, "p_timestamp", False)), - )) + props = { + b"Description": ("", "p_string", False), + b"LocalStart": (0, "p_timestamp", False), + b"LocalStop": (0, "p_timestamp", False), + b"ReferenceStart": (0, "p_timestamp", False), + b"ReferenceStop": (0, "p_timestamp", False), + } if override_defaults is not None: props.update(override_defaults) return FBXTemplate(b"AnimationStack", b"FbxAnimStack", props, nbr_users, [False]) def fbx_template_def_animlayer(scene, settings, override_defaults=None, nbr_users=0): - props = OrderedDict(( - (b"Weight", (100.0, "p_number", True)), - (b"Mute", (False, "p_bool", False)), - (b"Solo", (False, "p_bool", False)), - (b"Lock", (False, "p_bool", False)), - (b"Color", ((0.8, 0.8, 0.8), "p_color_rgb", False)), - (b"BlendMode", (0, "p_enum", False)), - (b"RotationAccumulationMode", (0, "p_enum", False)), - (b"ScaleAccumulationMode", (0, "p_enum", False)), - (b"BlendModeBypass", (0, "p_ulonglong", False)), - )) + props = { + b"Weight": (100.0, "p_number", True), + b"Mute": (False, "p_bool", False), + b"Solo": (False, "p_bool", False), + b"Lock": (False, "p_bool", False), + b"Color": ((0.8, 0.8, 0.8), "p_color_rgb", False), + b"BlendMode": (0, "p_enum", False), + b"RotationAccumulationMode": (0, "p_enum", False), + b"ScaleAccumulationMode": (0, "p_enum", False), + b"BlendModeBypass": (0, "p_ulonglong", False), + } if override_defaults is not None: props.update(override_defaults) return FBXTemplate(b"AnimationLayer", b"FbxAnimLayer", props, nbr_users, [False]) def fbx_template_def_animcurvenode(scene, settings, override_defaults=None, nbr_users=0): - props = OrderedDict(( - (FBX_ANIM_PROPSGROUP_NAME.encode(), (None, "p_compound", False)), - )) + props = { + FBX_ANIM_PROPSGROUP_NAME.encode(): (None, "p_compound", False), + } if override_defaults is not None: props.update(override_defaults) return FBXTemplate(b"AnimationCurveNode", b"FbxAnimCurveNode", props, nbr_users, [False]) def fbx_template_def_animcurve(scene, settings, override_defaults=None, nbr_users=0): - props = OrderedDict() + props = {} if override_defaults is not None: props.update(override_defaults) return FBXTemplate(b"AnimationCurve", b"", props, nbr_users, [False]) @@ -571,13 +572,13 @@ def fbx_data_empty_elements(root, empty, scene_data): # No custom properties, already saved with object (Model). -def fbx_data_lamp_elements(root, lamp, scene_data): +def fbx_data_light_elements(root, lamp, scene_data): """ Write the Lamp data block. """ gscale = scene_data.settings.global_scale - lamp_key = scene_data.data_lamps[lamp] + light_key = scene_data.data_lights[lamp] do_light = True decay_type = FBX_LIGHT_DECAY_TYPES['CONSTANT'] do_shadow = False @@ -585,11 +586,11 @@ def fbx_data_lamp_elements(root, lamp, scene_data): if lamp.type not in {'HEMI'}: if lamp.type not in {'SUN', 'AREA'}: decay_type = FBX_LIGHT_DECAY_TYPES[lamp.falloff_type] - do_light = (not lamp.use_only_shadow) and (lamp.use_specular or lamp.use_diffuse) - do_shadow = lamp.shadow_method not in {'NOSHADOW'} + do_light = True + do_shadow = lamp.use_shadow shadow_color = lamp.shadow_color - light = elem_data_single_int64(root, b"NodeAttribute", get_fbx_uuid_from_key(lamp_key)) + light = elem_data_single_int64(root, b"NodeAttribute", get_fbx_uuid_from_key(light_key)) light.add_string(fbx_name_class(lamp.name.encode(), b"NodeAttribute")) light.add_string(b"Light") @@ -629,8 +630,8 @@ def fbx_data_camera_elements(root, cam_obj, scene_data): # Real data now, good old camera! # Object transform info. loc, rot, scale, matrix, matrix_rot = cam_obj.fbx_object_tx(scene_data) - up = matrix_rot * Vector((0.0, 1.0, 0.0)) - to = matrix_rot * Vector((0.0, 0.0, -1.0)) + up = matrix_rot @ Vector((0.0, 1.0, 0.0)) + to = matrix_rot @ Vector((0.0, 0.0, -1.0)) # Render settings. # TODO We could export much more... render = scene_data.scene.render @@ -1111,38 +1112,39 @@ def fbx_data_mesh_elements(root, me_obj, scene_data, done_meshes): del _uvtuples_gen # Face's materials. - me_fbxmats_idx = scene_data.mesh_mat_indices.get(me) - if me_fbxmats_idx is not None: - me_blmats = me.materials - if me_fbxmats_idx and me_blmats: - lay_mat = elem_data_single_int32(geom, b"LayerElementMaterial", 0) - elem_data_single_int32(lay_mat, b"Version", FBX_GEOMETRY_MATERIAL_VERSION) - elem_data_single_string(lay_mat, b"Name", b"") - nbr_mats = len(me_fbxmats_idx) + me_fbxmaterials_idx = scene_data.mesh_material_indices.get(me) + if me_fbxmaterials_idx is not None: + me_blmaterials = me.materials + if me_fbxmaterials_idx and me_blmaterials: + lay_ma = elem_data_single_int32(geom, b"LayerElementMaterial", 0) + elem_data_single_int32(lay_ma, b"Version", FBX_GEOMETRY_MATERIAL_VERSION) + elem_data_single_string(lay_ma, b"Name", b"") + nbr_mats = len(me_fbxmaterials_idx) if nbr_mats > 1: t_pm = array.array(data_types.ARRAY_INT32, (0,)) * len(me.polygons) me.polygons.foreach_get("material_index", t_pm) # We have to validate mat indices, and map them to FBX indices. # Note a mat might not be in me_fbxmats_idx (e.g. node mats are ignored). - blmats_to_fbxmats_idxs = [me_fbxmats_idx[m] for m in me_blmats if m in me_fbxmats_idx] - mat_idx_limit = len(blmats_to_fbxmats_idxs) - def_mat = blmats_to_fbxmats_idxs[0] - _gen = (blmats_to_fbxmats_idxs[m] if m < mat_idx_limit else def_mat for m in t_pm) + blmaterials_to_fbxmaterials_idxs = [me_fbxmaterials_idx[m] + for m in me_blmaterials if m in me_fbxmaterials_idx] + ma_idx_limit = len(blmaterials_to_fbxmaterials_idxs) + def_ma = blmaterials_to_fbxmaterials_idxs[0] + _gen = (blmaterials_to_fbxmaterials_idxs[m] if m < ma_idx_limit else def_ma for m in t_pm) t_pm = array.array(data_types.ARRAY_INT32, _gen) - elem_data_single_string(lay_mat, b"MappingInformationType", b"ByPolygon") + elem_data_single_string(lay_ma, b"MappingInformationType", b"ByPolygon") # XXX Logically, should be "Direct" reference type, since we do not have any index array, and have one # value per polygon... # But looks like FBX expects it to be IndexToDirect here (maybe because materials are already # indices??? *sigh*). - elem_data_single_string(lay_mat, b"ReferenceInformationType", b"IndexToDirect") - elem_data_single_int32_array(lay_mat, b"Materials", t_pm) + elem_data_single_string(lay_ma, b"ReferenceInformationType", b"IndexToDirect") + elem_data_single_int32_array(lay_ma, b"Materials", t_pm) del t_pm else: - elem_data_single_string(lay_mat, b"MappingInformationType", b"AllSame") - elem_data_single_string(lay_mat, b"ReferenceInformationType", b"IndexToDirect") - elem_data_single_int32_array(lay_mat, b"Materials", [0]) + elem_data_single_string(lay_ma, b"MappingInformationType", b"AllSame") + elem_data_single_string(lay_ma, b"ReferenceInformationType", b"IndexToDirect") + elem_data_single_int32_array(lay_ma, b"Materials", [0]) # And the "layer TOC"... @@ -1171,10 +1173,10 @@ def fbx_data_mesh_elements(root, me_obj, scene_data, done_meshes): lay_uv = elem_empty(layer, b"LayerElement") elem_data_single_string(lay_uv, b"Type", b"LayerElementUV") elem_data_single_int32(lay_uv, b"TypedIndex", 0) - if me_fbxmats_idx is not None: - lay_mat = elem_empty(layer, b"LayerElement") - elem_data_single_string(lay_mat, b"Type", b"LayerElementMaterial") - elem_data_single_int32(lay_mat, b"TypedIndex", 0) + if me_fbxmaterials_idx is not None: + lay_ma = elem_empty(layer, b"LayerElement") + elem_data_single_string(lay_ma, b"Type", b"LayerElementMaterial") + elem_data_single_int32(lay_ma, b"TypedIndex", 0) # Add other uv and/or vcol layers... for vcolidx, uvidx, tspaceidx in zip_longest(range(1, vcolnumber), range(1, uvnumber), range(1, tspacenumber), @@ -1204,76 +1206,70 @@ def fbx_data_mesh_elements(root, me_obj, scene_data, done_meshes): done_meshes.add(me_key) -def check_skip_material(mat): - """Simple helper to check whether we actually support exporting that material or not""" - return mat.type not in {'SURFACE'} - - -def fbx_data_material_elements(root, mat, scene_data): +def fbx_data_material_elements(root, ma, scene_data): """ Write the Material data block. """ + ambient_color = (0.0, 0.0, 0.0) if scene_data.data_world: - ambient_color = next(iter(scene_data.data_world.keys())).ambient_color + ambient_color = next(iter(scene_data.data_world.keys())).color - mat_key, _objs = scene_data.data_materials[mat] - skip_mat = check_skip_material(mat) - node_mat = mat.use_nodes - mat_type = b"Phong" - # Approximation... - if not skip_mat and not node_mat and mat.specular_shader not in {'COOKTORR', 'PHONG', 'BLINN'}: - mat_type = b"Lambert" + ma_wrap = node_shader_utils.PrincipledBSDFWrapper(ma, is_readonly=True) + ma_key, _objs = scene_data.data_materials[ma] + ma_type = b"Phong" - fbx_mat = elem_data_single_int64(root, b"Material", get_fbx_uuid_from_key(mat_key)) - fbx_mat.add_string(fbx_name_class(mat.name.encode(), b"Material")) - fbx_mat.add_string(b"") + fbx_ma = elem_data_single_int64(root, b"Material", get_fbx_uuid_from_key(ma_key)) + fbx_ma.add_string(fbx_name_class(ma.name.encode(), b"Material")) + fbx_ma.add_string(b"") - elem_data_single_int32(fbx_mat, b"Version", FBX_MATERIAL_VERSION) + elem_data_single_int32(fbx_ma, b"Version", FBX_MATERIAL_VERSION) # those are not yet properties, it seems... - elem_data_single_string(fbx_mat, b"ShadingModel", mat_type) - elem_data_single_int32(fbx_mat, b"MultiLayer", 0) # Should be bool... + elem_data_single_string(fbx_ma, b"ShadingModel", ma_type) + elem_data_single_int32(fbx_ma, b"MultiLayer", 0) # Should be bool... tmpl = elem_props_template_init(scene_data.templates, b"Material") - props = elem_properties(fbx_mat) - - if not skip_mat: - elem_props_template_set(tmpl, props, "p_string", b"ShadingModel", mat_type.decode()) - elem_props_template_set(tmpl, props, "p_color", b"DiffuseColor", mat.diffuse_color) - elem_props_template_set(tmpl, props, "p_number", b"DiffuseFactor", mat.diffuse_intensity) - if not node_mat: - elem_props_template_set(tmpl, props, "p_color", b"EmissiveColor", mat.diffuse_color) - elem_props_template_set(tmpl, props, "p_number", b"EmissiveFactor", mat.emit) - elem_props_template_set(tmpl, props, "p_color", b"AmbientColor", ambient_color) - elem_props_template_set(tmpl, props, "p_number", b"AmbientFactor", mat.ambient) - elem_props_template_set(tmpl, props, "p_color", b"TransparentColor", - mat.diffuse_color if mat.use_transparency else (1.0, 1.0, 1.0)) - elem_props_template_set(tmpl, props, "p_number", b"TransparencyFactor", - 1.0 - mat.alpha if mat.use_transparency else 0.0) - elem_props_template_set(tmpl, props, "p_number", b"Opacity", mat.alpha if mat.use_transparency else 1.0) - elem_props_template_set(tmpl, props, "p_vector_3d", b"NormalMap", (0.0, 0.0, 0.0)) - # Not sure about those... - """ - b"Bump": ((0.0, 0.0, 0.0), "p_vector_3d"), - b"BumpFactor": (1.0, "p_double"), - b"DisplacementColor": ((0.0, 0.0, 0.0), "p_color_rgb"), - b"DisplacementFactor": (0.0, "p_double"), - """ - if mat_type == b"Phong": - elem_props_template_set(tmpl, props, "p_color", b"SpecularColor", mat.specular_color) - elem_props_template_set(tmpl, props, "p_number", b"SpecularFactor", mat.specular_intensity / 2.0) - # See Material template about those two! - elem_props_template_set(tmpl, props, "p_number", b"Shininess", (mat.specular_hardness - 1.0) / 5.10) - elem_props_template_set(tmpl, props, "p_number", b"ShininessExponent", (mat.specular_hardness - 1.0) / 5.10) - elem_props_template_set(tmpl, props, "p_color", b"ReflectionColor", mat.mirror_color) - elem_props_template_set(tmpl, props, "p_number", b"ReflectionFactor", - mat.raytrace_mirror.reflect_factor if mat.raytrace_mirror.use else 0.0) + props = elem_properties(fbx_ma) + + elem_props_template_set(tmpl, props, "p_string", b"ShadingModel", ma_type.decode()) + elem_props_template_set(tmpl, props, "p_color", b"DiffuseColor", ma_wrap.base_color) + # Not in Principled BSDF, so assuming always 1 + elem_props_template_set(tmpl, props, "p_number", b"DiffuseFactor", 1.0) + # Not in Principled BSDF, so assuming always 0 + elem_props_template_set(tmpl, props, "p_color", b"EmissiveColor", ma_wrap.base_color) + elem_props_template_set(tmpl, props, "p_number", b"EmissiveFactor", 0.0) + # Not in Principled BSDF, so assuming always 0 + elem_props_template_set(tmpl, props, "p_color", b"AmbientColor", ambient_color) + elem_props_template_set(tmpl, props, "p_number", b"AmbientFactor", 0.0) + elem_props_template_set(tmpl, props, "p_color", b"TransparentColor", ma_wrap.base_color) + elem_props_template_set(tmpl, props, "p_number", b"TransparencyFactor", ma_wrap.transmission) + elem_props_template_set(tmpl, props, "p_number", b"Opacity", 1.0 - ma_wrap.transmission) + elem_props_template_set(tmpl, props, "p_vector_3d", b"NormalMap", (0.0, 0.0, 0.0)) + # Not sure about those... + """ + b"Bump": ((0.0, 0.0, 0.0), "p_vector_3d"), + b"BumpFactor": (1.0, "p_double"), + b"DisplacementColor": ((0.0, 0.0, 0.0), "p_color_rgb"), + b"DisplacementFactor": (0.0, "p_double"), + """ + # TODO: use specular tint? + elem_props_template_set(tmpl, props, "p_color", b"SpecularColor", ma_wrap.base_color) + elem_props_template_set(tmpl, props, "p_number", b"SpecularFactor", ma_wrap.specular / 2.0) + # See Material template about those two! + # XXX Totally empirical conversion, trying to adapt it + # (from 0.0 - 100.0 FBX shininess range to 1.0 - 0.0 Principled BSDF range)... + shininess = (1.0 - ma_wrap.roughness) * 10 + shininess *= shininess + elem_props_template_set(tmpl, props, "p_number", b"Shininess", shininess) + elem_props_template_set(tmpl, props, "p_number", b"ShininessExponent", shininess) + elem_props_template_set(tmpl, props, "p_color", b"ReflectionColor", ma_wrap.base_color) + elem_props_template_set(tmpl, props, "p_number", b"ReflectionFactor", ma_wrap.metallic) elem_props_template_finalize(tmpl, props) # Custom properties. if scene_data.settings.use_custom_props: - fbx_data_element_custom_properties(props, mat) + fbx_data_element_custom_properties(props, ma) def _gen_vid_path(img, scene_data): @@ -1284,7 +1280,7 @@ def _gen_vid_path(img, scene_data): return fname_abs, fname_rel -def fbx_data_texture_file_elements(root, tex, scene_data): +def fbx_data_texture_file_elements(root, blender_tex_key, scene_data): """ Write the (file) Texture data block. """ @@ -1292,45 +1288,50 @@ def fbx_data_texture_file_elements(root, tex, scene_data): # Textures do not seem to use properties as much as they could. # For now assuming most logical and simple stuff. - tex_key, _mats = scene_data.data_textures[tex] - img = tex.texture.image + ma, sock_name = blender_tex_key + ma_wrap = node_shader_utils.PrincipledBSDFWrapper(ma, is_readonly=True) + tex_key, _fbx_prop = scene_data.data_textures[blender_tex_key] + tex = getattr(ma_wrap, sock_name) + img = tex.image fname_abs, fname_rel = _gen_vid_path(img, scene_data) fbx_tex = elem_data_single_int64(root, b"Texture", get_fbx_uuid_from_key(tex_key)) - fbx_tex.add_string(fbx_name_class(tex.name.encode(), b"Texture")) + fbx_tex.add_string(fbx_name_class(sock_name.encode(), b"Texture")) fbx_tex.add_string(b"") elem_data_single_string(fbx_tex, b"Type", b"TextureVideoClip") elem_data_single_int32(fbx_tex, b"Version", FBX_TEXTURE_VERSION) - elem_data_single_string(fbx_tex, b"TextureName", fbx_name_class(tex.name.encode(), b"Texture")) + elem_data_single_string(fbx_tex, b"TextureName", fbx_name_class(sock_name.encode(), b"Texture")) elem_data_single_string(fbx_tex, b"Media", fbx_name_class(img.name.encode(), b"Video")) elem_data_single_string_unicode(fbx_tex, b"FileName", fname_abs) elem_data_single_string_unicode(fbx_tex, b"RelativeFilename", fname_rel) alpha_source = 0 # None if img.use_alpha: - if tex.texture.use_calculate_alpha: - alpha_source = 1 # RGBIntensity as alpha. - else: - alpha_source = 2 # Black, i.e. alpha channel. + # ~ if tex.texture.use_calculate_alpha: + # ~ alpha_source = 1 # RGBIntensity as alpha. + # ~ else: + # ~ alpha_source = 2 # Black, i.e. alpha channel. + alpha_source = 2 # Black, i.e. alpha channel. # BlendMode not useful for now, only affects layered textures afaics. mapping = 0 # UV. uvset = None - if tex.texture_coords in {'ORCO'}: # XXX Others? - if tex.mapping in {'FLAT'}: + if tex.texcoords == 'ORCO': # XXX Others? + if tex.projection == 'FLAT': mapping = 1 # Planar - elif tex.mapping in {'CUBE'}: + elif tex.projection == 'CUBE': mapping = 4 # Box - elif tex.mapping in {'TUBE'}: + elif tex.projection == 'TUBE': mapping = 3 # Cylindrical - elif tex.mapping in {'SPHERE'}: + elif tex.projection == 'SPHERE': mapping = 2 # Spherical - elif tex.texture_coords in {'UV'}: + elif tex.texcoords == 'UV': mapping = 0 # UV # Yuck, UVs are linked by mere names it seems... :/ - uvset = tex.uv_layer + # XXX TODO how to get that now??? + # uvset = tex.uv_layer wrap_mode = 1 # Clamp - if tex.texture.extension in {'REPEAT'}: + if tex.extension == 'REPEAT': wrap_mode = 0 # Repeat tmpl = elem_props_template_init(scene_data.templates, b"TextureFile") @@ -1343,16 +1344,15 @@ def fbx_data_texture_file_elements(root, tex, scene_data): elem_props_template_set(tmpl, props, "p_string", b"UVSet", uvset) elem_props_template_set(tmpl, props, "p_enum", b"WrapModeU", wrap_mode) elem_props_template_set(tmpl, props, "p_enum", b"WrapModeV", wrap_mode) - elem_props_template_set(tmpl, props, "p_vector_3d", b"Translation", tex.offset) - elem_props_template_set(tmpl, props, "p_vector_3d", b"Scaling", tex.scale) + elem_props_template_set(tmpl, props, "p_vector_3d", b"Translation", tex.translation) + elem_props_template_set(tmpl, props, "p_vector_3d", b"Rotation", (-r for r in tex.rotation)) + elem_props_template_set(tmpl, props, "p_vector_3d", b"Scaling", (((1.0 / s) if s != 0.0 else 1.0) for s in tex.scale)) # UseMaterial should always be ON imho. elem_props_template_set(tmpl, props, "p_bool", b"UseMaterial", True) - elem_props_template_set(tmpl, props, "p_bool", b"UseMipMap", tex.texture.use_mipmap) + elem_props_template_set(tmpl, props, "p_bool", b"UseMipMap", False) elem_props_template_finalize(tmpl, props) - # Custom properties. - if scene_data.settings.use_custom_props: - fbx_data_element_custom_properties(props, tex.texture) + # No custom properties, since that's not a data-block anymore. def fbx_data_video_elements(root, vid, scene_data): @@ -1462,7 +1462,7 @@ def fbx_data_armature_elements(root, arm_obj, scene_data): bo_vg_idx = {bo_obj.bdata.name: ob.vertex_groups[bo_obj.bdata.name].index for bo_obj in clusters.keys() if bo_obj.bdata.name in ob.vertex_groups} valid_idxs = set(bo_vg_idx.values()) - vgroups = {vg.index: OrderedDict() for vg in ob.vertex_groups} + vgroups = {vg.index: {} for vg in ob.vertex_groups} verts_vgroups = (sorted(((vg.group, vg.weight) for vg in v.groups if vg.weight and vg.group in valid_idxs), key=lambda e: e[1], reverse=True) for v in me.vertices) @@ -1497,7 +1497,7 @@ def fbx_data_armature_elements(root, arm_obj, scene_data): # http://area.autodesk.com/forum/autodesk-fbx/fbx-sdk/why-the-values-return- # by-fbxcluster-gettransformmatrix-x-not-same-with-the-value-in-ascii-fbx-file/ elem_data_single_float64_array(fbx_clstr, b"Transform", - matrix4_to_array(mat_world_bones[bo_obj].inverted_safe() * mat_world_obj)) + matrix4_to_array(mat_world_bones[bo_obj].inverted_safe() @ mat_world_obj)) elem_data_single_float64_array(fbx_clstr, b"TransformLink", matrix4_to_array(mat_world_bones[bo_obj])) elem_data_single_float64_array(fbx_clstr, b"TransformAssociateModel", matrix4_to_array(mat_world_arm)) @@ -1570,7 +1570,7 @@ def fbx_data_object_elements(root, ob_obj, scene_data): obj_type = b"Null" elif (ob_obj.type in BLENDER_OBJECT_TYPES_MESHLIKE): obj_type = b"Mesh" - elif (ob_obj.type == 'LAMP'): + elif (ob_obj.type == 'LIGHT'): obj_type = b"Light" elif (ob_obj.type == 'CAMERA'): obj_type = b"Camera" @@ -1717,46 +1717,30 @@ def fbx_data_animation_elements(root, scene_data): # ##### Top-level FBX data container. ##### -def fbx_mat_properties_from_texture(tex): - """ - Returns a set of FBX metarial properties that are affected by the given texture. - Quite obviously, this is a fuzzy and far-from-perfect mapping! Amounts of influence are completely lost, e.g. - Note tex is actually expected to be a texture slot. - """ - # Mapping Blender -> FBX (blend_use_name, blend_fact_name, fbx_name). - blend_to_fbx = ( - # Lambert & Phong... - ("diffuse", "diffuse", b"DiffuseFactor"), - ("color_diffuse", "diffuse_color", b"DiffuseColor"), - ("alpha", "alpha", b"TransparencyFactor"), - ("diffuse", "diffuse", b"TransparentColor"), # Uses diffuse color in Blender! - ("emit", "emit", b"EmissiveFactor"), - ("diffuse", "diffuse", b"EmissiveColor"), # Uses diffuse color in Blender! - ("ambient", "ambient", b"AmbientFactor"), - # ("", "", b"AmbientColor"), # World stuff in Blender, for now ignore... - ("normal", "normal", b"NormalMap"), - # Note: unsure about those... :/ - # ("", "", b"Bump"), - # ("", "", b"BumpFactor"), - # ("", "", b"DisplacementColor"), - # ("", "", b"DisplacementFactor"), - # Phong only. - ("specular", "specular", b"SpecularFactor"), - ("color_spec", "specular_color", b"SpecularColor"), - # See Material template about those two! - ("hardness", "hardness", b"Shininess"), - ("hardness", "hardness", b"ShininessExponent"), - ("mirror", "mirror", b"ReflectionColor"), - ("raymir", "raymir", b"ReflectionFactor"), - ) - - tex_fbx_props = set() - for use_map_name, name_factor, fbx_prop_name in blend_to_fbx: - # Always export enabled textures, even if they have a null influence... - if getattr(tex, "use_map_" + use_map_name): - tex_fbx_props.add(fbx_prop_name) - - return tex_fbx_props +# Mapping Blender -> FBX (principled_socket_name, fbx_name). +PRINCIPLED_TEXTURE_SOCKETS_TO_FBX = ( + # ("diffuse", "diffuse", b"DiffuseFactor"), + ("base_color_texture", b"DiffuseColor"), + ("transmission_texture", b"TransparencyFactor"), + # ("base_color_texture", b"TransparentColor"), # Uses diffuse color in Blender! + # ("emit", "emit", b"EmissiveFactor"), + # ("diffuse", "diffuse", b"EmissiveColor"), # Uses diffuse color in Blender! + # ("ambient", "ambient", b"AmbientFactor"), + # ("", "", b"AmbientColor"), # World stuff in Blender, for now ignore... + ("normalmap_texture", b"NormalMap"), + # Note: unsure about those... :/ + # ("", "", b"Bump"), + # ("", "", b"BumpFactor"), + # ("", "", b"DisplacementColor"), + # ("", "", b"DisplacementFactor"), + ("specular_texture", b"SpecularFactor"), + # ("base_color", b"SpecularColor"), # TODO: use tint? + # See Material template about those two! + ("roughness_texture", b"Shininess"), + ("roughness_texture", b"ShininessExponent"), + # ("mirror", "mirror", b"ReflectionColor"), + ("metallic_texture", b"ReflectionFactor"), +) def fbx_skeleton_from_armature(scene, settings, arm_obj, objects, data_meshes, @@ -1771,7 +1755,7 @@ def fbx_skeleton_from_armature(scene, settings, arm_obj, objects, data_meshes, data_empties[arm_obj] = get_blender_empty_key(arm_obj.bdata) arm_data = arm_obj.bdata.data - bones = OrderedDict() + bones = {} for bo in arm_obj.bones: if settings.use_armature_deform_only: if bo.bdata.use_deform: @@ -1785,7 +1769,7 @@ def fbx_skeleton_from_armature(scene, settings, arm_obj, objects, data_meshes, else: bones[bo] = True - bones = OrderedDict((bo, None) for bo, use in bones.items() if use) + bones = {bo: None for bo, use in bones.items() if use} if not bones: return @@ -1813,8 +1797,8 @@ def fbx_skeleton_from_armature(scene, settings, arm_obj, objects, data_meshes, # Note: bindpose have no relations at all (no connections), so no need for any preprocess for them. # Create skin & clusters relations (note skins are connected to geometry, *not* model!). _key, me, _free = data_meshes[ob_obj] - clusters = OrderedDict((bo, get_blender_bone_cluster_key(arm_obj.bdata, me, bo.bdata)) for bo in bones) - data_deformers_skin.setdefault(arm_obj, OrderedDict())[me] = (get_blender_armature_skin_key(arm_obj.bdata, me), + clusters = {bo: get_blender_bone_cluster_key(arm_obj.bdata, me, bo.bdata) for bo in bones} + data_deformers_skin.setdefault(arm_obj, {})[me] = (get_blender_armature_skin_key(arm_obj.bdata, me), ob_obj, clusters) # We don't want a regular parent relationship for those in FBX... @@ -1849,9 +1833,9 @@ def fbx_generate_leaf_bones(settings, data_bones): bone_length = (parent.bdata.tail_local - parent.bdata.head_local).length matrix = Matrix.Translation((0, bone_length, 0)) if settings.bone_correction_matrix_inv: - matrix = settings.bone_correction_matrix_inv * matrix + matrix = settings.bone_correction_matrix_inv @ matrix if settings.bone_correction_matrix: - matrix = matrix * settings.bone_correction_matrix + matrix = matrix @ settings.bone_correction_matrix leaf_bones.append((node_name, parent_uuid, node_uuid, attr_uuid, matrix, hide, size)) return leaf_bones @@ -1864,6 +1848,7 @@ def fbx_animations_do(scene_data, ref_id, f_start, f_end, start_zero, objects=No bake_step = scene_data.settings.bake_anim_step simplify_fac = scene_data.settings.bake_anim_simplify_factor scene = scene_data.scene + depsgraph = scene_data.depsgraph force_keying = scene_data.settings.bake_anim_use_all_bones force_sek = scene_data.settings.bake_anim_force_startend_keying @@ -1874,16 +1859,14 @@ def fbx_animations_do(scene_data, ref_id, f_start, f_end, start_zero, objects=No continue if ob_obj.type == 'ARMATURE': objects |= {bo_obj for bo_obj in ob_obj.bones if bo_obj in scene_data.objects} - ob_obj.dupli_list_create(scene, 'RENDER') - for dp_obj in ob_obj.dupli_list: + for dp_obj in ob_obj.dupli_list_gen(depsgraph): if dp_obj in scene_data.objects: objects.add(dp_obj) - ob_obj.dupli_list_clear() else: objects = scene_data.objects back_currframe = scene.frame_current - animdata_ob = OrderedDict() + animdata_ob = {} p_rots = {} for ob_obj in objects: @@ -1899,8 +1882,8 @@ def fbx_animations_do(scene_data, ref_id, f_start, f_end, start_zero, objects=No p_rots[ob_obj] = rot force_key = (simplify_fac == 0.0) + animdata_shapes = {} - animdata_shapes = OrderedDict() for me, (me_key, _shapes_key, shapes) in scene_data.data_deformers_shape.items(): # Ignore absolute shape keys for now! if not me.shape_keys.use_relative: @@ -1911,7 +1894,7 @@ def fbx_animations_do(scene_data, ref_id, f_start, f_end, start_zero, objects=No acnode.add_group(me_key, shape.name, shape.name, (shape.name,)) animdata_shapes[channel_key] = (acnode, me, shape) - animdata_cameras = OrderedDict() + animdata_cameras = {} for cam_obj, cam_key in scene_data.data_cameras.items(): cam = cam_obj.bdata.data acnode = AnimationCurveNodeWrapper(cam_key, 'CAMERA_FOCAL', force_key, force_sek, (cam.lens,)) @@ -1920,10 +1903,10 @@ def fbx_animations_do(scene_data, ref_id, f_start, f_end, start_zero, objects=No currframe = f_start while currframe <= f_end: real_currframe = currframe - f_start if start_zero else currframe - scene.frame_set(int(currframe), currframe - int(currframe)) + scene.frame_set(int(currframe), subframe=currframe - int(currframe)) - for ob_obj in animdata_ob: - ob_obj.dupli_list_create(scene, 'RENDER') + for dp_obj in ob_obj.dupli_list_gen(depsgraph): + pass # Merely updating dupli matrix of ObjectWrapper... for ob_obj, (anim_loc, anim_rot, anim_scale) in animdata_ob.items(): # We compute baked loc/rot/scale for all objects (rot being euler-compat with previous value!). p_rot = p_rots.get(ob_obj, None) @@ -1932,17 +1915,15 @@ def fbx_animations_do(scene_data, ref_id, f_start, f_end, start_zero, objects=No anim_loc.add_keyframe(real_currframe, loc) anim_rot.add_keyframe(real_currframe, tuple(convert_rad_to_deg_iter(rot))) anim_scale.add_keyframe(real_currframe, scale) - for ob_obj in objects: - ob_obj.dupli_list_clear() for anim_shape, me, shape in animdata_shapes.values(): anim_shape.add_keyframe(real_currframe, (shape.value * 100.0,)) for anim_camera, camera in animdata_cameras.values(): anim_camera.add_keyframe(real_currframe, (camera.lens,)) currframe += bake_step - scene.frame_set(back_currframe, 0.0) + scene.frame_set(back_currframe, subframe=0.0) - animations = OrderedDict() + animations = {} # And now, produce final data (usable by FBX export code) # Objects-like loc/rot/scale... @@ -1952,34 +1933,28 @@ def fbx_animations_do(scene_data, ref_id, f_start, f_end, start_zero, objects=No if not anim: continue for obj_key, group_key, group, fbx_group, fbx_gname in anim.get_final_data(scene, ref_id, force_keep): - anim_data = animations.get(obj_key) - if anim_data is None: - anim_data = animations[obj_key] = ("dummy_unused_key", OrderedDict()) + anim_data = animations.setdefault(obj_key, ("dummy_unused_key", {})) anim_data[1][fbx_group] = (group_key, group, fbx_gname) # And meshes' shape keys. for channel_key, (anim_shape, me, shape) in animdata_shapes.items(): - final_keys = OrderedDict() + final_keys = {} anim_shape.simplify(simplify_fac, bake_step, force_keep) if not anim_shape: continue for elem_key, group_key, group, fbx_group, fbx_gname in anim_shape.get_final_data(scene, ref_id, force_keep): - anim_data = animations.get(elem_key) - if anim_data is None: - anim_data = animations[elem_key] = ("dummy_unused_key", OrderedDict()) - anim_data[1][fbx_group] = (group_key, group, fbx_gname) + anim_data = animations.setdefault(elem_key, ("dummy_unused_key", {})) + anim_data[1][fbx_group] = (group_key, group, fbx_gname) # And cameras' lens keys. for cam_key, (anim_camera, camera) in animdata_cameras.items(): - final_keys = OrderedDict() + final_keys = {} anim_camera.simplify(simplify_fac, bake_step, force_keep) if not anim_camera: continue for elem_key, group_key, group, fbx_group, fbx_gname in anim_camera.get_final_data(scene, ref_id, force_keep): - anim_data = animations.get(elem_key) - if anim_data is None: - anim_data = animations[elem_key] = ("dummy_unused_key", OrderedDict()) - anim_data[1][fbx_group] = (group_key, group, fbx_gname) + anim_data = animations.setdefault(elem_key, ("dummy_unused_key", {})) + anim_data[1][fbx_group] = (group_key, group, fbx_gname) astack_key = get_blender_anim_stack_key(scene, ref_id) alayer_key = get_blender_anim_layer_key(scene, ref_id) @@ -2045,7 +2020,7 @@ def fbx_animations(scene_data): add_anim(animations, animated, fbx_animations_do(scene_data, strip, strip.frame_start, strip.frame_end, True, force_keep=True)) strip.mute = True - scene.frame_set(scene.frame_current, 0.0) + scene.frame_set(scene.frame_current, subframe=0.0) for strip in strips: strip.mute = False @@ -2072,14 +2047,14 @@ def fbx_animations(scene_data): 'location', 'rotation_quaternion', 'rotation_axis_angle', 'rotation_euler', 'rotation_mode', 'scale', 'delta_location', 'delta_rotation_euler', 'delta_rotation_quaternion', 'delta_scale', 'lock_location', 'lock_rotation', 'lock_rotation_w', 'lock_rotations_4d', 'lock_scale', - 'tag', 'layers', 'select', 'track_axis', 'up_axis', 'active_material', 'active_material_index', - 'matrix_parent_inverse', 'empty_draw_type', 'empty_draw_size', 'empty_image_offset', 'pass_index', - 'color', 'hide', 'hide_select', 'hide_render', 'use_slow_parent', 'slow_parent_offset', - 'use_extra_recalc_object', 'use_extra_recalc_data', 'dupli_type', 'use_dupli_frames_speed', - 'use_dupli_vertices_rotation', 'use_dupli_faces_scale', 'dupli_faces_scale', 'dupli_group', + 'tag', 'track_axis', 'up_axis', 'active_material', 'active_material_index', + 'matrix_parent_inverse', 'empty_display_type', 'empty_display_size', 'empty_image_offset', 'pass_index', + 'color', 'hide_viewport', 'hide_select', 'hide_render', 'use_slow_parent', 'slow_parent_offset', + 'dupli_type', 'use_dupli_frames_speed', + 'use_dupli_vertices_rotation', 'use_dupli_faces_scale', 'dupli_faces_scale', 'dupli_frames_start', 'dupli_frames_end', 'dupli_frames_on', 'dupli_frames_off', - 'draw_type', 'show_bounds', 'draw_bounds_type', 'show_name', 'show_axis', 'show_texture_space', - 'show_wire', 'show_all_edges', 'show_transparent', 'show_x_ray', + 'display_type', 'show_bounds', 'display_bounds_type', 'show_name', 'show_axis', 'show_texture_space', + 'show_wire', 'show_all_edges', 'show_transparent', 'show_in_front', 'show_only_shape_key', 'use_shape_key_edit_mode', 'active_shape_key_index', ) for p in props: @@ -2124,7 +2099,7 @@ def fbx_animations(scene_data): pbo.matrix_basis = mat.copy() ob.animation_data.action = org_act restore_object(ob, ob_copy) - scene.frame_set(scene.frame_current, 0.0) + scene.frame_set(scene.frame_current, subframe=0.0) if pbones_matrices is not ...: for pbo, mat in zip(ob.pose.bones, pbones_matrices): @@ -2132,19 +2107,19 @@ def fbx_animations(scene_data): ob.animation_data.action = org_act bpy.data.objects.remove(ob_copy) - scene.frame_set(scene.frame_current, 0.0) + scene.frame_set(scene.frame_current, subframe=0.0) # Global (containing everything) animstack, only if not exporting NLA strips and/or all actions. if not scene_data.settings.bake_anim_use_nla_strips and not scene_data.settings.bake_anim_use_all_actions: add_anim(animations, animated, fbx_animations_do(scene_data, None, scene.frame_start, scene.frame_end, False)) # Be sure to update all matrices back to org state! - scene.frame_set(scene.frame_current, 0.0) + scene.frame_set(scene.frame_current, subframe=0.0) return animations, animated, frame_start, frame_end -def fbx_data_from_scene(scene, settings): +def fbx_data_from_scene(scene, depsgraph, settings): """ Do some pre-processing over scene's data... """ @@ -2159,34 +2134,32 @@ def fbx_data_from_scene(scene, settings): # This is rather simple for now, maybe we could end generating templates with most-used values # instead of default ones? - objects = OrderedDict() # Because we do not have any ordered set... + objects = {} # Because we do not have any ordered set... for ob in settings.context_objects: if ob.type not in objtypes: continue ob_obj = ObjectWrapper(ob) objects[ob_obj] = None # Duplis... - ob_obj.dupli_list_create(scene, 'RENDER') - for dp_obj in ob_obj.dupli_list: + for dp_obj in ob_obj.dupli_list_gen(depsgraph): if dp_obj.type not in dp_objtypes: continue objects[dp_obj] = None - ob_obj.dupli_list_clear() perfmon.step("FBX export prepare: Wrapping Data (lamps, cameras, empties)...") - data_lamps = OrderedDict((ob_obj.bdata.data, get_blenderID_key(ob_obj.bdata.data)) - for ob_obj in objects if ob_obj.type == 'LAMP') + data_lights = {ob_obj.bdata.data: get_blenderID_key(ob_obj.bdata.data) + for ob_obj in objects if ob_obj.type == 'LIGHT'} # Unfortunately, FBX camera data contains object-level data (like position, orientation, etc.)... - data_cameras = OrderedDict((ob_obj, get_blenderID_key(ob_obj.bdata.data)) - for ob_obj in objects if ob_obj.type == 'CAMERA') + data_cameras = {ob_obj: get_blenderID_key(ob_obj.bdata.data) + for ob_obj in objects if ob_obj.type == 'CAMERA'} # Yep! Contains nothing, but needed! - data_empties = OrderedDict((ob_obj, get_blender_empty_key(ob_obj.bdata)) - for ob_obj in objects if ob_obj.type == 'EMPTY') + data_empties = {ob_obj: get_blender_empty_key(ob_obj.bdata) + for ob_obj in objects if ob_obj.type == 'EMPTY'} perfmon.step("FBX export prepare: Wrapping Meshes...") - data_meshes = OrderedDict() + data_meshes = {} for ob_obj in objects: if ob_obj.type not in BLENDER_OBJECT_TYPES_MESHLIKE: continue @@ -2218,10 +2191,8 @@ def fbx_data_from_scene(scene, settings): use_org_data = False if not use_org_data: tmp_me = ob.to_mesh( - scene, - apply_modifiers=settings.use_mesh_modifiers, - settings='RENDER' if settings.use_mesh_modifiers_render else 'PREVIEW', - ) + depsgraph, + apply_modifiers=settings.use_mesh_modifiers) data_meshes[ob_obj] = (get_blenderID_key(tmp_me), tmp_me, True) # Re-enable temporary disabled modifiers. for mod, show_render in tmp_mods: @@ -2236,7 +2207,7 @@ def fbx_data_from_scene(scene, settings): perfmon.step("FBX export prepare: Wrapping ShapeKeys...") # ShapeKeys. - data_deformers_shape = OrderedDict() + data_deformers_shape = {} geom_mat_co = settings.global_matrix if settings.bake_space_transform else None for me_key, me, _free in data_meshes.values(): if not (me.shape_keys and len(me.shape_keys.key_blocks) > 1): # We do not want basis-only relative skeys... @@ -2274,13 +2245,13 @@ def fbx_data_from_scene(scene, settings): continue channel_key, geom_key = get_blender_mesh_shape_channel_key(me, shape) data = (channel_key, geom_key, shape_verts_co, shape_verts_idx) - data_deformers_shape.setdefault(me, (me_key, shapes_key, OrderedDict()))[2][shape] = data + data_deformers_shape.setdefault(me, (me_key, shapes_key, {}))[2][shape] = data perfmon.step("FBX export prepare: Wrapping Armatures...") # Armatures! - data_deformers_skin = OrderedDict() - data_bones = OrderedDict() + data_deformers_skin = {} + data_bones = {} arm_parents = set() for ob_obj in tuple(objects): if not (ob_obj.is_object and ob_obj.type in {'ARMATURE'}): @@ -2297,71 +2268,51 @@ def fbx_data_from_scene(scene, settings): # Some world settings are embedded in FBX materials... if scene.world: - data_world = OrderedDict(((scene.world, get_blenderID_key(scene.world)),)) + data_world = {scene.world: get_blenderID_key(scene.world)} else: - data_world = OrderedDict() + data_world = {} perfmon.step("FBX export prepare: Wrapping Materials...") - # TODO: Check all the mat stuff works even when mats are linked to Objects + # TODO: Check all the material stuff works even when they are linked to Objects # (we can then have the same mesh used with different materials...). # *Should* work, as FBX always links its materials to Models (i.e. objects). # XXX However, material indices would probably break... - data_materials = OrderedDict() + data_materials = {} for ob_obj in objects: # If obj is not a valid object for materials, wrapper will just return an empty tuple... - for mat_s in ob_obj.material_slots: - mat = mat_s.material - if mat is None: + for ma_s in ob_obj.material_slots: + ma = ma_s.material + if ma is None: continue # Empty slots! # Note theoretically, FBX supports any kind of materials, even GLSL shaders etc. # However, I doubt anything else than Lambert/Phong is really portable! - # We support any kind of 'surface' shader though, better to have some kind of default Lambert than nothing. - # Note we want to keep a 'dummy' empty mat even when we can't really support it, see T41396. - mat_data = data_materials.get(mat) - if mat_data is not None: - mat_data[1].append(ob_obj) - else: - data_materials[mat] = (get_blenderID_key(mat), [ob_obj]) + # Note we want to keep a 'dummy' empty material even when we can't really support it, see T41396. + ma_data = data_materials.setdefault(ma, (get_blenderID_key(ma), [])) + ma_data[1].append(ob_obj) perfmon.step("FBX export prepare: Wrapping Textures...") # Note FBX textures also hold their mapping info. # TODO: Support layers? - data_textures = OrderedDict() + data_textures = {} # FbxVideo also used to store static images... - data_videos = OrderedDict() + data_videos = {} # For now, do not use world textures, don't think they can be linked to anything FBX wise... - for mat in data_materials.keys(): - if check_skip_material(mat): - continue - for tex, use_tex in zip(mat.texture_slots, mat.use_textures): - if tex is None or tex.texture is None or not use_tex: - continue - # For now, only consider image textures. - # Note FBX does has support for procedural, but this is not portable at all (opaque blob), - # so not useful for us. - # TODO I think ENVIRONMENT_MAP should be usable in FBX as well, but for now let it aside. - # if tex.texture.type not in {'IMAGE', 'ENVIRONMENT_MAP'}: - if tex.texture.type not in {'IMAGE'}: - continue - img = tex.texture.image - if img is None: + for ma in data_materials.keys(): + # Note: with nodal shaders, we'll could be generating much more textures, but that's kind of unavoidable, + # given that textures actually do not exist anymore in material context in Blender... + ma_wrap = node_shader_utils.PrincipledBSDFWrapper(ma, is_readonly=True) + for sock_name, fbx_name in PRINCIPLED_TEXTURE_SOCKETS_TO_FBX: + tex = getattr(ma_wrap, sock_name) + if tex is None or tex.image is None: continue - # Find out whether we can actually use this texture for this material, in FBX context. - tex_fbx_props = fbx_mat_properties_from_texture(tex) - if not tex_fbx_props: - continue - tex_data = data_textures.get(tex) - if tex_data is not None: - tex_data[1][mat] = tex_fbx_props - else: - data_textures[tex] = (get_blenderID_key(tex), OrderedDict(((mat, tex_fbx_props),))) - vid_data = data_videos.get(img) - if vid_data is not None: - vid_data[1].append(tex) - else: - data_videos[img] = (get_blenderID_key(img), [tex]) + blender_tex_key = (ma, sock_name) + data_textures[blender_tex_key] = (get_blender_nodetexture_key(*blender_tex_key), fbx_name) + + img = tex.image + vid_data = data_videos.setdefault(img, (get_blenderID_key(img), [])) + vid_data[1].append(blender_tex_key) perfmon.step("FBX export prepare: Wrapping Animations...") @@ -2375,8 +2326,8 @@ def fbx_data_from_scene(scene, settings): # Kind of hack, we need a temp scene_data for object's space handling to bake animations... tmp_scdata = FBXExportData( None, None, None, - settings, scene, objects, None, None, 0.0, 0.0, - data_empties, data_lamps, data_cameras, data_meshes, None, + settings, scene, depsgraph, objects, None, None, 0.0, 0.0, + data_empties, data_lights, data_cameras, data_meshes, None, data_bones, data_leaf_bones, data_deformers_skin, data_deformers_shape, data_world, data_materials, data_textures, data_videos, ) @@ -2386,14 +2337,14 @@ def fbx_data_from_scene(scene, settings): perfmon.step("FBX export prepare: Generating templates...") - templates = OrderedDict() + templates = {} templates[b"GlobalSettings"] = fbx_template_def_globalsettings(scene, settings, nbr_users=1) if data_empties: templates[b"Null"] = fbx_template_def_null(scene, settings, nbr_users=len(data_empties)) - if data_lamps: - templates[b"Light"] = fbx_template_def_light(scene, settings, nbr_users=len(data_lamps)) + if data_lights: + templates[b"Light"] = fbx_template_def_light(scene, settings, nbr_users=len(data_lights)) if data_cameras: templates[b"Camera"] = fbx_template_def_camera(scene, settings, nbr_users=len(data_cameras)) @@ -2491,9 +2442,9 @@ def fbx_data_from_scene(scene, settings): bo_data_key = data_bones[ob_obj] connections.append((b"OO", get_fbx_uuid_from_key(bo_data_key), ob_obj.fbx_uuid, None)) else: - if ob_obj.type == 'LAMP': - lamp_key = data_lamps[ob_obj.bdata.data] - connections.append((b"OO", get_fbx_uuid_from_key(lamp_key), ob_obj.fbx_uuid, None)) + if ob_obj.type == 'LIGHT': + light_key = data_lights[ob_obj.bdata.data] + connections.append((b"OO", get_fbx_uuid_from_key(light_key), ob_obj.fbx_uuid, None)) elif ob_obj.type == 'CAMERA': cam_key = data_cameras[ob_obj] connections.append((b"OO", get_fbx_uuid_from_key(cam_key), ob_obj.fbx_uuid, None)) @@ -2533,35 +2484,33 @@ def fbx_data_from_scene(scene, settings): connections.append((b"OO", bo_obj.fbx_uuid, get_fbx_uuid_from_key(clstr_key), None)) # Materials - mesh_mat_indices = OrderedDict() + mesh_material_indices = {} _objs_indices = {} - for mat, (mat_key, ob_objs) in data_materials.items(): + for ma, (ma_key, ob_objs) in data_materials.items(): for ob_obj in ob_objs: - connections.append((b"OO", get_fbx_uuid_from_key(mat_key), ob_obj.fbx_uuid, None)) - # Get index of this mat for this object (or dupliobject). - # Mat indices for mesh faces are determined by their order in 'mat to ob' connections. - # Only mats for meshes currently... - # Note in case of dupliobjects a same me/mat idx will be generated several times... + connections.append((b"OO", get_fbx_uuid_from_key(ma_key), ob_obj.fbx_uuid, None)) + # Get index of this material for this object (or dupliobject). + # Material indices for mesh faces are determined by their order in 'ma to ob' connections. + # Only materials for meshes currently... + # Note in case of dupliobjects a same me/ma idx will be generated several times... # Should not be an issue in practice, and it's needed in case we export duplis but not the original! if ob_obj.type not in BLENDER_OBJECT_TYPES_MESHLIKE: continue _mesh_key, me, _free = data_meshes[ob_obj] idx = _objs_indices[ob_obj] = _objs_indices.get(ob_obj, -1) + 1 - mesh_mat_indices.setdefault(me, OrderedDict())[mat] = idx + mesh_material_indices.setdefault(me, {})[ma] = idx del _objs_indices # Textures - for tex, (tex_key, mats) in data_textures.items(): - for mat, fbx_mat_props in mats.items(): - mat_key, _ob_objs = data_materials[mat] - for fbx_prop in fbx_mat_props: - # texture -> material properties - connections.append((b"OP", get_fbx_uuid_from_key(tex_key), get_fbx_uuid_from_key(mat_key), fbx_prop)) + for (ma, sock_name), (tex_key, fbx_prop) in data_textures.items(): + ma_key, _ob_objs = data_materials[ma] + # texture -> material properties + connections.append((b"OP", get_fbx_uuid_from_key(tex_key), get_fbx_uuid_from_key(ma_key), fbx_prop)) # Images - for vid, (vid_key, texs) in data_videos.items(): - for tex in texs: - tex_key, _texs = data_textures[tex] + for vid, (vid_key, blender_tex_keys) in data_videos.items(): + for blender_tex_key in blender_tex_keys: + tex_key, _fbx_prop = data_textures[blender_tex_key] connections.append((b"OO", get_fbx_uuid_from_key(vid_key), get_fbx_uuid_from_key(tex_key), None)) # Animations @@ -2593,8 +2542,8 @@ def fbx_data_from_scene(scene, settings): return FBXExportData( templates, templates_users, connections, - settings, scene, objects, animations, animated, frame_start, frame_end, - data_empties, data_lamps, data_cameras, data_meshes, mesh_mat_indices, + settings, scene, depsgraph, objects, animations, animated, frame_start, frame_end, + data_empties, data_lights, data_cameras, data_meshes, mesh_material_indices, data_bones, data_leaf_bones, data_deformers_skin, data_deformers_shape, data_world, data_materials, data_textures, data_videos, ) @@ -2803,10 +2752,10 @@ def fbx_objects_elements(root, scene_data): for empty in scene_data.data_empties: fbx_data_empty_elements(objects, empty, scene_data) - perfmon.step("FBX export fetch lamps (%d)..." % len(scene_data.data_lamps)) + perfmon.step("FBX export fetch lamps (%d)..." % len(scene_data.data_lights)) - for lamp in scene_data.data_lamps: - fbx_data_lamp_elements(objects, lamp, scene_data) + for lamp in scene_data.data_lights: + fbx_data_light_elements(objects, lamp, scene_data) perfmon.step("FBX export fetch cameras (%d)..." % len(scene_data.data_cameras)) @@ -2827,12 +2776,10 @@ def fbx_objects_elements(root, scene_data): if ob_obj.is_dupli: continue fbx_data_object_elements(objects, ob_obj, scene_data) - ob_obj.dupli_list_create(scene_data.scene, 'RENDER') - for dp_obj in ob_obj.dupli_list: + for dp_obj in ob_obj.dupli_list_gen(scene_data.depsgraph): if dp_obj not in scene_data.objects: continue fbx_data_object_elements(objects, dp_obj, scene_data) - ob_obj.dupli_list_clear() perfmon.step("FBX export fetch remaining...") @@ -2844,11 +2791,11 @@ def fbx_objects_elements(root, scene_data): if scene_data.data_leaf_bones: fbx_data_leaf_bone_elements(objects, scene_data) - for mat in scene_data.data_materials: - fbx_data_material_elements(objects, mat, scene_data) + for ma in scene_data.data_materials: + fbx_data_material_elements(objects, ma, scene_data) - for tex in scene_data.data_textures: - fbx_data_texture_file_elements(objects, tex, scene_data) + for blender_tex_key in scene_data.data_textures: + fbx_data_texture_file_elements(objects, blender_tex_key, scene_data) for vid in scene_data.data_videos: fbx_data_video_elements(objects, vid, scene_data) @@ -2897,7 +2844,7 @@ def fbx_takes_elements(root, scene_data): # ##### "Main" functions. ##### # This func can be called with just the filepath -def save_single(operator, scene, filepath="", +def save_single(operator, scene, depsgraph, filepath="", global_matrix=Matrix(), apply_unit_scale=False, global_scale=1.0, @@ -2935,7 +2882,7 @@ def save_single(operator, scene, filepath="", ObjectWrapper.cache_clear() if object_types is None: - object_types = {'EMPTY', 'CAMERA', 'LAMP', 'ARMATURE', 'MESH', 'OTHER'} + object_types = {'EMPTY', 'CAMERA', 'LIGHT', 'ARMATURE', 'MESH', 'OTHER'} if 'OTHER' in object_types: object_types |= BLENDER_OTHER_OBJECT_TYPES @@ -2943,12 +2890,12 @@ def save_single(operator, scene, filepath="", # Default Blender unit is equivalent to meter, while FBX one is centimeter... unit_scale = units_blender_to_fbx_factor(scene) if apply_unit_scale else 100.0 if apply_scale_options == 'FBX_SCALE_NONE': - global_matrix = Matrix.Scale(unit_scale * global_scale, 4) * global_matrix + global_matrix = Matrix.Scale(unit_scale * global_scale, 4) @ global_matrix unit_scale = 1.0 elif apply_scale_options == 'FBX_SCALE_UNITS': - global_matrix = Matrix.Scale(global_scale, 4) * global_matrix + global_matrix = Matrix.Scale(global_scale, 4) @ global_matrix elif apply_scale_options == 'FBX_SCALE_CUSTOM': - global_matrix = Matrix.Scale(unit_scale, 4) * global_matrix + global_matrix = Matrix.Scale(unit_scale, 4) @ global_matrix unit_scale = global_scale else: # if apply_scale_options == 'FBX_SCALE_ALL': unit_scale = global_scale * unit_scale @@ -3004,7 +2951,7 @@ def save_single(operator, scene, filepath="", start_time = time.process_time() # Generate some data about exported scene... - scene_data = fbx_data_from_scene(scene, settings) + scene_data = fbx_data_from_scene(scene, depsgraph, settings) root = elem_empty(None, b"") # Root element has no id, as it is not saved per se! @@ -3098,7 +3045,7 @@ def save(operator, context, ret = None - active_object = context.scene.objects.active + active_object = context.view_layer.objects.active org_mode = None if active_object and active_object.mode != 'OBJECT' and bpy.ops.object.mode_set.poll(): @@ -3110,10 +3057,11 @@ def save(operator, context, if use_selection: kwargs_mod["context_objects"] = context.selected_objects else: - kwargs_mod["context_objects"] = context.scene.objects + kwargs_mod["context_objects"] = context.view_layer.objects - ret = save_single(operator, context.scene, filepath, **kwargs_mod) + ret = save_single(operator, context.scene, context.depsgraph, filepath, **kwargs_mod) else: + return # TODO Update for 2.8 fbxpath = filepath prefix = os.path.basename(fbxpath) diff --git a/io_scene_fbx/fbx_utils.py b/io_scene_fbx/fbx_utils.py index 0ed26b6a..7b3b9d0f 100644 --- a/io_scene_fbx/fbx_utils.py +++ b/io_scene_fbx/fbx_utils.py @@ -24,13 +24,13 @@ import math import time -from collections import namedtuple, OrderedDict +from collections import namedtuple from collections.abc import Iterable from itertools import zip_longest, chain import bpy import bpy_extras -from bpy.types import Object, Bone, PoseBone, DupliObject +from bpy.types import Object, Bone, PoseBone, DepsgraphObjectInstance from mathutils import Vector, Matrix from . import encode_bin, data_types @@ -71,7 +71,7 @@ FBX_ANIM_PROPSGROUP_NAME = "d" FBX_KTIME = 46186158000 # This is the number of "ktimes" in one second (yep, precision over the nanosecond...) -MAT_CONVERT_LAMP = Matrix.Rotation(math.pi / 2.0, 4, 'X') # Blender is -Z, FBX is -Y. +MAT_CONVERT_LIGHT = Matrix.Rotation(math.pi / 2.0, 4, 'X') # Blender is -Z, FBX is -Y. MAT_CONVERT_CAMERA = Matrix.Rotation(math.pi / 2.0, 4, 'Y') # Blender is -Z, FBX is +X. # XXX I can't get this working :( # MAT_CONVERT_BONE = Matrix.Rotation(math.pi / 2.0, 4, 'Z') # Blender is +Y, FBX is -X. @@ -271,14 +271,14 @@ def similar_values_iter(v1, v2, e=1e-6): def vcos_transformed_gen(raw_cos, m=None): # Note: we could most likely get much better performances with numpy, but will leave this as TODO for now. gen = zip(*(iter(raw_cos),) * 3) - return gen if m is None else (m * Vector(v) for v in gen) + return gen if m is None else (m @ Vector(v) for v in gen) def nors_transformed_gen(raw_nors, m=None): # Great, now normals are also expected 4D! # XXX Back to 3D normals for now! # gen = zip(*(iter(raw_nors),) * 3 + (_infinite_gen(1.0),)) gen = zip(*(iter(raw_nors),) * 3) - return gen if m is None else (m * Vector(v) for v in gen) + return gen if m is None else (m @ Vector(v) for v in gen) # ##### UIDs code. ##### @@ -324,7 +324,7 @@ def _key_to_uuid(uuids, key): def get_fbx_uuid_from_key(key): """ - Return an UUID for given key, which is assumed hasable. + Return an UUID for given key, which is assumed to be hashable. """ uuid = _keys_to_uuids.get(key, None) if uuid is None: @@ -431,6 +431,10 @@ def get_blender_anim_curve_key(scene, ref_id, obj_key, fbx_prop_name, fbx_prop_i fbx_prop_item_name, "AnimCurve")) +def get_blender_nodetexture_key(ma, socket_names): + return "|".join((get_blenderID_key(ma), *socket_names)) + + # ##### Element generators. ##### # Note: elem may be None, in this case the element is not added to any parent. @@ -614,12 +618,12 @@ def elem_props_template_init(templates, template_type): """ Init a writing template of given type, for *one* element's properties. """ - ret = OrderedDict() + ret = {} tmpl = templates.get(template_type) if tmpl is not None: written = tmpl.written[0] props = tmpl.properties - ret = OrderedDict((name, [val, ptype, anim, written]) for name, (val, ptype, anim) in props.items()) + ret = {name: [val, ptype, anim, written] for name, (val, ptype, anim) in props.items()} return ret @@ -671,14 +675,11 @@ def fbx_templates_generate(root, fbx_templates): # for Lights, Cameras, LibNodes, etc.). ref_templates = {(tmpl.type_name, tmpl.prop_type_name): tmpl for tmpl in fbx_templates.values()} - templates = OrderedDict() + templates = {} for type_name, prop_type_name, properties, nbr_users, _written in fbx_templates.values(): - tmpl = templates.get(type_name) - if tmpl is None: - templates[type_name] = [OrderedDict(((prop_type_name, (properties, nbr_users)),)), nbr_users] - else: - tmpl[0][prop_type_name] = (properties, nbr_users) - tmpl[1] += nbr_users + tmpl = templates.setdefault(type_name, [{}, 0]) + tmpl[0][prop_type_name] = (properties, nbr_users) + tmpl[1] += nbr_users for type_name, (subprops, nbr_users) in templates.items(): template = elem_data_single_string(root, b"ObjectType", type_name) @@ -844,7 +845,7 @@ class AnimationCurveNodeWrapper: for elem_key, fbx_group, fbx_gname, fbx_props in \ zip(self.elem_keys, self.fbx_group, self.fbx_gname, self.fbx_props): group_key = get_blender_anim_curve_node_key(scene, ref_id, elem_key, fbx_group) - group = OrderedDict() + group = {} for c, def_val, fbx_item in zip(curves, self.default_values, fbx_props): fbx_item = FBX_ANIM_PROPSGROUP_NAME + "|" + fbx_item curve_key = get_blender_anim_curve_key(scene, ref_id, elem_key, fbx_group, fbx_item) @@ -856,7 +857,7 @@ class AnimationCurveNodeWrapper: # ##### FBX objects generators. ##### -# FBX Model-like data (i.e. Blender objects, dupliobjects and bones) are wrapped in ObjectWrapper. +# FBX Model-like data (i.e. Blender objects, depsgraph instances and bones) are wrapped in ObjectWrapper. # This allows us to have a (nearly) same code FBX-wise for all those types. # The wrapper tries to stay as small as possible, by mostly using callbacks (property(get...)) # to actual Blender data it contains. @@ -870,9 +871,13 @@ class MetaObjectWrapper(type): dup_mat = None if isinstance(bdata, Object): key = get_blenderID_key(bdata) - elif isinstance(bdata, DupliObject): - key = "|".join((get_blenderID_key((bdata.id_data, bdata.object)), cls._get_dup_num_id(bdata))) - dup_mat = bdata.matrix.copy() + elif isinstance(bdata, DepsgraphObjectInstance): + if bdata.is_instance: + key = "|".join((get_blenderID_key((bdata.parent.original, bdata.instance_object.original)), + cls._get_dup_num_id(bdata))) + dup_mat = bdata.matrix_world.copy() + else: + key = get_blenderID_key(bdata.object.original) else: # isinstance(bdata, (Bone, PoseBone)): if isinstance(bdata, PoseBone): bdata = armature.data.bones[bdata.name] @@ -883,9 +888,9 @@ class MetaObjectWrapper(type): cache = cls._cache = {} instance = cache.get(key) if instance is not None: - # Duplis hack: since duplis are not persistent in Blender (we have to re-create them to get updated + # Duplis hack: since dupli instances are not persistent in Blender (we have to re-create them to get updated # info like matrix...), we *always* need to reset that matrix when calling ObjectWrapper() (all - # other data is supposed valid during whole cache live, so we can skip resetting it). + # other data is supposed valid during whole cache live span, so we can skip resetting it). instance._dupli_matrix = dup_mat return instance @@ -902,7 +907,7 @@ class ObjectWrapper(metaclass=MetaObjectWrapper): This class provides a same common interface for all (FBX-wise) object-like elements: * Blender Object * Blender Bone and PoseBone - * Blender DupliObject + * Blender DepsgraphObjectInstance (for dulis). Note since a same Blender object might be 'mapped' to several FBX models (esp. with duplis), we need to use a key to identify each. """ @@ -918,24 +923,42 @@ class ObjectWrapper(metaclass=MetaObjectWrapper): @staticmethod def _get_dup_num_id(bdata): - return ".".join(str(i) for i in bdata.persistent_id if i != 2147483647) + INVALID_IDS = {2147483647, 0} + pids = tuple(bdata.persistent_id) + idx_valid = 0 + prev_i = ... + for idx, i in enumerate(pids[::-1]): + if i not in INVALID_IDS or (idx == len(pids) and i == 0 and prev_i != 0): + idx_valid = len(pids) - idx + break + prev_i = i + return ".".join(str(i) for i in pids[:idx_valid]) def __init__(self, bdata, armature=None): """ - bdata might be an Object, DupliObject, Bone or PoseBone. + bdata might be an Object (deprecated), DepsgraphObjectInstance, Bone or PoseBone. If Bone or PoseBone, armature Object must be provided. """ - if isinstance(bdata, Object): + # Note: DepsgraphObjectInstance are purely runtime data, they become invalid as soon as we step to the next item! + # Hence we have to immediately copy *all* needed data... + if isinstance(bdata, Object): # DEPRECATED self._tag = 'OB' self.name = get_blenderID_name(bdata) self.bdata = bdata self._ref = None - elif isinstance(bdata, DupliObject): - self._tag = 'DP' - self.name = "|".join((get_blenderID_name((bdata.id_data, bdata.object)), - "Dupli", self._get_dup_num_id(bdata))) - self.bdata = bdata.object - self._ref = bdata.id_data + elif isinstance(bdata, DepsgraphObjectInstance): + if bdata.is_instance: + # Note that dupli instance matrix is set by meta-class initialization. + self._tag = 'DP' + self.name = "|".join((get_blenderID_name((bdata.parent.original, bdata.instance_object.original)), + "Dupli", self._get_dup_num_id(bdata))) + self.bdata = bdata.instance_object.original + self._ref = bdata.parent.original + else: + self._tag = 'OB' + self.name = get_blenderID_name(bdata) + self.bdata = bdata.object.original + self._ref = None else: # isinstance(bdata, (Bone, PoseBone)): if isinstance(bdata, PoseBone): bdata = armature.data.bones[bdata.name] @@ -951,13 +974,17 @@ class ObjectWrapper(metaclass=MetaObjectWrapper): def __hash__(self): return hash(self.key) + def __repr__(self): + return self.key + # #### Common to all _tag values. def get_fbx_uuid(self): return get_fbx_uuid_from_key(self.key) fbx_uuid = property(get_fbx_uuid) + # XXX Not sure how much that’s useful now... :/ def get_hide(self): - return self.bdata.hide + return self.bdata.hide_viewport if self._tag in {'OB', 'DP'} else self.bdata.hide hide = property(get_hide) def get_parent(self): @@ -974,7 +1001,7 @@ class ObjectWrapper(metaclass=MetaObjectWrapper): # Mere object parenting. return ObjectWrapper(self.bdata.parent) elif self._tag == 'DP': - return ObjectWrapper(self.bdata.parent or self._ref) + return ObjectWrapper(self._ref) else: # self._tag == 'BO' return ObjectWrapper(self.bdata.parent, self._ref) or ObjectWrapper(self._ref) parent = property(get_parent) @@ -983,12 +1010,12 @@ class ObjectWrapper(metaclass=MetaObjectWrapper): if self._tag == 'OB': return self.bdata.matrix_local.copy() elif self._tag == 'DP': - return self._ref.matrix_world.inverted_safe() * self._dupli_matrix + return self._ref.matrix_world.inverted_safe() @ self._dupli_matrix else: # 'BO', current pose # PoseBone.matrix is in armature space, bring in back in real local one! par = self.bdata.parent par_mat_inv = self._ref.pose.bones[par.name].matrix.inverted_safe() if par else Matrix() - return par_mat_inv * self._ref.pose.bones[self.bdata.name].matrix + return par_mat_inv @ self._ref.pose.bones[self.bdata.name].matrix matrix_local = property(get_matrix_local) def get_matrix_global(self): @@ -997,7 +1024,7 @@ class ObjectWrapper(metaclass=MetaObjectWrapper): elif self._tag == 'DP': return self._dupli_matrix else: # 'BO', current pose - return self._ref.matrix_world * self._ref.pose.bones[self.bdata.name].matrix + return self._ref.matrix_world @ self._ref.pose.bones[self.bdata.name].matrix matrix_global = property(get_matrix_global) def get_matrix_rest_local(self): @@ -1005,14 +1032,14 @@ class ObjectWrapper(metaclass=MetaObjectWrapper): # Bone.matrix_local is in armature space, bring in back in real local one! par = self.bdata.parent par_mat_inv = par.matrix_local.inverted_safe() if par else Matrix() - return par_mat_inv * self.bdata.matrix_local + return par_mat_inv @ self.bdata.matrix_local else: return self.matrix_local.copy() matrix_rest_local = property(get_matrix_rest_local) def get_matrix_rest_global(self): if self._tag == 'BO': - return self._ref.matrix_world * self.bdata.matrix_local + return self._ref.matrix_world @ self.bdata.matrix_local else: return self.matrix_global.copy() matrix_rest_global = property(get_matrix_rest_global) @@ -1065,41 +1092,41 @@ class ObjectWrapper(metaclass=MetaObjectWrapper): if self._tag == 'BO': # If we have a bone parent we need to undo the parent correction. if not is_global and scene_data.settings.bone_correction_matrix_inv and parent and parent.is_bone: - matrix = scene_data.settings.bone_correction_matrix_inv * matrix + matrix = scene_data.settings.bone_correction_matrix_inv @ matrix # Apply the bone correction. if scene_data.settings.bone_correction_matrix: - matrix = matrix * scene_data.settings.bone_correction_matrix - elif self.bdata.type == 'LAMP': - matrix = matrix * MAT_CONVERT_LAMP + matrix = matrix @ scene_data.settings.bone_correction_matrix + elif self.bdata.type == 'LIGHT': + matrix = matrix @ MAT_CONVERT_LIGHT elif self.bdata.type == 'CAMERA': - matrix = matrix * MAT_CONVERT_CAMERA + matrix = matrix @ MAT_CONVERT_CAMERA if self._tag in {'DP', 'OB'} and parent: if parent._tag == 'BO': # In bone parent case, we get transformation in **bone tip** space (sigh). # Have to bring it back into bone root, which is FBX expected value. - matrix = Matrix.Translation((0, (parent.bdata.tail - parent.bdata.head).length, 0)) * matrix + matrix = Matrix.Translation((0, (parent.bdata.tail - parent.bdata.head).length, 0)) @ matrix # Our matrix is in local space, time to bring it in its final desired space. if parent: if is_global: # Move matrix to global Blender space. - matrix = (parent.matrix_rest_global if rest else parent.matrix_global) * matrix + matrix = (parent.matrix_rest_global if rest else parent.matrix_global) @ matrix elif parent.use_bake_space_transform(scene_data): # Blender's and FBX's local space of parent may differ if we use bake_space_transform... # Apply parent's *Blender* local space... - matrix = (parent.matrix_rest_local if rest else parent.matrix_local) * matrix + matrix = (parent.matrix_rest_local if rest else parent.matrix_local) @ matrix # ...and move it back into parent's *FBX* local space. par_mat = parent.fbx_object_matrix(scene_data, rest=rest, local_space=True) - matrix = par_mat.inverted_safe() * matrix + matrix = par_mat.inverted_safe() @ matrix if self.use_bake_space_transform(scene_data): # If we bake the transforms we need to post-multiply inverse global transform. # This means that the global transform will not apply to children of this transform. - matrix = matrix * scene_data.settings.global_matrix_inv + matrix = matrix @ scene_data.settings.global_matrix_inv if is_global: # In any case, pre-multiply the global matrix to get it in FBX global space! - matrix = scene_data.settings.global_matrix * matrix + matrix = scene_data.settings.global_matrix @ matrix return matrix @@ -1164,19 +1191,11 @@ class ObjectWrapper(metaclass=MetaObjectWrapper): return True # #### Duplis... - def dupli_list_create(self, scene, settings='PREVIEW'): + def dupli_list_gen(self, depsgraph): if self._tag == 'OB' and self.bdata.is_duplicator: - self.bdata.dupli_list_create(scene, settings) - - def dupli_list_clear(self): - if self._tag == 'OB'and self.bdata.is_duplicator: - self.bdata.dupli_list_clear() - - def get_dupli_list(self): - if self._tag == 'OB'and self.bdata.is_duplicator: - return (ObjectWrapper(dup) for dup in self.bdata.dupli_list) + return (ObjectWrapper(dup) for dup in depsgraph.object_instances + if dup.parent and ObjectWrapper(dup.parent.original) == self) return () - dupli_list = property(get_dupli_list) def fbx_name_class(name, cls): @@ -1213,8 +1232,8 @@ FBXExportSettings = namedtuple("FBXExportSettings", ( # * animations. FBXExportData = namedtuple("FBXExportData", ( "templates", "templates_users", "connections", - "settings", "scene", "objects", "animations", "animated", "frame_start", "frame_end", - "data_empties", "data_lamps", "data_cameras", "data_meshes", "mesh_mat_indices", + "settings", "scene", "depsgraph", "objects", "animations", "animated", "frame_start", "frame_end", + "data_empties", "data_lights", "data_cameras", "data_meshes", "mesh_material_indices", "data_bones", "data_leaf_bones", "data_deformers_skin", "data_deformers_shape", "data_world", "data_materials", "data_textures", "data_videos", )) @@ -1223,11 +1242,11 @@ FBXExportData = namedtuple("FBXExportData", ( FBXImportSettings = namedtuple("FBXImportSettings", ( "report", "to_axes", "global_matrix", "global_scale", "bake_space_transform", "global_matrix_inv", "global_matrix_inv_transposed", - "use_custom_normals", "use_cycles", "use_image_search", + "use_custom_normals", "use_image_search", "use_alpha_decals", "decal_offset", "use_anim", "anim_offset", "use_custom_props", "use_custom_props_enum_as_string", - "cycles_material_wrap_map", "image_cache", + "nodal_material_wrap_map", "image_cache", "ignore_leaf_bones", "force_connect_children", "automatic_bone_orientation", "bone_correction_matrix", "use_prepost_rot", )) diff --git a/io_scene_fbx/import_fbx.py b/io_scene_fbx/import_fbx.py index 90dc08df..353a027f 100644 --- a/io_scene_fbx/import_fbx.py +++ b/io_scene_fbx/import_fbx.py @@ -60,7 +60,7 @@ fbx_elem_nil = None convert_deg_to_rad_iter = units_convertor_iter("degree", "radian") MAT_CONVERT_BONE = fbx_utils.MAT_CONVERT_BONE.inverted() -MAT_CONVERT_LAMP = fbx_utils.MAT_CONVERT_LAMP.inverted() +MAT_CONVERT_LIGHT = fbx_utils.MAT_CONVERT_LIGHT.inverted() MAT_CONVERT_CAMERA = fbx_utils.MAT_CONVERT_CAMERA.inverted() @@ -369,7 +369,7 @@ def blen_read_custom_properties(fbx_obj, blen_obj, settings): def blen_read_object_transform_do(transform_data): # This is a nightmare. FBX SDK uses Maya way to compute the transformation matrix of a node - utterly simple: # - # WorldTransform = ParentWorldTransform * T * Roff * Rp * Rpre * R * Rpost * Rp-1 * Soff * Sp * S * Sp-1 + # WorldTransform = ParentWorldTransform @ T @ Roff @ Rp @ Rpre @ R @ Rpost @ Rp-1 @ Soff @ Sp @ S @ Sp-1 # # Where all those terms are 4 x 4 matrices that contain: # WorldTransform: Transformation matrix of the node in global space. @@ -389,7 +389,7 @@ def blen_read_object_transform_do(transform_data): # But it was still too simple, and FBX notion of compatibility is... quite specific. So we also have to # support 3DSMax way: # - # WorldTransform = ParentWorldTransform * T * R * S * OT * OR * OS + # WorldTransform = ParentWorldTransform @ T @ R @ S @ OT @ OR @ OS # # Where all those terms are 4 x 4 matrices that contain: # WorldTransform: Transformation matrix of the node in global space @@ -414,7 +414,7 @@ def blen_read_object_transform_do(transform_data): # rotation to_rot = lambda rot, rot_ord: Euler(convert_deg_to_rad_iter(rot), rot_ord).to_matrix().to_4x4() - lcl_rot = to_rot(transform_data.rot, transform_data.rot_ord) * transform_data.rot_alt_mat + lcl_rot = to_rot(transform_data.rot, transform_data.rot_ord) @ transform_data.rot_alt_mat pre_rot = to_rot(transform_data.pre_rot, transform_data.rot_ord) pst_rot = to_rot(transform_data.pst_rot, transform_data.rot_ord) geom_rot = to_rot(transform_data.geom_rot, transform_data.rot_ord) @@ -431,21 +431,21 @@ def blen_read_object_transform_do(transform_data): geom_scale[0][0], geom_scale[1][1], geom_scale[2][2] = transform_data.geom_sca base_mat = ( - lcl_translation * - rot_ofs * - rot_piv * - pre_rot * - lcl_rot * - pst_rot * - rot_piv.inverted_safe() * - sca_ofs * - sca_piv * - lcl_scale * + lcl_translation @ + rot_ofs @ + rot_piv @ + pre_rot @ + lcl_rot @ + pst_rot @ + rot_piv.inverted_safe() @ + sca_ofs @ + sca_piv @ + lcl_scale @ sca_piv.inverted_safe() ) - geom_mat = geom_loc * geom_rot * geom_scale + geom_mat = geom_loc @ geom_rot @ geom_scale # We return mat without 'geometric transforms' too, because it is to be used for children, sigh... - return (base_mat * geom_mat, base_mat, geom_mat) + return (base_mat @ geom_mat, base_mat, geom_mat) # XXX This might be weak, now that we can add vgroups from both bones and shapes, name collisions become @@ -457,7 +457,7 @@ def add_vgroup_to_objects(vg_indices, vg_weights, vg_name, objects): # We replace/override here... vg = obj.vertex_groups.get(vg_name) if vg is None: - vg = obj.vertex_groups.new(vg_name) + vg = obj.vertex_groups.new(name=vg_name) for i, w in zip(vg_indices, vg_weights): vg.add((i,), w, 'REPLACE') @@ -601,7 +601,7 @@ def blen_read_animations_action_item(action, item, cnodes, fps, anim_offset): else: # Euler props[1] = (bl_obj.path_from_id("rotation_euler"), 3, grpname or "Euler Rotation") - blen_curves = [action.fcurves.new(prop, channel, grpname) + blen_curves = [action.fcurves.new(prop, index=channel, action_group=grpname) for prop, nbr_channels, grpname in props for channel in range(nbr_channels)] if isinstance(item, Material): @@ -613,7 +613,7 @@ def blen_read_animations_action_item(action, item, cnodes, fps, anim_offset): value[channel] = v for fc, v in zip(blen_curves, value): - fc.keyframe_points.insert(frame, v, {'NEEDED', 'FAST'}).interpolation = 'LINEAR' + fc.keyframe_points.insert(frame, v, options={'NEEDED', 'FAST'}).interpolation = 'LINEAR' elif isinstance(item, ShapeKey): for frame, values in blen_read_animations_curves_iter(fbx_curves, anim_offset, 0, fps): @@ -624,7 +624,7 @@ def blen_read_animations_action_item(action, item, cnodes, fps, anim_offset): value = v / 100.0 for fc, v in zip(blen_curves, (value,)): - fc.keyframe_points.insert(frame, v, {'NEEDED', 'FAST'}).interpolation = 'LINEAR' + fc.keyframe_points.insert(frame, v, options={'NEEDED', 'FAST'}).interpolation = 'LINEAR' elif isinstance(item, Camera): for frame, values in blen_read_animations_curves_iter(fbx_curves, anim_offset, 0, fps): @@ -635,7 +635,7 @@ def blen_read_animations_action_item(action, item, cnodes, fps, anim_offset): value = v for fc, v in zip(blen_curves, (value,)): - fc.keyframe_points.insert(frame, v, {'NEEDED', 'FAST'}).interpolation = 'LINEAR' + fc.keyframe_points.insert(frame, v, options={'NEEDED', 'FAST'}).interpolation = 'LINEAR' else: # Object or PoseBone: if item.is_bone: @@ -661,19 +661,19 @@ def blen_read_animations_action_item(action, item, cnodes, fps, anim_offset): # compensate for changes in the local matrix during processing if item.anim_compensation_matrix: - mat = mat * item.anim_compensation_matrix + mat = mat @ item.anim_compensation_matrix # apply pre- and post matrix # post-matrix will contain any correction for lights, camera and bone orientation # pre-matrix will contain any correction for a parent's correction matrix or the global matrix if item.pre_matrix: - mat = item.pre_matrix * mat + mat = item.pre_matrix @ mat if item.post_matrix: - mat = mat * item.post_matrix + mat = mat @ item.post_matrix # And now, remove that rest pose matrix from current mat (also in parent space). if restmat_inv: - mat = restmat_inv * mat + mat = restmat_inv @ mat # Now we have a virtual matrix of transform from AnimCurves, we can insert keyframes! loc, rot, sca = mat.decompose() @@ -686,7 +686,7 @@ def blen_read_animations_action_item(action, item, cnodes, fps, anim_offset): rot = rot.to_euler(rot_mode, rot_prev) rot_prev = rot for fc, value in zip(blen_curves, chain(loc, rot, sca)): - fc.keyframe_points.insert(frame, value, {'NEEDED', 'FAST'}).interpolation = 'LINEAR' + fc.keyframe_points.insert(frame, value, options={'NEEDED', 'FAST'}).interpolation = 'LINEAR' # Since we inserted our keyframes in 'FAST' mode, we have to update the fcurves now. for fc in blen_curves: @@ -1006,8 +1006,7 @@ def blen_read_geom_layer_uv(fbx_obj, mesh): fbx_layer_data = elem_prop_first(elem_find_first(fbx_layer, b'UV')) fbx_layer_index = elem_prop_first(elem_find_first(fbx_layer, b'UVIndex')) - uv_tex = mesh.uv_textures.new(name=fbx_layer_name) - uv_lay = mesh.uv_layers[-1] + uv_lay = mesh.uv_layers.new(name=fbx_layer_name) blen_data = uv_lay.data # some valid files omit this data @@ -1087,7 +1086,6 @@ def blen_read_geom_layer_smooth(fbx_obj, mesh): ) # We only set sharp edges here, not face smoothing itself... mesh.use_auto_smooth = True - mesh.show_edge_sharp = True return False elif fbx_layer_mapping == b'ByPolygon': blen_data = mesh.polygons @@ -1165,7 +1163,7 @@ def blen_read_geom(fbx_tmpl, fbx_obj, settings): if geom_mat_co is not None: def _vcos_transformed_gen(raw_cos, m=None): # Note: we could most likely get much better performances with numpy, but will leave this as TODO for now. - return chain(*(m * Vector(v) for v in zip(*(iter(raw_cos),) * 3))) + return chain(*(m @ Vector(v) for v in zip(*(iter(raw_cos),) * 3))) fbx_verts = array.array(fbx_verts.typecode, _vcos_transformed_gen(fbx_verts, geom_mat_co)) if fbx_verts is None: @@ -1242,7 +1240,7 @@ def blen_read_geom(fbx_tmpl, fbx_obj, settings): ok_normals = blen_read_geom_layer_normal(fbx_obj, mesh) else: def nortrans(v): - return geom_mat_no * Vector(v) + return geom_mat_no @ Vector(v) ok_normals = blen_read_geom_layer_normal(fbx_obj, mesh, nortrans) mesh.validate(clean_customdata=False) # *Very* important to not remove lnors here! @@ -1257,7 +1255,6 @@ def blen_read_geom(fbx_tmpl, fbx_obj, settings): mesh.normals_split_custom_set(tuple(zip(*(iter(clnors),) * 3))) mesh.use_auto_smooth = True - mesh.show_edge_sharp = True else: mesh.calc_normals() @@ -1319,9 +1316,12 @@ def blen_read_shape(fbx_tmpl, fbx_sdata, fbx_bcdata, meshes, scene): # Material def blen_read_material(fbx_tmpl, fbx_obj, settings): + from bpy_extras import node_shader_utils + from math import sqrt + elem_name_utf8 = elem_name_ensure_class(fbx_obj, b'Material') - cycles_material_wrap_map = settings.cycles_material_wrap_map + nodal_material_wrap_map = settings.nodal_material_wrap_map ma = bpy.data.materials.new(name=elem_name_utf8) const_color_white = 1.0, 1.0, 1.0 @@ -1329,43 +1329,23 @@ def blen_read_material(fbx_tmpl, fbx_obj, settings): fbx_props = (elem_find_first(fbx_obj, b'Properties70'), elem_find_first(fbx_tmpl, b'Properties70', fbx_elem_nil)) - ma_diff = elem_props_get_color_rgb(fbx_props, b'DiffuseColor', const_color_white) - ma_spec = elem_props_get_color_rgb(fbx_props, b'SpecularColor', const_color_white) - ma_alpha = elem_props_get_number(fbx_props, b'Opacity', 1.0) - ma_spec_intensity = ma.specular_intensity = elem_props_get_number(fbx_props, b'SpecularFactor', 0.25) * 2.0 - ma_spec_hardness = elem_props_get_number(fbx_props, b'Shininess', 9.6) - ma_refl_factor = elem_props_get_number(fbx_props, b'ReflectionFactor', 0.0) - ma_refl_color = elem_props_get_color_rgb(fbx_props, b'ReflectionColor', const_color_white) - - if settings.use_cycles: - from modules import cycles_shader_compat - # viewport color - ma.diffuse_color = ma_diff - - ma_wrap = cycles_shader_compat.CyclesShaderWrapper(ma) - ma_wrap.diffuse_color_set(ma_diff) - ma_wrap.specular_color_set([c * ma_spec_intensity for c in ma_spec]) - ma_wrap.hardness_value_set(((ma_spec_hardness + 3.0) / 5.0) - 0.65) - ma_wrap.alpha_value_set(ma_alpha) - ma_wrap.reflect_factor_set(ma_refl_factor) - ma_wrap.reflect_color_set(ma_refl_color) - - cycles_material_wrap_map[ma] = ma_wrap - else: - # TODO, number BumpFactor isnt used yet - ma.diffuse_color = ma_diff - ma.specular_color = ma_spec - ma.alpha = ma_alpha - if ma_alpha < 1.0: - ma.use_transparency = True - ma.transparency_method = 'RAYTRACE' - ma.specular_intensity = ma_spec_intensity - ma.specular_hardness = ma_spec_hardness * 5.10 + 1.0 - - if ma_refl_factor != 0.0: - ma.raytrace_mirror.use = True - ma.raytrace_mirror.reflect_factor = ma_refl_factor - ma.mirror_color = ma_refl_color + ma_wrap = node_shader_utils.PrincipledBSDFWrapper(ma, is_readonly=False, use_nodes=True) + ma_wrap.base_color = elem_props_get_color_rgb(fbx_props, b'DiffuseColor', const_color_white) + # No specular color in Principled BSDF shader, assumed to be either white or take some tint from diffuse one... + # TODO: add way to handle tint option (guesstimate from spec color + intensity...)? + ma_wrap.specular = elem_props_get_number(fbx_props, b'SpecularFactor', 0.25) * 2.0 + # XXX Totally empirical conversion, trying to adapt it + # (from 1.0 - 0.0 Principled BSDF range to 0.0 - 100.0 FBX shininess range)... + fbx_shininess = elem_props_get_number(fbx_props, b'Shininess', 20.0) + ma_wrap.roughness = 1.0 - (sqrt(fbx_shininess) / 10.0) + ma_wrap.transmission = 1.0 - elem_props_get_number(fbx_props, b'Opacity', 1.0) + ma_wrap.metallic = elem_props_get_number(fbx_props, b'ReflectionFactor', 0.0) + # We have no metallic (a.k.a. reflection) color... + # elem_props_get_color_rgb(fbx_props, b'ReflectionColor', const_color_white) + # (x / 7.142) is only a guess, cycles usable range is (0.0 -> 0.5) + ma_wrap.normalmap_strength = elem_props_get_number(fbx_props, b'BumpFactor', 2.5) / 7.142 + + nodal_material_wrap_map[ma] = ma_wrap if settings.use_custom_props: blen_read_custom_properties(fbx_obj, ma, settings) @@ -1479,7 +1459,7 @@ def blen_read_light(fbx_tmpl, fbx_obj, global_scale): 1: 'SUN', 2: 'SPOT'}.get(elem_props_get_enum(fbx_props, b'LightType', 0), 'POINT') - lamp = bpy.data.lamps.new(name=elem_name_utf8, type=light_type) + lamp = bpy.data.lights.new(name=elem_name_utf8, type=light_type) if light_type == 'SPOT': spot_size = elem_props_get_number(fbx_props, b'OuterAngle', None) @@ -1494,11 +1474,14 @@ def blen_read_light(fbx_tmpl, fbx_obj, global_scale): spot_blend = elem_props_get_number(fbx_props, b'HotSpot', 45.0) lamp.spot_blend = 1.0 - (spot_blend / spot_size) - # TODO, cycles + # TODO, cycles nodes??? lamp.color = elem_props_get_color_rgb(fbx_props, b'Color', (1.0, 1.0, 1.0)) lamp.energy = elem_props_get_number(fbx_props, b'Intensity', 100.0) / 100.0 lamp.distance = elem_props_get_number(fbx_props, b'DecayStart', 25.0) * global_scale - lamp.shadow_method = ('RAY_SHADOW' if elem_props_get_bool(fbx_props, b'CastShadow', True) else 'NOSHADOW') + lamp.use_shadow = elem_props_get_bool(fbx_props, b'CastShadow', True) + if hasattr(lamp, "cycles"): + lamp.cycles.cast_shadow = lamp.use_shadow + # Keeping this for now, but this is not used nor exposed anymore afaik... lamp.shadow_color = elem_props_get_color_rgb(fbx_props, b'ShadowColor', (0.0, 0.0, 0.0)) return lamp @@ -1612,7 +1595,7 @@ class FbxImportHelperNode: self.pre_matrix = settings.global_matrix if parent_correction_inv: - self.pre_matrix = parent_correction_inv * (self.pre_matrix if self.pre_matrix else Matrix()) + self.pre_matrix = parent_correction_inv @ (self.pre_matrix if self.pre_matrix else Matrix()) correction_matrix = None @@ -1700,12 +1683,12 @@ class FbxImportHelperNode: if self.fbx_type == b'Camera': correction_matrix = MAT_CONVERT_CAMERA elif self.fbx_type == b'Light': - correction_matrix = MAT_CONVERT_LAMP + correction_matrix = MAT_CONVERT_LIGHT self.post_matrix = correction_matrix if self.do_bake_transform(settings): - self.post_matrix = settings.global_matrix_inv * (self.post_matrix if self.post_matrix else Matrix()) + self.post_matrix = settings.global_matrix_inv @ (self.post_matrix if self.post_matrix else Matrix()) # process children correction_matrix_inv = correction_matrix.inverted_safe() if correction_matrix else None @@ -1782,29 +1765,29 @@ class FbxImportHelperNode: def get_world_matrix_as_parent(self): matrix = self.parent.get_world_matrix_as_parent() if self.parent else Matrix() if self.matrix_as_parent: - matrix = matrix * self.matrix_as_parent + matrix = matrix @ self.matrix_as_parent return matrix def get_world_matrix(self): matrix = self.parent.get_world_matrix_as_parent() if self.parent else Matrix() if self.matrix: - matrix = matrix * self.matrix + matrix = matrix @ self.matrix return matrix def get_matrix(self): matrix = self.matrix if self.matrix else Matrix() if self.pre_matrix: - matrix = self.pre_matrix * matrix + matrix = self.pre_matrix @ matrix if self.post_matrix: - matrix = matrix * self.post_matrix + matrix = matrix @ self.post_matrix return matrix def get_bind_matrix(self): matrix = self.bind_matrix if self.bind_matrix else Matrix() if self.pre_matrix: - matrix = self.pre_matrix * matrix + matrix = self.pre_matrix @ matrix if self.post_matrix: - matrix = matrix * self.post_matrix + matrix = matrix @ self.post_matrix return matrix def make_bind_pose_local(self, parent_matrix=None): @@ -1812,13 +1795,13 @@ class FbxImportHelperNode: parent_matrix = Matrix() if self.bind_matrix: - bind_matrix = parent_matrix.inverted_safe() * self.bind_matrix + bind_matrix = parent_matrix.inverted_safe() @ self.bind_matrix else: bind_matrix = self.matrix.copy() if self.matrix else None self.bind_matrix = bind_matrix if bind_matrix: - parent_matrix = parent_matrix * bind_matrix + parent_matrix = parent_matrix @ bind_matrix for child in self.children: child.make_bind_pose_local(parent_matrix) @@ -1838,8 +1821,8 @@ class FbxImportHelperNode: child.collect_skeleton_meshes(meshes) for m in meshes: old_matrix = m.matrix - m.matrix = armature_matrix_inv * m.get_world_matrix() - m.anim_compensation_matrix = old_matrix.inverted_safe() * m.matrix + m.matrix = armature_matrix_inv @ m.get_world_matrix() + m.anim_compensation_matrix = old_matrix.inverted_safe() @ m.matrix m.is_global_animation = True m.parent = self self.meshes = meshes @@ -1914,7 +1897,7 @@ class FbxImportHelperNode: bone.tail = bone_tail # And rotate/move it to its final "rest pose". - bone_matrix = parent_matrix * self.get_bind_matrix().normalized() + bone_matrix = parent_matrix @ self.get_bind_matrix().normalized() bone.matrix = bone_matrix @@ -1927,7 +1910,7 @@ class FbxImportHelperNode: if child.is_leaf and force_connect_children: # Arggggggggggggggggg! We do not want to create this bone, but we need its 'virtual head' location # to orient current one!!! - child_head = (bone_matrix * child.get_bind_matrix().normalized()).translation + child_head = (bone_matrix @ child.get_bind_matrix().normalized()).translation child_connect(bone, None, child_head, connect_ctx) elif child.is_bone and not child.ignore: child_bone = child.build_skeleton(arm, bone_matrix, bone_size, @@ -1958,7 +1941,7 @@ class FbxImportHelperNode: # Misc Attributes obj.color[0:3] = elem_props_get_color_rgb(fbx_props, b'Color', (0.8, 0.8, 0.8)) - obj.hide = not bool(elem_props_get_visibility(fbx_props, b'Visibility', 1.0)) + obj.hide_viewport = not bool(elem_props_get_visibility(fbx_props, b'Visibility', 1.0)) obj.matrix_basis = self.get_matrix() @@ -1967,12 +1950,12 @@ class FbxImportHelperNode: return obj - def build_skeleton_children(self, fbx_tmpl, settings, scene): + def build_skeleton_children(self, fbx_tmpl, settings, scene, view_layer): if self.is_bone: for child in self.children: if child.ignore: continue - child.build_skeleton_children(fbx_tmpl, settings, scene) + child.build_skeleton_children(fbx_tmpl, settings, scene, view_layer) return None else: # child is not a bone @@ -1984,11 +1967,11 @@ class FbxImportHelperNode: for child in self.children: if child.ignore: continue - child.build_skeleton_children(fbx_tmpl, settings, scene) + child.build_skeleton_children(fbx_tmpl, settings, scene, view_layer) # instance in scene - obj_base = scene.objects.link(obj) - obj_base.select = True + view_layer.collections.active.collection.objects.link(obj) + obj.select_set('SELECT') return obj @@ -2007,7 +1990,7 @@ class FbxImportHelperNode: # Blender attaches to the end of a bone, while FBX attaches to the start. # bone_child_matrix corrects for that. if child.pre_matrix: - child.pre_matrix = self.bone_child_matrix * child.pre_matrix + child.pre_matrix = self.bone_child_matrix @ child.pre_matrix else: child.pre_matrix = self.bone_child_matrix @@ -2027,7 +2010,7 @@ class FbxImportHelperNode: def set_pose_matrix(self, arm): pose_bone = arm.bl_obj.pose.bones[self.bl_bone] - pose_bone.matrix_basis = self.get_bind_matrix().inverted_safe() * self.get_matrix() + pose_bone.matrix_basis = self.get_bind_matrix().inverted_safe() @ self.get_matrix() for child in self.children: if child.ignore: @@ -2094,7 +2077,7 @@ class FbxImportHelperNode: if child.is_bone and not child.ignore: child.set_bone_weights() - def build_hierarchy(self, fbx_tmpl, settings, scene): + def build_hierarchy(self, fbx_tmpl, settings, scene, view_layer): if self.is_armature: # create when linking since we need object data elem_name_utf8 = self.fbx_name @@ -2114,15 +2097,15 @@ class FbxImportHelperNode: blen_read_custom_properties(self.fbx_elem, arm, settings) # instance in scene - obj_base = scene.objects.link(arm) - obj_base.select = True + view_layer.collections.active.collection.objects.link(arm) + arm.select_set('SELECT') # Add bones: # Switch to Edit mode. - scene.objects.active = arm - is_hidden = arm.hide - arm.hide = False # Can't switch to Edit mode hidden objects... + view_layer.objects.active = arm + is_hidden = arm.hide_viewport + arm.hide_viewport = False # Can't switch to Edit mode hidden objects... bpy.ops.object.mode_set(mode='EDIT') for child in self.children: @@ -2133,7 +2116,7 @@ class FbxImportHelperNode: bpy.ops.object.mode_set(mode='OBJECT') - arm.hide = is_hidden + arm.hide_viewport = is_hidden # Set pose matrix for child in self.children: @@ -2146,7 +2129,7 @@ class FbxImportHelperNode: for child in self.children: if child.ignore: continue - child_obj = child.build_skeleton_children(fbx_tmpl, settings, scene) + child_obj = child.build_skeleton_children(fbx_tmpl, settings, scene, view_layer) return arm elif self.fbx_elem and not self.is_bone: @@ -2154,16 +2137,16 @@ class FbxImportHelperNode: # walk through children for child in self.children: - child.build_hierarchy(fbx_tmpl, settings, scene) + child.build_hierarchy(fbx_tmpl, settings, scene, view_layer) # instance in scene - obj_base = scene.objects.link(obj) - obj_base.select = True + view_layer.collections.active.collection.objects.link(obj) + obj.select_set('SELECT') return obj else: for child in self.children: - child.build_hierarchy(fbx_tmpl, settings, scene) + child.build_hierarchy(fbx_tmpl, settings, scene, view_layer) return None @@ -2192,16 +2175,16 @@ class FbxImportHelperNode: # which we obviously cannot do in Blender. :/ if amat is None: amat = self.bind_matrix - amat = settings.global_matrix * (Matrix() if amat is None else amat) + amat = settings.global_matrix @ (Matrix() if amat is None else amat) if self.matrix_geom: - amat = amat * self.matrix_geom - mmat = settings.global_matrix * mmat + amat = amat @ self.matrix_geom + mmat = settings.global_matrix @ mmat if mesh.matrix_geom: - mmat = mmat * mesh.matrix_geom + mmat = mmat @ mesh.matrix_geom # Now that we have armature and mesh in there (global) bind 'state' (matrix), # we can compute inverse parenting matrix of the mesh. - me_obj.matrix_parent_inverse = amat.inverted_safe() * mmat * me_obj.matrix_basis.inverted_safe() + me_obj.matrix_parent_inverse = amat.inverted_safe() @ mmat @ me_obj.matrix_basis.inverted_safe() mod = mesh.bl_obj.modifiers.new(arm.name, 'ARMATURE') mod.object = arm @@ -2249,7 +2232,6 @@ def load(operator, context, filepath="", global_scale=1.0, bake_space_transform=False, use_custom_normals=True, - use_cycles=True, use_image_search=False, use_alpha_decals=False, decal_offset=0.0, @@ -2311,10 +2293,8 @@ def load(operator, context, filepath="", basedir = os.path.dirname(filepath) - cycles_material_wrap_map = {} + nodal_material_wrap_map = {} image_cache = {} - if not use_cycles: - texture_cache = {} # Tables: (FBX_byte_id -> [FBX_data, None or Blender_datablock]) fbx_table_nodes = {} @@ -2325,6 +2305,7 @@ def load(operator, context, filepath="", material_decals = None scene = context.scene + view_layer = context.view_layer # #### Get some info from GlobalSettings. @@ -2350,7 +2331,7 @@ def load(operator, context, filepath="", elem_props_get_integer(fbx_settings_props, b'CoordAxisSign', 1)) axis_key = (axis_up, axis_forward, axis_coord) axis_up, axis_forward = {v: k for k, v in RIGHT_HAND_AXES.items()}.get(axis_key, ('Z', 'Y')) - global_matrix = (Matrix.Scale(global_scale, 4) * + global_matrix = (Matrix.Scale(global_scale, 4) @ axis_conversion(from_forward=axis_forward, from_up=axis_up).to_4x4()) # To cancel out unwanted rotation/scale on nodes. @@ -2381,11 +2362,11 @@ def load(operator, context, filepath="", settings = FBXImportSettings( operator.report, (axis_up, axis_forward), global_matrix, global_scale, bake_space_transform, global_matrix_inv, global_matrix_inv_transposed, - use_custom_normals, use_cycles, use_image_search, + use_custom_normals, use_image_search, use_alpha_decals, decal_offset, use_anim, anim_offset, use_custom_props, use_custom_props_enum_as_string, - cycles_material_wrap_map, image_cache, + nodal_material_wrap_map, image_cache, ignore_leaf_bones, force_connect_children, automatic_bone_orientation, bone_correction_matrix, use_prepost_rot, ) @@ -2682,7 +2663,7 @@ def load(operator, context, filepath="", armature_matrix = tx_arm if tx_bone: - mesh_matrix = tx_bone * mesh_matrix + mesh_matrix = tx_bone @ mesh_matrix helper_node.bind_matrix = tx_bone # overwrite the bind matrix # Get the meshes driven by this cluster: (Shouldn't that be only one?) @@ -2725,7 +2706,7 @@ def load(operator, context, filepath="", root_helper.find_correction_matrix(settings) # build the Object/Armature/Bone hierarchy - root_helper.build_hierarchy(fbx_tmpl, settings, scene) + root_helper.build_hierarchy(fbx_tmpl, settings, scene, view_layer) # Link the Object/Armature/Bone hierarchy root_helper.link_hierarchy(fbx_tmpl, settings, scene) @@ -2857,8 +2838,7 @@ def load(operator, context, filepath="", continue mat = fbx_item[1] items.append((mat, lnk_prop)) - if settings.use_cycles: - print("WARNING! Importing material's animation is not supported for Cycles materials...") + print("WARNING! Importing material's animation is not supported for Nodal materials...") for al_uuid, al_ctype in fbx_connection_map.get(acn_uuid, ()): if al_ctype.props[0] != b'OO': continue @@ -2919,17 +2899,17 @@ def load(operator, context, filepath="", # So we have to be careful not to re-add endlessly the same material to a mesh! # This can easily happen with 'baked' dupliobjects, see T44386. # TODO: add an option to link materials to objects in Blender instead? - done_mats = set() + done_materials = set() for (fbx_lnk, fbx_lnk_item, fbx_lnk_type) in connection_filter_forward(fbx_uuid, b'Model'): # link materials fbx_lnk_uuid = elem_uuid(fbx_lnk) for (fbx_lnk_material, material, fbx_lnk_material_type) in connection_filter_reverse(fbx_lnk_uuid, b'Material'): - if material not in done_mats: + if material not in done_materials: mesh.materials.append(material) - done_mats.add(material) + done_materials.add(material) - # We have to validate mesh polygons' mat_idx, see T41015! + # We have to validate mesh polygons' ma_idx, see T41015! # Some FBX seem to have an extra 'default' material which is not defined in FBX file. if mesh.validate_material_indices(): print("WARNING: mesh '%s' had invalid material indices, those were reset to first material" % mesh.name) @@ -2943,51 +2923,36 @@ def load(operator, context, filepath="", fbx_tmpl = fbx_template_get((b'Material', b'KFbxSurfacePhong')) # b'KFbxSurfaceLambert' - # textures that use this material - def texture_bumpfac_get(fbx_obj): - assert(fbx_obj.id == b'Material') - fbx_props = (elem_find_first(fbx_obj, b'Properties70'), - elem_find_first(fbx_tmpl, b'Properties70', fbx_elem_nil)) - # (x / 7.142) is only a guess, cycles usable range is (0.0 -> 0.5) - return elem_props_get_number(fbx_props, b'BumpFactor', 2.5) / 7.142 - - def texture_mapping_get(fbx_obj): + def texture_mapping_set(fbx_obj, node_texture): assert(fbx_obj.id == b'Texture') fbx_props = (elem_find_first(fbx_obj, b'Properties70'), elem_find_first(fbx_tmpl, b'Properties70', fbx_elem_nil)) - return (elem_props_get_vector_3d(fbx_props, b'Translation', (0.0, 0.0, 0.0)), - elem_props_get_vector_3d(fbx_props, b'Rotation', (0.0, 0.0, 0.0)), - elem_props_get_vector_3d(fbx_props, b'Scaling', (1.0, 1.0, 1.0)), - (bool(elem_props_get_enum(fbx_props, b'WrapModeU', 0)), - bool(elem_props_get_enum(fbx_props, b'WrapModeV', 0)))) - - if not use_cycles: - # Simple function to make a new mtex and set defaults - def material_mtex_new(material, image, tex_map): - tex = texture_cache.get(image) - if tex is None: - tex = bpy.data.textures.new(name=image.name, type='IMAGE') - tex.image = image - texture_cache[image] = tex - - # copy custom properties from image object to texture - for key, value in image.items(): - tex[key] = value - - # delete custom properties on the image object - for key in image.keys(): - del image[key] - - mtex = material.texture_slots.add() - mtex.texture = tex - mtex.texture_coords = 'UV' - mtex.use_map_color_diffuse = False - - # No rotation here... - mtex.offset[:] = tex_map[0] - mtex.scale[:] = tex_map[2] - return mtex + loc = elem_props_get_vector_3d(fbx_props, b'Translation', (0.0, 0.0, 0.0)) + rot = tuple(-r for r in elem_props_get_vector_3d(fbx_props, b'Rotation', (0.0, 0.0, 0.0))) + scale = tuple(((1.0 / s) if s != 0.0 else 1.0) + for s in elem_props_get_vector_3d(fbx_props, b'Scaling', (1.0, 1.0, 1.0))) + clamp_uv = (bool(elem_props_get_enum(fbx_props, b'WrapModeU', 0)), + bool(elem_props_get_enum(fbx_props, b'WrapModeV', 0))) + + if (loc == (0.0, 0.0, 0.0) and + rot == (0.0, 0.0, 0.0) and + scale == (1.0, 1.0, 1.0) and + clamp_uv == (False, False)): + return + + node_texture.translation = loc + node_texture.rotation = rot + node_texture.scale = scale + + # awkward conversion UV clamping to min/max + node_texture.min = (0.0, 0.0, 0.0) + node_texture.max = (1.0, 1.0, 1.0) + node_texture.use_min = node_texture.use_max = clamp_uv[0] or clamp_uv[1] + if clamp_uv[0] != clamp_uv[1]: + # use bool as index + node_texture.min[not clamp[0]] = -1e9 + node_texture.max[not clamp[0]] = 1e9 for fbx_uuid, fbx_item in fbx_table_nodes.items(): fbx_obj, blen_data = fbx_item @@ -2999,112 +2964,44 @@ def load(operator, context, filepath="", image, fbx_lnk_type) in connection_filter_reverse(fbx_uuid, b'Texture'): - if use_cycles: - if fbx_lnk_type.props[0] == b'OP': - lnk_type = fbx_lnk_type.props[3] - - ma_wrap = cycles_material_wrap_map[material] - - # tx/rot/scale - tex_map = texture_mapping_get(fbx_lnk) - if (tex_map[0] == (0.0, 0.0, 0.0) and - tex_map[1] == (0.0, 0.0, 0.0) and - tex_map[2] == (1.0, 1.0, 1.0) and - tex_map[3] == (False, False)): - use_mapping = False - else: - use_mapping = True - tex_map_kw = { - "translation": tex_map[0], - "rotation": [-i for i in tex_map[1]], - "scale": [((1.0 / i) if i != 0.0 else 1.0) for i in tex_map[2]], - "clamp": tex_map[3], - } - - if lnk_type in {b'DiffuseColor', b'3dsMax|maps|texmap_diffuse'}: - ma_wrap.diffuse_image_set(image) - if use_mapping: - ma_wrap.diffuse_mapping_set(**tex_map_kw) - elif lnk_type == b'SpecularColor': - ma_wrap.specular_image_set(image) - if use_mapping: - ma_wrap.specular_mapping_set(**tex_map_kw) - elif lnk_type in {b'ReflectionColor', b'3dsMax|maps|texmap_reflection'}: - ma_wrap.reflect_image_set(image) - if use_mapping: - ma_wrap.reflect_mapping_set(**tex_map_kw) - elif lnk_type == b'TransparentColor': # alpha - ma_wrap.alpha_image_set(image) - if use_mapping: - ma_wrap.alpha_mapping_set(**tex_map_kw) - if use_alpha_decals: - material_decals.add(material) - elif lnk_type == b'DiffuseFactor': - pass # TODO - elif lnk_type == b'ShininessExponent': - ma_wrap.hardness_image_set(image) - if use_mapping: - ma_wrap.hardness_mapping_set(**tex_map_kw) - # XXX, applications abuse bump! - elif lnk_type in {b'NormalMap', b'Bump', b'3dsMax|maps|texmap_bump'}: - ma_wrap.normal_image_set(image) - ma_wrap.normal_factor_set(texture_bumpfac_get(fbx_obj)) - if use_mapping: - ma_wrap.normal_mapping_set(**tex_map_kw) - """ - elif lnk_type == b'Bump': - ma_wrap.bump_image_set(image) - ma_wrap.bump_factor_set(texture_bumpfac_get(fbx_obj)) - if use_mapping: - ma_wrap.bump_mapping_set(**tex_map_kw) - """ - else: - print("WARNING: material link %r ignored" % lnk_type) - - material_images.setdefault(material, {})[lnk_type] = (image, tex_map) - else: - if fbx_lnk_type.props[0] == b'OP': - lnk_type = fbx_lnk_type.props[3] - - # tx/rot/scale (rot is ignored here!). - tex_map = texture_mapping_get(fbx_lnk) - - mtex = material_mtex_new(material, image, tex_map) - - if lnk_type in {b'DiffuseColor', b'3dsMax|maps|texmap_diffuse'}: - mtex.use_map_color_diffuse = True - mtex.blend_type = 'MULTIPLY' - elif lnk_type == b'SpecularColor': - mtex.use_map_color_spec = True - mtex.blend_type = 'MULTIPLY' - elif lnk_type in {b'ReflectionColor', b'3dsMax|maps|texmap_reflection'}: - mtex.use_map_raymir = True - elif lnk_type == b'TransparentColor': # alpha - material.use_transparency = True - material.transparency_method = 'RAYTRACE' - material.alpha = 0.0 - mtex.use_map_alpha = True - mtex.alpha_factor = 1.0 - if use_alpha_decals: - material_decals.add(material) - elif lnk_type == b'DiffuseFactor': - mtex.use_map_diffuse = True - elif lnk_type == b'ShininessExponent': - mtex.use_map_hardness = True - # XXX, applications abuse bump! - elif lnk_type in {b'NormalMap', b'Bump', b'3dsMax|maps|texmap_bump'}: - mtex.texture.use_normal_map = True # not ideal! - mtex.use_map_normal = True - mtex.normal_factor = texture_bumpfac_get(fbx_obj) - """ - elif lnk_type == b'Bump': - mtex.use_map_normal = True - mtex.normal_factor = texture_bumpfac_get(fbx_obj) - """ - else: - print("WARNING: material link %r ignored" % lnk_type) + if fbx_lnk_type.props[0] == b'OP': + lnk_type = fbx_lnk_type.props[3] + + ma_wrap = nodal_material_wrap_map[material] + + if lnk_type in {b'DiffuseColor', b'3dsMax|maps|texmap_diffuse'}: + ma_wrap.base_color_texture.image = image + texture_mapping_set(fbx_lnk, ma_wrap.base_color_texture) + elif lnk_type in {b'SpecularColor', b'SpecularFactor'}: + # Intensity actually, not color... + ma_wrap.specular_texture.image = image + texture_mapping_set(fbx_lnk, ma_wrap.specular_texture) + elif lnk_type in {b'ReflectionColor', b'ReflectionFactor', b'3dsMax|maps|texmap_reflection'}: + # Intensity actually, not color... + ma_wrap.metallic_texture.image = image + texture_mapping_set(fbx_lnk, ma_wrap.metallic_texture) + elif lnk_type in {b'TransparentColor', b'TransparentFactor'}: + # Transparency... sort of... + ma_wrap.transmission_texture.image = image + texture_mapping_set(fbx_lnk, ma_wrap.transmission_texture) + if use_alpha_decals: + material_decals.add(material) + elif lnk_type == b'ShininessExponent': + # That is probably reversed compared to expected results? TODO... + ma_wrap.roughness_texture.image = image + texture_mapping_set(fbx_lnk, ma_wrap.roughness_texture) + # XXX, applications abuse bump! + elif lnk_type in {b'NormalMap', b'Bump', b'3dsMax|maps|texmap_bump'}: + ma_wrap.normalmap_texture.image = image + texture_mapping_set(fbx_lnk, ma_wrap.normalmap_texture) + """ + elif lnk_type == b'Bump': + # TODO displacement... + """ + else: + print("WARNING: material link %r ignored" % lnk_type) - material_images.setdefault(material, {})[lnk_type] = (image, tex_map) + material_images.setdefault(material, {})[lnk_type] = image # Check if the diffuse image has an alpha channel, # if so, use the alpha channel. @@ -3115,30 +3012,21 @@ def load(operator, context, filepath="", if fbx_obj.id != b'Material': continue material = fbx_table_nodes.get(fbx_uuid, (None, None))[1] - image, tex_map = material_images.get(material, {}).get(b'DiffuseColor', (None, None)) + image = material_images.get(material, {}).get(b'DiffuseColor', None) # do we have alpha? if image and image.depth == 32: if use_alpha_decals: material_decals.add(material) - if use_cycles: - ma_wrap = cycles_material_wrap_map[material] - if ma_wrap.node_bsdf_alpha.mute: - ma_wrap.alpha_image_set_from_diffuse() - else: - if not any((True for mtex in material.texture_slots if mtex and mtex.use_map_alpha)): - mtex = material_mtex_new(material, image, tex_map) + ma_wrap = nodal_material_wrap_map[material] + ma_wrap.transmission_texture.use_alpha = True + ma_wrap.transmission_texture.copy_from(ma_wrap.base_color_texture) - material.use_transparency = True - material.transparency_method = 'RAYTRACE' - material.alpha = 0.0 - mtex.use_map_alpha = True - mtex.alpha_factor = 1.0 - - # propagate mapping from diffuse to all other channels which have none defined. - if use_cycles: - ma_wrap = cycles_material_wrap_map[material] - ma_wrap.mapping_set_from_diffuse() + # Propagate mapping from diffuse to all other channels which have none defined. + # XXX Commenting for now, I do not really understand the logic here, why should diffuse mapping + # be applied to all others if not defined for them??? + # ~ ma_wrap = nodal_material_wrap_map[material] + # ~ ma_wrap.mapping_set_from_diffuse() _(); del _ @@ -3161,14 +3049,8 @@ def load(operator, context, filepath="", v.co += v.normal * decal_offset break - if use_cycles: - for obj in (obj for obj in bpy.data.objects if obj.data == mesh): - obj.cycles_visibility.shadow = False - else: - for material in mesh.materials: - if material in material_decals: - # receive but dont cast shadows - material.use_raytrace = False + for obj in (obj for obj in bpy.data.objects if obj.data == mesh): + obj.cycles_visibility.shadow = False _(); del _ perfmon.level_down() diff --git a/io_scene_ms3d/__init__.py b/io_scene_ms3d/__init__.py index 794aae6b..805b1d83 100644 --- a/io_scene_ms3d/__init__.py +++ b/io_scene_ms3d/__init__.py @@ -64,8 +64,8 @@ from bpy.utils import ( unregister_module, ) from bpy.types import ( - INFO_MT_file_export, - INFO_MT_file_import, + TOPBAR_MT_file_export, + TOPBAR_MT_file_import, ) @@ -82,16 +82,16 @@ def register(): ms3d_ui.register() register_module(__name__) - INFO_MT_file_export.append(Ms3dExportOperator.menu_func) - INFO_MT_file_import.append(Ms3dImportOperator.menu_func) + TOPBAR_MT_file_export.append(Ms3dExportOperator.menu_func) + TOPBAR_MT_file_import.append(Ms3dImportOperator.menu_func) def unregister(): ms3d_ui.unregister() unregister_module(__name__) - INFO_MT_file_export.remove(Ms3dExportOperator.menu_func) - INFO_MT_file_import.remove(Ms3dImportOperator.menu_func) + TOPBAR_MT_file_export.remove(Ms3dExportOperator.menu_func) + TOPBAR_MT_file_import.remove(Ms3dImportOperator.menu_func) ############################################################################### diff --git a/io_scene_ms3d/ms3d_import.py b/io_scene_ms3d/ms3d_import.py index a2205556..9a6fb42f 100644 --- a/io_scene_ms3d/ms3d_import.py +++ b/io_scene_ms3d/ms3d_import.py @@ -690,14 +690,14 @@ class Ms3dImporter(): blender_armature = blender_context.blend_data.armatures.new( ms3d_armature_name) blender_armature.ms3d.name = ms3d_model.name - blender_armature.draw_type = 'STICK' + blender_armature.display_type = 'STICK' blender_armature.show_axes = True blender_armature.use_auto_ik = True blender_armature_object = blender_context.blend_data.objects.new( ms3d_armature_object_name, blender_armature) blender_scene.objects.link(blender_armature_object) #blender_armature_object.location = blender_scene.cursor_location - blender_armature_object.show_x_ray = True + blender_armature_object.show_in_front = True ########################## # create new modifier diff --git a/io_scene_ms3d/ms3d_ui.py b/io_scene_ms3d/ms3d_ui.py index e7b1dfc4..c483df8a 100644 --- a/io_scene_ms3d/ms3d_ui.py +++ b/io_scene_ms3d/ms3d_ui.py @@ -210,7 +210,7 @@ class Ms3dUi: return ms3d_value ########################################################################### - ICON_OPTIONS = 'LAMP' + ICON_OPTIONS = 'LIGHT' ICON_OBJECT = 'WORLD' ICON_PROCESSING = 'OBJECT_DATAMODE' ICON_MODIFIER = 'MODIFIER' diff --git a/io_scene_obj/__init__.py b/io_scene_obj/__init__.py index 3bebdecd..e3d3d830 100644 --- a/io_scene_obj/__init__.py +++ b/io_scene_obj/__init__.py @@ -21,8 +21,8 @@ bl_info = { "name": "Wavefront OBJ format", "author": "Campbell Barton, Bastien Montagne", - "version": (2, 3, 7), - "blender": (2, 78, 0), + "version": (3, 4, 3), + "blender": (2, 80, 0), "location": "File > Import-Export", "description": "Import-Export OBJ, Import OBJ mesh, UV's, materials and textures", "warning": "", @@ -48,70 +48,68 @@ from bpy.props import ( from bpy_extras.io_utils import ( ImportHelper, ExportHelper, - orientation_helper_factory, + orientation_helper, path_reference_mode, axis_conversion, ) -IOOBJOrientationHelper = orientation_helper_factory("IOOBJOrientationHelper", axis_forward='-Z', axis_up='Y') - - -class ImportOBJ(bpy.types.Operator, ImportHelper, IOOBJOrientationHelper): +@orientation_helper(axis_forward='-Z', axis_up='Y') +class ImportOBJ(bpy.types.Operator, ImportHelper): """Load a Wavefront OBJ File""" bl_idname = "import_scene.obj" bl_label = "Import OBJ" bl_options = {'PRESET', 'UNDO'} filename_ext = ".obj" - filter_glob = StringProperty( + filter_glob: StringProperty( default="*.obj;*.mtl", options={'HIDDEN'}, ) - use_edges = BoolProperty( + use_edges: BoolProperty( name="Lines", description="Import lines and faces with 2 verts as edge", default=True, ) - use_smooth_groups = BoolProperty( + use_smooth_groups: BoolProperty( name="Smooth Groups", description="Surround smooth groups by sharp edges", default=True, ) - use_split_objects = BoolProperty( + use_split_objects: BoolProperty( name="Object", description="Import OBJ Objects into Blender Objects", default=True, ) - use_split_groups = BoolProperty( + use_split_groups: BoolProperty( name="Group", description="Import OBJ Groups into Blender Objects", default=True, ) - use_groups_as_vgroups = BoolProperty( + use_groups_as_vgroups: BoolProperty( name="Poly Groups", description="Import OBJ groups as vertex groups", default=False, ) - use_image_search = BoolProperty( + use_image_search: BoolProperty( name="Image Search", description="Search subdirs for any associated images " "(Warning, may be slow)", default=True, ) - split_mode = EnumProperty( + split_mode: EnumProperty( name="Split", items=(('ON', "Split", "Split geometry, omits unused verts"), ('OFF', "Keep Vert Order", "Keep vertex order from file"), ), ) - global_clamp_size = FloatProperty( + global_clight_size: FloatProperty( name="Clamp Size", description="Clamp bounds under this value (zero to disable)", min=0.0, max=1000.0, @@ -139,7 +137,6 @@ class ImportOBJ(bpy.types.Operator, ImportHelper, IOOBJOrientationHelper): from_up=self.axis_up, ).to_4x4() keywords["global_matrix"] = global_matrix - keywords["use_cycles"] = (context.scene.render.engine == 'CYCLES') if bpy.data.is_saved and context.user_preferences.filepaths.use_relative_paths: import os @@ -166,15 +163,16 @@ class ImportOBJ(bpy.types.Operator, ImportHelper, IOOBJOrientationHelper): else: row.prop(self, "use_groups_as_vgroups") - row = layout.split(percentage=0.67) - row.prop(self, "global_clamp_size") + row = layout.split(factor=0.67) + row.prop(self, "global_clight_size") layout.prop(self, "axis_forward") layout.prop(self, "axis_up") layout.prop(self, "use_image_search") -class ExportOBJ(bpy.types.Operator, ExportHelper, IOOBJOrientationHelper): +@orientation_helper(axis_forward='-Z', axis_up='Y') +class ExportOBJ(bpy.types.Operator, ExportHelper): """Save a Wavefront OBJ File""" bl_idname = "export_scene.obj" @@ -182,113 +180,113 @@ class ExportOBJ(bpy.types.Operator, ExportHelper, IOOBJOrientationHelper): bl_options = {'PRESET'} filename_ext = ".obj" - filter_glob = StringProperty( + filter_glob: StringProperty( default="*.obj;*.mtl", options={'HIDDEN'}, ) # context group - use_selection = BoolProperty( + use_selection: BoolProperty( name="Selection Only", description="Export selected objects only", default=False, ) - use_animation = BoolProperty( + use_animation: BoolProperty( name="Animation", description="Write out an OBJ for each frame", default=False, ) # object group - use_mesh_modifiers = BoolProperty( + use_mesh_modifiers: BoolProperty( name="Apply Modifiers", description="Apply modifiers", default=True, ) - use_mesh_modifiers_render = BoolProperty( + use_mesh_modifiers_render: BoolProperty( name="Use Modifiers Render Settings", description="Use render settings when applying modifiers to mesh objects", default=False, ) # extra data group - use_edges = BoolProperty( + use_edges: BoolProperty( name="Include Edges", description="", default=True, ) - use_smooth_groups = BoolProperty( + use_smooth_groups: BoolProperty( name="Smooth Groups", description="Write sharp edges as smooth groups", default=False, ) - use_smooth_groups_bitflags = BoolProperty( + use_smooth_groups_bitflags: BoolProperty( name="Bitflag Smooth Groups", description="Same as 'Smooth Groups', but generate smooth groups IDs as bitflags " "(produces at most 32 different smooth groups, usually much less)", default=False, ) - use_normals = BoolProperty( + use_normals: BoolProperty( name="Write Normals", description="Export one normal per vertex and per face, to represent flat faces and sharp edges", default=True, ) - use_uvs = BoolProperty( + use_uvs: BoolProperty( name="Include UVs", description="Write out the active UV coordinates", default=True, ) - use_materials = BoolProperty( + use_materials: BoolProperty( name="Write Materials", description="Write out the MTL file", default=True, ) - use_triangles = BoolProperty( + use_triangles: BoolProperty( name="Triangulate Faces", description="Convert all faces to triangles", default=False, ) - use_nurbs = BoolProperty( + use_nurbs: BoolProperty( name="Write Nurbs", description="Write nurbs curves as OBJ nurbs rather than " "converting to geometry", default=False, ) - use_vertex_groups = BoolProperty( + use_vertex_groups: BoolProperty( name="Polygroups", description="", default=False, ) # grouping group - use_blen_objects = BoolProperty( + use_blen_objects: BoolProperty( name="Objects as OBJ Objects", description="", default=True, ) - group_by_object = BoolProperty( + group_by_object: BoolProperty( name="Objects as OBJ Groups ", description="", default=False, ) - group_by_material = BoolProperty( + group_by_material: BoolProperty( name="Material Groups", description="", default=False, ) - keep_vertex_order = BoolProperty( + keep_vertex_order: BoolProperty( name="Keep Vertex Order", description="", default=False, ) - global_scale = FloatProperty( + global_scale: FloatProperty( name="Scale", min=0.01, max=1000.0, default=1.0, ) - path_mode = path_reference_mode + path_mode: path_reference_mode check_extension = True @@ -303,7 +301,7 @@ class ExportOBJ(bpy.types.Operator, ExportHelper, IOOBJOrientationHelper): "filter_glob", )) - global_matrix = (Matrix.Scale(self.global_scale, 4) * + global_matrix = (Matrix.Scale(self.global_scale, 4) @ axis_conversion(to_forward=self.axis_forward, to_up=self.axis_up, ).to_4x4()) @@ -330,13 +328,13 @@ def register(): for cls in classes: bpy.utils.register_class(cls) - bpy.types.INFO_MT_file_import.append(menu_func_import) - bpy.types.INFO_MT_file_export.append(menu_func_export) + bpy.types.TOPBAR_MT_file_import.append(menu_func_import) + bpy.types.TOPBAR_MT_file_export.append(menu_func_export) def unregister(): - bpy.types.INFO_MT_file_import.remove(menu_func_import) - bpy.types.INFO_MT_file_export.remove(menu_func_export) + bpy.types.TOPBAR_MT_file_import.remove(menu_func_import) + bpy.types.TOPBAR_MT_file_export.remove(menu_func_export) for cls in classes: bpy.utils.unregister_class(cls) diff --git a/io_scene_obj/export_obj.py b/io_scene_obj/export_obj.py index acdcbc6c..22a82234 100644 --- a/io_scene_obj/export_obj.py +++ b/io_scene_obj/export_obj.py @@ -21,8 +21,8 @@ import os import bpy -import mathutils -import bpy_extras.io_utils +from mathutils import Matrix, Vector, Color +from bpy_extras import io_utils, node_shader_utils from progress_report import ProgressReport, ProgressReportSubstep @@ -44,13 +44,8 @@ def mesh_triangulate(me): def write_mtl(scene, filepath, path_mode, copy_set, mtl_dict): - from mathutils import Color, Vector - world = scene.world - if world: - world_amb = world.ambient_color - else: - world_amb = Color((0.0, 0.0, 0.0)) + world_amb = Color((0.8, 0.8, 0.8)) source_dir = os.path.dirname(bpy.data.filepath) dest_dir = os.path.dirname(filepath) @@ -66,133 +61,100 @@ def write_mtl(scene, filepath, path_mode, copy_set, mtl_dict): # Write material/image combinations we have used. # Using mtl_dict.values() directly gives un-predictable order. - for mtl_mat_name, mat, face_img in mtl_dict_values: + for mtl_mat_name, mat in mtl_dict_values: # Get the Blender data for the material and the image. # Having an image named None will make a bug, dont do it :) fw('\nnewmtl %s\n' % mtl_mat_name) # Define a new material: matname_imgname - if mat: - use_mirror = mat.raytrace_mirror.use and mat.raytrace_mirror.reflect_factor != 0.0 + mat_wrap = node_shader_utils.PrincipledBSDFWrapper(mat) if mat else None - # convert from blenders spec to 0 - 1000 range. - if mat.specular_shader == 'WARDISO': - tspec = (0.4 - mat.specular_slope) / 0.0004 - else: - tspec = (mat.specular_hardness - 1) / 0.51 - fw('Ns %.6f\n' % tspec) - del tspec + if mat_wrap: + use_mirror = mat_wrap.metallic != 0.0 + use_transparency = mat_wrap.transmission != 0.0 + + # XXX Totally empirical conversion, trying to adapt it + # (from 1.0 - 0.0 Principled BSDF range to 0.0 - 900.0 OBJ specular exponent range)... + spec = (1.0 - mat_wrap.roughness) * 30 + spec *= spec + fw('Ns %.6f\n' % spec) # Ambient if use_mirror: - fw('Ka %.6f %.6f %.6f\n' % (mat.raytrace_mirror.reflect_factor * mat.mirror_color)[:]) + fw('Ka %.6f %.6f %.6f\n' % (mat_wrap.metallic, mat_wrap.metallic, mat_wrap.metallic)) else: - fw('Ka %.6f %.6f %.6f\n' % (mat.ambient, mat.ambient, mat.ambient)) # Do not use world color! - fw('Kd %.6f %.6f %.6f\n' % (mat.diffuse_intensity * mat.diffuse_color)[:]) # Diffuse - fw('Ks %.6f %.6f %.6f\n' % (mat.specular_intensity * mat.specular_color)[:]) # Specular + fw('Ka %.6f %.6f %.6f\n' % (1.0, 1.0, 1.0)) + fw('Kd %.6f %.6f %.6f\n' % mat_wrap.base_color[:3]) # Diffuse + # XXX TODO Find a way to handle tint and diffuse color, in a consistent way with import... + fw('Ks %.6f %.6f %.6f\n' % (mat_wrap.specular, mat_wrap.specular, mat_wrap.specular)) # Specular # Emission, not in original MTL standard but seems pretty common, see T45766. - # XXX Blender has no color emission, it's using diffuse color instead... - fw('Ke %.6f %.6f %.6f\n' % (mat.emit * mat.diffuse_color)[:]) - if hasattr(mat, "raytrace_transparency") and hasattr(mat.raytrace_transparency, "ior"): - fw('Ni %.6f\n' % mat.raytrace_transparency.ior) # Refraction index - else: - fw('Ni %.6f\n' % 1.0) - fw('d %.6f\n' % mat.alpha) # Alpha (obj uses 'd' for dissolve) + # XXX Not supported by current Principled-based shader. + fw('Ke 0.0 0.0 0.0\n') + fw('Ni %.6f\n' % mat_wrap.ior) # Refraction index + fw('d %.6f\n' % (1.0 - mat_wrap.transmission)) # Alpha (obj uses 'd' for dissolve) # See http://en.wikipedia.org/wiki/Wavefront_.obj_file for whole list of values... # Note that mapping is rather fuzzy sometimes, trying to do our best here. - if mat.use_shadeless: - fw('illum 0\n') # ignore lighting - elif mat.specular_intensity == 0: + if mat_wrap.specular == 0: fw('illum 1\n') # no specular. elif use_mirror: - if mat.use_transparency and mat.transparency_method == 'RAYTRACE': - if mat.raytrace_mirror.fresnel != 0.0: - fw('illum 7\n') # Reflection, Transparency, Ray trace and Fresnel - else: - fw('illum 6\n') # Reflection, Transparency, Ray trace - elif mat.raytrace_mirror.fresnel != 0.0: - fw('illum 5\n') # Reflection, Ray trace and Fresnel + if use_transparency: + fw('illum 6\n') # Reflection, Transparency, Ray trace else: fw('illum 3\n') # Reflection and Ray trace - elif mat.use_transparency and mat.transparency_method == 'RAYTRACE': + elif use_transparency: fw('illum 9\n') # 'Glass' transparency and no Ray trace reflection... fuzzy matching, but... else: fw('illum 2\n') # light normally - else: - # Write a dummy material here? - fw('Ns 0\n') - fw('Ka %.6f %.6f %.6f\n' % world_amb[:]) # Ambient, uses mirror color, - fw('Kd 0.8 0.8 0.8\n') - fw('Ks 0.8 0.8 0.8\n') - fw('d 1\n') # No alpha - fw('illum 2\n') # light normally - - # Write images! - if face_img: # We have an image on the face! - filepath = face_img.filepath - if filepath: # may be '' for generated images - # write relative image path - filepath = bpy_extras.io_utils.path_reference(filepath, source_dir, dest_dir, - path_mode, "", copy_set, face_img.library) - fw('map_Kd %s\n' % filepath) # Diffuse mapping image - del filepath - else: - # so we write the materials image. - face_img = None - - if mat: # No face image. if we havea material search for MTex image. - image_map = {} - # backwards so topmost are highest priority - for mtex in reversed(mat.texture_slots): - if mtex and mtex.texture and mtex.texture.type == 'IMAGE': - image = mtex.texture.image - if image: - # texface overrides others - if (mtex.use_map_color_diffuse and (face_img is None) and - (mtex.use_map_warp is False) and (mtex.texture_coords != 'REFLECTION')): - image_map["map_Kd"] = (mtex, image) - if mtex.use_map_ambient: - image_map["map_Ka"] = (mtex, image) - # this is the Spec intensity channel but Ks stands for specular Color - ''' - if mtex.use_map_specular: - image_map["map_Ks"] = (mtex, image) - ''' - if mtex.use_map_color_spec: # specular color - image_map["map_Ks"] = (mtex, image) - if mtex.use_map_hardness: # specular hardness/glossiness - image_map["map_Ns"] = (mtex, image) - if mtex.use_map_alpha: - image_map["map_d"] = (mtex, image) - if mtex.use_map_translucency: - image_map["map_Tr"] = (mtex, image) - if mtex.use_map_normal: - image_map["map_Bump"] = (mtex, image) - if mtex.use_map_displacement: - image_map["disp"] = (mtex, image) - if mtex.use_map_color_diffuse and (mtex.texture_coords == 'REFLECTION'): - image_map["refl"] = (mtex, image) - if mtex.use_map_emit: - image_map["map_Ke"] = (mtex, image) - - for key, (mtex, image) in sorted(image_map.items()): - filepath = bpy_extras.io_utils.path_reference(image.filepath, source_dir, dest_dir, - path_mode, "", copy_set, image.library) + #### And now, the image textures... + image_map = { + "map_Kd": "base_color_texture", + "map_Ka": None, # ambient... + "map_Ks": "specular_texture", + "map_Ns": "roughness_texture", + "map_d": "transmission_texture", + "map_Tr": None, # transmission roughness? + "map_Bump": "normalmap_texture", + "disp": None, # displacement... + "refl": "metallic_texture", + "map_Ke": None # emission... + } + + for key, mat_wrap_key in sorted(image_map.items()): + if mat_wrap_key is None: + continue + tex_wrap = getattr(mat_wrap, mat_wrap_key, None) + if tex_wrap is None: + continue + image = tex_wrap.image + if image is None: + continue + + filepath = io_utils.path_reference(image.filepath, source_dir, dest_dir, + path_mode, "", copy_set, image.library) options = [] if key == "map_Bump": - if mtex.normal_factor != 1.0: - options.append('-bm %.6f' % mtex.normal_factor) - if mtex.offset != Vector((0.0, 0.0, 0.0)): - options.append('-o %.6f %.6f %.6f' % mtex.offset[:]) - if mtex.scale != Vector((1.0, 1.0, 1.0)): - options.append('-s %.6f %.6f %.6f' % mtex.scale[:]) + if mat_wrap.normalmap_strengh != 1.0: + options.append('-bm %.6f' % mat_wrap.normalmap_strengh) + if tex_wrap.translation != Vector((0.0, 0.0, 0.0)): + options.append('-o %.6f %.6f %.6f' % tex_wrap.translation[:]) + if tex_wrap.scale != Vector((1.0, 1.0, 1.0)): + options.append('-s %.6f %.6f %.6f' % tex_wrap.scale[:]) if options: fw('%s %s %s\n' % (key, " ".join(options), repr(filepath)[1:-1])) else: fw('%s %s\n' % (key, repr(filepath)[1:-1])) + else: + # Write a dummy material here? + fw('Ns 500\n') + fw('Ka 0.8 0.8 0.8\n') + fw('Kd 0.8 0.8 0.8\n') + fw('Ks 0.8 0.8 0.8\n') + fw('d 1\n') # No alpha + fw('illum 2\n') # light normally + def test_nurbs_compat(ob): if ob.type != 'CURVE': @@ -233,7 +195,7 @@ def write_nurb(fw, ob, ob_mat): do_endpoints = (do_closed == 0) and nu.use_endpoint_u for pt in nu.points: - fw('v %.6f %.6f %.6f\n' % (ob_mat * pt.co.to_3d())[:]) + fw('v %.6f %.6f %.6f\n' % (ob_mat @ pt.co.to_3d())[:]) pt_num += 1 tot_verts += pt_num @@ -271,7 +233,7 @@ def write_nurb(fw, ob, ob_mat): return tot_verts -def write_file(filepath, objects, scene, +def write_file(filepath, objects, depsgraph, scene, EXPORT_TRI=False, EXPORT_EDGES=False, EXPORT_SMOOTH_GROUPS=False, @@ -298,7 +260,7 @@ def write_file(filepath, objects, scene, write( 'c:\\test\\foobar.obj', Blender.Object.GetSelected() ) # Using default options. """ if EXPORT_GLOBAL_MATRIX is None: - EXPORT_GLOBAL_MATRIX = mathutils.Matrix() + EXPORT_GLOBAL_MATRIX = Matrix() def veckey3d(v): return round(v.x, 4), round(v.y, 4), round(v.z, 4) @@ -382,14 +344,13 @@ def write_file(filepath, objects, scene, # Nurbs curve support if EXPORT_CURVE_AS_NURBS and test_nurbs_compat(ob): - ob_mat = EXPORT_GLOBAL_MATRIX * ob_mat + ob_mat = EXPORT_GLOBAL_MATRIX @ ob_mat totverts += write_nurb(fw, ob, ob_mat) continue # END NURBS try: - me = ob.to_mesh(scene, EXPORT_APPLY_MODIFIERS, calc_tessface=False, - settings='RENDER' if EXPORT_APPLY_MODIFIERS_RENDER else 'PREVIEW') + me = ob.to_mesh(depsgraph, EXPORT_APPLY_MODIFIERS) except RuntimeError: me = None @@ -401,15 +362,14 @@ def write_file(filepath, objects, scene, # _must_ do this first since it re-allocs arrays mesh_triangulate(me) - me.transform(EXPORT_GLOBAL_MATRIX * ob_mat) + me.transform(EXPORT_GLOBAL_MATRIX @ ob_mat) # If negative scaling, we have to invert the normals... if ob_mat.determinant() < 0.0: me.flip_normals() if EXPORT_UV: - faceuv = len(me.uv_textures) > 0 + faceuv = len(me.uv_layers) > 0 if faceuv: - uv_texture = me.uv_textures.active.data[:] uv_layer = me.uv_layers.active.data[:] else: faceuv = False @@ -418,7 +378,6 @@ def write_file(filepath, objects, scene, # Make our own list so it can be sorted to reduce context switching face_index_pairs = [(face, index) for index, face in enumerate(me.polygons)] - # faces = [ f for f in me.tessfaces ] if EXPORT_EDGES: edges = me.edges @@ -456,16 +415,7 @@ def write_file(filepath, objects, scene, if EXPORT_KEEP_VERT_ORDER: pass else: - if faceuv: - if smooth_groups: - sort_func = lambda a: (a[0].material_index, - hash(uv_texture[a[1]].image), - smooth_groups[a[1]] if a[0].use_smooth else False) - else: - sort_func = lambda a: (a[0].material_index, - hash(uv_texture[a[1]].image), - a[0].use_smooth) - elif len(materials) > 1: + if len(materials) > 1: if smooth_groups: sort_func = lambda a: (a[0].material_index, smooth_groups[a[1]] if a[0].use_smooth else False) @@ -559,9 +509,6 @@ def write_file(filepath, objects, scene, else: loops_to_normals = [] - if not faceuv: - f_image = None - subprogress2.step() # XXX @@ -581,15 +528,8 @@ def write_file(filepath, objects, scene, f_smooth = smooth_groups[f_index] f_mat = min(f.material_index, len(materials) - 1) - if faceuv: - tface = uv_texture[f_index] - f_image = tface.image - # MAKE KEY - if faceuv and f_image: # Object is always true. - key = material_names[f_mat], f_image.name - else: - key = material_names[f_mat], None # No image, use None instead. + key = material_names[f_mat], None # No image, use None instead. # Write the vertex group if EXPORT_POLYGROUPS: @@ -635,7 +575,7 @@ def write_file(filepath, objects, scene, i += 1 tmp_ext = "_%3d" % i mtl_name += tmp_ext - mat_data = mtl_dict[key] = mtl_name, materials[f_mat], f_image + mat_data = mtl_dict[key] = mtl_name, materials[f_mat] mtl_rev_dict[mtl_name] = key if EXPORT_GROUP_BY_MAT: @@ -714,7 +654,7 @@ def write_file(filepath, objects, scene, write_mtl(scene, mtlfilepath, EXPORT_PATH_MODE, copy_set, mtl_dict) # copy all collected files. - bpy_extras.io_utils.path_reference_copy(copy_set) + io_utils.path_reference_copy(copy_set) def _write(context, filepath, @@ -743,6 +683,7 @@ def _write(context, filepath, base_name, ext = os.path.splitext(filepath) context_name = [base_name, '', '', ext] # Base name, scene name, frame number, extension + depsgraph = context.depsgraph scene = context.scene # Exit edit mode before exporting, so current object states are exported properly. @@ -763,7 +704,7 @@ def _write(context, filepath, if EXPORT_ANIMATION: # Add frame to the filepath. context_name[2] = '_%.6d' % frame - scene.frame_set(frame, 0.0) + scene.frame_set(frame, subframe=0.0) if EXPORT_SEL_ONLY: objects = context.selected_objects else: @@ -774,7 +715,7 @@ def _write(context, filepath, # erm... bit of a problem here, this can overwrite files when exporting frames. not too bad. # EXPORT THE FILE. progress.enter_substeps(1) - write_file(full_path, objects, scene, + write_file(full_path, objects, depsgraph, scene, EXPORT_TRI, EXPORT_EDGES, EXPORT_SMOOTH_GROUPS, @@ -796,7 +737,7 @@ def _write(context, filepath, ) progress.leave_substeps() - scene.frame_set(orig_frame, 0.0) + scene.frame_set(orig_frame, subframe=0.0) progress.leave_substeps() diff --git a/io_scene_obj/import_obj.py b/io_scene_obj/import_obj.py index 52a9a291..4f3ee24a 100644 --- a/io_scene_obj/import_obj.py +++ b/io_scene_obj/import_obj.py @@ -87,21 +87,23 @@ def obj_image_load(context_imagepath_map, line, DIR, recursive, relpath): def create_materials(filepath, relpath, - material_libs, unique_materials, unique_material_images, - use_image_search, use_cycles, float_func): + material_libs, unique_materials, + use_image_search, float_func): """ Create all the used materials in this obj, assign colors and images to the materials from all referenced material libs """ + from math import sqrt + DIR = os.path.dirname(filepath) context_material_vars = set() # Don't load the same image multiple times context_imagepath_map = {} - cycles_material_wrap_map = {} + nodal_material_wrap_map = {} - def load_material_image(blender_material, mat_wrap, use_cycles, context_material_name, img_data, line, type): + def load_material_image(blender_material, mat_wrap, context_material_name, img_data, line, type): """ Set textures defined in .mtl file. """ @@ -120,105 +122,47 @@ def create_materials(filepath, relpath, # Absolute path - c:\.. etc would work here image = obj_image_load(context_imagepath_map, line, DIR, use_image_search, relpath) - texture = bpy.data.textures.new(name=type, type='IMAGE') - if image is not None: - texture.image = image - map_offset = map_options.get(b'-o') map_scale = map_options.get(b'-s') + def _generic_tex_set(nodetex, image, texcoords, translation, scale): + nodetex.image = image + nodetex.texcoords = texcoords + if translation is not None: + nodetex.translation = translation + if scale is not None: + nodetex.scale = scale + # Adds textures for materials (rendering) if type == 'Kd': - if use_cycles: - mat_wrap.diffuse_image_set(image) - mat_wrap.diffuse_mapping_set(coords='UV', translation=map_offset, scale=map_scale) - - mtex = blender_material.texture_slots.add() - mtex.texture = texture - mtex.texture_coords = 'UV' - mtex.use_map_color_diffuse = True - - # adds textures to faces (Textured/Alt-Z mode) - # Only apply the diffuse texture to the face if the image has not been set with the inline usemat func. - unique_material_images[context_material_name] = image # set the texface image + _generic_tex_set(mat_wrap.base_color_texture, image, 'UV', map_offset, map_scale) elif type == 'Ka': - if use_cycles: - # XXX Not supported? - print("WARNING, currently unsupported ambient texture, skipped.") - - mtex = blender_material.texture_slots.add() - mtex.use_map_color_diffuse = False - mtex.texture = texture - mtex.texture_coords = 'UV' - mtex.use_map_ambient = True + # XXX Not supported? + print("WARNING, currently unsupported ambient texture, skipped.") elif type == 'Ks': - if use_cycles: - mat_wrap.specular_image_set(image) - mat_wrap.specular_mapping_set(coords='UV', translation=map_offset, scale=map_scale) - - mtex = blender_material.texture_slots.add() - mtex.use_map_color_diffuse = False - mtex.texture = texture - mtex.texture_coords = 'UV' - mtex.use_map_color_spec = True + _generic_tex_set(mat_wrap.specular_texture, image, 'UV', map_offset, map_scale) elif type == 'Ke': - if use_cycles: - # XXX Not supported? - print("WARNING, currently unsupported emit texture, skipped.") - - mtex = blender_material.texture_slots.add() - mtex.use_map_color_diffuse = False - mtex.texture = texture - mtex.texture_coords = 'UV' - mtex.use_map_emit = True + # XXX Not supported? + print("WARNING, currently unsupported emit texture, skipped.") elif type == 'Bump': bump_mult = map_options.get(b'-bm') bump_mult = float(bump_mult[0]) if (bump_mult and len(bump_mult[0]) > 1) else 1.0 + mat_wrap.normalmap_strength_set(bump_mult) - if use_cycles: - mat_wrap.normal_image_set(image) - mat_wrap.normal_mapping_set(coords='UV', translation=map_offset, scale=map_scale) - if bump_mult: - mat_wrap.normal_factor_set(bump_mult) - - mtex = blender_material.texture_slots.add() - mtex.use_map_color_diffuse = False - mtex.texture = texture - mtex.texture_coords = 'UV' - mtex.use_map_normal = True - if bump_mult: - mtex.normal_factor = bump_mult + _generic_tex_set(mat_wrap.normalmap_texture, image, 'UV', map_offset, map_scale) elif type == 'D': - if use_cycles: - mat_wrap.alpha_image_set(image) - mat_wrap.alpha_mapping_set(coords='UV', translation=map_offset, scale=map_scale) - - mtex = blender_material.texture_slots.add() - mtex.use_map_color_diffuse = False - mtex.texture = texture - mtex.texture_coords = 'UV' - mtex.use_map_alpha = True - blender_material.use_transparency = True - blender_material.transparency_method = 'Z_TRANSPARENCY' - if "alpha" not in context_material_vars: - blender_material.alpha = 0.0 - # Todo, unset diffuse material alpha if it has an alpha channel + _generic_tex_set(mat_wrap.transmission_texture, image, 'UV', map_offset, map_scale) elif type == 'disp': - if use_cycles: - mat_wrap.bump_image_set(image) - mat_wrap.bump_mapping_set(coords='UV', translation=map_offset, scale=map_scale) - - mtex = blender_material.texture_slots.add() - mtex.use_map_color_diffuse = False - mtex.texture = texture - mtex.texture_coords = 'UV' - mtex.use_map_displacement = True + # XXX Not supported? + print("WARNING, currently unsupported displacement texture, skipped.") + # ~ mat_wrap.bump_image_set(image) + # ~ mat_wrap.bump_mapping_set(coords='UV', translation=map_offset, scale=map_scale) elif type == 'refl': map_type = map_options.get(b'-type') @@ -226,32 +170,12 @@ def create_materials(filepath, relpath, print("WARNING, unsupported reflection type '%s', defaulting to 'sphere'" "" % ' '.join(i.decode() for i in map_type)) - if use_cycles: - mat_wrap.diffuse_image_set(image, projection='SPHERE') - mat_wrap.diffuse_mapping_set(coords='Reflection', translation=map_offset, scale=map_scale) + _generic_tex_set(mat_wrap.base_color_texture, image, 'Reflection', map_offset, map_scale) + mat_wrap.base_color_texture.projection = 'SPHERE' - mtex = blender_material.texture_slots.add() - mtex.use_map_color_diffuse = False - mtex.texture = texture - mtex.texture_coords = 'REFLECTION' - mtex.use_map_color_diffuse = True - mtex.mapping = 'SPHERE' else: raise Exception("invalid type %r" % type) - if map_offset: - mtex.offset.x = float(map_offset[0]) - if len(map_offset) >= 2: - mtex.offset.y = float(map_offset[1]) - if len(map_offset) >= 3: - mtex.offset.z = float(map_offset[2]) - if map_scale: - mtex.scale.x = float(map_scale[0]) - if len(map_scale) >= 2: - mtex.scale.y = float(map_scale[1]) - if len(map_scale) >= 3: - mtex.scale.z = float(map_scale[2]) - # Add an MTL with the same name as the obj if no MTLs are spesified. temp_mtl = os.path.splitext((os.path.basename(filepath)))[0] + ".mtl" @@ -263,17 +187,10 @@ def create_materials(filepath, relpath, for name in unique_materials: # .keys() if name is not None: ma = unique_materials[name] = bpy.data.materials.new(name.decode('utf-8', "replace")) - unique_material_images[name] = None # assign None to all material images to start with, add to later. - if use_cycles: - from modules import cycles_shader_compat - ma_wrap = cycles_shader_compat.CyclesShaderWrapper(ma) - cycles_material_wrap_map[ma] = ma_wrap - - - # XXX Why was this needed? Cannot find any good reason, and adds stupid empty matslot in case we do not separate - # mesh (see T44947). - #~ unique_materials[None] = None - #~ unique_material_images[None] = None + from bpy_extras import node_shader_utils + ma_wrap = node_shader_utils.PrincipledBSDFWrapper(ma, is_readonly=False) + nodal_material_wrap_map[ma] = ma_wrap + ma_wrap.use_nodes = True for libname in sorted(material_libs): # print(libname) @@ -281,13 +198,13 @@ def create_materials(filepath, relpath, if not os.path.exists(mtlpath): print("\tMaterial not found MTL: %r" % mtlpath) else: - do_ambient = True + # Note: with modern Principled BSDF shader, things like ambient, raytrace or fresnel are always 'ON' + # (i.e. automatically controlled by other parameters). do_highlight = False do_reflection = False do_transparency = False do_glass = False - do_fresnel = False - do_raytrace = False + spec_colors = [0.0, 0.0, 0.0] emit_colors = [0.0, 0.0, 0.0] # print('\t\tloading mtl: %e' % mtlpath) @@ -305,133 +222,112 @@ def create_materials(filepath, relpath, if line_id == b'newmtl': # Finalize previous mat, if any. if context_material: + if "specular" in context_material_vars: + # XXX This is highly approximated, not sure whether we can do better... + # TODO: Find a way to guesstimate best value from diffuse color... + # IDEA: Use standard deviation of both spec and diff colors (i.e. how far away they are + # from some grey), and apply the the proportion between those two as tint factor? + spec = sum(spec_color) / 3.0 + # ~ spec_var = math.sqrt(sum((c - spec) ** 2 for c in spec_color) / 3.0) + # ~ diff = sum(context_mat_wrap.base_color) / 3.0 + # ~ diff_var = math.sqrt(sum((c - diff) ** 2 for c in context_mat_wrap.base_color) / 3.0) + # ~ tint = min(1.0, spec_var / diff_var) + context_mat_wrap.specular = spec + context_mat_wrap.specular_tint = 0.0 + if "roughness" not in context_material_vars: + context_mat_wrap.roughness = 0.0 + + emit_value = sum(emit_colors) / 3.0 if emit_value > 1e-6: - if use_cycles: - print("WARNING, currently unsupported emit value, skipped.") + print("WARNING, emit value unsupported by Principled BSDF shader, skipped.") # We have to adapt it to diffuse color too... emit_value /= sum(context_material.diffuse_color) / 3.0 - context_material.emit = emit_value - - if not do_ambient: - context_material.ambient = 0.0 + # ~ context_material.emit = emit_value + # FIXME, how else to use this? if do_highlight: - if use_cycles: - context_mat_wrap.hardness_value_set(1.0) - # FIXME, how else to use this? - context_material.specular_intensity = 1.0 + if "specular" not in context_material_vars: + context_mat_wrap.specular = 1.0 + if "roughness" not in context_material_vars: + context_mat_wrap.roughness = 0.0 else: - if use_cycles: - context_mat_wrap.hardness_value_set(0.0) + if "specular" not in context_material_vars: + context_mat_wrap.specular = 0.0 + if "roughness" not in context_material_vars: + context_mat_wrap.roughness = 1.0 if do_reflection: - if use_cycles: - context_mat_wrap.reflect_factor_set(1.0) - context_material.raytrace_mirror.use = True - context_material.raytrace_mirror.reflect_factor = 1.0 + if "metallic" not in context_material_vars: + context_mat_wrap.metallic = 1.0 if do_transparency: - context_material.use_transparency = True - context_material.transparency_method = 'RAYTRACE' if do_raytrace else 'Z_TRANSPARENCY' - if "alpha" not in context_material_vars: - if use_cycles: - context_mat_wrap.alpha_value_set(0.0) - context_material.alpha = 0.0 + if "ior" not in context_material_vars: + context_mat_wrap.ior = 1.0 + if "transmission" not in context_material_vars: + context_mat_wrap.transmission = 1.0 + # EEVEE only + context_material.blend_method = 'BLEND' if do_glass: - if use_cycles: - print("WARNING, currently unsupported glass material, skipped.") if "ior" not in context_material_vars: - context_material.raytrace_transparency.ior = 1.5 - - if do_fresnel: - if use_cycles: - print("WARNING, currently unsupported fresnel option, skipped.") - context_material.raytrace_mirror.fresnel = 1.0 # could be any value for 'ON' - - """ - if do_raytrace: - context_material.use_raytrace = True - else: - context_material.use_raytrace = False - """ - # XXX, this is not following the OBJ spec, but this was - # written when raytracing wasnt default, annoying to disable for blender users. - context_material.use_raytrace = True + context_mat_wrap.ior = 1.5 context_material_name = line_value(line_split) context_material = unique_materials.get(context_material_name) - if use_cycles and context_material is not None: - context_mat_wrap = cycles_material_wrap_map[context_material] + if context_material is not None: + context_mat_wrap = nodal_material_wrap_map[context_material] context_material_vars.clear() + spec_colors = [0.0, 0.0, 0.0] emit_colors[:] = [0.0, 0.0, 0.0] - do_ambient = True do_highlight = False do_reflection = False do_transparency = False do_glass = False - do_fresnel = False - do_raytrace = False elif context_material: # we need to make a material to assign properties to it. if line_id == b'ka': - col = (float_func(line_split[1]), float_func(line_split[2]), float_func(line_split[3])) - if use_cycles: - context_mat_wrap.reflect_color_set(col) - context_material.mirror_color = col - # This is highly approximated, but let's try to stick as close from exporter as possible... :/ - context_material.ambient = sum(context_material.mirror_color) / 3 + refl = (float_func(line_split[1]) + float_func(line_split[2]) + float_func(line_split[3])) / 3.0 + context_mat_wrap.metallic = refl + context_material_vars.add("metallic") elif line_id == b'kd': col = (float_func(line_split[1]), float_func(line_split[2]), float_func(line_split[3])) - if use_cycles: - context_mat_wrap.diffuse_color_set(col) - context_material.diffuse_color = col - context_material.diffuse_intensity = 1.0 + context_mat_wrap.base_color = col elif line_id == b'ks': - col = (float_func(line_split[1]), float_func(line_split[2]), float_func(line_split[3])) - if use_cycles: - context_mat_wrap.specular_color_set(col) - context_mat_wrap.hardness_value_set(1.0) - context_material.specular_color = col - context_material.specular_intensity = 1.0 + spec_color = (float_func(line_split[1]) + float_func(line_split[2]) + float_func(line_split[3])) + context_material_vars.add("specular") elif line_id == b'ke': # We cannot set context_material.emit right now, we need final diffuse color as well for this. + # XXX Unsupported currently emit_colors[:] = [ float_func(line_split[1]), float_func(line_split[2]), float_func(line_split[3])] elif line_id == b'ns': - if use_cycles: - context_mat_wrap.hardness_value_set(((float_func(line_split[1]) + 3.0) / 50.0) - 0.65) - context_material.specular_hardness = int((float_func(line_split[1]) * 0.51) + 1) - elif line_id == b'ni': # Refraction index (between 1 and 3). - if use_cycles: - print("WARNING, currently unsupported glass material, skipped.") - context_material.raytrace_transparency.ior = max(1, min(float_func(line_split[1]), 3)) + # XXX Totally empirical conversion, trying to adapt it + # (from 0.0 - 900.0 OBJ specular exponent range to 1.0 - 0.0 Principled BSDF range)... + context_mat_wrap.roughness = 1.0 - (sqrt(float_func(line_split[1])) / 30) + context_material_vars.add("roughness") + elif line_id == b'ni': # Refraction index (between 0.001 and 10). + context_mat_wrap.ior = float_func(line_split[1]) context_material_vars.add("ior") elif line_id == b'd': # dissolve (transparency) - if use_cycles: - context_mat_wrap.alpha_value_set(float_func(line_split[1])) - context_material.alpha = float_func(line_split[1]) - context_material.use_transparency = True - context_material.transparency_method = 'Z_TRANSPARENCY' - context_material_vars.add("alpha") + context_mat_wrap.transmission = 1.0 - float_func(line_split[1]) + context_material_vars.add("transmission") elif line_id == b'tr': # translucency - if use_cycles: - print("WARNING, currently unsupported translucency option, skipped.") - context_material.translucency = float_func(line_split[1]) + print("WARNING, currently unsupported 'tr' translucency option, skipped.") elif line_id == b'tf': # rgb, filter color, blender has no support for this. - pass + print("WARNING, currently unsupported 'tf' filter color option, skipped.") elif line_id == b'illum': illum = get_int(line_split[1]) # inline comments are from the spec, v4.2 if illum == 0: # Color on and Ambient off - do_ambient = False + print("WARNING, Principled BSDF shader does not support illumination 0 mode " + "(colors with no ambient), skipped.") elif illum == 1: # Color on and Ambient on pass @@ -441,32 +337,25 @@ def create_materials(filepath, relpath, elif illum == 3: # Reflection on and Ray trace on do_reflection = True - do_raytrace = True elif illum == 4: # Transparency: Glass on # Reflection: Ray trace on do_transparency = True do_reflection = True do_glass = True - do_raytrace = True elif illum == 5: # Reflection: Fresnel on and Ray trace on do_reflection = True - do_fresnel = True - do_raytrace = True elif illum == 6: # Transparency: Refraction on # Reflection: Fresnel off and Ray trace on do_transparency = True do_reflection = True - do_raytrace = True elif illum == 7: # Transparency: Refraction on # Reflection: Fresnel on and Ray trace on do_transparency = True do_reflection = True - do_fresnel = True - do_raytrace = True elif illum == 8: # Reflection on and Ray trace off do_reflection = True @@ -474,58 +363,58 @@ def create_materials(filepath, relpath, # Transparency: Glass on # Reflection: Ray trace off do_transparency = True - do_reflection = True + do_reflection = False do_glass = True elif illum == 10: # Casts shadows onto invisible surfaces - - # blender can't do this + print("WARNING, Principled BSDF shader does not support illumination 10 mode " + "(cast shadows on invisible surfaces), skipped.") pass elif line_id == b'map_ka': img_data = line.split()[1:] if img_data: - load_material_image(context_material, context_mat_wrap, use_cycles, + load_material_image(context_material, context_mat_wrap, context_material_name, img_data, line, 'Ka') elif line_id == b'map_ks': img_data = line.split()[1:] if img_data: - load_material_image(context_material, context_mat_wrap, use_cycles, + load_material_image(context_material, context_mat_wrap, context_material_name, img_data, line, 'Ks') elif line_id == b'map_kd': img_data = line.split()[1:] if img_data: - load_material_image(context_material, context_mat_wrap, use_cycles, + load_material_image(context_material, context_mat_wrap, context_material_name, img_data, line, 'Kd') elif line_id == b'map_ke': img_data = line.split()[1:] if img_data: - load_material_image(context_material, context_mat_wrap, use_cycles, + load_material_image(context_material, context_mat_wrap, context_material_name, img_data, line, 'Ke') elif line_id in {b'map_bump', b'bump'}: # 'bump' is incorrect but some files use it. img_data = line.split()[1:] if img_data: - load_material_image(context_material, context_mat_wrap, use_cycles, + load_material_image(context_material, context_mat_wrap, context_material_name, img_data, line, 'Bump') elif line_id in {b'map_d', b'map_tr'}: # Alpha map - Dissolve img_data = line.split()[1:] if img_data: - load_material_image(context_material, context_mat_wrap, use_cycles, + load_material_image(context_material, context_mat_wrap, context_material_name, img_data, line, 'D') elif line_id in {b'map_disp', b'disp'}: # displacementmap img_data = line.split()[1:] if img_data: - load_material_image(context_material, context_mat_wrap, use_cycles, + load_material_image(context_material, context_mat_wrap, context_material_name, img_data, line, 'disp') elif line_id in {b'map_refl', b'refl'}: # reflectionmap img_data = line.split()[1:] if img_data: - load_material_image(context_material, context_mat_wrap, use_cycles, + load_material_image(context_material, context_mat_wrap, context_material_name, img_data, line, 'refl') else: - print("\t%r:%r (ignored)" % (filepath, line)) + print("WARNING: %r:%r (ignored)" % (filepath, line)) mtl.close() @@ -601,7 +490,6 @@ def create_mesh(new_objects, verts_tex, faces, unique_materials, - unique_material_images, unique_smooth_groups, vertex_groups, dataname, @@ -756,7 +644,7 @@ def create_mesh(new_objects, me.create_normals_split() if verts_tex and me.polygons: - me.uv_textures.new() + me.uv_layers.new() context_material_old = -1 # avoid a dict lookup mat = 0 # rare case it may be un-initialized. @@ -788,11 +676,6 @@ def create_mesh(new_objects, me.loops[lidx].normal[:] = verts_nor[0 if (face_noidx is ...) else face_noidx] if verts_tex and face_vert_tex_indices: - if context_material: - image = unique_material_images[context_material] - if image: # Can be none if the material dosnt have an image. - me.uv_textures[0].data[i].image = image - blen_uvs = me.uv_layers[0] for face_uvidx, lidx in zip(face_vert_tex_indices, blen_poly.loop_indices): blen_uvs.data[lidx].uv = verts_tex[0 if (face_uvidx is ...) else face_uvidx] @@ -829,7 +712,6 @@ def create_mesh(new_objects, for e in me.edges: if e.key in sharp_edges: e.use_edge_sharp = True - me.show_edge_sharp = True if verts_nor: clnors = array.array('f', [0.0] * (len(me.loops) * 3)) @@ -840,7 +722,6 @@ def create_mesh(new_objects, me.normals_split_custom_set(tuple(zip(*(iter(clnors),) * 3))) me.use_auto_smooth = True - me.show_edge_sharp = True ob = bpy.data.objects.new(me.name, me) new_objects.append(ob) @@ -966,14 +847,13 @@ def get_int(svalue): def load(context, filepath, *, - global_clamp_size=0.0, + global_clight_size=0.0, use_smooth_groups=True, use_edges=True, use_split_objects=True, use_split_groups=True, use_image_search=True, use_groups_as_vgroups=False, - use_cycles=True, relpath=None, global_matrix=None ): @@ -1042,7 +922,6 @@ def load(context, # Until we can use sets unique_materials = {} - unique_material_images = {} unique_smooth_groups = {} # unique_obects= {} - no use for this variable since the objects are stored in the face. @@ -1264,7 +1143,7 @@ def load(context, progress.step("Done, loading materials and images...") create_materials(filepath, relpath, material_libs, unique_materials, - unique_material_images, use_image_search, use_cycles, float_func) + use_image_search, float_func) progress.step("Done, building geometries (verts:%i faces:%i materials: %i smoothgroups:%i) ..." % (len(verts_loc), len(faces), len(unique_materials), len(unique_smooth_groups))) @@ -1290,7 +1169,6 @@ def load(context, verts_tex if use_vtex else [], faces_split, unique_materials_split, - unique_material_images, unique_smooth_groups, vertex_groups, dataname, @@ -1300,10 +1178,17 @@ def load(context, for context_nurbs in nurbs: create_nurbs(context_nurbs, verts_loc, new_objects) + view_layer = context.view_layer + if view_layer.collections.active: + collection = view_layer.collections.active.collection + else: + collection = scene.master_collection.new() + view_layer.collections.link(collection) + # Create new obj for obj in new_objects: - base = scene.objects.link(obj) - base.select = True + collection.objects.link(obj) + obj.select_set('SELECT') # we could apply this anywhere before scaling. obj.matrix_world = global_matrix @@ -1313,7 +1198,7 @@ def load(context, axis_min = [1000000000] * 3 axis_max = [-1000000000] * 3 - if global_clamp_size: + if global_clight_size: # Get all object bounds for ob in new_objects: for v in ob.bound_box: @@ -1327,7 +1212,7 @@ def load(context, max_axis = max(axis_max[0] - axis_min[0], axis_max[1] - axis_min[1], axis_max[2] - axis_min[2]) scale = 1.0 - while global_clamp_size < max_axis * scale: + while global_clight_size < max_axis * scale: scale = scale / 10.0 for obj in new_objects: diff --git a/io_scene_vrml2/__init__.py b/io_scene_vrml2/__init__.py index d6c0da2f..4a420f70 100644 --- a/io_scene_vrml2/__init__.py +++ b/io_scene_vrml2/__init__.py @@ -47,16 +47,14 @@ from bpy.props import ( ) from bpy_extras.io_utils import ( ExportHelper, - orientation_helper_factory, + orientation_helper, path_reference_mode, axis_conversion, ) -ExportVRMLOrientationHelper = orientation_helper_factory("ExportVRMLOrientationHelper", axis_forward='Z', axis_up='Y') - - -class ExportVRML(bpy.types.Operator, ExportHelper, ExportVRMLOrientationHelper): +@orientation_helper(axis_forward='Z', axis_up='Y') +class ExportVRML(bpy.types.Operator, ExportHelper): """Export mesh objects as a VRML2, colors and texture coordinates""" bl_idname = "export_scene.vrml2" bl_label = "Export VRML2" @@ -151,13 +149,13 @@ def menu_func_export(self, context): def register(): bpy.utils.register_module(__name__) - bpy.types.INFO_MT_file_export.append(menu_func_export) + bpy.types.TOPBAR_MT_file_export.append(menu_func_export) def unregister(): bpy.utils.unregister_module(__name__) - bpy.types.INFO_MT_file_export.remove(menu_func_export) + bpy.types.TOPBAR_MT_file_export.remove(menu_func_export) if __name__ == "__main__": register() diff --git a/io_scene_vrml2/export_vrml2.py b/io_scene_vrml2/export_vrml2.py index 06f79fc1..22114582 100644 --- a/io_scene_vrml2/export_vrml2.py +++ b/io_scene_vrml2/export_vrml2.py @@ -163,7 +163,7 @@ def save_object(fw, global_matrix, if is_editmode: bpy.ops.object.editmode_toggle() - me = obj.to_mesh(scene, True, 'PREVIEW', calc_tessface=False) + me = obj.to_mesh(scene, True, 'PREVIEW') bm = bmesh.new() bm.from_mesh(me) diff --git a/io_scene_x/__init__.py b/io_scene_x/__init__.py index 001dca61..404d9dc2 100644 --- a/io_scene_x/__init__.py +++ b/io_scene_x/__init__.py @@ -176,13 +176,13 @@ def menu_func(self, context): def register(): bpy.utils.register_module(__name__) - bpy.types.INFO_MT_file_export.append(menu_func) + bpy.types.TOPBAR_MT_file_export.append(menu_func) def unregister(): bpy.utils.unregister_module(__name__) - bpy.types.INFO_MT_file_export.remove(menu_func) + bpy.types.TOPBAR_MT_file_export.remove(menu_func) if __name__ == "__main__": diff --git a/io_scene_x3d/__init__.py b/io_scene_x3d/__init__.py index d5c555a1..06a9a122 100644 --- a/io_scene_x3d/__init__.py +++ b/io_scene_x3d/__init__.py @@ -48,16 +48,14 @@ from bpy.props import ( from bpy_extras.io_utils import ( ImportHelper, ExportHelper, - orientation_helper_factory, + orientation_helper, axis_conversion, path_reference_mode, ) -IOX3DOrientationHelper = orientation_helper_factory("IOX3DOrientationHelper", axis_forward='Z', axis_up='Y') - - -class ImportX3D(bpy.types.Operator, ImportHelper, IOX3DOrientationHelper): +@orientation_helper(axis_forward='Z', axis_up='Y') +class ImportX3D(bpy.types.Operator, ImportHelper): """Import an X3D or VRML2 file""" bl_idname = "import_scene.x3d" bl_label = "Import X3D/VRML2" @@ -81,7 +79,8 @@ class ImportX3D(bpy.types.Operator, ImportHelper, IOX3DOrientationHelper): return import_x3d.load(context, **keywords) -class ExportX3D(bpy.types.Operator, ExportHelper, IOX3DOrientationHelper): +@orientation_helper(axis_forward='Z', axis_up='Y') +class ExportX3D(bpy.types.Operator, ExportHelper): """Export selection to Extensible 3D file (.x3d)""" bl_idname = "export_scene.x3d" bl_label = 'Export X3D' @@ -172,15 +171,15 @@ def menu_func_export(self, context): def register(): bpy.utils.register_module(__name__) - bpy.types.INFO_MT_file_import.append(menu_func_import) - bpy.types.INFO_MT_file_export.append(menu_func_export) + bpy.types.TOPBAR_MT_file_import.append(menu_func_import) + bpy.types.TOPBAR_MT_file_export.append(menu_func_export) def unregister(): bpy.utils.unregister_module(__name__) - bpy.types.INFO_MT_file_import.remove(menu_func_import) - bpy.types.INFO_MT_file_export.remove(menu_func_export) + bpy.types.TOPBAR_MT_file_import.remove(menu_func_import) + bpy.types.TOPBAR_MT_file_export.remove(menu_func_export) # NOTES # - blender version is hardcoded diff --git a/io_scene_x3d/export_x3d.py b/io_scene_x3d/export_x3d.py index c2ebfca7..d6c4a293 100644 --- a/io_scene_x3d/export_x3d.py +++ b/io_scene_x3d/export_x3d.py @@ -48,7 +48,7 @@ H3D_CAMERA_FOLLOW = 'CAMERA_FOLLOW_TRANSFORM' H3D_VIEW_MATRIX = 'view_matrix' -def clamp_color(col): +def clight_color(col): return tuple([max(min(c, 1.0), 0.0) for c in col]) @@ -164,14 +164,14 @@ def h3d_shader_glsl_frag_patch(filepath, scene, global_vars, frag_uniform_var_ma lines.append("%s\n" % v) lines.append("// h3d custom vars end\n") lines.append("\n") - elif l.lstrip().startswith("lamp_visibility_other("): + elif l.lstrip().startswith("light_visibility_other("): w = l.split(', ') last_transform = w[1] + "_transform" # XXX - HACK!!! w[1] = '(view_matrix * %s_transform * vec4(%s.x, %s.y, %s.z, 1.0)).xyz' % (w[1], w[1], w[1], w[1]) l = ", ".join(w) - elif l.lstrip().startswith("lamp_visibility_sun_hemi("): + elif l.lstrip().startswith("light_visibility_sun_hemi("): w = l.split(', ') - w[0] = w[0][len("lamp_visibility_sun_hemi(") + 1:] + w[0] = w[0][len("light_visibility_sun_hemi(") + 1:] if not h3d_is_object_view(scene, frag_uniform_var_map[w[0]]): w[0] = '(mat3(normalize(view_matrix[0].xyz), normalize(view_matrix[1].xyz), normalize(view_matrix[2].xyz)) * -%s)' % w[0] @@ -179,10 +179,10 @@ def h3d_shader_glsl_frag_patch(filepath, scene, global_vars, frag_uniform_var_ma w[0] = ('(mat3(normalize((view_matrix*%s)[0].xyz), normalize((view_matrix*%s)[1].xyz), normalize((view_matrix*%s)[2].xyz)) * -%s)' % (last_transform, last_transform, last_transform, w[0])) - l = "\tlamp_visibility_sun_hemi(" + ", ".join(w) - elif l.lstrip().startswith("lamp_visibility_spot_circle("): + l = "\tlight_visibility_sun_hemi(" + ", ".join(w) + elif l.lstrip().startswith("light_visibility_spot_circle("): w = l.split(', ') - w[0] = w[0][len("lamp_visibility_spot_circle(") + 1:] + w[0] = w[0][len("light_visibility_spot_circle(") + 1:] if not h3d_is_object_view(scene, frag_uniform_var_map[w[0]]): w[0] = '(mat3(normalize(view_matrix[0].xyz), normalize(view_matrix[1].xyz), normalize(view_matrix[2].xyz)) * -%s)' % w[0] @@ -190,7 +190,7 @@ def h3d_shader_glsl_frag_patch(filepath, scene, global_vars, frag_uniform_var_ma w[0] = ('(mat3(normalize((view_matrix*%s)[0].xyz), normalize((view_matrix*%s)[1].xyz), normalize((view_matrix*%s)[2].xyz)) * %s)' % (last_transform, last_transform, last_transform, w[0])) - l = "\tlamp_visibility_spot_circle(" + ", ".join(w) + l = "\tlight_visibility_spot_circle(" + ", ".join(w) lines.append(l) @@ -241,7 +241,7 @@ def export(file, # since objects of different types will always have # different decorated names. uuid_cache_object = {} # object - uuid_cache_lamp = {} # 'LA_' + object.name + uuid_cache_light = {} # 'LA_' + object.name uuid_cache_view = {} # object, different namespace uuid_cache_mesh = {} # mesh uuid_cache_material = {} # material @@ -261,7 +261,7 @@ def export(file, # prevent uuid collisions. uuid_cache = {} uuid_cache_object = uuid_cache # object - uuid_cache_lamp = uuid_cache # 'LA_' + object.name + uuid_cache_light = uuid_cache # 'LA_' + object.name uuid_cache_view = uuid_cache # object, different namespace uuid_cache_mesh = uuid_cache # mesh uuid_cache_material = uuid_cache # material @@ -370,16 +370,16 @@ def export(file, ident_step = ident + (' ' * (-len(ident) + \ fw('%s<Fog ' % ident))) fw('fogType="%s"\n' % ('LINEAR' if (mtype == 'LINEAR') else 'EXPONENTIAL')) - fw(ident_step + 'color="%.3f %.3f %.3f"\n' % clamp_color(world.horizon_color)) + fw(ident_step + 'color="%.3f %.3f %.3f"\n' % clight_color(world.horizon_color)) fw(ident_step + 'visibilityRange="%.3f"\n' % mparam.depth) fw(ident_step + '/>\n') else: return - def writeNavigationInfo(ident, scene, has_lamp): + def writeNavigationInfo(ident, scene, has_light): ident_step = ident + (' ' * (-len(ident) + \ fw('%s<NavigationInfo ' % ident))) - fw('headlight="%s"\n' % bool_as_str(not has_lamp)) + fw('headlight="%s"\n' % bool_as_str(not has_light)) fw(ident_step + 'visibilityLimit="0.0"\n') fw(ident_step + 'type=\'"EXAMINE", "ANY"\'\n') fw(ident_step + 'avatarSize="0.25, 1.75, 0.75"\n') @@ -411,8 +411,8 @@ def export(file, return ident def writeSpotLight(ident, obj, matrix, lamp, world): - # note, lamp_id is not re-used - lamp_id = quoteattr(unique_name(obj, LA_ + obj.name, uuid_cache_lamp, clean_func=clean_def, sep="_")) + # note, light_id is not re-used + light_id = quoteattr(unique_name(obj, LA_ + obj.name, uuid_cache_light, clean_func=clean_def, sep="_")) if world: ambi = world.ambient_color @@ -435,11 +435,11 @@ def export(file, # radius = lamp.dist*math.cos(beamWidth) ident_step = ident + (' ' * (-len(ident) + \ fw('%s<SpotLight ' % ident))) - fw('DEF=%s\n' % lamp_id) + fw('DEF=%s\n' % light_id) fw(ident_step + 'radius="%.4f"\n' % radius) fw(ident_step + 'ambientIntensity="%.4f"\n' % amb_intensity) fw(ident_step + 'intensity="%.4f"\n' % intensity) - fw(ident_step + 'color="%.4f %.4f %.4f"\n' % clamp_color(lamp.color)) + fw(ident_step + 'color="%.4f %.4f %.4f"\n' % clight_color(lamp.color)) fw(ident_step + 'beamWidth="%.4f"\n' % beamWidth) fw(ident_step + 'cutOffAngle="%.4f"\n' % cutOffAngle) fw(ident_step + 'direction="%.4f %.4f %.4f"\n' % orientation) @@ -447,8 +447,8 @@ def export(file, fw(ident_step + '/>\n') def writeDirectionalLight(ident, obj, matrix, lamp, world): - # note, lamp_id is not re-used - lamp_id = quoteattr(unique_name(obj, LA_ + obj.name, uuid_cache_lamp, clean_func=clean_def, sep="_")) + # note, light_id is not re-used + light_id = quoteattr(unique_name(obj, LA_ + obj.name, uuid_cache_light, clean_func=clean_def, sep="_")) if world: ambi = world.ambient_color @@ -464,16 +464,16 @@ def export(file, ident_step = ident + (' ' * (-len(ident) + \ fw('%s<DirectionalLight ' % ident))) - fw('DEF=%s\n' % lamp_id) + fw('DEF=%s\n' % light_id) fw(ident_step + 'ambientIntensity="%.4f"\n' % amb_intensity) - fw(ident_step + 'color="%.4f %.4f %.4f"\n' % clamp_color(lamp.color)) + fw(ident_step + 'color="%.4f %.4f %.4f"\n' % clight_color(lamp.color)) fw(ident_step + 'intensity="%.4f"\n' % intensity) fw(ident_step + 'direction="%.4f %.4f %.4f"\n' % orientation) fw(ident_step + '/>\n') def writePointLight(ident, obj, matrix, lamp, world): - # note, lamp_id is not re-used - lamp_id = quoteattr(unique_name(obj, LA_ + obj.name, uuid_cache_lamp, clean_func=clean_def, sep="_")) + # note, light_id is not re-used + light_id = quoteattr(unique_name(obj, LA_ + obj.name, uuid_cache_light, clean_func=clean_def, sep="_")) if world: ambi = world.ambient_color @@ -488,9 +488,9 @@ def export(file, ident_step = ident + (' ' * (-len(ident) + \ fw('%s<PointLight ' % ident))) - fw('DEF=%s\n' % lamp_id) + fw('DEF=%s\n' % light_id) fw(ident_step + 'ambientIntensity="%.4f"\n' % amb_intensity) - fw(ident_step + 'color="%.4f %.4f %.4f"\n' % clamp_color(lamp.color)) + fw(ident_step + 'color="%.4f %.4f %.4f"\n' % clight_color(lamp.color)) fw(ident_step + 'intensity="%.4f"\n' % intensity) fw(ident_step + 'radius="%.4f" \n' % lamp.distance) @@ -1002,9 +1002,9 @@ def export(file, ident_step = ident + (' ' * (-len(ident) + \ fw('%s<Material ' % ident))) fw('DEF=%s\n' % material_id) - fw(ident_step + 'diffuseColor="%.3f %.3f %.3f"\n' % clamp_color(diffuseColor)) - fw(ident_step + 'specularColor="%.3f %.3f %.3f"\n' % clamp_color(specColor)) - fw(ident_step + 'emissiveColor="%.3f %.3f %.3f"\n' % clamp_color(emitColor)) + fw(ident_step + 'diffuseColor="%.3f %.3f %.3f"\n' % clight_color(diffuseColor)) + fw(ident_step + 'specularColor="%.3f %.3f %.3f"\n' % clight_color(specColor)) + fw(ident_step + 'emissiveColor="%.3f %.3f %.3f"\n' % clight_color(emitColor)) fw(ident_step + 'ambientIntensity="%.3f"\n' % ambient) fw(ident_step + 'shininess="%.3f"\n' % shininess) fw(ident_step + 'transparency="%s"\n' % transp) @@ -1035,12 +1035,12 @@ def export(file, #~ GPU_DATA_4F 5 #~ GPU_DATA_4UB 8 #~ GPU_DATA_9F 6 - #~ GPU_DYNAMIC_LAMP_DYNCO 7 - #~ GPU_DYNAMIC_LAMP_DYNCOL 11 - #~ GPU_DYNAMIC_LAMP_DYNENERGY 10 - #~ GPU_DYNAMIC_LAMP_DYNIMAT 8 - #~ GPU_DYNAMIC_LAMP_DYNPERSMAT 9 - #~ GPU_DYNAMIC_LAMP_DYNVEC 6 + #~ GPU_DYNAMIC_LIGHT_DYNCO 7 + #~ GPU_DYNAMIC_LIGHT_DYNCOL 11 + #~ GPU_DYNAMIC_LIGHT_DYNENERGY 10 + #~ GPU_DYNAMIC_LIGHT_DYNIMAT 8 + #~ GPU_DYNAMIC_LIGHT_DYNPERSMAT 9 + #~ GPU_DYNAMIC_LIGHT_DYNVEC 6 #~ GPU_DYNAMIC_OBJECT_COLOR 5 #~ GPU_DYNAMIC_OBJECT_IMAT 4 #~ GPU_DYNAMIC_OBJECT_MAT 2 @@ -1134,45 +1134,45 @@ def export(file, writeImageTexture(ident + '\t', uniform['image']) fw('%s</field>\n' % ident) - elif uniform['type'] == gpu.GPU_DYNAMIC_LAMP_DYNCO: - lamp_obj = uniform['lamp'] - frag_uniform_var_map[uniform['varname']] = lamp_obj + elif uniform['type'] == gpu.GPU_DYNAMIC_LIGHT_DYNCO: + light_obj = uniform['lamp'] + frag_uniform_var_map[uniform['varname']] = light_obj if uniform['datatype'] == gpu.GPU_DATA_3F: # should always be true! - lamp_obj_id = quoteattr(unique_name(lamp_obj, LA_ + lamp_obj.name, uuid_cache_lamp, clean_func=clean_def, sep="_")) - lamp_obj_transform_id = quoteattr(unique_name(lamp_obj, lamp_obj.name, uuid_cache_object, clean_func=clean_def, sep="_")) + light_obj_id = quoteattr(unique_name(light_obj, LA_ + light_obj.name, uuid_cache_light, clean_func=clean_def, sep="_")) + light_obj_transform_id = quoteattr(unique_name(light_obj, light_obj.name, uuid_cache_object, clean_func=clean_def, sep="_")) - value = '%.6f %.6f %.6f' % (global_matrix * lamp_obj.matrix_world).to_translation()[:] - field_descr = " <!--- Lamp DynCo '%s' -->" % lamp_obj.name + value = '%.6f %.6f %.6f' % (global_matrix * light_obj.matrix_world).to_translation()[:] + field_descr = " <!--- Lamp DynCo '%s' -->" % light_obj.name fw('%s<field name="%s" type="SFVec3f" accessType="inputOutput" value="%s" />%s\n' % (ident, uniform['varname'], value, field_descr)) # ------------------------------------------------------ # shader-patch - field_descr = " <!--- Lamp DynCo '%s' (shader patch) -->" % lamp_obj.name + field_descr = " <!--- Lamp DynCo '%s' (shader patch) -->" % light_obj.name fw('%s<field name="%s_transform" type="SFMatrix4f" accessType="inputOutput" />%s\n' % (ident, uniform['varname'], field_descr)) # transform frag_vars.append("uniform mat4 %s_transform;" % uniform['varname']) h3d_material_route.append( '<ROUTE fromNode=%s fromField="accumulatedForward" toNode=%s toField="%s_transform" />%s' % - (suffix_quoted_str(lamp_obj_transform_id, _TRANSFORM), material_id, uniform['varname'], field_descr)) + (suffix_quoted_str(light_obj_transform_id, _TRANSFORM), material_id, uniform['varname'], field_descr)) h3d_material_route.append( '<ROUTE fromNode=%s fromField="location" toNode=%s toField="%s" /> %s' % - (lamp_obj_id, material_id, uniform['varname'], field_descr)) + (light_obj_id, material_id, uniform['varname'], field_descr)) # ------------------------------------------------------ else: assert(0) - elif uniform['type'] == gpu.GPU_DYNAMIC_LAMP_DYNCOL: + elif uniform['type'] == gpu.GPU_DYNAMIC_LIGHT_DYNCOL: # odd we have both 3, 4 types. - lamp_obj = uniform['lamp'] - frag_uniform_var_map[uniform['varname']] = lamp_obj + light_obj = uniform['lamp'] + frag_uniform_var_map[uniform['varname']] = light_obj - lamp = lamp_obj.data + lamp = light_obj.data value = '%.6f %.6f %.6f' % (lamp.color * lamp.energy)[:] - field_descr = " <!--- Lamp DynColor '%s' -->" % lamp_obj.name + field_descr = " <!--- Lamp DynColor '%s' -->" % light_obj.name if uniform['datatype'] == gpu.GPU_DATA_3F: fw('%s<field name="%s" type="SFVec3f" accessType="inputOutput" value="%s" />%s\n' % (ident, uniform['varname'], value, field_descr)) elif uniform['datatype'] == gpu.GPU_DATA_4F: @@ -1180,26 +1180,26 @@ def export(file, else: assert(0) - elif uniform['type'] == gpu.GPU_DYNAMIC_LAMP_DYNENERGY: + elif uniform['type'] == gpu.GPU_DYNAMIC_LIGHT_DYNENERGY: # not used ? assert(0) - elif uniform['type'] == gpu.GPU_DYNAMIC_LAMP_DYNVEC: - lamp_obj = uniform['lamp'] - frag_uniform_var_map[uniform['varname']] = lamp_obj + elif uniform['type'] == gpu.GPU_DYNAMIC_LIGHT_DYNVEC: + light_obj = uniform['lamp'] + frag_uniform_var_map[uniform['varname']] = light_obj if uniform['datatype'] == gpu.GPU_DATA_3F: - lamp_obj = uniform['lamp'] - value = '%.6f %.6f %.6f' % ((global_matrix * lamp_obj.matrix_world).to_quaternion() * mathutils.Vector((0.0, 0.0, 1.0))).normalized()[:] - field_descr = " <!--- Lamp DynDirection '%s' -->" % lamp_obj.name + light_obj = uniform['lamp'] + value = '%.6f %.6f %.6f' % ((global_matrix * light_obj.matrix_world).to_quaternion() * mathutils.Vector((0.0, 0.0, 1.0))).normalized()[:] + field_descr = " <!--- Lamp DynDirection '%s' -->" % light_obj.name fw('%s<field name="%s" type="SFVec3f" accessType="inputOutput" value="%s" />%s\n' % (ident, uniform['varname'], value, field_descr)) # route so we can have the lamp update the view - if h3d_is_object_view(scene, lamp_obj): - lamp_id = quoteattr(unique_name(lamp_obj, LA_ + lamp_obj.name, uuid_cache_lamp, clean_func=clean_def, sep="_")) + if h3d_is_object_view(scene, light_obj): + light_id = quoteattr(unique_name(light_obj, LA_ + light_obj.name, uuid_cache_light, clean_func=clean_def, sep="_")) h3d_material_route.append( '<ROUTE fromNode=%s fromField="direction" toNode=%s toField="%s" />%s' % - (lamp_id, material_id, uniform['varname'], field_descr)) + (light_id, material_id, uniform['varname'], field_descr)) else: assert(0) @@ -1330,9 +1330,9 @@ def export(file, blending = world.use_sky_blend, world.use_sky_paper, world.use_sky_real - grd_triple = clamp_color(world.horizon_color) - sky_triple = clamp_color(world.zenith_color) - mix_triple = clamp_color((grd_triple[i] + sky_triple[i]) / 2.0 for i in range(3)) + grd_triple = clight_color(world.horizon_color) + sky_triple = clight_color(world.zenith_color) + mix_triple = clight_color((grd_triple[i] + sky_triple[i]) / 2.0 for i in range(3)) ident_step = ident + (' ' * (-len(ident) + \ fw('%s<Background ' % ident))) @@ -1469,7 +1469,7 @@ def export(file, if do_remove: bpy.data.meshes.remove(me) - elif obj_type == 'LAMP': + elif obj_type == 'LIGHT': data = obj.data datatype = data.type if datatype == 'POINT': @@ -1521,7 +1521,7 @@ def export(file, ident = '' ident = writeHeader(ident) - writeNavigationInfo(ident, scene, any(obj.type == 'LAMP' for obj in objects)) + writeNavigationInfo(ident, scene, any(obj.type == 'LIGHT' for obj in objects)) writeBackground(ident, world) writeFog(ident, world) diff --git a/io_scene_x3d/import_x3d.py b/io_scene_x3d/import_x3d.py index 83dcc83d..d2592ecd 100644 --- a/io_scene_x3d/import_x3d.py +++ b/io_scene_x3d/import_x3d.py @@ -2790,9 +2790,9 @@ def appearance_LoadTexture(tex_node, ancestry, node): if bpyima: # Loading can still fail repeat_s = tex_node.getFieldAsBool('repeatS', True, ancestry) - bpyima.use_clamp_x = not repeat_s + bpyima.use_clight_x = not repeat_s repeat_t = tex_node.getFieldAsBool('repeatT', True, ancestry) - bpyima.use_clamp_y = not repeat_t + bpyima.use_clight_y = not repeat_t # Update the desc-based cache if desc: @@ -3148,7 +3148,7 @@ def importLamp_PointLight(node, ancestry): # is_on = node.getFieldAsBool('on', True, ancestry) # TODO radius = node.getFieldAsFloat('radius', 100.0, ancestry) - bpylamp = bpy.data.lamps.new(vrmlname, 'POINT') + bpylamp = bpy.data.lights.new(vrmlname, 'POINT') bpylamp.energy = intensity bpylamp.distance = radius bpylamp.color = color @@ -3169,7 +3169,7 @@ def importLamp_DirectionalLight(node, ancestry): intensity = node.getFieldAsFloat('intensity', 1.0, ancestry) # max is documented to be 1.0 but some files have higher. # is_on = node.getFieldAsBool('on', True, ancestry) # TODO - bpylamp = bpy.data.lamps.new(vrmlname, 'SUN') + bpylamp = bpy.data.lights.new(vrmlname, 'SUN') bpylamp.energy = intensity bpylamp.color = color @@ -3197,7 +3197,7 @@ def importLamp_SpotLight(node, ancestry): # is_on = node.getFieldAsBool('on', True, ancestry) # TODO radius = node.getFieldAsFloat('radius', 100.0, ancestry) - bpylamp = bpy.data.lamps.new(vrmlname, 'SPOT') + bpylamp = bpy.data.lights.new(vrmlname, 'SPOT') bpylamp.energy = intensity bpylamp.distance = radius bpylamp.color = color @@ -3271,8 +3271,8 @@ def importTransform(bpyscene, node, ancestry, global_matrix): bpyob.matrix_world = getFinalMatrix(node, None, ancestry, global_matrix) # so they are not too annoying - bpyob.empty_draw_type = 'PLAIN_AXES' - bpyob.empty_draw_size = 0.2 + bpyob.empty_display_type = 'PLAIN_AXES' + bpyob.empty_display_size = 0.2 #def importTimeSensor(node): diff --git a/io_shape_mdd/__init__.py b/io_shape_mdd/__init__.py index 99623241..b6f0e734 100644 --- a/io_shape_mdd/__init__.py +++ b/io_shape_mdd/__init__.py @@ -22,7 +22,7 @@ bl_info = { "name": "NewTek MDD format", "author": "Bill L.Nieuwendorp", "version": (1, 0, 1), - "blender": (2, 57, 0), + "blender": (2, 80, 0), "location": "File > Import-Export", "description": "Import-Export MDD as mesh shape keys", "warning": "", @@ -57,17 +57,17 @@ class ImportMDD(bpy.types.Operator, ImportHelper): filename_ext = ".mdd" - filter_glob = StringProperty( + filter_glob: StringProperty( default="*.mdd", options={'HIDDEN'}, ) - frame_start = IntProperty( + frame_start: IntProperty( name="Start Frame", description="Start frame for inserting animation", min=-300000, max=300000, default=0, ) - frame_step = IntProperty( + frame_step: IntProperty( name="Step", min=1, max=1000, default=1, @@ -97,7 +97,7 @@ class ExportMDD(bpy.types.Operator, ExportHelper): bl_label = "Export MDD" filename_ext = ".mdd" - filter_glob = StringProperty(default="*.mdd", options={'HIDDEN'}) + filter_glob: StringProperty(default="*.mdd", options={'HIDDEN'}) # get first scene to get min and max properties for frames, fps @@ -108,25 +108,25 @@ class ExportMDD(bpy.types.Operator, ExportHelper): # List of operator properties, the attributes will be assigned # to the class instance from the operator settings before calling. - fps = FloatProperty( + fps: FloatProperty( name="Frames Per Second", description="Number of frames/second", min=minfps, max=maxfps, default=25.0, ) - frame_start = IntProperty( + frame_start: IntProperty( name="Start Frame", description="Start frame for baking", min=minframe, max=maxframe, default=1, ) - frame_end = IntProperty( + frame_end: IntProperty( name="End Frame", description="End frame for baking", min=minframe, max=maxframe, default=250, ) - use_rest_frame = BoolProperty( + use_rest_frame: BoolProperty( name="Rest Frame", description="Write the rest state at the first frame", default=False, @@ -164,18 +164,25 @@ def menu_func_export(self, context): ) +classes = ( + ImportMDD, + ExportMDD +) + def register(): - bpy.utils.register_module(__name__) + for cls in classes: + bpy.utils.register_class(cls) - bpy.types.INFO_MT_file_import.append(menu_func_import) - bpy.types.INFO_MT_file_export.append(menu_func_export) + bpy.types.TOPBAR_MT_file_import.append(menu_func_import) + bpy.types.TOPBAR_MT_file_export.append(menu_func_export) def unregister(): - bpy.utils.unregister_module(__name__) + for cls in classes: + bpy.utils.unregister_class(cls) - bpy.types.INFO_MT_file_import.remove(menu_func_import) - bpy.types.INFO_MT_file_export.remove(menu_func_export) + bpy.types.TOPBAR_MT_file_import.remove(menu_func_import) + bpy.types.TOPBAR_MT_file_export.remove(menu_func_export) if __name__ == "__main__": register() diff --git a/io_shape_mdd/export_mdd.py b/io_shape_mdd/export_mdd.py index 04ca8238..48e34f29 100644 --- a/io_shape_mdd/export_mdd.py +++ b/io_shape_mdd/export_mdd.py @@ -67,7 +67,7 @@ def save(context, filepath="", frame_start=1, frame_end=300, fps=25.0, use_rest_ orig_frame = scene.frame_current scene.frame_set(frame_start) - me = obj.to_mesh(scene, True, 'PREVIEW') + me = obj.to_mesh(context.depsgraph, True) #Flip y and z ''' @@ -95,21 +95,21 @@ def save(context, filepath="", frame_start=1, frame_end=300, fps=25.0, use_rest_ if use_rest_frame: check_vertcount(me, numverts) - me.transform(mat_flip * obj.matrix_world) + me.transform(mat_flip @ obj.matrix_world) f.write(pack(">%df" % (numverts * 3), *[axis for v in me.vertices for axis in v.co])) - bpy.data.meshes.remove(me, do_unlink=True) + bpy.data.meshes.remove(me) for frame in range(frame_start, frame_end + 1): # in order to start at desired frame scene.frame_set(frame) - me = obj.to_mesh(scene, True, 'PREVIEW') + me = obj.to_mesh(context.depsgraph, True) check_vertcount(me, numverts) - me.transform(mat_flip * obj.matrix_world) + me.transform(mat_flip @ obj.matrix_world) # Write the vertex data f.write(pack(">%df" % (numverts * 3), *[axis for v in me.vertices for axis in v.co])) - bpy.data.meshes.remove(me, do_unlink=True) + bpy.data.meshes.remove(me) f.close() diff --git a/light_field_tools/light_field_tools.py b/light_field_tools/light_field_tools.py index 82d86ba4..5ab2092f 100644 --- a/light_field_tools/light_field_tools.py +++ b/light_field_tools/light_field_tools.py @@ -189,7 +189,7 @@ class OBJECT_OT_create_lightfield_rig(Operator): cam.data.angle = scene.lightfield.angle # display options of the camera - cam.data.draw_size = 0.15 + cam.data.display_size = 0.15 cam.data.lens_unit = 'FOV' # handler parent @@ -228,7 +228,7 @@ class OBJECT_OT_create_lightfield_rig(Operator): def createSpot(self, index, textured=False): scene = bpy.context.scene - bpy.ops.object.lamp_add( + bpy.ops.object.light_add( type='SPOT') spot = bpy.context.active_object diff --git a/materials_utils/__init__.py b/materials_utils/__init__.py index 5b5cda6f..94975e6b 100644 --- a/materials_utils/__init__.py +++ b/materials_utils/__init__.py @@ -2506,7 +2506,7 @@ def check_mat_name_unique(name_id="Material_new"): def included_object_types(objects): # Pass the bpy.data.objects.type to avoid needless assigning/removing # included - type that can have materials - included = ['MESH', 'CURVE', 'SURFACE', 'FONT', 'META'] + included = ['MESH', 'CURVE', 'SURFACE', 'FONT', 'META', 'GPENCIL'] obj = objects return bool(obj and obj in included) diff --git a/measureit/measureit_main.py b/measureit/measureit_main.py index 2ea41da1..91d57ce8 100644 --- a/measureit/measureit_main.py +++ b/measureit/measureit_main.py @@ -1344,7 +1344,7 @@ class AddLinkButton(Operator): if o is None: return False else: - if o.type == "MESH" or o.type == "EMPTY" or o.type == "CAMERA" or o.type == "LAMP": + if o.type == "MESH" or o.type == "EMPTY" or o.type == "CAMERA" or o.type == "LIGHT": if bpy.context.mode == 'OBJECT': return True else: @@ -1490,7 +1490,7 @@ class AddOriginButton(Operator): if o is None: return False else: - if o.type == "MESH" or o.type == "EMPTY" or o.type == "CAMERA" or o.type == "LAMP": + if o.type == "MESH" or o.type == "EMPTY" or o.type == "CAMERA" or o.type == "LIGHT": if bpy.context.mode == 'OBJECT': return True else: @@ -1892,7 +1892,7 @@ class AddNoteButton(Operator): bpy.ops.object.empty_add(type='PLAIN_AXES') myempty = bpy.data.objects[bpy.context.active_object.name] myempty.location = bpy.context.scene.cursor_location - myempty.empty_draw_size = 0.01 + myempty.empty_display_size = 0.01 myempty.name = "Annotation" # Add properties scene = context.scene diff --git a/mesh_carver.py b/mesh_carver.py index 74624abd..5fd18492 100644 --- a/mesh_carver.py +++ b/mesh_carver.py @@ -1618,7 +1618,7 @@ def update_bevel(context): mod.limit_method = 'WEIGHT' mod.width = 0.01 mod.profile = 0.699099 - mod.use_clamp_overlap = False + mod.use_clight_overlap = False mod.segments = 3 mod.loop_slide = False @@ -1676,7 +1676,7 @@ def CreateBevel(context, CurrentObject): mod.limit_method = 'WEIGHT' mod.width = 0.01 mod.profile = 0.699099 - mod.use_clamp_overlap = False + mod.use_clight_overlap = False mod.segments = 3 mod.loop_slide = False @@ -1964,12 +1964,12 @@ def duplicateObject(self): ob_new.rotation_quaternion = qRot ob_new.rotation_mode = 'XYZ' - if (ob_new.draw_type == "WIRE") and (self.BrushSolidify is False): + if (ob_new.display_type == "WIRE") and (self.BrushSolidify is False): ob_new.hide = True if self.BrushSolidify: - ob_new.draw_type = "SOLID" - ob_new.show_x_ray = False + ob_new.display_type = "SOLID" + ob_new.show_in_front = False for o in bpy.context.selected_objects: UndoAdd(self, "DUPLICATE", o) @@ -2070,20 +2070,20 @@ def boolean_operation(bool_type="DIFFERENCE"): ) BoolMod.object = bpy.context.selected_objects[sel_index] BoolMod.operation = bool_type - bpy.context.selected_objects[sel_index].draw_type = 'WIRE' + bpy.context.selected_objects[sel_index].display_type = 'WIRE' def Rebool(context, self): LastObj = context.active_object Brush = context.selected_objects[0] - Brush.draw_type = "WIRE" + Brush.display_type = "WIRE" obj = context.selected_objects[1] bpy.ops.object.select_all(action='TOGGLE') context.scene.objects.active = obj - obj.draw_type = "SOLID" + obj.display_type = "SOLID" obj.select = True bpy.ops.object.duplicate_move( OBJECT_OT_duplicate={ @@ -2124,7 +2124,7 @@ def Rebool(context, self): mb.show_viewport = False if self.ObjectBrush or self.ProfileBrush: - LastObjectCreated.show_x_ray = False + LastObjectCreated.show_in_front = False try: bpy.ops.object.modifier_apply(apply_as='DATA', modifier="CT_SOLIDIFY") except: @@ -2177,7 +2177,7 @@ def createMeshFromData(self): scn.objects.active = ob ob.select = True ob.location = Vector((10000.0, 0.0, 0.0)) - ob.draw_type = "WIRE" + ob.display_type = "WIRE" self.SolidifyPossible = True else: @@ -2390,7 +2390,7 @@ class Carver(bpy.types.Operator): self.ProfileBrush.select = True context.scene.objects.active = self.ProfileBrush # Set xRay - self.ProfileBrush.show_x_ray = True + self.ProfileBrush.show_in_front = True bpy.ops.object.modifier_add(type='SOLIDIFY') context.object.modifiers["Solidify"].name = "CT_SOLIDIFY" @@ -2407,8 +2407,8 @@ class Carver(bpy.types.Operator): self.ObjectBrush.scale = self.InitBrushScale self.ObjectBrush.rotation_quaternion = self.InitBrushQRotation self.ObjectBrush.rotation_euler = self.InitBrushERotation - self.ObjectBrush.draw_type = self.ObjectBrush_DT - self.ObjectBrush.show_x_ray = self.XRay + self.ObjectBrush.display_type = self.ObjectBrush_DT + self.ObjectBrush.show_in_front = self.XRay # Remove solidify modifier Selection_Save(self) @@ -2430,7 +2430,7 @@ class Carver(bpy.types.Operator): self.ObjectBrush.select = True context.scene.objects.active = self.ObjectBrush # Set xRay - self.ObjectBrush.show_x_ray = True + self.ObjectBrush.show_in_front = True bpy.ops.object.modifier_add(type='SOLIDIFY') context.object.modifiers["Solidify"].name = "CT_SOLIDIFY" context.object.modifiers["CT_SOLIDIFY"].thickness = 0.1 @@ -2529,12 +2529,12 @@ class Carver(bpy.types.Operator): self.ObjectBrush.select = True context.scene.objects.active = self.ObjectBrush # Active le xray - self.ObjectBrush.show_x_ray = True + self.ObjectBrush.show_in_front = True else: self.ProfileBrush.select = True context.scene.objects.active = self.ProfileBrush # Active le xray - self.ProfileBrush.show_x_ray = True + self.ProfileBrush.show_in_front = True bpy.ops.object.modifier_add(type='SOLIDIFY') context.object.modifiers["Solidify"].name = "CT_SOLIDIFY" @@ -2773,8 +2773,8 @@ class Carver(bpy.types.Operator): self.ObjectBrush.scale = self.InitBrushScale self.ObjectBrush.rotation_quaternion = self.InitBrushQRotation self.ObjectBrush.rotation_euler = self.InitBrushERotation - self.ObjectBrush.draw_type = self.ObjectBrush_DT - self.ObjectBrush.show_x_ray = self.XRay + self.ObjectBrush.display_type = self.ObjectBrush_DT + self.ObjectBrush.show_in_front = self.XRay # remove solidify Selection_Save(self) @@ -2844,8 +2844,8 @@ class Carver(bpy.types.Operator): self.ObjectBrush.scale = self.InitBrushScale self.ObjectBrush.rotation_quaternion = self.InitBrushQRotation self.ObjectBrush.rotation_euler = self.InitBrushERotation - self.ObjectBrush.draw_type = self.ObjectBrush_DT - self.ObjectBrush.show_x_ray = self.XRay + self.ObjectBrush.display_type = self.ObjectBrush_DT + self.ObjectBrush.show_in_front = self.XRay # Remove solidify modifier Selection_Save(self) @@ -3089,8 +3089,8 @@ class Carver(bpy.types.Operator): self.InitBrushScale = self.ObjectBrush.scale.copy() self.InitBrushQRotation = self.ObjectBrush.rotation_quaternion.copy() self.InitBrushERotation = self.ObjectBrush.rotation_euler.copy() - self.ObjectBrush_DT = self.ObjectBrush.draw_type - self.XRay = self.ObjectBrush.show_x_ray + self.ObjectBrush_DT = self.ObjectBrush.display_type + self.XRay = self.ObjectBrush.show_in_front # Test if flat object z = self.ObjectBrush.data.vertices[0].co.z ErrorMarge = 0.01 @@ -3363,7 +3363,7 @@ class Carver(bpy.types.Operator): bpy.ops.object.delete(use_global=False) else: if self.ObjectMode: - self.ObjectBrush.draw_type = self.ObjectBrush_DT + self.ObjectBrush.display_type = self.ObjectBrush_DT if len(context.selected_objects) > 0: bpy.ops.object.select_all(action='TOGGLE') @@ -3392,9 +3392,9 @@ class Carver(bpy.types.Operator): # If object has children, set "Wire" draw type if self.ObjectBrush is not None: if len(self.ObjectBrush.children) > 0: - self.ObjectBrush.draw_type = "WIRE" + self.ObjectBrush.display_type = "WIRE" if self.ProfileMode: - self.ProfileBrush.draw_type = "WIRE" + self.ProfileBrush.display_type = "WIRE" if bLocalView: bpy.ops.view3d.localview() diff --git a/mesh_custom_normals_tools.py b/mesh_custom_normals_tools.py deleted file mode 100644 index 462b7609..00000000 --- a/mesh_custom_normals_tools.py +++ /dev/null @@ -1,90 +0,0 @@ -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# ***** END GPL LICENCE BLOCK ***** - -bl_info = { - "name": "Custom Normals Tools", - "author": "Bastien Montagne (mont29)", - "version": (0, 0, 1), - "blender": (2, 75, 0), - "location": "3DView > Tools", - "description": "Various tools/helpers for custom normals", - "warning": "", - "support": 'OFFICIAL', - "category": "Mesh", -} - - -import bpy - - -class MESH_OT_flip_custom_normals(bpy.types.Operator): - """Flip active mesh's normals, including custom ones (only in Object mode)""" - bl_idname = "mesh.flip_custom_normals" - bl_label = "Flip Custom Normals" - bl_options = {'UNDO'} - - @classmethod - def poll(cls, context): - return context.object and context.object.type == 'MESH' and context.object.mode == 'OBJECT' - - def execute(self, context): - me = context.object.data - - if me.has_custom_normals: - me.calc_normals_split() - clnors = [0.0] * 3 * len(me.loops) - me.loops.foreach_get("normal", clnors) - - bpy.ops.object.mode_set(mode='EDIT') - bpy.ops.mesh.select_all(action='SELECT') - bpy.ops.mesh.flip_normals() - bpy.ops.object.mode_set(mode='OBJECT') - - me = context.object.data - if me.has_custom_normals: - clnors[:] = list(zip(*[(-n for n in clnors)] * 3)) - # We also have to take in account that the winding was reverted... - for p in me.polygons: - ls = p.loop_start + 1 - le = ls + p.loop_total - 1 - clnors[ls:le] = reversed(clnors[ls:le]) - me.normals_split_custom_set(clnors) - - context.scene.update() - return {'FINISHED'} - - -def flip_custom_normals_draw_func(self, context): - if isinstance(self, bpy.types.Panel): - self.layout.label("Custom Normal Tools:") - self.layout.operator(MESH_OT_flip_custom_normals.bl_idname) - - -def register(): - bpy.utils.register_module(__name__) - bpy.types.VIEW3D_PT_tools_object.append(flip_custom_normals_draw_func) - - -def unregister(): - bpy.types.VIEW3D_PT_tools_object.remove(flip_custom_normals_draw_func) - bpy.utils.unregister_module(__name__) - - -if __name__ == "__main__": - register() diff --git a/mesh_extra_tools/mesh_extrude_and_reshape.py b/mesh_extra_tools/mesh_extrude_and_reshape.py index 8716bfb1..696e775d 100644 --- a/mesh_extra_tools/mesh_extrude_and_reshape.py +++ b/mesh_extra_tools/mesh_extrude_and_reshape.py @@ -304,7 +304,7 @@ class Extrude_and_Reshape(Operator): nf = bmesh.utils.face_split(f, v1, v2) # sp_faces2.update({f, nf[0]}) - bmesh.update_edit_mesh(self.mesh, tessface=True, destructive=True) + bmesh.update_edit_mesh(self.mesh, loop_triangles=True, destructive=True) return {'FINISHED'} if self.cancel: return {'FINISHED'} @@ -345,7 +345,7 @@ class Extrude_and_Reshape(Operator): dfaces = bmesh.ops.dissolve_edges( self.bm, edges=geom, use_verts=True, use_face_split=False ) - bmesh.update_edit_mesh(self.mesh, tessface=True, destructive=True) + bmesh.update_edit_mesh(self.mesh, loop_triangles=True, destructive=True) bpy.ops.transform.translate( 'INVOKE_DEFAULT', constraint_axis=(False, False, True), constraint_orientation='NORMAL', release_confirm=True diff --git a/mesh_extra_tools/mesh_filletplus.py b/mesh_extra_tools/mesh_filletplus.py index 442adb54..f3c9cbdf 100644 --- a/mesh_extra_tools/mesh_filletplus.py +++ b/mesh_extra_tools/mesh_filletplus.py @@ -201,7 +201,7 @@ def fillets(list_0, startv, vertlist, face, adj, n, out, flip, radius): bm.edges.index_update() bm.faces.index_update() - me.update(calc_edges=True, calc_tessface=True) + me.update(calc_edges=True, calc_loop_triangles=True) bmesh.ops.recalc_face_normals(bm, faces=bm.faces) except Exception as e: diff --git a/mesh_extra_tools/mesh_vertex_chamfer.py b/mesh_extra_tools/mesh_vertex_chamfer.py index 62383c38..a80ba270 100644 --- a/mesh_extra_tools/mesh_vertex_chamfer.py +++ b/mesh_extra_tools/mesh_vertex_chamfer.py @@ -144,7 +144,7 @@ class VertexChamfer(Operator): else: v.co += displace * v.normal - me.calc_tessface() + me.calc_loop_triangles() return {'FINISHED'} diff --git a/mesh_looptools.py b/mesh_looptools.py index 62417f21..6e7d2b14 100644 --- a/mesh_looptools.py +++ b/mesh_looptools.py @@ -20,7 +20,7 @@ bl_info = { "name": "LoopTools", "author": "Bart Crouch", "version": (4, 6, 7), - "blender": (2, 72, 2), + "blender": (2, 80, 0), "location": "View3D > Toolbar and View3D > Specials (W-key)", "warning": "", "description": "Mesh modelling toolkit. Several tools to aid modelling", @@ -110,10 +110,11 @@ loops, derived, mapping): del looptools_cache[tool] # prepare values to be saved to cache input = [v.index for v in bm.verts if v.select and not v.hide] - modifiers = [mod.name for mod in object.modifiers if mod.show_viewport and - mod.type == 'MIRROR'] + modifiers = [mod.name for mod in object.modifiers if mod.show_viewport + and mod.type == 'MIRROR'] # update cache - looptools_cache[tool] = {"input": input, "object": object.name, + looptools_cache[tool] = { + "input": input, "object": object.name, "input_method": input_method, "boundaries": boundaries, "single_loops": single_loops, "loops": loops, "derived": derived, "mapping": mapping, "modifiers": modifiers} @@ -276,7 +277,7 @@ def calculate_plane(bm_mod, loop, method="best_fit", object=False): vec2 = mathutils.Vector((1.0, 1.0, 1.0)) for i in range(itermax): vec = vec2 - vec2 = mat * vec + vec2 = mat @ vec if vec2.length != 0: vec2 /= vec2.length if vec2 == vec: @@ -831,7 +832,7 @@ def terminate(global_undo): # update editmesh cached data obj = bpy.context.active_object if obj.mode == 'EDIT': - bmesh.update_edit_mesh(obj.data, tessface=True, destructive=True) + bmesh.update_edit_mesh(obj.data, loop_triangles=True, destructive=True) bpy.context.user_preferences.edit.use_global_undo = global_undo @@ -1043,11 +1044,11 @@ def bridge_calculate_lines(bm, loops, mode, twist, reverse): itermax = 500 iter = 0 vec = mathutils.Vector((1.0, 1.0, 1.0)) - vec2 = (mat * vec) / (mat * vec).length + vec2 = (mat @ vec) / (mat @ vec).length while vec != vec2 and iter < itermax: iter += 1 vec = vec2 - vec2 = mat * vec + vec2 = mat @ vec if vec2.length != 0: vec2 /= vec2.length if vec2.length == 0: @@ -1079,7 +1080,7 @@ def bridge_calculate_lines(bm, loops, mode, twist, reverse): # match start vertex of loop1 with loop2 target_vector = bm.verts[loop2[0]].co - center2 - dif_angles = [[(rotation_matrix * (bm.verts[vertex].co - center1) + dif_angles = [[(rotation_matrix @ (bm.verts[vertex].co - center1) ).angle(target_vector, 0), False, i] for i, vertex in enumerate(loop1)] dif_angles.sort() @@ -1161,7 +1162,7 @@ def bridge_calculate_lines(bm, loops, mode, twist, reverse): shifting = False break to_last, to_first = [ - (rotation_matrix * (bm.verts[loop1[-1]].co - center1)).angle( + (rotation_matrix @ (bm.verts[loop1[-1]].co - center1)).angle( (bm.verts[loop2[i]].co - center2), 0) for i in [-1, 0] ] if to_first < to_last: @@ -1802,7 +1803,7 @@ def circle_calculate_best_fit(locs_2d): jmat2.invert() except: pass - dx0, dy0, dr = jmat2 * k2 + dx0, dy0, dr = jmat2 @ k2 x0 += dx0 y0 += dy0 r += dr @@ -2610,7 +2611,7 @@ def gstretch_align_pairs(ls_pairs, object, bm_mod, method): else: relative_distance = relative_lengths[i] - loc1 = object.matrix_world * bm_mod.verts[v_index].co + loc1 = object.matrix_world @ bm_mod.verts[v_index].co loc2, stroke_lengths_cache = gstretch_eval_stroke(stroke, relative_distance, stroke_lengths_cache) total_distance += (loc2 - loc1).length @@ -2683,7 +2684,7 @@ def gstretch_calculate_verts(loop, stroke, object, bm_mod, method): relative_distance = relative_lengths[i] loc, stroke_lengths_cache = gstretch_eval_stroke(stroke, relative_distance, stroke_lengths_cache) - loc = matrix_inverse * loc + loc = matrix_inverse @ loc move.append([v_index, loc]) return(move) @@ -2828,8 +2829,8 @@ def gstretch_eval_stroke(stroke, distance, stroke_lengths_cache=False): def gstretch_get_fake_strokes(object, bm_mod, loops): strokes = [] for loop in loops: - p1 = object.matrix_world * bm_mod.verts[loop[0][0]].co - p2 = object.matrix_world * bm_mod.verts[loop[0][-1]].co + p1 = object.matrix_world @ bm_mod.verts[loop[0][0]].co + p2 = object.matrix_world @ bm_mod.verts[loop[0][-1]].co strokes.append(gstretch_fake_stroke([p1, p2])) return(strokes) @@ -2866,7 +2867,7 @@ def gstretch_match_loops_strokes(loops, strokes, object, bm_mod): for v_index in loop[0]: center += bm_mod.verts[v_index].co center /= len(loop[0]) - center = object.matrix_world * center + center = object.matrix_world @ center loop_centers.append([center, loop]) # calculate stroke centers @@ -3189,14 +3190,14 @@ class Bridge(Operator): bl_description = "Bridge two, or loft several, loops of vertices" bl_options = {'REGISTER', 'UNDO'} - cubic_strength = FloatProperty( + cubic_strength: FloatProperty( name="Strength", description="Higher strength results in more fluid curves", default=1.0, soft_min=-3.0, soft_max=3.0 ) - interpolation = EnumProperty( + interpolation: EnumProperty( name="Interpolation mode", items=(('cubic', "Cubic", "Gives curved results"), ('linear', "Linear", "Basic, fast, straight interpolation")), @@ -3204,18 +3205,18 @@ class Bridge(Operator): "segments", default='cubic' ) - loft = BoolProperty( + loft: BoolProperty( name="Loft", description="Loft multiple loops, instead of considering them as " "a multi-input for bridging", default=False ) - loft_loop = BoolProperty( + loft_loop: BoolProperty( name="Loop", description="Connect the first and the last loop with each other", default=False ) - min_width = IntProperty( + min_width: IntProperty( name="Minimum width", description="Segments with an edge smaller than this are merged " "(compared to base edge)", @@ -3224,32 +3225,32 @@ class Bridge(Operator): max=100, subtype='PERCENTAGE' ) - mode = EnumProperty( + mode: EnumProperty( name="Mode", items=(('basic', "Basic", "Fast algorithm"), ('shortest', "Shortest edge", "Slower algorithm with better vertex matching")), description="Algorithm used for bridging", default='shortest' ) - remove_faces = BoolProperty( + remove_faces: BoolProperty( name="Remove faces", description="Remove faces that are internal after bridging", default=True ) - reverse = BoolProperty( + reverse: BoolProperty( name="Reverse", description="Manually override the direction in which the loops " "are bridged. Only use if the tool gives the wrong result", default=False ) - segments = IntProperty( + segments: IntProperty( name="Segments", description="Number of segments used to bridge the gap (0=automatic)", default=1, min=0, soft_max=20 ) - twist = IntProperty( + twist: IntProperty( name="Twist", description="Twist what vertices are connected to each other", default=0 @@ -3367,7 +3368,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, tessface=False, + bmesh.update_edit_mesh(object.data, loop_triangles=False, destructive=True) bpy.ops.mesh.normals_make_consistent() @@ -3384,24 +3385,24 @@ class Circle(Operator): bl_description = "Move selected vertices into a circle shape" bl_options = {'REGISTER', 'UNDO'} - custom_radius = BoolProperty( + custom_radius: BoolProperty( name="Radius", description="Force a custom radius", default=False ) - fit = EnumProperty( + fit: EnumProperty( name="Method", items=(("best", "Best fit", "Non-linear least squares"), ("inside", "Fit inside", "Only move vertices towards the center")), description="Method used for fitting a circle to the vertices", default='best' ) - flatten = BoolProperty( + flatten: BoolProperty( name="Flatten", description="Flatten the circle, instead of projecting it on the mesh", default=True ) - influence = FloatProperty( + influence: FloatProperty( name="Influence", description="Force of the tool", default=100.0, @@ -3410,28 +3411,28 @@ class Circle(Operator): precision=1, subtype='PERCENTAGE' ) - lock_x = BoolProperty( + lock_x: BoolProperty( name="Lock X", description="Lock editing of the x-coordinate", default=False ) - lock_y = BoolProperty( + lock_y: BoolProperty( name="Lock Y", description="Lock editing of the y-coordinate", default=False ) - lock_z = BoolProperty(name="Lock Z", + lock_z: BoolProperty(name="Lock Z", description="Lock editing of the z-coordinate", default=False ) - radius = FloatProperty( + radius: FloatProperty( name="Radius", description="Custom radius for circle", default=1.0, min=0.0, soft_max=1000.0 ) - regular = BoolProperty( + regular: BoolProperty( name="Regular", description="Distribute vertices at constant distances along the circle", default=True @@ -3557,12 +3558,12 @@ class Curve(Operator): bl_description = "Turn a loop into a smooth curve" bl_options = {'REGISTER', 'UNDO'} - boundaries = BoolProperty( + boundaries: BoolProperty( name="Boundaries", description="Limit the tool to work within the boundaries of the selected vertices", default=False ) - influence = FloatProperty( + influence: FloatProperty( name="Influence", description="Force of the tool", default=100.0, @@ -3571,34 +3572,34 @@ class Curve(Operator): precision=1, subtype='PERCENTAGE' ) - interpolation = EnumProperty( + interpolation: EnumProperty( name="Interpolation", items=(("cubic", "Cubic", "Natural cubic spline, smooth results"), ("linear", "Linear", "Simple and fast linear algorithm")), description="Algorithm used for interpolation", default='cubic' ) - lock_x = BoolProperty( + lock_x: BoolProperty( name="Lock X", description="Lock editing of the x-coordinate", default=False ) - lock_y = BoolProperty( + lock_y: BoolProperty( name="Lock Y", description="Lock editing of the y-coordinate", default=False ) - lock_z = BoolProperty( + lock_z: BoolProperty( name="Lock Z", description="Lock editing of the z-coordinate", default=False ) - regular = BoolProperty( + regular: BoolProperty( name="Regular", description="Distribute vertices at constant distances along the curve", default=True ) - restriction = EnumProperty( + restriction: EnumProperty( name="Restriction", items=(("none", "None", "No restrictions on vertex movement"), ("extrude", "Extrude only", "Only allow extrusions (no indentations)"), @@ -3702,7 +3703,7 @@ class Flatten(Operator): bl_description = "Flatten vertices on a best-fitting plane" bl_options = {'REGISTER', 'UNDO'} - influence = FloatProperty( + influence: FloatProperty( name="Influence", description="Force of the tool", default=100.0, @@ -3711,21 +3712,21 @@ class Flatten(Operator): precision=1, subtype='PERCENTAGE' ) - lock_x = BoolProperty( + lock_x: BoolProperty( name="Lock X", description="Lock editing of the x-coordinate", default=False ) - lock_y = BoolProperty( + lock_y: BoolProperty( name="Lock Y", description="Lock editing of the y-coordinate", default=False ) - lock_z = BoolProperty(name="Lock Z", + lock_z: BoolProperty(name="Lock Z", description="Lock editing of the z-coordinate", default=False ) - plane = EnumProperty( + plane: EnumProperty( name="Plane", items=(("best_fit", "Best fit", "Calculate a best fitting plane"), ("normal", "Normal", "Derive plane from averaging vertex normals"), @@ -3733,7 +3734,7 @@ class Flatten(Operator): description="Plane on which vertices are flattened", default='best_fit' ) - restriction = EnumProperty( + restriction: EnumProperty( name="Restriction", items=(("none", "None", "No restrictions on vertex movement"), ("bounding_box", "Bounding box", "Vertices are restricted to " @@ -3841,7 +3842,7 @@ class GStretch(Operator): bl_description = "Stretch selected vertices to Grease Pencil stroke" bl_options = {'REGISTER', 'UNDO'} - conversion = EnumProperty( + conversion: EnumProperty( name="Conversion", items=(("distance", "Distance", "Set the distance between vertices " "of the converted grease pencil stroke"), @@ -3856,7 +3857,7 @@ class GStretch(Operator): "use this simplification method", default='limit_vertices' ) - conversion_distance = FloatProperty( + conversion_distance: FloatProperty( name="Distance", description="Absolute distance between vertices along the converted " "grease pencil stroke", @@ -3865,7 +3866,7 @@ class GStretch(Operator): soft_min=0.01, soft_max=100 ) - conversion_max = IntProperty( + conversion_max: IntProperty( name="Max Vertices", description="Maximum number of vertices grease pencil strokes will " "have, when they are converted to geomtery", @@ -3874,7 +3875,7 @@ class GStretch(Operator): soft_max=500, update=gstretch_update_min ) - conversion_min = IntProperty( + conversion_min: IntProperty( name="Min Vertices", description="Minimum number of vertices grease pencil strokes will " "have, when they are converted to geomtery", @@ -3883,7 +3884,7 @@ class GStretch(Operator): soft_max=500, update=gstretch_update_max ) - conversion_vertices = IntProperty( + conversion_vertices: IntProperty( name="Vertices", description="Number of vertices grease pencil strokes will " "have, when they are converted to geometry. If strokes have less " @@ -3892,13 +3893,13 @@ class GStretch(Operator): min=3, soft_max=500 ) - delete_strokes = BoolProperty( + delete_strokes: BoolProperty( name="Delete strokes", description="Remove Grease Pencil strokes if they have been used " "for Gstretch. WARNING: DOES NOT SUPPORT UNDO", default=False ) - influence = FloatProperty( + influence: FloatProperty( name="Influence", description="Force of the tool", default=100.0, @@ -3907,22 +3908,22 @@ class GStretch(Operator): precision=1, subtype='PERCENTAGE' ) - lock_x = BoolProperty( + lock_x: BoolProperty( name="Lock X", description="Lock editing of the x-coordinate", default=False ) - lock_y = BoolProperty( + lock_y: BoolProperty( name="Lock Y", description="Lock editing of the y-coordinate", default=False ) - lock_z = BoolProperty( + lock_z: BoolProperty( name="Lock Z", description="Lock editing of the z-coordinate", default=False ) - method = EnumProperty( + method: EnumProperty( name="Method", items=(("project", "Project", "Project vertices onto the stroke, " "using vertex normals and connected edges"), @@ -4086,7 +4087,7 @@ class GStretch(Operator): lock = [self.lock_x, self.lock_y, self.lock_z] else: lock = False - bmesh.update_edit_mesh(object.data, tessface=True, destructive=True) + bmesh.update_edit_mesh(object.data, loop_triangles=True, destructive=True) move_verts(object, bm, mapping, move, lock, self.influence) # cleaning up @@ -4104,7 +4105,7 @@ class Relax(Operator): bl_description = "Relax the loop, so it is smoother" bl_options = {'REGISTER', 'UNDO'} - input = EnumProperty( + input: EnumProperty( name="Input", items=(("all", "Parallel (all)", "Also use non-selected " "parallel loops as input"), @@ -4112,14 +4113,14 @@ class Relax(Operator): description="Loops that are relaxed", default='selected' ) - interpolation = EnumProperty( + interpolation: EnumProperty( name="Interpolation", items=(("cubic", "Cubic", "Natural cubic spline, smooth results"), ("linear", "Linear", "Simple and fast linear algorithm")), description="Algorithm used for interpolation", default='cubic' ) - iterations = EnumProperty( + iterations: EnumProperty( name="Iterations", items=(("1", "1", "One"), ("3", "3", "Three"), @@ -4129,7 +4130,7 @@ class Relax(Operator): description="Number of times the loop is relaxed", default="1" ) - regular = BoolProperty( + regular: BoolProperty( name="Regular", description="Distribute vertices at constant distances along the loop", default=True @@ -4203,7 +4204,7 @@ class Space(Operator): bl_description = "Space the vertices in a regular distrubtion on the loop" bl_options = {'REGISTER', 'UNDO'} - influence = FloatProperty( + influence: FloatProperty( name="Influence", description="Force of the tool", default=100.0, @@ -4212,7 +4213,7 @@ class Space(Operator): precision=1, subtype='PERCENTAGE' ) - input = EnumProperty( + input: EnumProperty( name="Input", items=(("all", "Parallel (all)", "Also use non-selected " "parallel loops as input"), @@ -4220,24 +4221,24 @@ class Space(Operator): description="Loops that are spaced", default='selected' ) - interpolation = EnumProperty( + interpolation: EnumProperty( name="Interpolation", items=(("cubic", "Cubic", "Natural cubic spline, smooth results"), ("linear", "Linear", "Vertices are projected on existing edges")), description="Algorithm used for interpolation", default='cubic' ) - lock_x = BoolProperty( + lock_x: BoolProperty( name="Lock X", description="Lock editing of the x-coordinate", default=False ) - lock_y = BoolProperty( + lock_y: BoolProperty( name="Lock Y", description="Lock editing of the y-coordinate", default=False ) - lock_z = BoolProperty( + lock_z: BoolProperty( name="Lock Z", description="Lock editing of the z-coordinate", default=False @@ -4347,8 +4348,8 @@ class VIEW3D_MT_edit_mesh_looptools(Menu): # panel containing all tools class VIEW3D_PT_tools_looptools(Panel): bl_space_type = 'VIEW_3D' - bl_region_type = 'TOOLS' - bl_category = 'Tools' + bl_region_type = 'UI' + bl_category = 'View' bl_context = "mesh_edit" bl_label = "LoopTools" bl_options = {'DEFAULT_CLOSED'} @@ -4359,7 +4360,7 @@ class VIEW3D_PT_tools_looptools(Panel): lt = context.window_manager.looptools # bridge - first line - split = col.split(percentage=0.15, align=True) + split = col.split(factor=0.15, align=True) if lt.display_bridge: split.prop(lt, "display_bridge", text="", icon='DOWNARROW_HLT') else: @@ -4395,7 +4396,7 @@ class VIEW3D_PT_tools_looptools(Panel): row.prop(lt, "bridge_reverse") # circle - first line - split = col.split(percentage=0.15, align=True) + split = col.split(factor=0.15, align=True) if lt.display_circle: split.prop(lt, "display_circle", text="", icon='DOWNARROW_HLT') else: @@ -4433,7 +4434,7 @@ class VIEW3D_PT_tools_looptools(Panel): col_move.prop(lt, "circle_influence") # curve - first line - split = col.split(percentage=0.15, align=True) + split = col.split(factor=0.15, align=True) if lt.display_curve: split.prop(lt, "display_curve", text="", icon='DOWNARROW_HLT') else: @@ -4465,7 +4466,7 @@ class VIEW3D_PT_tools_looptools(Panel): col_move.prop(lt, "curve_influence") # flatten - first line - split = col.split(percentage=0.15, align=True) + split = col.split(factor=0.15, align=True) if lt.display_flatten: split.prop(lt, "display_flatten", text="", icon='DOWNARROW_HLT') else: @@ -4495,7 +4496,7 @@ class VIEW3D_PT_tools_looptools(Panel): col_move.prop(lt, "flatten_influence") # gstretch - first line - split = col.split(percentage=0.15, align=True) + split = col.split(factor=0.15, align=True) if lt.display_gstretch: split.prop(lt, "display_gstretch", text="", icon='DOWNARROW_HLT') else: @@ -4536,7 +4537,7 @@ class VIEW3D_PT_tools_looptools(Panel): box.operator("remove.gp", text="Delete GP Strokes") # loft - first line - split = col.split(percentage=0.15, align=True) + split = col.split(factor=0.15, align=True) if lt.display_loft: split.prop(lt, "display_loft", text="", icon='DOWNARROW_HLT') else: @@ -4573,7 +4574,7 @@ class VIEW3D_PT_tools_looptools(Panel): row.prop(lt, "bridge_reverse") # relax - first line - split = col.split(percentage=0.15, align=True) + split = col.split(factor=0.15, align=True) if lt.display_relax: split.prop(lt, "display_relax", text="", icon='DOWNARROW_HLT') else: @@ -4588,7 +4589,7 @@ class VIEW3D_PT_tools_looptools(Panel): box.prop(lt, "relax_regular") # space - first line - split = col.split(percentage=0.15, align=True) + split = col.split(factor=0.15, align=True) if lt.display_space: split.prop(lt, "display_space", text="", icon='DOWNARROW_HLT') else: @@ -4625,74 +4626,74 @@ class LoopToolsProps(PropertyGroup): bpy.context.window_manager.looptools """ # general display properties - display_bridge = BoolProperty( + display_bridge: BoolProperty( name="Bridge settings", description="Display settings of the Bridge tool", default=False ) - display_circle = BoolProperty( + display_circle: BoolProperty( name="Circle settings", description="Display settings of the Circle tool", default=False ) - display_curve = BoolProperty( + display_curve: BoolProperty( name="Curve settings", description="Display settings of the Curve tool", default=False ) - display_flatten = BoolProperty( + display_flatten: BoolProperty( name="Flatten settings", description="Display settings of the Flatten tool", default=False ) - display_gstretch = BoolProperty( + display_gstretch: BoolProperty( name="Gstretch settings", description="Display settings of the Gstretch tool", default=False ) - display_loft = BoolProperty( + display_loft: BoolProperty( name="Loft settings", description="Display settings of the Loft tool", default=False ) - display_relax = BoolProperty( + display_relax: BoolProperty( name="Relax settings", description="Display settings of the Relax tool", default=False ) - display_space = BoolProperty( + display_space: BoolProperty( name="Space settings", description="Display settings of the Space tool", default=False ) # bridge properties - bridge_cubic_strength = FloatProperty( + bridge_cubic_strength: FloatProperty( name="Strength", description="Higher strength results in more fluid curves", default=1.0, soft_min=-3.0, soft_max=3.0 ) - bridge_interpolation = EnumProperty( + bridge_interpolation: EnumProperty( name="Interpolation mode", items=(('cubic', "Cubic", "Gives curved results"), ('linear', "Linear", "Basic, fast, straight interpolation")), description="Interpolation mode: algorithm used when creating segments", default='cubic' ) - bridge_loft = BoolProperty( + bridge_loft: BoolProperty( name="Loft", description="Loft multiple loops, instead of considering them as " "a multi-input for bridging", default=False ) - bridge_loft_loop = BoolProperty( + bridge_loft_loop: BoolProperty( name="Loop", description="Connect the first and the last loop with each other", default=False ) - bridge_min_width = IntProperty( + bridge_min_width: IntProperty( name="Minimum width", description="Segments with an edge smaller than this are merged " "(compared to base edge)", @@ -4701,7 +4702,7 @@ class LoopToolsProps(PropertyGroup): max=100, subtype='PERCENTAGE' ) - bridge_mode = EnumProperty( + bridge_mode: EnumProperty( name="Mode", items=(('basic', "Basic", "Fast algorithm"), ('shortest', "Shortest edge", "Slower algorithm with " @@ -4709,49 +4710,49 @@ class LoopToolsProps(PropertyGroup): description="Algorithm used for bridging", default='shortest' ) - bridge_remove_faces = BoolProperty( + bridge_remove_faces: BoolProperty( name="Remove faces", description="Remove faces that are internal after bridging", default=True ) - bridge_reverse = BoolProperty( + bridge_reverse: BoolProperty( name="Reverse", description="Manually override the direction in which the loops " "are bridged. Only use if the tool gives the wrong result", default=False ) - bridge_segments = IntProperty( + bridge_segments: IntProperty( name="Segments", description="Number of segments used to bridge the gap (0=automatic)", default=1, min=0, soft_max=20 ) - bridge_twist = IntProperty( + bridge_twist: IntProperty( name="Twist", description="Twist what vertices are connected to each other", default=0 ) # circle properties - circle_custom_radius = BoolProperty( + circle_custom_radius: BoolProperty( name="Radius", description="Force a custom radius", default=False ) - circle_fit = EnumProperty( + circle_fit: EnumProperty( name="Method", items=(("best", "Best fit", "Non-linear least squares"), ("inside", "Fit inside", "Only move vertices towards the center")), description="Method used for fitting a circle to the vertices", default='best' ) - circle_flatten = BoolProperty( + circle_flatten: BoolProperty( name="Flatten", description="Flatten the circle, instead of projecting it on the mesh", default=True ) - circle_influence = FloatProperty( + circle_influence: FloatProperty( name="Influence", description="Force of the tool", default=100.0, @@ -4760,41 +4761,41 @@ class LoopToolsProps(PropertyGroup): precision=1, subtype='PERCENTAGE' ) - circle_lock_x = BoolProperty( + circle_lock_x: BoolProperty( name="Lock X", description="Lock editing of the x-coordinate", default=False ) - circle_lock_y = BoolProperty( + circle_lock_y: BoolProperty( name="Lock Y", description="Lock editing of the y-coordinate", default=False ) - circle_lock_z = BoolProperty( + circle_lock_z: BoolProperty( name="Lock Z", description="Lock editing of the z-coordinate", default=False ) - circle_radius = FloatProperty( + circle_radius: FloatProperty( name="Radius", description="Custom radius for circle", default=1.0, min=0.0, soft_max=1000.0 ) - circle_regular = BoolProperty( + circle_regular: BoolProperty( name="Regular", description="Distribute vertices at constant distances along the circle", default=True ) # curve properties - curve_boundaries = BoolProperty( + curve_boundaries: BoolProperty( name="Boundaries", description="Limit the tool to work within the boundaries of the " "selected vertices", default=False ) - curve_influence = FloatProperty( + curve_influence: FloatProperty( name="Influence", description="Force of the tool", default=100.0, @@ -4803,34 +4804,34 @@ class LoopToolsProps(PropertyGroup): precision=1, subtype='PERCENTAGE' ) - curve_interpolation = EnumProperty( + curve_interpolation: EnumProperty( name="Interpolation", items=(("cubic", "Cubic", "Natural cubic spline, smooth results"), ("linear", "Linear", "Simple and fast linear algorithm")), description="Algorithm used for interpolation", default='cubic' ) - curve_lock_x = BoolProperty( + curve_lock_x: BoolProperty( name="Lock X", description="Lock editing of the x-coordinate", default=False ) - curve_lock_y = BoolProperty( + curve_lock_y: BoolProperty( name="Lock Y", description="Lock editing of the y-coordinate", default=False ) - curve_lock_z = BoolProperty( + curve_lock_z: BoolProperty( name="Lock Z", description="Lock editing of the z-coordinate", default=False ) - curve_regular = BoolProperty( + curve_regular: BoolProperty( name="Regular", description="Distribute vertices at constant distances along the curve", default=True ) - curve_restriction = EnumProperty( + curve_restriction: EnumProperty( name="Restriction", items=(("none", "None", "No restrictions on vertex movement"), ("extrude", "Extrude only", "Only allow extrusions (no indentations)"), @@ -4840,7 +4841,7 @@ class LoopToolsProps(PropertyGroup): ) # flatten properties - flatten_influence = FloatProperty( + flatten_influence: FloatProperty( name="Influence", description="Force of the tool", default=100.0, @@ -4849,20 +4850,20 @@ class LoopToolsProps(PropertyGroup): precision=1, subtype='PERCENTAGE' ) - flatten_lock_x = BoolProperty( + flatten_lock_x: BoolProperty( name="Lock X", description="Lock editing of the x-coordinate", default=False) - flatten_lock_y = BoolProperty(name="Lock Y", + flatten_lock_y: BoolProperty(name="Lock Y", description="Lock editing of the y-coordinate", default=False ) - flatten_lock_z = BoolProperty( + flatten_lock_z: BoolProperty( name="Lock Z", description="Lock editing of the z-coordinate", default=False ) - flatten_plane = EnumProperty( + flatten_plane: EnumProperty( name="Plane", items=(("best_fit", "Best fit", "Calculate a best fitting plane"), ("normal", "Normal", "Derive plane from averaging vertex " @@ -4872,7 +4873,7 @@ class LoopToolsProps(PropertyGroup): description="Plane on which vertices are flattened", default='best_fit' ) - flatten_restriction = EnumProperty( + flatten_restriction: EnumProperty( name="Restriction", items=(("none", "None", "No restrictions on vertex movement"), ("bounding_box", "Bounding box", "Vertices are restricted to " @@ -4882,7 +4883,7 @@ class LoopToolsProps(PropertyGroup): ) # gstretch properties - gstretch_conversion = EnumProperty( + gstretch_conversion: EnumProperty( name="Conversion", items=(("distance", "Distance", "Set the distance between vertices " "of the converted grease pencil stroke"), @@ -4897,7 +4898,7 @@ class LoopToolsProps(PropertyGroup): "use this simplification method", default='limit_vertices' ) - gstretch_conversion_distance = FloatProperty( + gstretch_conversion_distance: FloatProperty( name="Distance", description="Absolute distance between vertices along the converted " "grease pencil stroke", @@ -4906,7 +4907,7 @@ class LoopToolsProps(PropertyGroup): soft_min=0.01, soft_max=100 ) - gstretch_conversion_max = IntProperty( + gstretch_conversion_max: IntProperty( name="Max Vertices", description="Maximum number of vertices grease pencil strokes will " "have, when they are converted to geomtery", @@ -4915,7 +4916,7 @@ class LoopToolsProps(PropertyGroup): soft_max=500, update=gstretch_update_min ) - gstretch_conversion_min = IntProperty( + gstretch_conversion_min: IntProperty( name="Min Vertices", description="Minimum number of vertices grease pencil strokes will " "have, when they are converted to geomtery", @@ -4924,7 +4925,7 @@ class LoopToolsProps(PropertyGroup): soft_max=500, update=gstretch_update_max ) - gstretch_conversion_vertices = IntProperty( + gstretch_conversion_vertices: IntProperty( name="Vertices", description="Number of vertices grease pencil strokes will " "have, when they are converted to geometry. If strokes have less " @@ -4933,13 +4934,13 @@ class LoopToolsProps(PropertyGroup): min=3, soft_max=500 ) - gstretch_delete_strokes = BoolProperty( + gstretch_delete_strokes: BoolProperty( name="Delete strokes", description="Remove Grease Pencil strokes if they have been used " "for Gstretch. WARNING: DOES NOT SUPPORT UNDO", default=False ) - gstretch_influence = FloatProperty( + gstretch_influence: FloatProperty( name="Influence", description="Force of the tool", default=100.0, @@ -4948,22 +4949,22 @@ class LoopToolsProps(PropertyGroup): precision=1, subtype='PERCENTAGE' ) - gstretch_lock_x = BoolProperty( + gstretch_lock_x: BoolProperty( name="Lock X", description="Lock editing of the x-coordinate", default=False ) - gstretch_lock_y = BoolProperty( + gstretch_lock_y: BoolProperty( name="Lock Y", description="Lock editing of the y-coordinate", default=False ) - gstretch_lock_z = BoolProperty( + gstretch_lock_z: BoolProperty( name="Lock Z", description="Lock editing of the z-coordinate", default=False ) - gstretch_method = EnumProperty( + gstretch_method: EnumProperty( name="Method", items=(("project", "Project", "Project vertices onto the stroke, " "using vertex normals and connected edges"), @@ -4977,21 +4978,21 @@ class LoopToolsProps(PropertyGroup): ) # relax properties - relax_input = EnumProperty(name="Input", + relax_input: EnumProperty(name="Input", items=(("all", "Parallel (all)", "Also use non-selected " "parallel loops as input"), ("selected", "Selection", "Only use selected vertices as input")), description="Loops that are relaxed", default='selected' ) - relax_interpolation = EnumProperty( + relax_interpolation: EnumProperty( name="Interpolation", items=(("cubic", "Cubic", "Natural cubic spline, smooth results"), ("linear", "Linear", "Simple and fast linear algorithm")), description="Algorithm used for interpolation", default='cubic' ) - relax_iterations = EnumProperty(name="Iterations", + relax_iterations: EnumProperty(name="Iterations", items=(("1", "1", "One"), ("3", "3", "Three"), ("5", "5", "Five"), @@ -5000,14 +5001,14 @@ class LoopToolsProps(PropertyGroup): description="Number of times the loop is relaxed", default="1" ) - relax_regular = BoolProperty( + relax_regular: BoolProperty( name="Regular", description="Distribute vertices at constant distances along the loop", default=True ) # space properties - space_influence = FloatProperty( + space_influence: FloatProperty( name="Influence", description="Force of the tool", default=100.0, @@ -5016,7 +5017,7 @@ class LoopToolsProps(PropertyGroup): precision=1, subtype='PERCENTAGE' ) - space_input = EnumProperty( + space_input: EnumProperty( name="Input", items=(("all", "Parallel (all)", "Also use non-selected " "parallel loops as input"), @@ -5024,24 +5025,24 @@ class LoopToolsProps(PropertyGroup): description="Loops that are spaced", default='selected' ) - space_interpolation = EnumProperty( + space_interpolation: EnumProperty( name="Interpolation", items=(("cubic", "Cubic", "Natural cubic spline, smooth results"), ("linear", "Linear", "Vertices are projected on existing edges")), description="Algorithm used for interpolation", default='cubic' ) - space_lock_x = BoolProperty( + space_lock_x: BoolProperty( name="Lock X", description="Lock editing of the x-coordinate", default=False ) - space_lock_y = BoolProperty( + space_lock_y: BoolProperty( name="Lock Y", description="Lock editing of the y-coordinate", default=False ) - space_lock_z = BoolProperty( + space_lock_z: BoolProperty( name="Lock Z", description="Lock editing of the z-coordinate", default=False @@ -5083,7 +5084,7 @@ class LoopPreferences(AddonPreferences): # when defining this in a submodule of a python package. bl_idname = __name__ - category = StringProperty( + category: StringProperty( name="Tab Category", description="Choose a name for the category of the panel", default="Tools", @@ -5127,12 +5128,13 @@ def register(): # unregistering and removing menus def unregister(): - for cls in classes: + for cls in reversed(classes): bpy.utils.unregister_class(cls) bpy.types.VIEW3D_MT_edit_mesh_specials.remove(menu_func) try: del bpy.types.WindowManager.looptools - except: + except Exception as e: + print('unregister fail:\n', e) pass diff --git a/mesh_snap_utilities_line.py b/mesh_snap_utilities_line.py index 8f2f2a94..e70e8b52 100644 --- a/mesh_snap_utilities_line.py +++ b/mesh_snap_utilities_line.py @@ -355,7 +355,7 @@ def draw_line(self, obj, bm, bm_geom, location): drawing_is_dirt = False update_edit_mesh = False - tessface = False + loop_triangles = False if bm_geom is None: vert = bm.verts.new(location) @@ -437,7 +437,7 @@ def draw_line(self, obj, bm, bm_geom, location): facesp = bmesh.utils.face_split_edgenet(face, ed_list) del split_faces update_edit_mesh = True - tessface = True + loop_triangles = True else: if self.intersect: facesp = bmesh.ops.connect_vert_pair(bm, verts=[v1, v2], verts_exclude=bm.verts) @@ -450,7 +450,7 @@ def draw_line(self, obj, bm, bm_geom, location): for edge in facesp['edges']: self.list_edges.append(edge) update_edit_mesh = True - tessface = True + loop_triangles = True # create face if self.create_face: @@ -469,10 +469,10 @@ def draw_line(self, obj, bm, bm_geom, location): bmesh.ops.edgenet_fill(bm, edges=list(ed_list)) update_edit_mesh = True - tessface = True + loop_triangles = True # print('face created') if update_edit_mesh: - bmesh.update_edit_mesh(obj.data, tessface = tessface) + bmesh.update_edit_mesh(obj.data, loop_triangles = loop_triangles) self.sctx.update_drawn_snap_object(self.snap_obj) #bm.verts.index_update() elif drawing_is_dirt: diff --git a/modules/rna_manual_reference.py b/modules/rna_manual_reference.py index 6f7903ef..0f72ad87 100644 --- a/modules/rna_manual_reference.py +++ b/modules/rna_manual_reference.py @@ -253,7 +253,6 @@ url_manual_mapping = ( ("bpy.types.cyclesrendersettings*", "render/cycles/settings/index.html#bpy-types-cyclesrendersettings"), ("bpy.types.datatransfermodifier*", "modeling/modifiers/modify/data_transfer.html#bpy-types-datatransfermodifier"), ("bpy.types.dynamicpaintmodifier*", "physics/dynamic_paint/index.html#bpy-types-dynamicpaintmodifier"), - ("bpy.types.expressioncontroller*", "game_engine/logic/controllers/types/expression.html#bpy-types-expressioncontroller"), ("bpy.types.ffmpegsettings.audio*", "render/output/video.html#bpy-types-ffmpegsettings-audio"), ("bpy.types.followpathconstraint*", "rigging/constraints/relationship/follow_path.html#bpy-types-followpathconstraint"), ("bpy.types.gaussianblursequence*", "editors/vse/sequencer/strips/effects/blur.html#bpy-types-gaussianblursequence"), @@ -333,7 +332,7 @@ url_manual_mapping = ( ("bpy.ops.sound.bake_animation*", "data_system/scenes/properties.html#bpy-ops-sound-bake-animation"), ("bpy.ops.transform.edge_slide*", "modeling/meshes/editing/edges.html#bpy-ops-transform-edge-slide"), ("bpy.ops.transform.vert_slide*", "modeling/meshes/editing/vertices.html#bpy-ops-transform-vert-slide"), - ("bpy.ops.view3d.select_border*", "editors/3dview/object/selecting/tools.html#bpy-ops-view3d-select-border"), + ("bpy.ops.view3d.select_box*", "editors/3dview/object/selecting/tools.html#bpy-ops-view3d-select-border"), ("bpy.ops.view3d.select_circle*", "editors/3dview/object/selecting/tools.html#bpy-ops-view3d-select-circle"), ("bpy.types.adjustmentsequence*", "editors/vse/sequencer/strips/effects/adjustment.html#bpy-types-adjustmentsequence"), ("bpy.types.alphaundersequence*", "editors/vse/sequencer/strips/effects/alpha_over_under_overdrop.html#bpy-types-alphaundersequence"), @@ -344,8 +343,6 @@ url_manual_mapping = ( ("bpy.types.compositornodemask*", "compositing/types/input/mask.html#bpy-types-compositornodemask"), ("bpy.types.compositornodemath*", "compositing/types/converter/math.html#bpy-types-compositornodemath"), ("bpy.types.compositornodetime*", "compositing/types/input/time.html#bpy-types-compositornodetime"), - ("bpy.types.constraintactuator*", "game_engine/logic/actuators/types/constraint.html#bpy-types-constraintactuator"), - ("bpy.types.editobjectactuator*", "game_engine/logic/actuators/types/edit_object.html#bpy-types-editobjectactuator"), ("bpy.types.fluidfluidsettings*", "physics/fluid/types/fluid_object.html#bpy-types-fluidfluidsettings"), ("bpy.types.fmodifiergenerator*", "editors/graph_editor/fcurves/modifiers.html#bpy-types-fmodifiergenerator"), ("bpy.types.freestylelinestyle*", "render/freestyle/parameter_editor/line_style/index.html#bpy-types-freestylelinestyle"), @@ -372,7 +369,6 @@ url_manual_mapping = ( ("bpy.types.shrinkwrapmodifier*", "modeling/modifiers/deform/shrinkwrap.html#bpy-types-shrinkwrapmodifier"), ("bpy.types.splineikconstraint*", "rigging/constraints/tracking/spline_ik.html#bpy-types-splineikconstraint"), ("bpy.types.texturenodetexture*", "render/blender_render/textures/nodes/types/input/texture.html#bpy-types-texturenodetexture"), - ("bpy.types.visibilityactuator*", "game_engine/logic/actuators/types/visibility.html#bpy-types-visibilityactuator"), ("bpy.ops.anim.keyframe_clear*", "animation/keyframes/editing.html#bpy-ops-anim-keyframe-clear"), ("bpy.ops.curve.primitive*add*", "modeling/curves/primitives.html#bpy-ops-curve-primitive-add"), ("bpy.ops.mesh.duplicate_move*", "modeling/meshes/editing/duplicating/duplicate.html#bpy-ops-mesh-duplicate-move"), @@ -386,7 +382,7 @@ url_manual_mapping = ( ("bpy.types.alphaoversequence*", "editors/vse/sequencer/strips/effects/alpha_over_under_overdrop.html#bpy-types-alphaoversequence"), ("bpy.types.armatureeditbones*", "rigging/armatures/bones/editing/index.html#bpy-types-armatureeditbones"), ("bpy.types.childofconstraint*", "rigging/constraints/relationship/child_of.html#bpy-types-childofconstraint"), - ("bpy.types.clamptoconstraint*", "rigging/constraints/tracking/clamp_to.html#bpy-types-clamptoconstraint"), + ("bpy.types.clamptoconstraint*", "rigging/constraints/tracking/clight_to.html#bpy-types-clamptoconstraint"), ("bpy.types.collisionmodifier*", "physics/collision.html#bpy-types-collisionmodifier"), ("bpy.types.collisionsettings*", "physics/collision.html#bpy-types-collisionsettings"), ("bpy.types.compositornodergb*", "compositing/types/input/rgb.html#bpy-types-compositornodergb"), @@ -428,12 +424,10 @@ url_manual_mapping = ( ("bpy.ops.transform.tosphere*", "modeling/meshes/editing/transform/to_sphere.html#bpy-ops-transform-tosphere"), ("bpy.types.actionconstraint*", "rigging/constraints/relationship/action.html#bpy-types-actionconstraint"), ("bpy.types.addonpreferences*", "preferences/addons.html#bpy-types-addonpreferences"), - ("bpy.types.armatureactuator*", "game_engine/logic/actuators/types/armature.html#bpy-types-armatureactuator"), ("bpy.types.armaturemodifier*", "modeling/modifiers/deform/armature.html#bpy-types-armaturemodifier"), ("bpy.types.decimatemodifier*", "modeling/modifiers/generate/decimate.html#bpy-types-decimatemodifier"), ("bpy.types.displacemodifier*", "modeling/modifiers/deform/displace.html#bpy-types-displacemodifier"), ("bpy.types.displaysafeareas*", "render/blender_render/camera/object_data.html#bpy-types-displaysafeareas"), - ("bpy.types.filter2dactuator*", "game_engine/logic/actuators/types/filter_2d.html#bpy-types-filter2dactuator"), ("bpy.types.fmodifierstepped*", "editors/graph_editor/fcurves/modifiers.html#bpy-types-fmodifierstepped"), ("bpy.types.freestylelineset*", "render/freestyle/parameter_editor/line_set.html#bpy-types-freestylelineset"), ("bpy.types.material.ambient*", "render/blender_render/materials/properties/shading.html#bpy-types-material-ambient"), @@ -441,12 +435,10 @@ url_manual_mapping = ( ("bpy.types.multicamsequence*", "editors/vse/sequencer/strips/effects/multicam.html#bpy-types-multicamsequence"), ("bpy.types.multiplysequence*", "editors/vse/sequencer/strips/effects/multiply.html#bpy-types-multiplysequence"), ("bpy.types.multiresmodifier*", "modeling/modifiers/generate/multiresolution.html#bpy-types-multiresmodifier"), - ("bpy.types.object.draw_type*", "editors/3dview/object/properties/display.html#bpy-types-object-draw-type"), + ("bpy.types.object.display_type*", "editors/3dview/object/properties/display.html#bpy-types-object-draw-type"), ("bpy.types.object.use_extra*", "editors/3dview/object/properties/relations/extras.html#bpy-types-object-use-extra"), ("bpy.types.overdropsequence*", "editors/vse/sequencer/strips/effects/alpha_over_under_overdrop.html#bpy-types-overdropsequence"), ("bpy.types.particlesettings*", "physics/particles/index.html#bpy-types-particlesettings"), - ("bpy.types.propertyactuator*", "game_engine/logic/actuators/types/property.html#bpy-types-propertyactuator"), - ("bpy.types.pythoncontroller*", "game_engine/logic/controllers/types/python.html#bpy-types-pythoncontroller"), ("bpy.types.scenerenderlayer*", "render/cycles/settings/scene/render_layers/layers.html#bpy-types-scenerenderlayer"), ("bpy.types.sequencemodifier*", "editors/vse/sequencer/properties/modifiers.html#bpy-types-sequencemodifier"), ("bpy.types.shadernodeinvert*", "render/cycles/nodes/types/color/invert.html#bpy-types-shadernodeinvert"), @@ -462,7 +454,6 @@ url_manual_mapping = ( ("bpy.types.spaceimageeditor*", "editors/uv_image/image/index.html#bpy-types-spaceimageeditor"), ("bpy.types.spacelogiceditor*", "editors/logic_editor.html#bpy-types-spacelogiceditor"), ("bpy.types.sphfluidsettings*", "physics/fluid/index.html#bpy-types-sphfluidsettings"), - ("bpy.types.steeringactuator*", "game_engine/logic/actuators/types/steering.html#bpy-types-steeringactuator"), ("bpy.types.subtractsequence*", "editors/vse/sequencer/strips/effects/subtract.html#bpy-types-subtractsequence"), ("bpy.types.texturenodegroup*", "render/blender_render/textures/nodes/types/groups.html#bpy-types-texturenodegroup"), ("bpy.types.texturenodeimage*", "render/blender_render/textures/nodes/types/input/image.html#bpy-types-texturenodeimage"), @@ -481,7 +472,6 @@ url_manual_mapping = ( ("bpy.ops.uv.remove_doubles*", "editors/uv_image/uv/editing/layout.html#bpy-ops-uv-remove-doubles"), ("bpy.types.backgroundimage*", "editors/3dview/properties/background_images.html#bpy-types-backgroundimage"), ("bpy.types.booleanmodifier*", "modeling/modifiers/generate/booleans.html#bpy-types-booleanmodifier"), - ("bpy.types.collisionsensor*", "game_engine/logic/sensors/types/collision.html#bpy-types-collisionsensor"), ("bpy.types.constraint.mute*", "rigging/constraints/interface/header.html#bpy-types-constraint-mute"), ("bpy.types.explodemodifier*", "modeling/modifiers/simulate/explode.html#bpy-types-explodemodifier"), ("bpy.types.fcurvemodifiers*", "editors/graph_editor/fcurves/modifiers.html#bpy-types-fcurvemodifiers"), @@ -491,7 +481,6 @@ url_manual_mapping = ( ("bpy.types.fmodifierlimits*", "editors/graph_editor/fcurves/modifiers.html#bpy-types-fmodifierlimits"), ("bpy.types.gpussaosettings*", "editors/3dview/properties/shading.html#bpy-types-gpussaosettings"), ("bpy.types.latticemodifier*", "modeling/modifiers/deform/lattice.html#bpy-types-latticemodifier"), - ("bpy.types.messageactuator*", "game_engine/logic/actuators/types/message.html#bpy-types-messageactuator"), ("bpy.types.musgravetexture*", "render/blender_render/textures/types/procedural/musgrave.html#bpy-types-musgravetexture"), ("bpy.types.object.location*", "editors/3dview/object/properties/transforms.html#bpy-types-object-location"), ("bpy.types.object.rotation*", "editors/3dview/object/properties/transforms.html#bpy-types-object-rotation"), @@ -516,28 +505,18 @@ url_manual_mapping = ( ("bpy.ops.transform.resize*", "editors/3dview/object/editing/transform/basics.html#bpy-ops-transform-resize"), ("bpy.ops.transform.rotate*", "editors/3dview/object/editing/transform/basics.html#bpy-ops-transform-rotate"), ("bpy.ops.view3d.localview*", "editors/3dview/navigate/views.html#bpy-ops-view3d-localview"), - ("bpy.types.actionactuator*", "game_engine/logic/actuators/types/action.html#bpy-types-actionactuator"), - ("bpy.types.actuatorsensor*", "game_engine/logic/sensors/types/actuator.html#bpy-types-actuatorsensor"), - ("bpy.types.armaturesensor*", "game_engine/logic/sensors/types/armature.html#bpy-types-armaturesensor"), - ("bpy.types.cameraactuator*", "game_engine/logic/actuators/types/camera.html#bpy-types-cameraactuator"), ("bpy.types.curvesmodifier*", "editors/vse/sequencer/properties/modifiers.html#bpy-types-curvesmodifier"), ("bpy.types.effectsequence*", "editors/vse/sequencer/properties/filter.html#bpy-types-effectsequence"), ("bpy.types.ffmpegsettings*", "render/output/video.html#bpy-types-ffmpegsettings"), ("bpy.types.fmodifiernoise*", "editors/graph_editor/fcurves/modifiers.html#bpy-types-fmodifiernoise"), ("bpy.types.gpudofsettings*", "editors/3dview/properties/shading.html#bpy-types-gpudofsettings"), - ("bpy.types.joysticksensor*", "game_engine/logic/sensors/types/joystick.html#bpy-types-joysticksensor"), - ("bpy.types.keyboardsensor*", "game_engine/logic/sensors/types/keyboard.html#bpy-types-keyboardsensor"), ("bpy.types.materialstrand*", "render/blender_render/materials/properties/strands.html#bpy-types-materialstrand"), ("bpy.types.materialvolume*", "render/blender_render/materials/special_effects/volume.html#bpy-types-materialvolume"), ("bpy.types.mirrormodifier*", "modeling/modifiers/generate/mirror.html#bpy-types-mirrormodifier"), ("bpy.types.movieclipproxy*", "editors/movie_clip_editor/properties/proxy.html#bpy-types-movieclipproxy"), ("bpy.types.object.up_axis*", "editors/3dview/object/properties/relations/extras.html#bpy-types-object-up-axis"), - ("bpy.types.objectactuator*", "game_engine/logic/actuators/types/motion.html#bpy-types-objectactuator"), - ("bpy.types.parentactuator*", "game_engine/logic/actuators/types/parent.html#bpy-types-parentactuator"), ("bpy.types.particlesystem*", "physics/particles/index.html#bpy-types-particlesystem"), ("bpy.types.particletarget*", "physics/particles/emitter/physics/keyed.html#bpy-types-particletarget"), - ("bpy.types.propertysensor*", "game_engine/logic/sensors/types/property.html#bpy-types-propertysensor"), - ("bpy.types.randomactuator*", "game_engine/logic/actuators/types/random.html#bpy-types-randomactuator"), ("bpy.types.remeshmodifier*", "modeling/modifiers/generate/remesh.html#bpy-types-remeshmodifier"), ("bpy.types.rendersettings*", "render/index.html#bpy-types-rendersettings"), ("bpy.types.rigidbodyworld*", "physics/rigid_body/world.html#bpy-types-rigidbodyworld"), @@ -571,9 +550,7 @@ url_manual_mapping = ( ("bpy.types.gpufxsettings*", "editors/3dview/properties/shading.html#bpy-types-gpufxsettings"), ("bpy.types.imagesequence*", "editors/vse/sequencer/strips/movie_image.html#bpy-types-imagesequence"), ("bpy.types.marbletexture*", "render/blender_render/textures/types/procedural/marble.html#bpy-types-marbletexture"), - ("bpy.types.messagesensor*", "game_engine/logic/sensors/types/message.html#bpy-types-messagesensor"), ("bpy.types.modifier.show*", "modeling/modifiers/introduction.html#bpy-types-modifier-show"), - ("bpy.types.mouseactuator*", "game_engine/logic/actuators/types/mouse.html#bpy-types-mouseactuator"), ("bpy.types.moviesequence*", "editors/vse/sequencer/strips/movie_image.html#bpy-types-moviesequence"), ("bpy.types.movietracking*", "editors/movie_clip_editor/tracking/index.html#bpy-types-movietracking"), ("bpy.types.object.layers*", "editors/3dview/object/properties/relations/layers.html#bpy-types-object-layers"), @@ -581,18 +558,15 @@ url_manual_mapping = ( ("bpy.types.oceanmodifier*", "modeling/modifiers/simulate/ocean.html#bpy-types-oceanmodifier"), ("bpy.types.particlebrush*", "physics/particles/mode.html#bpy-types-particlebrush"), ("bpy.types.scene.gravity*", "physics/gravity.html#bpy-types-scene-gravity"), - ("bpy.types.sceneactuator*", "game_engine/logic/actuators/types/scene.html#bpy-types-sceneactuator"), ("bpy.types.scenesequence*", "editors/vse/sequencer/strips/scene.html#bpy-types-scenesequence"), ("bpy.types.screwmodifier*", "modeling/modifiers/generate/screw.html#bpy-types-screwmodifier"), ("bpy.types.sequenceproxy*", "editors/vse/sequencer/properties/proxy_timecode.html#bpy-types-sequenceproxy"), ("bpy.types.shadernodergb*", "render/cycles/nodes/types/input/rgb.html#bpy-types-shadernodergb"), ("bpy.types.smokemodifier*", "physics/smoke/index.html#bpy-types-smokemodifier"), - ("bpy.types.soundactuator*", "game_engine/logic/actuators/types/sound.html#bpy-types-soundactuator"), ("bpy.types.soundsequence*", "editors/vse/sequencer/strips/sound.html#bpy-types-soundsequence"), ("bpy.types.spaceoutliner*", "editors/outliner.html#bpy-types-spaceoutliner"), ("bpy.types.spacetimeline*", "editors/timeline.html#bpy-types-spacetimeline"), ("bpy.types.spaceuveditor*", "editors/uv_image/uv/index.html#bpy-types-spaceuveditor"), - ("bpy.types.stateactuator*", "game_engine/logic/actuators/types/state.html#bpy-types-stateactuator"), ("bpy.types.stuccitexture*", "render/blender_render/textures/types/procedural/stucci.html#bpy-types-stuccitexture"), ("bpy.types.windowmanager*", "interface/index.html#bpy-types-windowmanager"), ("bpy.types.worldlighting*", "render/blender_render/world/ambient_occlusion.html#bpy-types-worldlighting"), @@ -600,12 +574,10 @@ url_manual_mapping = ( ("bpy.ops.object.convert*", "editors/3dview/object/editing/introduction.html#bpy-ops-object-convert"), ("bpy.ops.object.speaker*", "render/audio/speaker.html#bpy-ops-object-speaker"), ("bpy.ops.transform.bend*", "modeling/meshes/editing/transform/bend.html#bpy-ops-transform-bend"), - ("bpy.types.alwayssensor*", "game_engine/logic/sensors/types/always.html#bpy-types-alwayssensor"), ("bpy.types.bakesettings*", "render/cycles/baking.html#bpy-types-bakesettings"), ("bpy.types.blendtexture*", "render/blender_render/textures/types/procedural/blend.html#bpy-types-blendtexture"), ("bpy.types.castmodifier*", "modeling/modifiers/deform/cast.html#bpy-types-castmodifier"), ("bpy.types.colormanaged*", "render/post_process/color_management.html#bpy-types-colormanaged"), - ("bpy.types.gameactuator*", "game_engine/logic/actuators/types/game.html#bpy-types-gameactuator"), ("bpy.types.glowsequence*", "editors/vse/sequencer/strips/effects/glow.html#bpy-types-glowsequence"), ("bpy.types.gpencilbrush*", "interface/grease_pencil/drawing/brushes.html#bpy-types-gpencilbrush"), ("bpy.types.greasepencil*", "interface/grease_pencil/index.html#bpy-types-greasepencil"), @@ -623,7 +595,6 @@ url_manual_mapping = ( ("bpy.types.object.scale*", "editors/3dview/object/properties/transforms.html#bpy-types-object-scale"), ("bpy.types.oceantexture*", "render/blender_render/textures/types/procedural/ocean.html#bpy-types-oceantexture"), ("bpy.types.particleedit*", "physics/particles/mode.html#bpy-types-particleedit"), - ("bpy.types.randomsensor*", "game_engine/logic/sensors/types/random.html#bpy-types-randomsensor"), ("bpy.types.scene.camera*", "data_system/scenes/properties.html#bpy-types-scene-camera"), ("bpy.types.sequencecrop*", "editors/vse/sequencer/properties/input.html#bpy-types-sequencecrop"), ("bpy.types.skinmodifier*", "modeling/modifiers/generate/skin.html#bpy-types-skinmodifier"), @@ -641,14 +612,11 @@ url_manual_mapping = ( ("bpy.ops.wm.properties*", "data_system/custom_properties.html#bpy-ops-wm-properties"), ("bpy.types.addsequence*", "editors/vse/sequencer/strips/effects/add.html#bpy-types-addsequence"), ("bpy.types.consoleline*", "editors/python_console.html#bpy-types-consoleline"), - ("bpy.types.delaysensor*", "game_engine/logic/sensors/types/delay.html#bpy-types-delaysensor"), ("bpy.types.meshstatvis*", "modeling/meshes/mesh_analysis.html#bpy-types-meshstatvis"), - ("bpy.types.mousesensor*", "game_engine/logic/sensors/types/mouse.html#bpy-types-mousesensor"), ("bpy.types.nodesetting*", "editors/node_editor/nodes/parts.html#bpy-types-nodesetting"), ("bpy.types.object.lock*", "editors/3dview/object/properties/transforms.html#bpy-types-object-lock"), ("bpy.types.object.show*", "editors/3dview/object/properties/display.html#bpy-types-object-show"), ("bpy.types.particlekey*", "physics/particles/emitter/physics/keyed.html#bpy-types-particlekey"), - ("bpy.types.radarsensor*", "game_engine/logic/sensors/types/radar.html#bpy-types-radarsensor"), ("bpy.types.renderlayer*", "render/post_process/layers.html#bpy-types-renderlayer"), ("bpy.types.spaceview3d*", "editors/3dview/index.html#bpy-types-spaceview3d"), ("bpy.types.uipopupmenu*", "interface/controls/buttons/menus.html#bpy-types-uipopupmenu"), @@ -665,8 +633,6 @@ url_manual_mapping = ( ("bpy.types.bpy_struct*", "data_system/custom_properties.html#bpy-types-bpy-struct"), ("bpy.types.compositor*", "compositing/index.html#bpy-types-compositor"), ("bpy.types.constraint*", "rigging/constraints/index.html#bpy-types-constraint"), - ("bpy.types.controller*", "game_engine/logic/controllers/index.html#bpy-types-controller"), - ("bpy.types.nearsensor*", "game_engine/logic/sensors/types/near.html#bpy-types-nearsensor"), ("bpy.types.nodesocket*", "editors/node_editor/nodes/parts.html#bpy-types-nodesocket"), ("bpy.types.pointcache*", "physics/baking.html#bpy-types-pointcache"), ("bpy.types.renderpass*", "render/blender_render/settings/passes.html#bpy-types-renderpass"), @@ -687,7 +653,6 @@ url_manual_mapping = ( ("bpy.types.nodeframe*", "editors/node_editor/nodes/frame.html#bpy-types-nodeframe"), ("bpy.types.nodegroup*", "editors/node_editor/nodes/groups.html#bpy-types-nodegroup"), ("bpy.types.pointlamp*", "render/blender_render/lighting/lamps/point.html#bpy-types-pointlamp"), - ("bpy.types.raysensor*", "game_engine/logic/sensors/types/ray.html#bpy-types-raysensor"), ("bpy.types.spaceinfo*", "editors/info/index.html#bpy-types-spaceinfo"), ("bpy.types.textcurve*", "modeling/texts/index.html#bpy-types-textcurve"), ("bpy.types.uipiemenu*", "interface/controls/buttons/menus.html#bpy-types-uipiemenu"), @@ -697,14 +662,12 @@ url_manual_mapping = ( ("bpy.ops.mesh.noise*", "modeling/meshes/editing/transform/noise.html#bpy-ops-mesh-noise"), ("bpy.ops.mesh.screw*", "modeling/meshes/editing/duplicating/screw.html#bpy-ops-mesh-screw"), ("bpy.ops.safe_areas*", "render/blender_render/camera/object_data.html#bpy-ops-safe-areas"), - ("bpy.types.actuator*", "game_engine/logic/actuators/index.html#bpy-types-actuator"), ("bpy.types.arealamp*", "render/blender_render/lighting/lamps/area/index.html#bpy-types-arealamp"), ("bpy.types.armature*", "rigging/armatures/index.html#bpy-types-armature"), ("bpy.types.editbone*", "rigging/armatures/bones/editing/index.html#bpy-types-editbone"), ("bpy.types.hemilamp*", "render/blender_render/lighting/lamps/hemi.html#bpy-types-hemilamp"), ("bpy.types.keyframe*", "animation/keyframes/index.html#bpy-types-keyframe"), ("bpy.types.linesets*", "render/freestyle/parameter_editor/line_set.html#bpy-types-linesets"), - ("bpy.types.lodlevel*", "game_engine/settings/object.html#bpy-types-lodlevel"), ("bpy.types.material*", "render/blender_render/materials/index.html#bpy-types-material"), ("bpy.types.metaball*", "modeling/metas/index.html#bpy-types-metaball"), ("bpy.types.modifier*", "modeling/modifiers/index.html#bpy-types-modifier"), @@ -748,7 +711,6 @@ url_manual_mapping = ( ("bpy.types.render*", "render/index.html#bpy-types-render"), ("bpy.types.screen*", "interface/window_system/screens.html#bpy-types-screen"), ("bpy.types.sculpt*", "sculpt_paint/sculpting/index.html#bpy-types-sculpt"), - ("bpy.types.sensor*", "game_engine/logic/sensors/index.html#bpy-types-sensor"), ("bpy.types.shader*", "render/cycles/nodes/types/shaders/index.html#bpy-types-shader"), ("bpy.types.window*", "interface/index.html#bpy-types-window"), ("bpy.ops.buttons*", "interface/index.html#bpy-ops-buttons"), @@ -792,7 +754,7 @@ url_manual_mapping = ( ("bpy.types.area*", "interface/window_system/areas.html#bpy-types-area"), ("bpy.types.boid*", "physics/particles/emitter/physics/boids.html#bpy-types-boid"), ("bpy.types.bone*", "rigging/armatures/bones/index.html#bpy-types-bone"), - ("bpy.types.lamp*", "render/blender_render/lighting/index.html#bpy-types-lamp"), + ("bpy.types.light*", "render/blender_render/lighting/index.html#bpy-types-lamp"), ("bpy.types.mask*", "editors/movie_clip_editor/masking/index.html#bpy-types-mask"), ("bpy.types.menu*", "interface/controls/buttons/menus.html#bpy-types-menu"), ("bpy.types.mesh*", "modeling/meshes/index.html#bpy-types-mesh"), @@ -805,7 +767,6 @@ url_manual_mapping = ( ("bpy.ops.graph*", "editors/graph_editor/index.html#bpy-ops-graph"), ("bpy.ops.group*", "editors/3dview/object/properties/relations/groups.html#bpy-ops-group"), ("bpy.ops.image*", "data_system/files/media/image_formats.html#bpy-ops-image"), - ("bpy.ops.logic*", "game_engine/logic/index.html#bpy-ops-logic"), ("bpy.ops.mball*", "modeling/metas/index.html#bpy-ops-mball"), ("bpy.ops.paint*", "sculpt_paint/index.html#bpy-ops-paint"), ("bpy.ops.scene*", "data_system/scenes/index.html#bpy-ops-scene"), @@ -818,7 +779,7 @@ url_manual_mapping = ( ("bpy.ops.file*", "editors/file_browser/index.html#bpy-ops-file"), ("bpy.ops.font*", "modeling/texts/index.html#bpy-ops-font"), ("bpy.ops.info*", "editors/info/index.html#bpy-ops-info"), - ("bpy.ops.lamp*", "render/blender_render/lighting/index.html#bpy-ops-lamp"), + ("bpy.ops.light*", "render/blender_render/lighting/index.html#bpy-ops-lamp"), ("bpy.ops.mask*", "editors/movie_clip_editor/masking/index.html#bpy-ops-mask"), ("bpy.ops.mesh*", "modeling/meshes/index.html#bpy-ops-mesh"), ("bpy.ops.node*", "editors/node_editor/nodes/index.html#bpy-ops-node"), diff --git a/modules/snap_context/mesh_drawing.py b/modules/snap_context/mesh_drawing.py index bdfca4d3..95660622 100644 --- a/modules/snap_context/mesh_drawing.py +++ b/modules/snap_context/mesh_drawing.py @@ -52,26 +52,15 @@ def get_bmesh_vert_co_array(bm): def get_mesh_tri_verts_array(me): - me.calc_tessface() - len_tessfaces = len(me.tessfaces) - if len_tessfaces: - tessfaces = np.empty(len_tessfaces * 4, 'i4') - me.tessfaces.foreach_get("vertices_raw", tessfaces) - tessfaces.shape = (-1, 4) - - quad_indices = tessfaces[:, 3].nonzero()[0] - tris = np.empty(((len_tessfaces + len(quad_indices)), 3), 'i4') - - tris[:len_tessfaces] = tessfaces[:, :3] - tris[len_tessfaces:] = tessfaces[quad_indices][:, (0, 2, 3)] - - del tessfaces - return tris + me.calc_loop_triangles() + tris = [tri.vertices[:] for tri in me.loop_triangles] + if tris: + return np.array(tris, 'i4') return None def get_bmesh_tri_verts_array(bm): - ltris = bm.calc_tessface() + ltris = bm.calc_loop_triangles() tris = [[ltri[0].vert.index, ltri[1].vert.index, ltri[2].vert.index] for ltri in ltris if not ltri[0].face.hide] if tris: return np.array(tris, 'i4') diff --git a/netrender/ui.py b/netrender/ui.py index c5c22329..bcd83197 100644 --- a/netrender/ui.py +++ b/netrender/ui.py @@ -35,7 +35,7 @@ ADDRESS_TEST_TIMEOUT = 30 def base_poll(cls, context): rd = context.scene.render - return (rd.use_game_engine==False) and (rd.engine in cls.COMPAT_ENGINES) + return (rd.engine in cls.COMPAT_ENGINES) def init_file(): @@ -96,7 +96,7 @@ class NetRenderButtonsPanel(): @classmethod def poll(cls, context): rd = context.scene.render - return rd.engine == 'NET_RENDER' and rd.use_game_engine == False + return rd.engine == 'NET_RENDER' # Setting panel, use in the scene for now. class RENDER_PT_network_settings(NetRenderButtonsPanel, bpy.types.Panel): diff --git a/node_wrangler.py b/node_wrangler.py index 6ccf2ecd..2b5e2091 100644 --- a/node_wrangler.py +++ b/node_wrangler.py @@ -20,7 +20,7 @@ bl_info = { "name": "Node Wrangler", "author": "Bartek Skorupa, Greg Zaal, Sebastian Koenig, Christian Brinkmann, Florian Meyer", "version": (3, 35), - "blender": (2, 78, 0), + "blender": (2, 80, 0), "location": "Node Editor Toolbar or Ctrl-Space", "description": "Various tools to enhance and speed up node-based workflow", "warning": "", @@ -115,7 +115,7 @@ shaders_input_nodes_props = ( # Keeping mixed case to avoid having to translate entries when adding new nodes in operators. shaders_output_nodes_props = ( ('ShaderNodeOutputMaterial', 'OUTPUT_MATERIAL', 'Material Output'), - ('ShaderNodeOutputLamp', 'OUTPUT_LAMP', 'Lamp Output'), + ('ShaderNodeOutputLight', 'OUTPUT_LIGHT', 'Light Output'), ('ShaderNodeOutputWorld', 'OUTPUT_WORLD', 'World Output'), ) # (rna_type.identifier, type, rna_type.name) @@ -332,7 +332,7 @@ compo_layout_nodes_props = ( blender_mat_input_nodes_props = ( ('ShaderNodeMaterial', 'MATERIAL', 'Material'), ('ShaderNodeCameraData', 'CAMERA', 'Camera Data'), - ('ShaderNodeLampData', 'LAMP', 'Lamp Data'), + ('ShaderNodeLightData', 'LIGHT', 'Light Data'), ('ShaderNodeValue', 'VALUE', 'Value'), ('ShaderNodeRGB', 'RGB', 'RGB'), ('ShaderNodeTexture', 'TEXTURE', 'Texture'), @@ -547,6 +547,10 @@ draw_color_sets = { } +def is_cycles_or_eevee(context): + return context.scene.render.engine in {'CYCLES', 'BLENDER_EEVEE'} + + def nice_hotkey_name(punc): # convert the ugly string name into the actual character pairs = ( @@ -1000,39 +1004,39 @@ def get_nodes_links(context): # Principled prefs class NWPrincipledPreferences(bpy.types.PropertyGroup): - base_color = StringProperty( + base_color: StringProperty( name='Base Color', default='diffuse diff albedo base col color', description='Naming Components for Base Color maps') - sss_color = StringProperty( + sss_color: StringProperty( name='Subsurface Color', default='sss subsurface', description='Naming Components for Subsurface Color maps') - metallic = StringProperty( + metallic: StringProperty( name='Metallic', default='metallic metalness metal mtl', description='Naming Components for metallness maps') - specular = StringProperty( + specular: StringProperty( name='Specular', default='specularity specular spec spc', description='Naming Components for Specular maps') - normal = StringProperty( + normal: StringProperty( name='Normal', default='normal nor nrm nrml norm', description='Naming Components for Normal maps') - bump = StringProperty( + bump: StringProperty( name='Bump', default='bump bmp', description='Naming Components for bump maps') - rough = StringProperty( + rough: StringProperty( name='Roughness', default='roughness rough rgh', description='Naming Components for roughness maps') - gloss = StringProperty( + gloss: StringProperty( name='Gloss', default='gloss glossy glossyness', description='Naming Components for glossy maps') - displacement = StringProperty( + displacement: StringProperty( name='Displacement', default='displacement displace disp dsp height heightmap', description='Naming Components for displacement maps') @@ -1041,7 +1045,7 @@ class NWPrincipledPreferences(bpy.types.PropertyGroup): class NWNodeWrangler(bpy.types.AddonPreferences): bl_idname = __name__ - merge_hide = EnumProperty( + merge_hide: EnumProperty( name="Hide Mix nodes", items=( ("ALWAYS", "Always", "Always collapse the new merge nodes"), @@ -1050,7 +1054,7 @@ class NWNodeWrangler(bpy.types.AddonPreferences): ), default='NON_SHADER', description="When merging nodes with the Ctrl+Numpad0 hotkey (and similar) specify whether to collapse them or show the full node with options expanded") - merge_position = EnumProperty( + merge_position: EnumProperty( name="Mix Node Position", items=( ("CENTER", "Center", "Place the Mix node between the two nodes"), @@ -1059,22 +1063,22 @@ class NWNodeWrangler(bpy.types.AddonPreferences): default='CENTER', description="When merging nodes with the Ctrl+Numpad0 hotkey (and similar) specify the position of the new nodes") - show_hotkey_list = BoolProperty( + show_hotkey_list: BoolProperty( name="Show Hotkey List", default=False, description="Expand this box into a list of all the hotkeys for functions in this addon" ) - hotkey_list_filter = StringProperty( + hotkey_list_filter: StringProperty( name=" Filter by Name", default="", description="Show only hotkeys that have this text in their name" ) - show_principled_lists = BoolProperty( + show_principled_lists: BoolProperty( name="Show Principled naming tags", default=False, description="Expand this box into a list of all naming tags for principled texture setup" ) - principled_tags = bpy.props.PointerProperty(type=NWPrincipledPreferences) + principled_tags: bpy.props.PointerProperty(type=NWPrincipledPreferences) def draw(self, context): layout = self.layout @@ -1113,7 +1117,7 @@ class NWNodeWrangler(bpy.types.AddonPreferences): if self.hotkey_list_filter.lower() in hotkey_name.lower(): row = col.row(align=True) - row.label(hotkey_name) + row.label(text=hotkey_name) keystr = nice_hotkey_name(hotkey[1]) if hotkey[4]: keystr = "Shift " + keystr @@ -1121,7 +1125,7 @@ class NWNodeWrangler(bpy.types.AddonPreferences): keystr = "Alt " + keystr if hotkey[3]: keystr = "Ctrl " + keystr - row.label(keystr) + row.label(text=keystr) @@ -1223,7 +1227,7 @@ class NWLazyConnect(Operator, NWBase): bl_idname = "node.nw_lazy_connect" bl_label = "Lazy Connect" bl_options = {'REGISTER', 'UNDO'} - with_menu = BoolProperty() + with_menu: BoolProperty() def modal(self, context, event): context.area.tag_redraw() @@ -1329,12 +1333,12 @@ class NWDeleteUnused(Operator, NWBase): bl_label = 'Delete Unused Nodes' bl_options = {'REGISTER', 'UNDO'} - delete_muted = BoolProperty(name="Delete Muted", description="Delete (but reconnect, like Ctrl-X) all muted nodes", default=True) - delete_frames = BoolProperty(name="Delete Empty Frames", description="Delete all frames that have no nodes inside them", default=True) + delete_muted: BoolProperty(name="Delete Muted", description="Delete (but reconnect, like Ctrl-X) all muted nodes", default=True) + delete_frames: BoolProperty(name="Delete Empty Frames", description="Delete all frames that have no nodes inside them", default=True) def is_unused_node(self, node): end_types = ['OUTPUT_MATERIAL', 'OUTPUT', 'VIEWER', 'COMPOSITE', \ - 'SPLITVIEWER', 'OUTPUT_FILE', 'LEVELS', 'OUTPUT_LAMP', \ + 'SPLITVIEWER', 'OUTPUT_FILE', 'LEVELS', 'OUTPUT_LIGHT', \ 'OUTPUT_WORLD', 'GROUP_INPUT', 'GROUP_OUTPUT', 'FRAME'] if node.type in end_types: return False @@ -1558,8 +1562,8 @@ class NWResetBG(Operator, NWBase): def execute(self, context): context.space_data.backdrop_zoom = 1 - context.space_data.backdrop_x = 0 - context.space_data.backdrop_y = 0 + context.space_data.backdrop_offset[0] = 0 + context.space_data.backdrop_offset[1] = 0 return {'FINISHED'} @@ -1567,9 +1571,10 @@ class NWAddAttrNode(Operator, NWBase): """Add an Attribute node with this name""" bl_idname = 'node.nw_add_attr_node' bl_label = 'Add UV map' - attr_name = StringProperty() bl_options = {'REGISTER', 'UNDO'} + attr_name: StringProperty() + def execute(self, context): bpy.ops.node.add_node('INVOKE_DEFAULT', use_transform=True, type="ShaderNodeAttribute") nodes, links = get_nodes_links(context) @@ -1585,7 +1590,7 @@ class NWEmissionViewer(Operator, NWBase): @classmethod def poll(cls, context): - is_cycles = context.scene.render.engine == 'CYCLES' + is_cycles = is_cycles_or_eevee(context) if nw_check(context): space = context.space_data if space.tree_type == 'ShaderNodeTree' and is_cycles: @@ -1600,13 +1605,13 @@ class NWEmissionViewer(Operator, NWBase): space = context.space_data shader_type = space.shader_type if shader_type == 'OBJECT': - if space.id not in [lamp for lamp in bpy.data.lamps]: # cannot use bpy.data.lamps directly as iterable + if space.id not in [light for light in bpy.data.lights]: # cannot use bpy.data.lights directly as iterable shader_output_type = "OUTPUT_MATERIAL" shader_output_ident = "ShaderNodeOutputMaterial" shader_viewer_ident = "ShaderNodeEmission" else: - shader_output_type = "OUTPUT_LAMP" - shader_output_ident = "ShaderNodeOutputLamp" + shader_output_type = "OUTPUT_LIGHT" + shader_output_ident = "ShaderNodeOutputLight" shader_viewer_ident = "ShaderNodeEmission" elif shader_type == 'WORLD': @@ -1734,9 +1739,19 @@ class NWFrameSelected(Operator, NWBase): bl_label = "Frame Selected" bl_description = "Add a frame node and parent the selected nodes to it" bl_options = {'REGISTER', 'UNDO'} - label_prop = StringProperty(name='Label', default=' ', description='The visual name of the frame node') - color_prop = FloatVectorProperty(name="Color", description="The color of the frame node", default=(0.6, 0.6, 0.6), - min=0, max=1, step=1, precision=3, subtype='COLOR_GAMMA', size=3) + + label_prop: StringProperty( + name='Label', + description='The visual name of the frame node', + default=' ' + ) + color_prop: FloatVectorProperty( + name="Color", + description="The color of the frame node", + default=(0.6, 0.6, 0.6), + min=0, max=1, step=1, precision=3, + subtype='COLOR_GAMMA', size=3 + ) def execute(self, context): nodes, links = get_nodes_links(context) @@ -1795,7 +1810,7 @@ class NWSwitchNodeType(Operator, NWBase): bl_label = "Switch Node Type" bl_options = {'REGISTER', 'UNDO'} - to_type = EnumProperty( + to_type: EnumProperty( name="Switch to type", items=list(shaders_input_nodes_props) + list(shaders_output_nodes_props) + @@ -2009,12 +2024,12 @@ class NWMergeNodes(Operator, NWBase): bl_description = "Merge Selected Nodes" bl_options = {'REGISTER', 'UNDO'} - mode = EnumProperty( + mode: EnumProperty( name="mode", description="All possible blend types and math operations", items=blend_types + [op for op in operations if op not in blend_types], ) - merge_type = EnumProperty( + merge_type: EnumProperty( name="merge type", description="Type of Merge to be used", items=( @@ -2260,11 +2275,11 @@ class NWBatchChangeNodes(Operator, NWBase): bl_description = "Batch Change Blend Type and Math Operation" bl_options = {'REGISTER', 'UNDO'} - blend_type = EnumProperty( + blend_type: EnumProperty( name="Blend Type", items=blend_types + navs, ) - operation = EnumProperty( + operation: EnumProperty( name="Operation", items=operations + navs, ) @@ -2326,7 +2341,7 @@ class NWChangeMixFactor(Operator, NWBase): # option: Change factor. # If option is 1.0 or 0.0 - set to 1.0 or 0.0 # Else - change factor by option value. - option = FloatProperty() + option: FloatProperty() def execute(self, context): nodes, links = get_nodes_links(context) @@ -2462,7 +2477,7 @@ class NWCopyLabel(Operator, NWBase): bl_label = "Copy Label" bl_options = {'REGISTER', 'UNDO'} - option = EnumProperty( + option: EnumProperty( name="option", description="Source of name of label", items=( @@ -2506,7 +2521,7 @@ class NWClearLabel(Operator, NWBase): bl_label = "Clear Label" bl_options = {'REGISTER', 'UNDO'} - option = BoolProperty() + option: BoolProperty() def execute(self, context): nodes, links = get_nodes_links(context) @@ -2528,16 +2543,16 @@ class NWModifyLabels(Operator, NWBase): bl_label = "Modify Labels" bl_options = {'REGISTER', 'UNDO'} - prepend = StringProperty( + prepend: StringProperty( name="Add to Beginning" ) - append = StringProperty( + append: StringProperty( name="Add to End" ) - replace_from = StringProperty( + replace_from: StringProperty( name="Text to Replace" ) - replace_to = StringProperty( + replace_to: StringProperty( name="Replace with" ) @@ -2561,14 +2576,14 @@ class NWAddTextureSetup(Operator, NWBase): bl_description = "Add Texture Node Setup to Selected Shaders" bl_options = {'REGISTER', 'UNDO'} - add_mapping = BoolProperty(name="Add Mapping Nodes", description="Create coordinate and mapping nodes for the texture (ignored for selected texture nodes)", default=True) + add_mapping: BoolProperty(name="Add Mapping Nodes", description="Create coordinate and mapping nodes for the texture (ignored for selected texture nodes)", default=True) @classmethod def poll(cls, context): valid = False if nw_check(context): space = context.space_data - if space.tree_type == 'ShaderNodeTree' and context.scene.render.engine == 'CYCLES': + if space.tree_type == 'ShaderNodeTree' and is_cycles_or_eevee(context): valid = True return valid @@ -2639,26 +2654,28 @@ class NWAddPrincipledSetup(Operator, NWBase, ImportHelper): bl_description = "Add Texture Node Setup for Principled BSDF" bl_options = {'REGISTER', 'UNDO'} - directory = StringProperty( - name='Directory', - subtype='DIR_PATH', - default='', - description='Folder to search in for image files') - files = CollectionProperty( - type=bpy.types.OperatorFileListElement, - options={'HIDDEN', 'SKIP_SAVE'}) + directory: StringProperty( + name='Directory', + subtype='DIR_PATH', + default='', + description='Folder to search in for image files' + ) + files: CollectionProperty( + type=bpy.types.OperatorFileListElement, + options={'HIDDEN', 'SKIP_SAVE'} + ) order = [ "filepath", "files", - ] + ] @classmethod def poll(cls, context): valid = False if nw_check(context): space = context.space_data - if space.tree_type == 'ShaderNodeTree' and context.scene.render.engine == 'CYCLES': + if space.tree_type == 'ShaderNodeTree' and is_cycles_or_eevee(context): valid = True return valid @@ -2752,35 +2769,18 @@ class NWAddPrincipledSetup(Operator, NWBase, ImportHelper): disp_texture.color_space = 'NONE' # Add displacement offset nodes - math_sub = nodes.new(type='ShaderNodeMath') - math_sub.operation = 'SUBTRACT' - math_sub.label = 'Offset' - math_sub.location = active_node.location + Vector((0, -560)) - math_mul = nodes.new(type='ShaderNodeMath') - math_mul.operation = 'MULTIPLY' - math_mul.label = 'Strength' - math_mul.location = math_sub.location + Vector((200, 0)) - link = links.new(math_mul.inputs[0], math_sub.outputs[0]) - link = links.new(math_sub.inputs[0], disp_texture.outputs[0]) - - # Turn on true displacement in the material + disp_node = nodes.new(type='ShaderNodeDisplacement') + disp_node.location = active_node.location + Vector((0, -560)) + link = links.new(disp_node.inputs[0], disp_texture.outputs[0]) + + # TODO Turn on true displacement in the material # Too complicated for now - ''' - # Frame. Does not update immediately - # Seems to need an editor redraw - frame = nodes.new(type='NodeFrame') - frame.label = 'Displacement' - math_sub.parent = frame - math_mul.parent = frame - frame.update() - ''' - - #find output node + # Find output node output_node = [n for n in nodes if n.bl_idname == 'ShaderNodeOutputMaterial'] if output_node: if not output_node[0].inputs[2].is_linked: - link = links.new(output_node[0].inputs[2], math_mul.outputs[0]) + link = links.new(output_node[0].inputs[2], disp_node.outputs[0]) continue @@ -2847,23 +2847,24 @@ class NWAddPrincipledSetup(Operator, NWBase, ImportHelper): # Alignment for i, texture_node in enumerate(texture_nodes): - offset = Vector((-400, (i * -260) + 200)) + offset = Vector((-550, (i * -280) + 200)) texture_node.location = active_node.location + offset if normal_node: # Extra alignment if normal node was added - normal_node.location = normal_node_texture.location + Vector((200, 0)) + normal_node.location = normal_node_texture.location + Vector((300, 0)) if roughness_node: # Alignment of invert node if glossy map - invert_node.location = roughness_node.location + Vector((200, 0)) + invert_node.location = roughness_node.location + Vector((300, 0)) # Add texture input + mapping mapping = nodes.new(type='ShaderNodeMapping') - mapping.location = active_node.location + Vector((-900, 0)) + mapping.location = active_node.location + Vector((-1050, 0)) if len(texture_nodes) > 1: # If more than one texture add reroute node in between reroute = nodes.new(type='NodeReroute') + texture_nodes.append(reroute) tex_coords = Vector((texture_nodes[0].location.x, sum(n.location.y for n in texture_nodes)/len(texture_nodes))) reroute.location = tex_coords + Vector((-50, -120)) for texture_node in texture_nodes: @@ -2877,6 +2878,20 @@ class NWAddPrincipledSetup(Operator, NWBase, ImportHelper): texture_input.location = mapping.location + Vector((-200, 0)) link = links.new(mapping.inputs[0], texture_input.outputs[2]) + # Create frame around tex coords and mapping + frame = nodes.new(type='NodeFrame') + frame.label = 'Mapping' + mapping.parent = frame + texture_input.parent = frame + frame.update() + + # Create frame around texture nodes + frame = nodes.new(type='NodeFrame') + frame.label = 'Textures' + for tnode in texture_nodes: + tnode.parent = frame + frame.update() + # Just to be sure active_node.select = False nodes.update() @@ -2892,7 +2907,7 @@ class NWAddReroutes(Operator, NWBase): bl_description = "Add Reroutes to Outputs" bl_options = {'REGISTER', 'UNDO'} - option = EnumProperty( + option: EnumProperty( name="option", items=[ ('ALL', 'to all', 'Add to all outputs'), @@ -2992,9 +3007,9 @@ class NWLinkActiveToSelected(Operator, NWBase): bl_label = "Link Active Node to Selected" bl_options = {'REGISTER', 'UNDO'} - replace = BoolProperty() - use_node_name = BoolProperty() - use_outputs_names = BoolProperty() + replace: BoolProperty() + use_node_name: BoolProperty() + use_outputs_names: BoolProperty() @classmethod def poll(cls, context): @@ -3072,7 +3087,7 @@ class NWAlignNodes(Operator, NWBase): bl_idname = "node.nw_align_nodes" bl_label = "Align Nodes" bl_options = {'REGISTER', 'UNDO'} - margin = IntProperty(name='Margin', default=50, description='The amount of space between nodes') + margin: IntProperty(name='Margin', default=50, description='The amount of space between nodes') def execute(self, context): nodes, links = get_nodes_links(context) @@ -3142,7 +3157,7 @@ class NWSelectParentChildren(Operator, NWBase): bl_label = "Select Parent or Children" bl_options = {'REGISTER', 'UNDO'} - option = EnumProperty( + option: EnumProperty( name="option", items=( ('PARENT', 'Select Parent', 'Select Parent Frame'), @@ -3225,7 +3240,7 @@ class NWLinkToOutputNode(Operator, NWBase): if not output_node: bpy.ops.node.select_all(action="DESELECT") if tree_type == 'ShaderNodeTree': - if context.scene.render.engine == 'CYCLES': + if is_cycles_or_eevee(context): output_node = nodes.new('ShaderNodeOutputMaterial') else: output_node = nodes.new('ShaderNodeOutput') @@ -3246,7 +3261,7 @@ class NWLinkToOutputNode(Operator, NWBase): break out_input_index = 0 - if tree_type == 'ShaderNodeTree' and context.scene.render.engine == 'CYCLES': + if tree_type == 'ShaderNodeTree' and is_cycles_or_eevee(context): if active.outputs[output_index].name == 'Volume': out_input_index = 1 elif active.outputs[output_index].type != 'SHADER': # connect to displacement if not a shader @@ -3263,8 +3278,8 @@ class NWMakeLink(Operator, NWBase): bl_idname = 'node.nw_make_link' bl_label = 'Make Link' bl_options = {'REGISTER', 'UNDO'} - from_socket = IntProperty() - to_socket = IntProperty() + from_socket: IntProperty() + to_socket: IntProperty() def execute(self, context): nodes, links = get_nodes_links(context) @@ -3284,7 +3299,7 @@ class NWCallInputsMenu(Operator, NWBase): bl_idname = 'node.nw_call_inputs_menu' bl_label = 'Make Link' bl_options = {'REGISTER', 'UNDO'} - from_socket = IntProperty() + from_socket: IntProperty() def execute(self, context): nodes, links = get_nodes_links(context) @@ -3305,9 +3320,17 @@ class NWAddSequence(Operator, ImportHelper): bl_idname = 'node.nw_add_sequence' bl_label = 'Import Image Sequence' bl_options = {'REGISTER', 'UNDO'} - directory = StringProperty(subtype="DIR_PATH") - filename = StringProperty(subtype="FILE_NAME") - files = CollectionProperty(type=bpy.types.OperatorFileListElement, options={'HIDDEN', 'SKIP_SAVE'}) + + directory: StringProperty( + subtype="DIR_PATH" + ) + filename: StringProperty( + subtype="FILE_NAME" + ) + files: CollectionProperty( + type=bpy.types.OperatorFileListElement, + options={'HIDDEN', 'SKIP_SAVE'} + ) def execute(self, context): nodes, links = get_nodes_links(context) @@ -3399,8 +3422,13 @@ class NWAddMultipleImages(Operator, ImportHelper): bl_idname = 'node.nw_add_multiple_images' bl_label = 'Open Selected Images' bl_options = {'REGISTER', 'UNDO'} - directory = StringProperty(subtype="DIR_PATH") - files = CollectionProperty(type=bpy.types.OperatorFileListElement, options={'HIDDEN', 'SKIP_SAVE'}) + directory: StringProperty( + subtype="DIR_PATH" + ) + files: CollectionProperty( + type=bpy.types.OperatorFileListElement, + options={'HIDDEN', 'SKIP_SAVE'} + ) def execute(self, context): nodes, links = get_nodes_links(context) @@ -3447,8 +3475,8 @@ class NWViewerFocus(bpy.types.Operator): bl_idname = "node.nw_viewer_focus" bl_label = "Viewer Focus" - x = bpy.props.IntProperty() - y = bpy.props.IntProperty() + x: bpy.props.IntProperty() + y: bpy.props.IntProperty() @classmethod def poll(cls, context): @@ -3502,8 +3530,8 @@ class NWSaveViewer(bpy.types.Operator, ExportHelper): """Save the current viewer node to an image file""" bl_idname = "node.nw_save_viewer" bl_label = "Save This Image" - filepath = StringProperty(subtype="FILE_PATH") - filename_ext = EnumProperty( + filepath: StringProperty(subtype="FILE_PATH") + filename_ext: EnumProperty( name="Format", description="Choose the file format to save to", items=(('.bmp', "PNG", ""), @@ -3681,7 +3709,7 @@ def drawlayout(context, layout, mode='non-panel'): col.menu(NWSwitchNodeTypeMenu.bl_idname, text="Switch Node Type") col.separator() - if tree_type == 'ShaderNodeTree' and context.scene.render.engine == 'CYCLES': + if tree_type == 'ShaderNodeTree' and is_cycles_or_eevee(context): col = layout.column(align=True) col.operator(NWAddTextureSetup.bl_idname, text="Add Texture Setup", icon='NODE_SEL') col.operator(NWAddPrincipledSetup.bl_idname, text="Add Principled Setup", icon='NODE_SEL') @@ -3722,7 +3750,7 @@ def drawlayout(context, layout, mode='non-panel'): col.separator() col = layout.column(align=True) - col.operator(NWAlignNodes.bl_idname, icon='ALIGN') + col.operator(NWAlignNodes.bl_idname, icon='CENTER_ONLY') col.separator() col = layout.column(align=True) @@ -3737,11 +3765,11 @@ class NodeWranglerPanel(Panel, NWBase): bl_region_type = "TOOLS" bl_category = "Node Wrangler" - prepend = StringProperty( + prepend: StringProperty( name='prepend', ) - append = StringProperty() - remove = StringProperty() + append: StringProperty() + remove: StringProperty() def draw(self, context): self.layout.label(text="(Quick access: Ctrl+Space)") @@ -3766,7 +3794,7 @@ class NWMergeNodesMenu(Menu, NWBase): def draw(self, context): type = context.space_data.tree_type layout = self.layout - if type == 'ShaderNodeTree' and context.scene.render.engine == 'CYCLES': + if type == 'ShaderNodeTree' and is_cycles_or_eevee(context): layout.menu(NWMergeShadersMenu.bl_idname, text="Use Shaders") layout.menu(NWMergeMixMenu.bl_idname, text="Use Mix Nodes") layout.menu(NWMergeMathMenu.bl_idname, text="Use Math Nodes") @@ -3990,7 +4018,7 @@ class NWVertColMenu(bpy.types.Menu): valid = False if nw_check(context): snode = context.space_data - valid = snode.tree_type == 'ShaderNodeTree' and context.scene.render.engine == 'CYCLES' + valid = snode.tree_type == 'ShaderNodeTree' and is_cycles_or_eevee(context) return valid def draw(self, context): @@ -4025,7 +4053,7 @@ class NWSwitchNodeTypeMenu(Menu, NWBase): layout = self.layout tree = context.space_data.node_tree if tree.type == 'SHADER': - if context.scene.render.engine == 'CYCLES': + if is_cycles_or_eevee(context): layout.menu(NWSwitchShadersInputSubmenu.bl_idname) layout.menu(NWSwitchShadersOutputSubmenu.bl_idname) layout.menu(NWSwitchShadersShaderSubmenu.bl_idname) @@ -4034,7 +4062,7 @@ class NWSwitchNodeTypeMenu(Menu, NWBase): layout.menu(NWSwitchShadersVectorSubmenu.bl_idname) layout.menu(NWSwitchShadersConverterSubmenu.bl_idname) layout.menu(NWSwitchShadersLayoutSubmenu.bl_idname) - if context.scene.render.engine != 'CYCLES': + else: layout.menu(NWSwitchMatInputSubmenu.bl_idname) layout.menu(NWSwitchMatOutputSubmenu.bl_idname) layout.menu(NWSwitchMatColorSubmenu.bl_idname) diff --git a/object_boolean_tools.py b/object_boolean_tools.py index 4c7e1bc1..a9728069 100644 --- a/object_boolean_tools.py +++ b/object_boolean_tools.py @@ -159,9 +159,9 @@ def Operation(context, _operation): obj.modifiers.remove(mod) """ if useWire: - selObj.draw_type = "WIRE" + selObj.display_type = "WIRE" else: - selObj.draw_type = "BOUNDS" + selObj.display_type = "BOUNDS" cyclesVis.camera = False cyclesVis.diffuse = False @@ -200,7 +200,7 @@ def Remove(context, thisObj_name, Prop): # if it's the brush object if obj.name == _thisObj_name: cyclesVis = obj.cycles_visibility - obj.draw_type = "TEXTURED" + obj.display_type = "TEXTURED" del obj["BoolToolBrush"] del obj["BoolTool_FTransform"] cyclesVis.camera = True @@ -229,7 +229,7 @@ def Remove(context, thisObj_name, Prop): if (actObj.name in mod.name): Canvas.modifiers.remove(mod) cyclesVis = actObj.cycles_visibility - actObj.draw_type = "TEXTURED" + actObj.display_type = "TEXTURED" del actObj["BoolToolBrush"] del actObj["BoolTool_FTransform"] cyclesVis.camera = True @@ -509,9 +509,9 @@ class BTool_FastTransform(Operator): if isBrush(actObj) and actObj["BoolTool_FTransform"] == "True": EnableThisBrush(bpy.context, "False") if useWire: - actObj.draw_type = "WIRE" + actObj.display_type = "WIRE" else: - actObj.draw_type = "BOUNDS" + actObj.display_type = "BOUNDS" if self.operator == "Translate": bpy.ops.transform.translate('INVOKE_DEFAULT') @@ -523,13 +523,13 @@ class BTool_FastTransform(Operator): if event.type == 'LEFTMOUSE': if isBrush(actObj): EnableThisBrush(bpy.context, "True") - actObj.draw_type = "WIRE" + actObj.display_type = "WIRE" return {'FINISHED'} if event.type in {'RIGHTMOUSE', 'ESC'}: if isBrush(actObj): EnableThisBrush(bpy.context, "True") - actObj.draw_type = "WIRE" + actObj.display_type = "WIRE" return {'CANCELLED'} return {'RUNNING_MODAL'} @@ -914,18 +914,18 @@ class VIEW3D_MT_booltool_menu(Menu): layout = self.layout layout.label("Auto Boolean:") - layout.operator(OBJECT_OT_BoolTool_Auto_Difference.bl_idname, text='Difference', icon="ROTACTIVE") - layout.operator(OBJECT_OT_BoolTool_Auto_Union.bl_idname, text='Union', icon="ROTATECOLLECTION") - layout.operator(OBJECT_OT_BoolTool_Auto_Intersect.bl_idname, text='Intersect', icon="ROTATECENTER") - layout.operator(OBJECT_OT_BoolTool_Auto_Slice.bl_idname, text='Slice', icon="ROTATECENTER") - layout.operator(OBJECT_OT_BoolTool_Auto_Subtract.bl_idname, text='Subtract', icon="ROTACTIVE") + layout.operator(OBJECT_OT_BoolTool_Auto_Difference.bl_idname, text='Difference', icon='PIVOT_ACTIVE') + layout.operator(OBJECT_OT_BoolTool_Auto_Union.bl_idname, text='Union', icon='PIVOT_INDIVIDUAL') + layout.operator(OBJECT_OT_BoolTool_Auto_Intersect.bl_idname, text='Intersect', icon='PIVOT_MEDIAN') + layout.operator(OBJECT_OT_BoolTool_Auto_Slice.bl_idname, text='Slice', icon='PIVOT_MEDIAN') + layout.operator(OBJECT_OT_BoolTool_Auto_Subtract.bl_idname, text='Subtract', icon='PIVOT_ACTIVE') layout.separator() layout.label("Brush Boolean:") - layout.operator(BTool_Diff.bl_idname, icon="ROTACTIVE") - layout.operator(BTool_Union.bl_idname, icon="ROTATECOLLECTION") - layout.operator(BTool_Inters.bl_idname, icon="ROTATECENTER") - layout.operator(BTool_Slice.bl_idname, icon="ROTATECENTER") + layout.operator(BTool_Diff.bl_idname, icon='PIVOT_ACTIVE') + layout.operator(BTool_Union.bl_idname, icon='PIVOT_INDIVIDUAL') + layout.operator(BTool_Inters.bl_idname, icon='PIVOT_MEDIAN') + layout.operator(BTool_Slice.bl_idname, icon='PIVOT_MEDIAN') if (isCanvas(context.active_object)): layout.separator() @@ -977,16 +977,16 @@ class VIEW3D_PT_booltool_tools(Panel): col.enabled = obs_len > 1 col.label("Auto Boolean:", icon="MODIFIER") col.separator() - col.operator(OBJECT_OT_BoolTool_Auto_Difference.bl_idname, text='Difference', icon="ROTACTIVE") - col.operator(OBJECT_OT_BoolTool_Auto_Union.bl_idname, text='Union', icon="ROTATECOLLECTION") - col.operator(OBJECT_OT_BoolTool_Auto_Intersect.bl_idname, text='Intersect', icon="ROTATECENTER") + col.operator(OBJECT_OT_BoolTool_Auto_Difference.bl_idname, text='Difference', icon='PIVOT_ACTIVE') + col.operator(OBJECT_OT_BoolTool_Auto_Union.bl_idname, text='Union', icon='PIVOT_INDIVIDUAL') + col.operator(OBJECT_OT_BoolTool_Auto_Intersect.bl_idname, text='Intersect', icon='PIVOT_MEDIAN') main.separator() col = main.column(align=True) col.enabled = obs_len == 2 - col.operator(OBJECT_OT_BoolTool_Auto_Slice.bl_idname, text='Slice', icon="ROTATECENTER") - col.operator(OBJECT_OT_BoolTool_Auto_Subtract.bl_idname, text='Subtract', icon="ROTACTIVE") + col.operator(OBJECT_OT_BoolTool_Auto_Slice.bl_idname, text='Slice', icon='PIVOT_MEDIAN') + col.operator(OBJECT_OT_BoolTool_Auto_Subtract.bl_idname, text='Subtract', icon='PIVOT_ACTIVE') main.separator() @@ -994,10 +994,10 @@ class VIEW3D_PT_booltool_tools(Panel): col.enabled = obs_len > 1 col.label("Brush Boolean:", icon="MODIFIER") col.separator() - col.operator(BTool_Diff.bl_idname, text="Difference", icon="ROTACTIVE") - col.operator(BTool_Union.bl_idname, text="Union", icon="ROTATECOLLECTION") - col.operator(BTool_Inters.bl_idname, text="Intersect", icon="ROTATECENTER") - col.operator(BTool_Slice.bl_idname, text="Slice", icon="ROTATECENTER") + col.operator(BTool_Diff.bl_idname, text="Difference", icon='PIVOT_ACTIVE') + col.operator(BTool_Union.bl_idname, text="Union", icon='PIVOT_INDIVIDUAL') + col.operator(BTool_Inters.bl_idname, text="Intersect", icon='PIVOT_MEDIAN') + col.operator(BTool_Slice.bl_idname, text="Slice", icon='PIVOT_MEDIAN') main.separator() diff --git a/object_cloud_gen.py b/object_cloud_gen.py index 008763fc..6601b8f1 100644 --- a/object_cloud_gen.py +++ b/object_cloud_gen.py @@ -563,7 +563,7 @@ class GenerateCloud(Operator): # Select all of the left over boxes so people can immediately # press generate again if they want for eachMember in definitionObjects: - eachMember.draw_type = 'SOLID' + eachMember.display_type = 'SOLID' eachMember.select = True eachMember.hide_render = False @@ -576,7 +576,7 @@ class GenerateCloud(Operator): # Create a new object cloudPnts cloudPnts = addNewObject(scene, "CloudPoints", bounds) cloudPnts["CloudMember"] = "CreatedObj" - cloudPnts.draw_type = 'WIRE' + cloudPnts.display_type = 'WIRE' cloudPnts.hide_render = True makeParent(bounds, cloudPnts, scene) @@ -606,7 +606,7 @@ class GenerateCloud(Operator): selectedObjects[0] ) - bounds.draw_type = 'BOUNDS' + bounds.display_type = 'BOUNDS' bounds.hide_render = False # Just add a Definition Property designating this @@ -630,7 +630,7 @@ class GenerateCloud(Operator): for selObj in selectedObjects: selObj["CloudMember"] = "DefinitionObj" selObj.name = "DefinitionObj" - selObj.draw_type = 'WIRE' + selObj.display_type = 'WIRE' selObj.hide_render = True selObj.hide = True makeParent(bounds, selObj, scene) @@ -638,7 +638,7 @@ class GenerateCloud(Operator): # Do the same to the 1. object since it is no longer in list. firstObject["CloudMember"] = "DefinitionObj" firstObject.name = "DefinitionObj" - firstObject.draw_type = 'WIRE' + firstObject.display_type = 'WIRE' firstObject.hide_render = True makeParent(bounds, firstObject, scene) @@ -646,7 +646,7 @@ class GenerateCloud(Operator): # Create a new object cloud. cloud = addNewObject(scene, "CloudMesh", bounds) cloud["CloudMember"] = "CreatedObj" - cloud.draw_type = 'WIRE' + cloud.display_type = 'WIRE' cloud.hide_render = True makeParent(bounds, cloud, scene) @@ -677,7 +677,7 @@ class GenerateCloud(Operator): cloudParticles.settings.frame_end = 0 cloudParticles.settings.emit_from = 'VOLUME' cloudParticles.settings.lifetime = scene.frame_end - cloudParticles.settings.draw_method = 'DOT' + cloudParticles.settings.display_method = 'DOT' cloudParticles.settings.render_type = 'NONE' cloudParticles.settings.distribution = 'RAND' cloudParticles.settings.physics_type = 'NEWTON' @@ -836,7 +836,7 @@ class GenerateCloud(Operator): # Create a new object cloudPnts cloudPnts = addNewObject(scene, "CloudPoints", bounds) cloudPnts["CloudMember"] = "CreatedObj" - cloudPnts.draw_type = 'WIRE' + cloudPnts.display_type = 'WIRE' cloudPnts.hide_render = True makeParent(bounds, cloudPnts, scene) diff --git a/object_collections.py b/object_collections.py new file mode 100644 index 00000000..9c7d6d76 --- /dev/null +++ b/object_collections.py @@ -0,0 +1,309 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + +import bpy +from bpy.types import ( + Operator, + Panel, + Menu, + ) + + +from bpy.props import ( + EnumProperty, + IntProperty, + ) + + +bl_info = { + "name": "Collections", + "author": "Dalai Felinto", + "version": (1, 0), + "blender": (2, 80, 0), + "description": "Panel to set/unset object collections", + "warning": "", + "wiki_url": "", + "tracker_url": "", + "category": "Object"} + + +# ##################################################################################### +# Operators +# ##################################################################################### + +class OBJECT_OT_collection_add(Operator): + """Add an object to a new collection""" + bl_idname = "object.collection_add" + bl_label = "Add to New Collection" + + def execute(self, context): + scene = context.scene + collection = scene.master_collection.collections.new() + collection.objects.link(context.object) + return {'FINISHED'} + + +class OBJECT_OT_collection_remove(Operator): + """Remove the active object from this collection""" + bl_idname = "object.collection_remove" + bl_label = "Remove from Collection" + + def execute(self, context): + collection = context.scene_collection + collection.objects.unlink(context.object) + return {'FINISHED'} + + +def get_collection_from_id_recursive(collection, collection_id, current_id): + """Return len of collection and the collection if it was a match""" + if collection_id == current_id: + return collection, 0 + + current_id += 1 + + for collection_nested in collection.collections: + matched_collection, current_id = get_collection_from_id_recursive( + collection_nested, + collection_id, + current_id) + if matched_collection is not None: + return matched_collection, 0 + + return None, current_id + + +def get_collection_from_id(scene, collection_id): + master_collection = scene.master_collection + return get_collection_from_id_recursive(master_collection, collection_id, 0)[0] + + +def collection_items_recursive(path, collection, items, current_id, object_name): + name = collection.name + current_id += 1 + + if object_name not in collection.objects: + items.append((str(current_id), path + name, "")) + path += name + " / " + + for collection_nested in collection.collections: + current_id = collection_items_recursive(path, collection_nested, items, current_id, object_name) + return current_id + + +def collection_items(self, context): + items = [] + + master_collection = context.scene.master_collection + object_name = context.object.name + + if object_name not in master_collection.objects: + items.append(('0', "Master Collection", "", 'COLLAPSEMENU', 0)) + + current_id = 0 + for collection in master_collection.collections: + current_id = collection_items_recursive("", collection, items, current_id, object_name) + + return items + + +class OBJECT_OT_collection_link(Operator): + """Add an object to an existing collection""" + bl_idname = "object.collection_link" + bl_label = "Link to Collection" + + collection_index = IntProperty( + name = "Collection Index", + default = -1, + options = {'SKIP_SAVE'}, + ) + + type = EnumProperty( + name = "", + description = "Dynamic enum for collections", + items=collection_items, + ) + + def execute(self, context): + if self.collection_index == -1: + self.collection_index = int(self.type) + + collection = get_collection_from_id(context.scene, self.collection_index) + + if collection is None: + # It should never ever happen! + self.report({'ERROR'}, "Unexpected error: collection {0} is invalid".format( + self.collection_index)) + return {'CANCELLED'} + + collection.objects.link(context.object) + return {'FINISHED'} + + def invoke(self, context, events): + if self.collection_index != -1: + return self.execute(context) + + wm = context.window_manager + wm.invoke_search_popup(self) + return {'FINISHED'} + + +def find_collection_parent(collection, collection_parent): + for collection_nested in collection_parent.collections: + if collection_nested == collection: + return collection_parent + + found_collection = find_collection_parent(collection, collection_nested) + if found_collection: + return found_collection + return None + + +class OBJECT_OT_collection_unlink(Operator): + """Unlink the collection from all objects""" + bl_idname = "object.collection_unlink" + bl_label = "Unlink Collection" + + def execute(self, context): + collection = context.scene_collection + master_collection = context.scene.master_collection + + collection_parent = find_collection_parent(collection, master_collection) + if collection_parent is None: + self.report({'ERROR'}, "Cannot find {0}'s parent".format(collection.name)) + return {'CANCELLED'} + + collection_parent.collections.remove(collection) + return {'CANCELLED'} + + +def select_collection_objects(collection): + for ob in collection.objects: + ob.select_set('SELECT') + + for collection_nested in collection.collections: + select_collection_objects(collection_nested) + + +class OBJECT_OT_collection_select(Operator): + """Select all objects in collection""" + bl_idname = "object.collection_select" + bl_label = "Select Collection" + + def execute(self, context): + collection = context.scene_collection + select_collection_objects(collection) + return {'FINISHED'} + + +# ##################################################################################### +# Interface +# ##################################################################################### + +class COLLECTION_MT_specials(Menu): + bl_label = "Collection Specials" + + def draw(self, context): + layout = self.layout + + col = layout.column() + col.active = context.scene_collection != context.scene.master_collection + col.operator("object.collection_unlink", icon='X', text="Unlink Collection") + + layout.operator("object.collection_select", text="Select Collection") + + +def all_collections_get(context): + """Iterator over all scene collections + """ + def all_collections_recursive_get(collection_parent, collections): + collections.append(collection_parent) + for collection_nested in collection_parent.collections: + all_collections_recursive_get(collection_nested, collections) + + scene = context.scene + master_collection = scene.master_collection + + collections = [] + + all_collections_recursive_get(master_collection, collections) + + return collections + + +class OBJECT_PT_collections(Panel): + bl_space_type = 'PROPERTIES' + bl_region_type = 'WINDOW' + bl_context = "object" + bl_label = "Collections" + + def draw(self, context): + layout = self.layout + row = layout.row(align=True) + + obj = context.object + master_collection = bpy.context.scene.master_collection + + if master_collection.collections: + row.operator("object.collection_link", text="Add to Collection") + else: + row.operator("object.collection_link", text="Add to Collection").collection_index = 0 + row.operator("object.collection_add", text="", icon='ADD') + + obj_name = obj.name + for collection in all_collections_get(context): + collection_objects = collection.objects + if obj_name in collection.objects: + col = layout.column(align=True) + col.context_pointer_set("scene_collection", collection) + + row = col.box().row() + if collection == master_collection: + row.label(text=collection.name) + else: + row.prop(collection, "name", text="") + row.operator("object.collection_remove", text="", icon='X', emboss=False) + row.menu("COLLECTION_MT_specials", icon='DOWNARROW_HLT', text="") + + +# ##################################################################################### +# Register/Unregister +# ##################################################################################### + +classes = ( + COLLECTION_MT_specials, + OBJECT_PT_collections, + OBJECT_OT_collection_add, + OBJECT_OT_collection_remove, + OBJECT_OT_collection_link, + OBJECT_OT_collection_unlink, + OBJECT_OT_collection_select, +) + + +def register(): + for cls in classes: + bpy.utils.register_class(cls) + + +def unregister(): + for cls in classes: + bpy.utils.unregister_class(cls) + + +if __name__ == "__main__": + register() diff --git a/object_fracture/__init__.py b/object_fracture/__init__.py index 0ac9f403..5dad8801 100644 --- a/object_fracture/__init__.py +++ b/object_fracture/__init__.py @@ -40,8 +40,8 @@ else: import bpy -class INFO_MT_add_fracture_objects(bpy.types.Menu): - bl_idname = "INFO_MT_add_fracture_objects" +class VIEW3D_MT_add_fracture_objects(bpy.types.Menu): + bl_idname = "VIEW3D_MT_add_fracture_objects" bl_label = "Fracture Helper Objects" def draw(self, context): @@ -57,21 +57,21 @@ class INFO_MT_add_fracture_objects(bpy.types.Menu): def menu_func(self, context): - self.layout.menu("INFO_MT_add_fracture_objects") + self.layout.menu("VIEW3D_MT_add_fracture_objects") def register(): bpy.utils.register_module(__name__) # Add the "add fracture objects" menu to the "Add" menu - bpy.types.INFO_MT_add.append(menu_func) + bpy.types.VIEW3D_MT_add.append(menu_func) def unregister(): bpy.utils.unregister_module(__name__) # Remove "add fracture objects" menu from the "Add" menu. - bpy.types.INFO_MT_add.remove(menu_func) + bpy.types.VIEW3D_MT_add.remove(menu_func) if __name__ == "__main__": diff --git a/object_fracture_cell/__init__.py b/object_fracture_cell/__init__.py index ad4cdf39..891027f2 100644 --- a/object_fracture_cell/__init__.py +++ b/object_fracture_cell/__init__.py @@ -75,8 +75,8 @@ def main_object(scene, obj, level, **kw): obj.select = False if kw_copy["use_debug_redraw"]: - obj_draw_type_prev = obj.draw_type - obj.draw_type = 'WIRE' + obj_display_type_prev = obj.display_type + obj.display_type = 'WIRE' objects = fracture_cell_setup.cell_fracture_objects(scene, obj, **kw_copy) objects = fracture_cell_setup.cell_fracture_boolean(scene, obj, objects, @@ -172,7 +172,7 @@ def main_object(scene, obj, level, **kw): group.objects.link(obj_cell) if kw_copy["use_debug_redraw"]: - obj.draw_type = obj_draw_type_prev + obj.display_type = obj_display_type_prev # testing only! # obj.hide = True diff --git a/object_grease_scatter.py b/object_grease_scatter.py index 105b40ea..df1c7cce 100644 --- a/object_grease_scatter.py +++ b/object_grease_scatter.py @@ -390,12 +390,12 @@ def menu_func(self, context): def register(): bpy.utils.register_class(Scatter) - bpy.types.INFO_MT_mesh_add.append(menu_func) + bpy.types.VIEW3D_MT_mesh_add.append(menu_func) def unregister(): bpy.utils.unregister_class(Scatter) - bpy.types.INFO_MT_mesh_add.remove(menu_func) + bpy.types.VIEW3D_MT_mesh_add.remove(menu_func) #if __name__ == "__main__": # _main() diff --git a/object_print3d_utils/__init__.py b/object_print3d_utils/__init__.py index 5ae1d3d6..6bf2a8a7 100644 --- a/object_print3d_utils/__init__.py +++ b/object_print3d_utils/__init__.py @@ -21,7 +21,7 @@ bl_info = { "name": "3D Print Toolbox", "author": "Campbell Barton", - "blender": (2, 79, 0), + "blender": (2, 80, 0), "location": "3D View > Toolbox", "description": "Utilities for 3D printing", "wiki_url": "https://wiki.blender.org/index.php/Extensions:2.6/Py/" @@ -59,101 +59,66 @@ else: class Print3D_Scene_Props(PropertyGroup): - export_format = EnumProperty( - name="Format", - description="Format type to export to", - items=(('STL', "STL", ""), - ('PLY', "PLY", ""), - ('WRL', "VRML2", ""), - ('X3D', "X3D", ""), - ('OBJ', "OBJ", "")), - default='STL', - ) - use_export_texture = BoolProperty( - name="Copy Textures", - description="Copy textures on export to the output path", - default=False, - ) - use_apply_scale = BoolProperty( - name="Apply Scale", - description="Apply scene scale setting on export", - default=False, - ) - export_path = StringProperty( - name="Export Directory", - description="Path to directory where the files are created", - default="//", maxlen=1024, subtype="DIR_PATH", - ) - thickness_min = FloatProperty( - name="Thickness", - description="Minimum thickness", - subtype='DISTANCE', - default=0.001, # 1mm - min=0.0, max=10.0, - ) - threshold_zero = FloatProperty( - name="Threshold", - description="Limit for checking zero area/length", - default=0.0001, - precision=5, - min=0.0, max=0.2, - ) - angle_distort = FloatProperty( - name="Angle", - description="Limit for checking distorted faces", - subtype='ANGLE', - default=math.radians(45.0), - min=0.0, max=math.radians(180.0), - ) - angle_sharp = FloatProperty( - name="Angle", - subtype='ANGLE', - default=math.radians(160.0), - min=0.0, max=math.radians(180.0), - ) - angle_overhang = FloatProperty( - name="Angle", - subtype='ANGLE', - default=math.radians(45.0), - min=0.0, max=math.radians(90.0), - ) - - -# Update panel category name -panels = ( - ui.VIEW3D_PT_Print3D_Object, - ui.VIEW3D_PT_Print3D_Mesh, + export_format: EnumProperty( + name="Format", + description="Format type to export to", + items=( + ('STL', "STL", ""), + ('PLY', "PLY", ""), + ('WRL', "VRML2", ""), + ('X3D', "X3D", ""), + ('OBJ', "OBJ", ""), + ), + default='STL', + ) + use_export_texture: BoolProperty( + name="Copy Textures", + description="Copy textures on export to the output path", + default=False, + ) + use_apply_scale: BoolProperty( + name="Apply Scale", + description="Apply scene scale setting on export", + default=False, + ) + export_path: StringProperty( + name="Export Directory", + description="Path to directory where the files are created", + default="//", maxlen=1024, subtype="DIR_PATH", + ) + thickness_min: FloatProperty( + name="Thickness", + description="Minimum thickness", + subtype='DISTANCE', + default=0.001, # 1mm + min=0.0, max=10.0, + ) + threshold_zero: FloatProperty( + name="Threshold", + description="Limit for checking zero area/length", + default=0.0001, + precision=5, + min=0.0, max=0.2, + ) + angle_distort: FloatProperty( + name="Angle", + description="Limit for checking distorted faces", + subtype='ANGLE', + default=math.radians(45.0), + min=0.0, max=math.radians(180.0), + ) + angle_sharp: FloatProperty( + name="Angle", + subtype='ANGLE', + default=math.radians(160.0), + min=0.0, max=math.radians(180.0), + ) + angle_overhang: FloatProperty( + name="Angle", + subtype='ANGLE', + default=math.radians(45.0), + min=0.0, max=math.radians(90.0), ) - - -def update_panels(self, context): - try: - for panel in panels: - if "bl_rna" in panel.__dict__: - bpy.utils.unregister_class(panel) - - for panel in panels: - panel.bl_category = context.user_preferences.addons[__name__].preferences.category - bpy.utils.register_class(panel) - - except Exception as e: - message = "3D Print Toolbox: Updating Panel locations has failed" - print("\n[{}]\n{}\n\nError:\n{}".format(__name__, message, e)) - - -class Print3D_Preferences(AddonPreferences): - bl_idname = __name__ - - category = StringProperty( - name="Tab Category", - description="Choose a name for the category of the panel", - default="3D Printing", - update=update_panels, - ) - - def draw(self, context): - layout = self.layout - layout.prop(self, "category") classes = ( @@ -185,8 +150,7 @@ classes = ( operators.MESH_OT_Print3D_Export, Print3D_Scene_Props, - Print3D_Preferences, - ) +) def register(): @@ -195,8 +159,6 @@ def register(): bpy.types.Scene.print_3d = PointerProperty(type=Print3D_Scene_Props) - update_panels(None, bpy.context) - def unregister(): for cls in classes: diff --git a/object_print3d_utils/export.py b/object_print3d_utils/export.py index cbb607d2..00277958 100644 --- a/object_print3d_utils/export.py +++ b/object_print3d_utils/export.py @@ -53,11 +53,12 @@ def image_copy_guess(filepath, objects): def write_mesh(context, info, report_cb): scene = context.scene + layer = context.view_layer unit = scene.unit_settings print_3d = scene.print_3d - obj_base = scene.object_bases.active - obj = obj_base.object + # obj_base = layer.object_bases.active + obj = layer.objects.active export_format = print_3d.export_format global_scale = unit.scale_length if (unit.system != 'NONE' and print_3d.use_apply_scale) else 1.0 @@ -73,13 +74,16 @@ def write_mesh(context, info, report_cb): bpy.ops.object.mode_set(mode='OBJECT', toggle=False) from . import mesh_helpers - obj_base_tmp = mesh_helpers.object_merge(context, context_override["selected_objects"]) - context_override["active_object"] = obj_base_tmp.object - context_override["selected_bases"] = [obj_base_tmp] - context_override["selected_objects"] = [obj_base_tmp.object] + obj_tmp = mesh_helpers.object_merge(context, context_override["selected_objects"]) + context_override["active_object"] = obj_tmp + # context_override["selected_bases"] = [obj_base_tmp] + context_override["selected_objects"] = [obj_tmp] else: + # XXX28 + ''' if obj_base not in context_override["selected_bases"]: context_override["selected_bases"].append(obj_base) + ''' if obj not in context_override["selected_objects"]: context_override["selected_objects"].append(obj) diff --git a/object_print3d_utils/mesh_helpers.py b/object_print3d_utils/mesh_helpers.py index a5d5f74f..873f30d2 100644 --- a/object_print3d_utils/mesh_helpers.py +++ b/object_print3d_utils/mesh_helpers.py @@ -32,7 +32,7 @@ def bmesh_copy_from_object(obj, transform=True, triangulate=True, apply_modifier if apply_modifiers and obj.modifiers: import bpy - me = obj.to_mesh(bpy.context.scene, True, 'PREVIEW', calc_tessface=False) + me = obj.to_mesh(bpy.context.scene, True, 'PREVIEW') bm = bmesh.new() bm.from_mesh(me) bpy.data.meshes.remove(me) @@ -157,19 +157,31 @@ def bmesh_check_thick_object(obj, thickness): # Create a real mesh (lame!) context = bpy.context scene = context.scene + layer = context.view_layer + layer_collection = context.layer_collection + if layer_collection is None: + scene_collection = scene.master_collection.collections.new("") + layer_collection = layer.collections.link(scene_collection) + else: + scene_collection = layer_collection.collection + me_tmp = bpy.data.meshes.new(name="~temp~") bm.to_mesh(me_tmp) # bm.free() # delay free obj_tmp = bpy.data.objects.new(name=me_tmp.name, object_data=me_tmp) - base = scene.objects.link(obj_tmp) + # base = scene.objects.link(obj_tmp) + scene_collection.objects.link(obj_tmp) # Add new object to local view layer + # XXX28 + ''' v3d = None if context.space_data and context.space_data.type == 'VIEW_3D': v3d = context.space_data if v3d and v3d.local_view: base.layers_from_view(context.space_data) + ''' scene.update() ray_cast = obj_tmp.ray_cast @@ -190,7 +202,7 @@ def bmesh_check_thick_object(obj, thickness): p_b = p - no_end p_dir = p_b - p_a - ok, co, no, index = ray_cast(p_a, p_dir, p_dir.length) + ok, co, no, index = ray_cast(p_a, p_dir, distance=p_dir.length) if ok: # Add the face we hit @@ -203,7 +215,7 @@ def bmesh_check_thick_object(obj, thickness): # finished with bm bm.free() - scene.objects.unlink(obj_tmp) + scene_collection.objects.unlink(obj_tmp) bpy.data.objects.remove(obj_tmp) bpy.data.meshes.remove(me_tmp) @@ -228,17 +240,24 @@ def object_merge(context, objects): seq.remove(seq[i]) scene = context.scene + layer = context.view_layer + layer_collection = context.layer_collection + if layer_collection is None: + scene_collection = scene.master_collection.collections.new("") + layer_collection = layer.collections.link(scene_collection) + else: + scene_collection = layer_collection.collection # deselect all for obj in scene.objects: - obj.select = False + obj.select_set('DESELECT') # add empty object mesh_base = bpy.data.meshes.new(name="~tmp~") obj_base = bpy.data.objects.new(name="~tmp~", object_data=mesh_base) - base_base = scene.objects.link(obj_base) - scene.objects.active = obj_base - obj_base.select = True + scene_collection.objects.link(obj_base) + layer.objects.active = obj_base + obj_base.select_set('SELECT') # loop over all meshes for obj in objects: @@ -246,29 +265,29 @@ def object_merge(context, objects): continue # convert each to a mesh - mesh_new = obj.to_mesh(scene=scene, - apply_modifiers=True, - settings='PREVIEW', - calc_tessface=False) + mesh_new = obj.to_mesh( + depsgraph=context.depsgraph, + apply_modifiers=True, + ) # remove non-active uvs/vcols cd_remove_all_but_active(mesh_new.vertex_colors) - cd_remove_all_but_active(mesh_new.uv_textures) + cd_remove_all_but_active(mesh_new.uv_layers) # join into base mesh obj_new = bpy.data.objects.new(name="~tmp-new~", object_data=mesh_new) - base_new = scene.objects.link(obj_new) + base_new = scene_collection.objects.link(obj_new) obj_new.matrix_world = obj.matrix_world fake_context = context.copy() fake_context["active_object"] = obj_base - fake_context["selected_editable_bases"] = [base_base, base_new] + fake_context["selected_editable_objects"] = [obj_base, obj_new] bpy.ops.object.join(fake_context) del base_new, obj_new # remove object and its mesh, join does this - # scene.objects.unlink(obj_new) + # scene_collection.objects.unlink(obj_new) # bpy.data.objects.remove(obj_new) bpy.data.meshes.remove(mesh_new) @@ -276,7 +295,8 @@ def object_merge(context, objects): scene.update() # return new object - return base_base + return obj_base + def face_is_distorted(ele, angle_distort): diff --git a/object_print3d_utils/operators.py b/object_print3d_utils/operators.py index e7ff4713..ebc1a730 100644 --- a/object_print3d_utils/operators.py +++ b/object_print3d_utils/operators.py @@ -23,15 +23,15 @@ import bpy from bpy.types import Operator from bpy.props import ( - IntProperty, - FloatProperty, - ) + IntProperty, + FloatProperty, +) import bmesh from . import ( - mesh_helpers, - report, - ) + mesh_helpers, + report, +) def clean_float(text): @@ -430,16 +430,16 @@ class MESH_OT_Print3D_Clean_Non_Manifold(Operator): bl_label = "Print3D Clean Non-Manifold and Inverted" bl_options = {'REGISTER', 'UNDO'} - threshold = bpy.props.FloatProperty( - name="threshold", - description="Minimum distance between elements to merge", - default=0.0001, - ) - sides = bpy.props.IntProperty( - name="sides", - description="Number of sides in hole required to fill", - default=4, - ) + threshold: bpy.props.FloatProperty( + name="threshold", + description="Minimum distance between elements to merge", + default=0.0001, + ) + sides: bpy.props.IntProperty( + name="sides", + description="Number of sides in hole required to fill", + default=4, + ) def execute(self, context): self.context = context @@ -600,7 +600,7 @@ class MESH_OT_Print3D_Select_Report(Operator): bl_label = "Print3D Select Report" bl_options = {'INTERNAL'} - index = IntProperty() + index: IntProperty() _type_to_mode = { bmesh.types.BMVert: 'VERT', @@ -659,14 +659,14 @@ class MESH_OT_Print3D_Scale_To_Volume(Operator): bl_label = "Scale to Volume" bl_options = {'REGISTER', 'UNDO'} - volume_init = FloatProperty( - options={'HIDDEN'}, - ) - volume = FloatProperty( - name="Volume", - unit='VOLUME', - min=0.0, max=100000.0, - ) + volume_init: FloatProperty( + options={'HIDDEN'}, + ) + volume: FloatProperty( + name="Volume", + unit='VOLUME', + min=0.0, max=100000.0, + ) def execute(self, context): import math @@ -705,17 +705,17 @@ class MESH_OT_Print3D_Scale_To_Bounds(Operator): bl_label = "Scale to Bounds" bl_options = {'REGISTER', 'UNDO'} - length_init = FloatProperty( - options={'HIDDEN'}, - ) - axis_init = IntProperty( - options={'HIDDEN'}, - ) - length = FloatProperty( - name="Length Limit", - unit='LENGTH', - min=0.0, max=100000.0, - ) + length_init: FloatProperty( + options={'HIDDEN'}, + ) + axis_init: IntProperty( + options={'HIDDEN'}, + ) + length: FloatProperty( + name="Length Limit", + unit='LENGTH', + min=0.0, max=100000.0, + ) def execute(self, context): scale = self.length / self.length_init @@ -731,11 +731,11 @@ class MESH_OT_Print3D_Scale_To_Bounds(Operator): return max(((max(v[i] for v in vecs) - min(v[i] for v in vecs)), i) for i in range(3)) if context.mode == 'EDIT_MESH': - length, axis = calc_length([Vector(v) * obj.matrix_world + length, axis = calc_length([Vector(v) @ obj.matrix_world for obj in [context.edit_object] for v in obj.bound_box]) else: - length, axis = calc_length([Vector(v) * obj.matrix_world + length, axis = calc_length([Vector(v) @ obj.matrix_world for obj in context.selected_editable_objects if obj.type == 'MESH' for v in obj.bound_box]) diff --git a/object_print3d_utils/ui.py b/object_print3d_utils/ui.py index 6e5c3284..44634bbc 100644 --- a/object_print3d_utils/ui.py +++ b/object_print3d_utils/ui.py @@ -29,7 +29,7 @@ from . import report class Print3D_ToolBar: bl_label = "Print3D" bl_space_type = 'VIEW_3D' - bl_region_type = 'TOOLS' + bl_region_type = 'UI' _type_to_icon = { bmesh.types.BMVert: 'VERTEXSEL', @@ -49,7 +49,7 @@ class Print3D_ToolBar: if info: obj = context.edit_object - layout.label("Output:") + layout.label(text="Output:") box = layout.box() col = box.column(align=False) # box.alert = True @@ -61,7 +61,7 @@ class Print3D_ToolBar: icon=Print3D_ToolBar._type_to_icon[bm_type]).index = i layout.operator("mesh.select_non_manifold", text='Non Manifold Extended') else: - col.label(text) + col.label(text=text) def draw(self, context): @@ -73,13 +73,13 @@ class Print3D_ToolBar: # TODO, presets row = layout.row() - row.label("Statistics:") + row.label(text="Statistics:") rowsub = layout.row(align=True) rowsub.operator("mesh.print3d_info_volume", text="Volume") rowsub.operator("mesh.print3d_info_area", text="Area") row = layout.row() - row.label("Checks:") + row.label(text="Checks:") col = layout.column(align=True) col.operator("mesh.print3d_check_solid", text="Solid") col.operator("mesh.print3d_check_intersect", text="Intersections") @@ -102,7 +102,7 @@ class Print3D_ToolBar: col.operator("mesh.print3d_check_all", text="Check All") row = layout.row() - row.label("Cleanup:") + row.label(text="Cleanup:") col = layout.column(align=True) col.operator("mesh.print3d_clean_isolated", text="Isolated") rowsub = col.row(align=True) @@ -114,14 +114,14 @@ class Print3D_ToolBar: # col.operator("mesh.print3d_clean_thin", text="Wall Thickness") row = layout.row() - row.label("Scale To:") + row.label(text="Scale To:") rowsub = layout.row(align=True) rowsub.operator("mesh.print3d_scale_to_volume", text="Volume") rowsub.operator("mesh.print3d_scale_to_bounds", text="Bounds") col = layout.column() rowsub = col.row(align=True) - rowsub.label("Export Path:") + rowsub.label(text="Export Path:") rowsub.prop(print_3d, "use_apply_scale", text="", icon='MAN_SCALE') rowsub.prop(print_3d, "use_export_texture", text="", icon='FILE_IMAGE') rowsub = col.row() diff --git a/oscurart_tools/oscurart_meshes.py b/oscurart_tools/oscurart_meshes.py index 70f4df1c..61c6fa54 100644 --- a/oscurart_tools/oscurart_meshes.py +++ b/oscurart_tools/oscurart_meshes.py @@ -321,8 +321,7 @@ def DefOscObjectToMesh(): MESH = ACTOBJ.to_mesh( scene=bpy.context.scene, apply_modifiers=True, - settings="RENDER", - calc_tessface=True) + settings="RENDER") OBJECT = bpy.data.objects.new(("%s_Freeze") % (ACTOBJ.name), MESH) bpy.context.scene.objects.link(OBJECT) @@ -601,7 +600,7 @@ def defPasteUvsIsland(self, uvOffset, rotateUv,context): bm = bmesh.from_edit_mesh(bpy.context.object.data) bmesh.ops.reverse_uvs(bm, faces=[f for f in bm.faces if f.select]) bmesh.ops.rotate_uvs(bm, faces=[f for f in bm.faces if f.select]) - #bmesh.update_edit_mesh(bpy.context.object.data, tessface=False, destructive=False) + #bmesh.update_edit_mesh(bpy.context.object.data, loop_triangles=False, destructive=False) diff --git a/paint_palette.py b/paint_palette.py index cf0e58e9..320163ad 100644 --- a/paint_palette.py +++ b/paint_palette.py @@ -462,12 +462,12 @@ def color_palette_draw(self, context): row = layout.row(align=True) row.menu("PALETTE_MT_menu", text=PALETTE_MT_menu.bl_label) - row.operator("palette.preset_add", text="", icon="ZOOMIN").remove_active = False - row.operator("palette.preset_add", text="", icon="ZOOMOUT").remove_active = True + row.operator("palette.preset_add", text="", icon='ADD').remove_active = False + row.operator("palette.preset_add", text="", icon='REMOVE').remove_active = True col = layout.column(align=True) row = col.row(align=True) - row.operator("palette_props.add_color", icon="ZOOMIN") + row.operator("palette_props.add_color", icon='ADD') row.prop(palette_props, "index") row.operator("palette_props.remove_color", icon="PANEL_CLOSE") diff --git a/pie_menus_official/__init__.py b/pie_menus_official/__init__.py index 513ae2b3..52c8d346 100644 --- a/pie_menus_official/__init__.py +++ b/pie_menus_official/__init__.py @@ -31,7 +31,7 @@ bl_info = { "name": "UI Pie Menu Official", "author": "Antony Riakiotakis, Sebastian Koenig", "version": (1, 1, 5), - "blender": (2, 7, 7), + "blender": (2, 80, 0), "description": "Individual Pie Menu Activation List", "location": "Addons Preferences", "warning": "", @@ -129,42 +129,42 @@ class UIToolsPreferences(AddonPreferences): op = sub.operator('wm.context_toggle', text='', icon=icon, emboss=False) op.data_path = 'addon_prefs.show_expanded_' + mod_name - sub.label('{}: {}'.format(info['category'], info['name'])) + sub.label(text='{}: {}'.format(info['category'], info['name'])) sub = row.row() sub.alignment = 'RIGHT' if info.get('warning'): - sub.label('', icon='ERROR') + sub.label(text='', icon='ERROR') sub.prop(self, 'use_' + mod_name, text='') # The second stage if expand: if info.get('description'): - split = col.row().split(percentage=0.15) - split.label('Description:') - split.label(info['description']) + split = col.row().split(factor=0.15) + split.label(text='Description:') + split.label(text=info['description']) if info.get('location'): - split = col.row().split(percentage=0.15) - split.label('Location:') - split.label(info['location']) + split = col.row().split(factor=0.15) + split.label(text='Location:') + split.label(text=info['location']) """ if info.get('author'): - split = col.row().split(percentage=0.15) - split.label('Author:') - split.label(info['author']) + split = col.row().split(factor=0.15) + split.label(text='Author:') + split.label(text=info['author']) """ if info.get('version'): - split = col.row().split(percentage=0.15) - split.label('Version:') - split.label('.'.join(str(x) for x in info['version']), + split = col.row().split(factor=0.15) + split.label(text='Version:') + split.label(text='.'.join(str(x) for x in info['version']), translate=False) if info.get('warning'): - split = col.row().split(percentage=0.15) - split.label('Warning:') - split.label(' ' + info['warning'], icon='ERROR') + split = col.row().split(factor=0.15) + split.label(text='Warning:') + split.label(text=' ' + info['warning'], icon='ERROR') tot_row = int(bool(info.get('wiki_url'))) if tot_row: - split = col.row().split(percentage=0.15) + split = col.row().split(factor=0.15) split.label(text='Internet:') if info.get('wiki_url'): op = split.operator('wm.url_open', diff --git a/pie_menus_official/pie_manipulator_of.py b/pie_menus_official/pie_manipulator_of.py index 04ced83a..eb475cf7 100644 --- a/pie_menus_official/pie_manipulator_of.py +++ b/pie_menus_official/pie_manipulator_of.py @@ -26,7 +26,7 @@ class VIEW3D_manipulator_set_of(Operator): bl_label = "Set Manipulator" bl_idname = "view3d.manipulator_set" - type = EnumProperty( + type: EnumProperty( name="Type", items=(('TRANSLATE', "Translate", "Use the manipulator for movement transformations"), ('ROTATE', "Rotate", "Use the manipulator for rotation transformations"), @@ -36,7 +36,7 @@ class VIEW3D_manipulator_set_of(Operator): def execute(self, context): # show manipulator if user selects an option - context.space_data.show_manipulator = True + context.space_data.show_gizmo = True context.space_data.transform_manipulators = {self.type} return {'FINISHED'} @@ -50,10 +50,10 @@ class VIEW3D_PIE_manipulator_of(Menu): layout = self.layout pie = layout.menu_pie() - pie.operator("view3d.manipulator_set", icon='MAN_TRANS', text="Translate").type = 'TRANSLATE' - pie.operator("view3d.manipulator_set", icon='MAN_ROT', text="Rotate").type = 'ROTATE' - pie.operator("view3d.manipulator_set", icon='MAN_SCALE', text="Scale").type = 'SCALE' - pie.prop(context.space_data, "show_manipulator") + pie.operator("wm.tool_set_by_name", icon='MAN_TRANS', text="Translate").name = "Move" + pie.operator("wm.tool_set_by_name", icon='MAN_ROT', text="Rotate").name = "Rotate" + pie.operator("wm.tool_set_by_name", icon='MAN_SCALE', text="Scale").name = "Scale" + pie.prop(context.space_data, "show_gizmo") classes = ( diff --git a/pie_menus_official/pie_pivot_of.py b/pie_menus_official/pie_pivot_of.py index 88677b69..ec48d359 100644 --- a/pie_menus_official/pie_pivot_of.py +++ b/pie_menus_official/pie_pivot_of.py @@ -24,9 +24,9 @@ class VIEW3D_PIE_pivot_of(Menu): layout = self.layout pie = layout.menu_pie() - pie.prop(context.space_data, "pivot_point", expand=True) + pie.prop(context.scene.tool_settings, "transform_pivot_point", expand=True) if context.active_object and context.active_object.mode == 'OBJECT': - pie.prop(context.space_data, "use_pivot_point_align", text="Center Points") + pie.prop(context.scene.tool_settings, "use_transform_pivot_point_align", text="Center Points") classes = ( diff --git a/pie_menus_official/pie_view_of.py b/pie_menus_official/pie_view_of.py index 40b79217..1c1f3df2 100644 --- a/pie_menus_official/pie_view_of.py +++ b/pie_menus_official/pie_view_of.py @@ -38,7 +38,7 @@ class VIEW3D_PIE_view_of(Menu): layout = self.layout pie = layout.menu_pie() - pie.operator_enum("VIEW3D_OT_viewnumpad", "type") + pie.operator_enum("VIEW3D_OT_view_axis", "type") pie.operator("wm.call_menu_pie", text="More", icon='PLUS').name = "VIEW3D_PIE_view_more_of" diff --git a/render_povray/__init__.py b/render_povray/__init__.py index a8b07887..9d7254ea 100644 --- a/render_povray/__init__.py +++ b/render_povray/__init__.py @@ -2274,11 +2274,11 @@ class PovrayPreferences(AddonPreferences): def register(): bpy.utils.register_module(__name__) - bpy.types.INFO_MT_add.prepend(ui.menu_func_add) - bpy.types.INFO_MT_file_import.append(ui.menu_func_import) + bpy.types.VIEW3D_MT_add.prepend(ui.menu_func_add) + bpy.types.TOPBAR_MT_file_import.append(ui.menu_func_import) bpy.types.TEXT_MT_templates.append(ui.menu_func_templates) bpy.types.RENDER_PT_povray_radiosity.prepend(ui.rad_panel_func) - bpy.types.LAMP_PT_POV_lamp.prepend(ui.lamp_panel_func) + bpy.types.LIGHT_PT_POV_light.prepend(ui.light_panel_func) bpy.types.WORLD_PT_world.prepend(ui.world_panel_func) # was used for parametric objects but made the other addon unreachable on # unregister for other tools to use created a user action call instead @@ -2312,11 +2312,11 @@ def unregister(): #bpy.types.TEXTURE_PT_context_texture.remove(TEXTURE_PT_povray_type) #addon_utils.disable("add_mesh_extra_objects", default_set=False) bpy.types.WORLD_PT_world.remove(ui.world_panel_func) - bpy.types.LAMP_PT_POV_lamp.remove(ui.lamp_panel_func) + bpy.types.LIGHT_PT_POV_light.remove(ui.light_panel_func) bpy.types.RENDER_PT_povray_radiosity.remove(ui.rad_panel_func) bpy.types.TEXT_MT_templates.remove(ui.menu_func_templates) - bpy.types.INFO_MT_file_import.remove(ui.menu_func_import) - bpy.types.INFO_MT_add.remove(ui.menu_func_add) + bpy.types.TOPBAR_MT_file_import.remove(ui.menu_func_import) + bpy.types.VIEW3D_MT_add.remove(ui.menu_func_add) bpy.utils.unregister_module(__name__) diff --git a/render_povray/nodes.py b/render_povray/nodes.py index a4acd138..a8281c8a 100644 --- a/render_povray/nodes.py +++ b/render_povray/nodes.py @@ -52,7 +52,7 @@ class ObjectNodeTree(bpy.types.NodeTree): @classmethod def get_from_context(cls, context): ob = context.active_object - if ob and ob.type not in {'LAMP'}: + if ob and ob.type not in {'LIGHT'}: ma = ob.active_material if ma is not None: nt_name = ma.node_tree @@ -517,7 +517,7 @@ class PovrayColorImageNode(Node, ObjectNodeTree): im=image split = column.split(percentage=0.8,align=True) split.prop_search(self,"image",context.blend_data,"images",text="") - split.operator("pov.imageopen",text="",icon="FILESEL") + split.operator("pov.imageopen",text="",icon="FILEBROWSER") if im is not None: column.prop(im,"source",text="") column.prop(self,"map_type",text="") @@ -535,7 +535,7 @@ class PovrayColorImageNode(Node, ObjectNodeTree): im=image split = column.split(percentage=0.8,align=True) split.prop_search(self,"image",context.blend_data,"images",text="") - split.operator("pov.imageopen",text="",icon="FILESEL") + split.operator("pov.imageopen",text="",icon="FILEBROWSER") if im is not None: column.prop(im,"source",text="") column.prop(self,"map_type",text="") @@ -597,7 +597,7 @@ class PovrayBumpMapNode(Node, ObjectNodeTree): im=image split = column.split(percentage=0.8,align=True) split.prop_search(self,"image",context.blend_data,"images",text="") - split.operator("pov.imageopen",text="",icon="FILESEL") + split.operator("pov.imageopen",text="",icon="FILEBROWSER") if im is not None: column.prop(im,"source",text="") column.prop(self,"map_type",text="") @@ -613,7 +613,7 @@ class PovrayBumpMapNode(Node, ObjectNodeTree): im=image split = column.split(percentage=0.8,align=True) split.prop_search(self,"image",context.blend_data,"images",text="") - split.operator("pov.imageopen",text="",icon="FILESEL") + split.operator("pov.imageopen",text="",icon="FILEBROWSER") if im is not None: column.prop(im,"source",text="") column.prop(self,"map_type",text="") @@ -668,7 +668,7 @@ class PovrayImagePatternNode(Node, ObjectNodeTree): im=image split = column.split(percentage=0.8,align=True) split.prop_search(self,"image",context.blend_data,"images",text="") - split.operator("pov.imageopen",text="",icon="FILESEL") + split.operator("pov.imageopen",text="",icon="FILEBROWSER") if im is not None: column.prop(im,"source",text="") column.prop(self,"map_type",text="") @@ -687,7 +687,7 @@ class PovrayImagePatternNode(Node, ObjectNodeTree): im=image split = column.split(percentage=0.8,align=True) split.prop_search(self,"image",context.blend_data,"images",text="") - split.operator("pov.imageopen",text="",icon="FILESEL") + split.operator("pov.imageopen",text="",icon="FILEBROWSER") if im is not None: column.prop(im,"source",text="") column.prop(self,"map_type",text="") diff --git a/render_povray/primitives.py b/render_povray/primitives.py index d7dfe663..1ae43c1a 100644 --- a/render_povray/primitives.py +++ b/render_povray/primitives.py @@ -1052,7 +1052,7 @@ class POVRAY_OT_rainbow_add(bpy.types.Operator): def execute(self,context): cam = context.scene.camera - bpy.ops.object.lamp_add(type='SPOT', radius=1) + bpy.ops.object.light_add(type='SPOT', radius=1) ob = context.object ob.data.show_cone = False ob.data.spot_blend = 0.5 diff --git a/render_povray/render.py b/render_povray/render.py index 26352b2d..227a588c 100644 --- a/render_povray/render.py +++ b/render_povray/render.py @@ -2067,7 +2067,7 @@ def write_pov(filename, scene=None, info_callback=None): # XXX I moved all those checks here, as there is no need to compute names # for object we won't export here! - if (ob.type in {'LAMP', 'CAMERA', #'EMPTY', #empties can bear dupligroups + if (ob.type in {'LIGHT', 'CAMERA', #'EMPTY', #empties can bear dupligroups 'META', 'ARMATURE', 'LATTICE'}): continue smokeFlag=False @@ -2111,7 +2111,7 @@ def write_pov(filename, scene=None, info_callback=None): strandShape = 0.0 # Set the number of particles to render count rather than 3d view display pSys.set_resolution(scene, ob, 'RENDER') - steps = pSys.settings.draw_step + steps = pSys.settings.display_step steps = 3 ** steps # or (power of 2 rather than 3) + 1 # Formerly : len(particle.hair_keys) totalNumberOfHairs = ( len(pSys.particles) + len(pSys.child_particles) ) @@ -2163,7 +2163,7 @@ def write_pov(filename, scene=None, info_callback=None): elif step == 0: hDiameter = strandStart else: - hDiameter += (strandEnd-strandStart)/(pSys.settings.draw_step+1) #XXX +1 or not? + hDiameter += (strandEnd-strandStart)/(pSys.settings.display_step+1) #XXX +1 or not? if step == 0 and pSys.settings.use_hair_bspline: # Write three times the first point to compensate pov Bezier handling file.write('<%.6g,%.6g,%.6g>,%.7g,\n' % (co[0], co[1], co[2], abs(hDiameter))) @@ -2689,7 +2689,7 @@ def write_pov(filename, scene=None, info_callback=None): importance = ob.pov.importance_value if me: me_materials = me.materials - me_faces = me.tessfaces[:] + me_faces = me.loop_triangles[:] #if len(me_faces)==0: #tabWrite("\n//dummy sphere to represent empty mesh location\n") #tabWrite("#declare %s =sphere {<0, 0, 0>,0 pigment{rgbt 1} no_image no_reflection no_radiosity photons{pass_through collect off} hollow}\n" % povdataname) @@ -2700,16 +2700,16 @@ def write_pov(filename, scene=None, info_callback=None): tabWrite("#declare %s =sphere {<0, 0, 0>,0 pigment{rgbt 1} no_image no_reflection no_radiosity photons{pass_through collect off} hollow}\n" % povdataname) continue - uv_textures = me.tessface_uv_textures - if len(uv_textures) > 0: - if me.uv_textures.active and uv_textures.active.data: - uv_layer = uv_textures.active.data + uv_layers = me.uv_layers + if len(uv_layers) > 0: + if me.uv_layers.active and uv_layers.active.data: + uv_layer = uv_layers.active.data else: uv_layer = None try: #vcol_layer = me.vertex_colors.active.data - vcol_layer = me.tessface_vertex_colors.active.data + vcol_layer = me.vertex_colors.active.data except AttributeError: vcol_layer = None @@ -2717,9 +2717,6 @@ def write_pov(filename, scene=None, info_callback=None): faces_normals = [f.normal[:] for f in me_faces] verts_normals = [v.normal[:] for v in me.vertices] - # quads incur an extra face - quadCount = sum(1 for f in faces_verts if len(f) == 4) - # Use named declaration to allow reference e.g. for baking. MR file.write("\n") tabWrite("#declare %s =\n" % povdataname) @@ -2775,12 +2772,8 @@ def write_pov(filename, scene=None, info_callback=None): # Generate unique UV's uniqueUVs = {} #n = 0 - for fi, uv in enumerate(uv_layer): - - if len(faces_verts[fi]) == 4: - uvs = uv_layer[fi].uv[0], uv_layer[fi].uv[1], uv_layer[fi].uv[2], uv_layer[fi].uv[3] - else: - uvs = uv_layer[fi].uv[0], uv_layer[fi].uv[1], uv_layer[fi].uv[2] + for f in me.faces: + uvs = [uv_layer[l].uv[:] for l in f.loops] for uv in uvs: uniqueUVs[uv[:]] = [-1] @@ -2811,7 +2804,7 @@ def write_pov(filename, scene=None, info_callback=None): if me.vertex_colors: #Write down vertex colors as a texture for each vertex tabWrite("texture_list {\n") - tabWrite("%d\n" % (((len(me_faces)-quadCount) * 3 )+ quadCount * 4)) # works only with tris and quad mesh for now + tabWrite("%d\n" % (len(me_faces) * 3)) # assumes we have only triangles VcolIdx=0 if comments: file.write("\n //Vertex colors: one simple pigment texture per vertex\n") @@ -2824,12 +2817,7 @@ def write_pov(filename, scene=None, info_callback=None): material = None if material: #and material.use_vertex_color_paint: #Always use vertex color when there is some for now - col = vcol_layer[fi] - - if len(faces_verts[fi]) == 4: - cols = col.color1, col.color2, col.color3, col.color4 - else: - cols = col.color1, col.color2, col.color3 + cols = [vcol_layer[l].color[:] for l in f.loops] for col in cols: key = col[0], col[1], col[2], material_index # Material index! @@ -2857,135 +2845,107 @@ def write_pov(filename, scene=None, info_callback=None): tabWrite("\n}\n") # Face indices tabWrite("\nface_indices {\n") - tabWrite("%d" % (len(me_faces) + quadCount)) # faces count + tabWrite("%d" % (len(me_faces))) # faces count tabStr = tab * tabLevel for fi, f in enumerate(me_faces): fv = faces_verts[fi] material_index = f.material_index - if len(fv) == 4: - indices = (0, 1, 2), (0, 2, 3) - else: - indices = ((0, 1, 2),) if vcol_layer: - col = vcol_layer[fi] - - if len(fv) == 4: - cols = col.color1, col.color2, col.color3, col.color4 - else: - cols = col.color1, col.color2, col.color3 + cols = [vcol_layer[l].color[:] for l in f.loops] if not me_materials or me_materials[material_index] is None: # No materials - for i1, i2, i3 in indices: - if linebreaksinlists: - file.write(",\n") - # vert count - file.write(tabStr + "<%d,%d,%d>" % (fv[i1], fv[i2], fv[i3])) - else: - file.write(", ") - file.write("<%d,%d,%d>" % (fv[i1], fv[i2], fv[i3])) # vert count + if linebreaksinlists: + file.write(",\n") + # vert count + file.write(tabStr + "<%d,%d,%d>" % (fv[0], fv[1], fv[2])) + else: + file.write(", ") + file.write("<%d,%d,%d>" % (fv[0], fv[1], fv[2])) # vert count else: material = me_materials[material_index] - for i1, i2, i3 in indices: - if me.vertex_colors: #and material.use_vertex_color_paint: - # Color per vertex - vertex color + if me.vertex_colors: #and material.use_vertex_color_paint: + # Color per vertex - vertex color - col1 = cols[i1] - col2 = cols[i2] - col3 = cols[i3] + col1 = cols[0] + col2 = cols[1] + col3 = cols[2] - ci1 = vertCols[col1[0], col1[1], col1[2], material_index][0] - ci2 = vertCols[col2[0], col2[1], col2[2], material_index][0] - ci3 = vertCols[col3[0], col3[1], col3[2], material_index][0] - else: - # Color per material - flat material color - if material.subsurface_scattering.use: - diffuse_color = [i * j for i, j in zip(material.subsurface_scattering.color[:], material.diffuse_color[:])] - else: - diffuse_color = material.diffuse_color[:] - ci1 = ci2 = ci3 = vertCols[diffuse_color[0], diffuse_color[1], \ - diffuse_color[2], f.material_index][0] - # ci are zero based index so we'll subtract 1 from them - if linebreaksinlists: - file.write(",\n") - file.write(tabStr + "<%d,%d,%d>, %d,%d,%d" % \ - (fv[i1], fv[i2], fv[i3], ci1-1, ci2-1, ci3-1)) # vert count + ci1 = vertCols[col1[0], col1[1], col1[2], material_index][0] + ci2 = vertCols[col2[0], col2[1], col2[2], material_index][0] + ci3 = vertCols[col3[0], col3[1], col3[2], material_index][0] + else: + # Color per material - flat material color + if material.subsurface_scattering.use: + diffuse_color = [i * j for i, j in zip(material.subsurface_scattering.color[:], material.diffuse_color[:])] else: - file.write(", ") - file.write("<%d,%d,%d>, %d,%d,%d" % \ - (fv[i1], fv[i2], fv[i3], ci1-1, ci2-1, ci3-1)) # vert count + diffuse_color = material.diffuse_color[:] + ci1 = ci2 = ci3 = vertCols[diffuse_color[0], diffuse_color[1], \ + diffuse_color[2], f.material_index][0] + # ci are zero based index so we'll subtract 1 from them + if linebreaksinlists: + file.write(",\n") + file.write(tabStr + "<%d,%d,%d>, %d,%d,%d" % \ + (fv[0], fv[1], fv[2], ci1-1, ci2-1, ci3-1)) # vert count + else: + file.write(", ") + file.write("<%d,%d,%d>, %d,%d,%d" % \ + (fv[0], fv[1], fv[2], ci1-1, ci2-1, ci3-1)) # vert count file.write("\n") tabWrite("}\n") # normal_indices indices tabWrite("normal_indices {\n") - tabWrite("%d" % (len(me_faces) + quadCount)) # faces count + tabWrite("%d" % (len(me_faces))) # faces count tabStr = tab * tabLevel for fi, fv in enumerate(faces_verts): - if len(fv) == 4: - indices = (0, 1, 2), (0, 2, 3) + if me_faces[fi].use_smooth: + if linebreaksinlists: + file.write(",\n") + file.write(tabStr + "<%d,%d,%d>" %\ + (uniqueNormals[verts_normals[fv[0]]][0],\ + uniqueNormals[verts_normals[fv[1]]][0],\ + uniqueNormals[verts_normals[fv[2]]][0])) # vert count + else: + file.write(", ") + file.write("<%d,%d,%d>" %\ + (uniqueNormals[verts_normals[fv[0]]][0],\ + uniqueNormals[verts_normals[fv[1]]][0],\ + uniqueNormals[verts_normals[fv[2]]][0])) # vert count else: - indices = ((0, 1, 2),) - - for i1, i2, i3 in indices: - if me_faces[fi].use_smooth: - if linebreaksinlists: - file.write(",\n") - file.write(tabStr + "<%d,%d,%d>" %\ - (uniqueNormals[verts_normals[fv[i1]]][0],\ - uniqueNormals[verts_normals[fv[i2]]][0],\ - uniqueNormals[verts_normals[fv[i3]]][0])) # vert count - else: - file.write(", ") - file.write("<%d,%d,%d>" %\ - (uniqueNormals[verts_normals[fv[i1]]][0],\ - uniqueNormals[verts_normals[fv[i2]]][0],\ - uniqueNormals[verts_normals[fv[i3]]][0])) # vert count + idx = uniqueNormals[faces_normals[fi]][0] + if linebreaksinlists: + file.write(",\n") + file.write(tabStr + "<%d,%d,%d>" % (idx, idx, idx)) # vert count else: - idx = uniqueNormals[faces_normals[fi]][0] - if linebreaksinlists: - file.write(",\n") - file.write(tabStr + "<%d,%d,%d>" % (idx, idx, idx)) # vert count - else: - file.write(", ") - file.write("<%d,%d,%d>" % (idx, idx, idx)) # vert count + file.write(", ") + file.write("<%d,%d,%d>" % (idx, idx, idx)) # vert count file.write("\n") tabWrite("}\n") if uv_layer: tabWrite("uv_indices {\n") - tabWrite("%d" % (len(me_faces) + quadCount)) # faces count + tabWrite("%d" % (len(me_faces))) # faces count tabStr = tab * tabLevel - for fi, fv in enumerate(faces_verts): - - if len(fv) == 4: - indices = (0, 1, 2), (0, 2, 3) - else: - indices = ((0, 1, 2),) - - uv = uv_layer[fi] - if len(faces_verts[fi]) == 4: - uvs = uv.uv[0][:], uv.uv[1][:], uv.uv[2][:], uv.uv[3][:] + for f in me_faces: + uvs = [uv_layer[l].uv[:] for l in f.loops] + + if linebreaksinlists: + file.write(",\n") + file.write(tabStr + "<%d,%d,%d>" % ( + uniqueUVs[uvs[0]][0],\ + uniqueUVs[uvs[1]][0],\ + uniqueUVs[uvs[2]][0])) else: - uvs = uv.uv[0][:], uv.uv[1][:], uv.uv[2][:] - - for i1, i2, i3 in indices: - if linebreaksinlists: - file.write(",\n") - file.write(tabStr + "<%d,%d,%d>" % ( - uniqueUVs[uvs[i1]][0],\ - uniqueUVs[uvs[i2]][0],\ - uniqueUVs[uvs[i3]][0])) - else: - file.write(", ") - file.write("<%d,%d,%d>" % ( - uniqueUVs[uvs[i1]][0],\ - uniqueUVs[uvs[i2]][0],\ - uniqueUVs[uvs[i3]][0])) + file.write(", ") + file.write("<%d,%d,%d>" % ( + uniqueUVs[uvs[0]][0],\ + uniqueUVs[uvs[1]][0],\ + uniqueUVs[uvs[2]][0])) file.write("\n") tabWrite("}\n") @@ -3108,140 +3068,111 @@ def write_pov(filename, scene=None, info_callback=None): # Face indices tabWrite("face_indices {\n") - tabWrite("%d" % (len(me_faces) + quadCount)) # faces count + tabWrite("%d" % (len(me_faces))) # faces count tabStr = tab * tabLevel for fi, f in enumerate(me_faces): fv = faces_verts[fi] material_index = f.material_index - if len(fv) == 4: - indices = (0, 1, 2), (0, 2, 3) - else: - indices = ((0, 1, 2),) if vcol_layer: - col = vcol_layer[fi] - - if len(fv) == 4: - cols = col.color1, col.color2, col.color3, col.color4 - else: - cols = col.color1, col.color2, col.color3 + cols = [vcol_layer[l].color[:] for l in f.loops] if not me_materials or me_materials[material_index] is None: # No materials - for i1, i2, i3 in indices: - if linebreaksinlists: - file.write(",\n") - # vert count - file.write(tabStr + "<%d,%d,%d>" % (fv[i1], fv[i2], fv[i3])) - else: - file.write(", ") - file.write("<%d,%d,%d>" % (fv[i1], fv[i2], fv[i3])) # vert count + if linebreaksinlists: + file.write(",\n") + # vert count + file.write(tabStr + "<%d,%d,%d>" % (fv[0], fv[1], fv[2])) + else: + file.write(", ") + file.write("<%d,%d,%d>" % (fv[0], fv[1], fv[2])) # vert count else: material = me_materials[material_index] - for i1, i2, i3 in indices: - ci1 = ci2 = ci3 = f.material_index - if me.vertex_colors: #and material.use_vertex_color_paint: - # Color per vertex - vertex color - - col1 = cols[i1] - col2 = cols[i2] - col3 = cols[i3] - - ci1 = vertCols[col1[0], col1[1], col1[2], material_index][0] - ci2 = vertCols[col2[0], col2[1], col2[2], material_index][0] - ci3 = vertCols[col3[0], col3[1], col3[2], material_index][0] - elif material.pov.material_use_nodes: - ci1 = ci2 = ci3 = 0 + ci1 = ci2 = ci3 = f.material_index + if me.vertex_colors: #and material.use_vertex_color_paint: + # Color per vertex - vertex color + + col1 = cols[0] + col2 = cols[1] + col3 = cols[2] + + ci1 = vertCols[col1[0], col1[1], col1[2], material_index][0] + ci2 = vertCols[col2[0], col2[1], col2[2], material_index][0] + ci3 = vertCols[col3[0], col3[1], col3[2], material_index][0] + elif material.pov.material_use_nodes: + ci1 = ci2 = ci3 = 0 + else: + # Color per material - flat material color + if material.subsurface_scattering.use: + diffuse_color = [i * j for i, j in + zip(material.subsurface_scattering.color[:], + material.diffuse_color[:])] else: - # Color per material - flat material color - if material.subsurface_scattering.use: - diffuse_color = [i * j for i, j in - zip(material.subsurface_scattering.color[:], - material.diffuse_color[:])] - else: - diffuse_color = material.diffuse_color[:] - ci1 = ci2 = ci3 = vertCols[diffuse_color[0], diffuse_color[1], \ - diffuse_color[2], f.material_index][0] + diffuse_color = material.diffuse_color[:] + ci1 = ci2 = ci3 = vertCols[diffuse_color[0], diffuse_color[1], \ + diffuse_color[2], f.material_index][0] - if linebreaksinlists: - file.write(",\n") - file.write(tabStr + "<%d,%d,%d>, %d,%d,%d" % \ - (fv[i1], fv[i2], fv[i3], ci1, ci2, ci3)) # vert count - else: - file.write(", ") - file.write("<%d,%d,%d>, %d,%d,%d" % \ - (fv[i1], fv[i2], fv[i3], ci1, ci2, ci3)) # vert count + if linebreaksinlists: + file.write(",\n") + file.write(tabStr + "<%d,%d,%d>, %d,%d,%d" % \ + (fv[0], fv[1], fv[2], ci1, ci2, ci3)) # vert count + else: + file.write(", ") + file.write("<%d,%d,%d>, %d,%d,%d" % \ + (fv[0], fv[1], fv[2], ci1, ci2, ci3)) # vert count file.write("\n") tabWrite("}\n") # normal_indices indices tabWrite("normal_indices {\n") - tabWrite("%d" % (len(me_faces) + quadCount)) # faces count + tabWrite("%d" % (len(me_faces))) # faces count tabStr = tab * tabLevel for fi, fv in enumerate(faces_verts): - - if len(fv) == 4: - indices = (0, 1, 2), (0, 2, 3) + if me_faces[fi].use_smooth: + if linebreaksinlists: + file.write(",\n") + file.write(tabStr + "<%d,%d,%d>" %\ + (uniqueNormals[verts_normals[fv[0]]][0],\ + uniqueNormals[verts_normals[fv[1]]][0],\ + uniqueNormals[verts_normals[fv[2]]][0])) # vert count + else: + file.write(", ") + file.write("<%d,%d,%d>" %\ + (uniqueNormals[verts_normals[fv[0]]][0],\ + uniqueNormals[verts_normals[fv[1]]][0],\ + uniqueNormals[verts_normals[fv[2]]][0])) # vert count else: - indices = ((0, 1, 2),) - - for i1, i2, i3 in indices: - if me_faces[fi].use_smooth: - if linebreaksinlists: - file.write(",\n") - file.write(tabStr + "<%d,%d,%d>" %\ - (uniqueNormals[verts_normals[fv[i1]]][0],\ - uniqueNormals[verts_normals[fv[i2]]][0],\ - uniqueNormals[verts_normals[fv[i3]]][0])) # vert count - else: - file.write(", ") - file.write("<%d,%d,%d>" %\ - (uniqueNormals[verts_normals[fv[i1]]][0],\ - uniqueNormals[verts_normals[fv[i2]]][0],\ - uniqueNormals[verts_normals[fv[i3]]][0])) # vert count + idx = uniqueNormals[faces_normals[fi]][0] + if linebreaksinlists: + file.write(",\n") + file.write(tabStr + "<%d,%d,%d>" % (idx, idx, idx)) # vertcount else: - idx = uniqueNormals[faces_normals[fi]][0] - if linebreaksinlists: - file.write(",\n") - file.write(tabStr + "<%d,%d,%d>" % (idx, idx, idx)) # vertcount - else: - file.write(", ") - file.write("<%d,%d,%d>" % (idx, idx, idx)) # vert count + file.write(", ") + file.write("<%d,%d,%d>" % (idx, idx, idx)) # vert count file.write("\n") tabWrite("}\n") if uv_layer: tabWrite("uv_indices {\n") - tabWrite("%d" % (len(me_faces) + quadCount)) # faces count + tabWrite("%d" % (len(me_faces))) # faces count tabStr = tab * tabLevel - for fi, fv in enumerate(faces_verts): - - if len(fv) == 4: - indices = (0, 1, 2), (0, 2, 3) - else: - indices = ((0, 1, 2),) - - uv = uv_layer[fi] - if len(faces_verts[fi]) == 4: - uvs = uv.uv[0][:], uv.uv[1][:], uv.uv[2][:], uv.uv[3][:] + for f in me_faces: + uvs = [uv_layer[l].uv[:] for l in f.loops] + + if linebreaksinlists: + file.write(",\n") + file.write(tabStr + "<%d,%d,%d>" % ( + uniqueUVs[uvs[0]][0],\ + uniqueUVs[uvs[1]][0],\ + uniqueUVs[uvs[2]][0])) else: - uvs = uv.uv[0][:], uv.uv[1][:], uv.uv[2][:] - - for i1, i2, i3 in indices: - if linebreaksinlists: - file.write(",\n") - file.write(tabStr + "<%d,%d,%d>" % ( - uniqueUVs[uvs[i1]][0],\ - uniqueUVs[uvs[i2]][0],\ - uniqueUVs[uvs[i3]][0])) - else: - file.write(", ") - file.write("<%d,%d,%d>" % ( - uniqueUVs[uvs[i1]][0],\ - uniqueUVs[uvs[i2]][0],\ - uniqueUVs[uvs[i3]][0])) + file.write(", ") + file.write("<%d,%d,%d>" % ( + uniqueUVs[uvs[0]][0],\ + uniqueUVs[uvs[1]][0],\ + uniqueUVs[uvs[2]][0])) file.write("\n") tabWrite("}\n") @@ -3666,11 +3597,11 @@ def write_pov(filename, scene=None, info_callback=None): csg = True sel = renderable_objects(scene) - exportLamps([L for L in sel if (L.type == 'LAMP' and L.pov.object_as != 'RAINBOW')]) + exportLamps([L for L in sel if (L.type == 'LIGHT' and L.pov.object_as != 'RAINBOW')]) if comments: file.write("\n//--Rainbows--\n\n") - exportRainbows([L for L in sel if (L.type == 'LAMP' and L.pov.object_as == 'RAINBOW')]) + exportRainbows([L for L in sel if (L.type == 'LIGHT' and L.pov.object_as == 'RAINBOW')]) if comments: diff --git a/render_povray/ui.py b/render_povray/ui.py index 34123794..1d5a621f 100644 --- a/render_povray/ui.py +++ b/render_povray/ui.py @@ -214,15 +214,12 @@ del properties_data_modifier from bl_ui import properties_material for member in dir(properties_material): subclass = getattr(properties_material, member) - if subclass not in (properties_material.MATERIAL_PT_transp_game, - properties_material.MATERIAL_PT_game_settings, - properties_material.MATERIAL_PT_physics): - try: - #mat=context.material - #if mat and mat.type == "SURFACE" and (engine in cls.COMPAT_ENGINES) and not (mat.pov.material_use_nodes or mat.use_nodes): - subclass.COMPAT_ENGINES.add('POVRAY_RENDER') - except: - pass + try: + #mat=context.material + #if mat and mat.type == "SURFACE" and (engine in cls.COMPAT_ENGINES) and not (mat.pov.material_use_nodes or mat.use_nodes): + subclass.COMPAT_ENGINES.add('POVRAY_RENDER') + except: + pass del properties_material @@ -294,7 +291,7 @@ class RenderButtonsPanel(): @classmethod def poll(cls, context): rd = context.scene.render - return (rd.use_game_engine is False) and (rd.engine in cls.COMPAT_ENGINES) + return (rd.engine in cls.COMPAT_ENGINES) class ModifierButtonsPanel(): bl_space_type = 'PROPERTIES' @@ -306,7 +303,7 @@ class ModifierButtonsPanel(): def poll(cls, context): mods = context.object.modifiers rd = context.scene.render - return mods and (rd.use_game_engine is False) and (rd.engine in cls.COMPAT_ENGINES) + return mods and (rd.engine in cls.COMPAT_ENGINES) class MaterialButtonsPanel(): bl_space_type = 'PROPERTIES' @@ -318,7 +315,7 @@ class MaterialButtonsPanel(): def poll(cls, context): mat = context.material rd = context.scene.render - return mat and (rd.use_game_engine is False) and (rd.engine in cls.COMPAT_ENGINES) + return mat (rd.engine in cls.COMPAT_ENGINES) class TextureButtonsPanel(): @@ -331,7 +328,7 @@ class TextureButtonsPanel(): def poll(cls, context): tex = context.texture rd = context.scene.render - return tex and (rd.use_game_engine is False) and (rd.engine in cls.COMPAT_ENGINES) + return tex and (rd.engine in cls.COMPAT_ENGINES) # class TextureTypePanel(TextureButtonsPanel): @@ -352,7 +349,7 @@ class ObjectButtonsPanel(): def poll(cls, context): obj = context.object rd = context.scene.render - return obj and (rd.use_game_engine is False) and (rd.engine in cls.COMPAT_ENGINES) + return obj and (rd.engine in cls.COMPAT_ENGINES) class CameraDataButtonsPanel(): bl_space_type = 'PROPERTIES' @@ -364,7 +361,7 @@ class CameraDataButtonsPanel(): def poll(cls, context): cam = context.camera rd = context.scene.render - return cam and (rd.use_game_engine is False) and (rd.engine in cls.COMPAT_ENGINES) + return cam and (rd.engine in cls.COMPAT_ENGINES) class WorldButtonsPanel(): bl_space_type = 'PROPERTIES' @@ -376,7 +373,7 @@ class WorldButtonsPanel(): def poll(cls, context): wld = context.world rd = context.scene.render - return wld and (rd.use_game_engine is False) and (rd.engine in cls.COMPAT_ENGINES) + return wld and (rd.engine in cls.COMPAT_ENGINES) class TextButtonsPanel(): bl_space_type = 'TEXT_EDITOR' @@ -388,7 +385,7 @@ class TextButtonsPanel(): def poll(cls, context): text = context.space_data rd = context.scene.render - return text and (rd.use_game_engine is False) and (rd.engine in cls.COMPAT_ENGINES) + return text and (rd.engine in cls.COMPAT_ENGINES) from bl_ui import properties_data_mesh # These panels are kept @@ -464,25 +461,25 @@ del properties_data_mesh ################################################################################ -# from bl_ui import properties_data_lamp -# for member in dir(properties_data_lamp): - # subclass = getattr(properties_data_lamp, member) +# from bl_ui import properties_data_light +# for member in dir(properties_data_light): + # subclass = getattr(properties_data_light, member) # try: # subclass.COMPAT_ENGINES.add('POVRAY_RENDER') # except: # pass -# del properties_data_lamp -#########################LAMPS################################ +# del properties_data_light +#########################LIGHTS################################ -from bl_ui import properties_data_lamp +from bl_ui import properties_data_light # These panels are kept -properties_data_lamp.DATA_PT_custom_props_lamp.COMPAT_ENGINES.add('POVRAY_RENDER') -properties_data_lamp.DATA_PT_context_lamp.COMPAT_ENGINES.add('POVRAY_RENDER') +properties_data_light.DATA_PT_custom_props_light.COMPAT_ENGINES.add('POVRAY_RENDER') +properties_data_light.DATA_PT_context_light.COMPAT_ENGINES.add('POVRAY_RENDER') ## make some native panels contextual to some object variable ## by recreating custom panels inheriting their properties -class PovLampButtonsPanel(properties_data_lamp.DataButtonsPanel): +class PovLampButtonsPanel(properties_data_light.DataButtonsPanel): COMPAT_ENGINES = {'POVRAY_RENDER'} POV_OBJECT_TYPES = {'RAINBOW'} @@ -499,17 +496,17 @@ class PovLampButtonsPanel(properties_data_lamp.DataButtonsPanel): # Complex py/bpy/rna interactions (with metaclass and all) simply do not allow it to work. # So we simply have to explicitly copy here the interesting bits. ;) -class LAMP_PT_POV_preview(PovLampButtonsPanel, bpy.types.Panel): - bl_label = properties_data_lamp.DATA_PT_preview.bl_label +class LIGHT_PT_POV_preview(PovLampButtonsPanel, bpy.types.Panel): + bl_label = properties_data_light.DATA_PT_preview.bl_label - draw = properties_data_lamp.DATA_PT_preview.draw + draw = properties_data_light.DATA_PT_preview.draw -class LAMP_PT_POV_lamp(PovLampButtonsPanel, bpy.types.Panel): - bl_label = properties_data_lamp.DATA_PT_lamp.bl_label +class LIGHT_PT_POV_light(PovLampButtonsPanel, bpy.types.Panel): + bl_label = properties_data_light.DATA_PT_light.bl_label - draw = properties_data_lamp.DATA_PT_lamp.draw + draw = properties_data_light.DATA_PT_light.draw -class POV_LAMP_MT_presets(bpy.types.Menu): +class POV_LIGHT_MT_presets(bpy.types.Menu): bl_label = "Lamp Presets" preset_subdir = "pov/lamp" preset_operator = "script.execute_preset" @@ -518,19 +515,19 @@ class POV_LAMP_MT_presets(bpy.types.Menu): class AddPresetLamp(AddPresetBase, bpy.types.Operator): '''Add a Lamp Preset''' - bl_idname = "object.lamp_preset_add" + bl_idname = "object.light_preset_add" bl_label = "Add Lamp Preset" - preset_menu = "POV_LAMP_MT_presets" + preset_menu = "POV_LIGHT_MT_presets" # variable used for all preset values preset_defines = [ - "lampdata = bpy.context.object.data" + "lightdata = bpy.context.object.data" ] # properties to store in the preset preset_values = [ - "lampdata.type", - "lampdata.color", + "lightdata.type", + "lightdata.color", ] # where to store the preset @@ -541,68 +538,68 @@ class AddPresetLamp(AddPresetBase, bpy.types.Operator): # Draw into an existing panel -def lamp_panel_func(self, context): +def light_panel_func(self, context): layout = self.layout row = layout.row(align=True) - row.menu(POV_LAMP_MT_presets.__name__, text=POV_LAMP_MT_presets.bl_label) + row.menu(POV_LIGHT_MT_presets.__name__, text=POV_LIGHT_MT_presets.bl_label) row.operator(AddPresetLamp.bl_idname, text="", icon='ZOOMIN') row.operator(AddPresetLamp.bl_idname, text="", icon='ZOOMOUT').remove_active = True classes = ( - POV_LAMP_MT_presets, + POV_LIGHT_MT_presets, AddPresetLamp, ) -class LAMP_PT_POV_sunsky(PovLampButtonsPanel, bpy.types.Panel): - bl_label = properties_data_lamp.DATA_PT_sunsky.bl_label +class LIGHT_PT_POV_sunsky(PovLampButtonsPanel, bpy.types.Panel): + bl_label = properties_data_light.DATA_PT_sunsky.bl_label @classmethod def poll(cls, context): - lamp = context.lamp + lamp = context.light engine = context.scene.render.engine return (lamp and lamp.type == 'SUN') and (engine in cls.COMPAT_ENGINES) - draw = properties_data_lamp.DATA_PT_sunsky.draw + draw = properties_data_light.DATA_PT_sunsky.draw -class LAMP_PT_POV_shadow(PovLampButtonsPanel, bpy.types.Panel): - bl_label = properties_data_lamp.DATA_PT_shadow.bl_label +class LIGHT_PT_POV_shadow(PovLampButtonsPanel, bpy.types.Panel): + bl_label = properties_data_light.DATA_PT_shadow.bl_label - draw = properties_data_lamp.DATA_PT_shadow.draw + draw = properties_data_light.DATA_PT_shadow.draw -class LAMP_PT_POV_area(PovLampButtonsPanel, bpy.types.Panel): - bl_label = properties_data_lamp.DATA_PT_area.bl_label +class LIGHT_PT_POV_area(PovLampButtonsPanel, bpy.types.Panel): + bl_label = properties_data_light.DATA_PT_area.bl_label @classmethod def poll(cls, context): - lamp = context.lamp + lamp = context.light engine = context.scene.render.engine return (lamp and lamp.type == 'AREA') and (engine in cls.COMPAT_ENGINES) - draw = properties_data_lamp.DATA_PT_area.draw + draw = properties_data_light.DATA_PT_area.draw -class LAMP_PT_POV_spot(PovLampButtonsPanel, bpy.types.Panel): - bl_label = properties_data_lamp.DATA_PT_spot.bl_label +class LIGHT_PT_POV_spot(PovLampButtonsPanel, bpy.types.Panel): + bl_label = properties_data_light.DATA_PT_spot.bl_label @classmethod def poll(cls, context): - lamp = context.lamp + lamp = context.light engine = context.scene.render.engine return (lamp and lamp.type == 'SPOT') and (engine in cls.COMPAT_ENGINES) - draw = properties_data_lamp.DATA_PT_spot.draw + draw = properties_data_light.DATA_PT_spot.draw -class LAMP_PT_POV_falloff_curve(PovLampButtonsPanel, bpy.types.Panel): - bl_label = properties_data_lamp.DATA_PT_falloff_curve.bl_label - bl_options = properties_data_lamp.DATA_PT_falloff_curve.bl_options +class LIGHT_PT_POV_falloff_curve(PovLampButtonsPanel, bpy.types.Panel): + bl_label = properties_data_light.DATA_PT_falloff_curve.bl_label + bl_options = properties_data_light.DATA_PT_falloff_curve.bl_options @classmethod def poll(cls, context): - lamp = context.lamp + lamp = context.light engine = context.scene.render.engine return (lamp and lamp.type in {'POINT', 'SPOT'} and lamp.falloff_type == 'CUSTOM_CURVE') and (engine in cls.COMPAT_ENGINES) - draw = properties_data_lamp.DATA_PT_falloff_curve.draw + draw = properties_data_light.DATA_PT_falloff_curve.draw class OBJECT_PT_povray_obj_rainbow(PovLampButtonsPanel, bpy.types.Panel): bl_label = "POV-Ray Rainbow" @@ -644,7 +641,7 @@ class OBJECT_PT_povray_obj_rainbow(PovLampButtonsPanel, bpy.types.Panel): col.prop(obj.pov, "arc_angle") col.prop(obj.pov, "falloff_angle") -del properties_data_lamp +del properties_data_light ############################################################################### class RENDER_PT_povray_export_settings(RenderButtonsPanel, bpy.types.Panel): diff --git a/rigify/__init__.py b/rigify/__init__.py index fa93533b..3c0efdfd 100644 --- a/rigify/__init__.py +++ b/rigify/__init__.py @@ -22,7 +22,7 @@ bl_info = { "name": "Rigify", "version": (0, 5), "author": "Nathan Vegdahl, Lucio Rossi, Ivan Cappiello", - "blender": (2, 78, 0), + "blender": (2, 80, 0), "description": "Automatic rigging from building-block components", "location": "Armature properties, Bone properties, View3d tools panel, Armature Add menu", "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/" @@ -44,7 +44,15 @@ import bpy import sys import os from bpy.types import AddonPreferences -from bpy.props import BoolProperty +from bpy.props import ( + BoolProperty, + IntProperty, + EnumProperty, + StringProperty, + FloatVectorProperty, + PointerProperty, + CollectionProperty, +) class RigifyPreferences(AddonPreferences): @@ -118,14 +126,13 @@ class RigifyPreferences(AddonPreferences): register() - legacy_mode = BoolProperty( + legacy_mode: BoolProperty( name='Rigify Legacy Mode', description='Select if you want to use Rigify in legacy mode', default=False, update=update_legacy ) - - show_expanded = BoolProperty() + show_expanded: BoolProperty() def draw(self, context): layout = self.layout @@ -143,71 +150,71 @@ class RigifyPreferences(AddonPreferences): op = sub.operator('wm.context_toggle', text='', icon=icon, emboss=False) op.data_path = 'addon_prefs.show_expanded' - sub.label('{}: {}'.format('Rigify', 'Enable Legacy Mode')) + sub.label(text='{}: {}'.format('Rigify', 'Enable Legacy Mode')) sub = row.row() sub.alignment = 'RIGHT' sub.prop(self, 'legacy_mode') if expand: - split = col.row().split(percentage=0.15) - split.label('Description:') + split = col.row().split(factor=0.15) + split.label(text='Description:') split.label(text='When enabled the add-on will run in legacy mode using the old 2.76b feature set.') row = layout.row() - row.label("End of Rigify Preferences") + row.label(text="End of Rigify Preferences") class RigifyName(bpy.types.PropertyGroup): - name = bpy.props.StringProperty() + name: StringProperty() class RigifyColorSet(bpy.types.PropertyGroup): - name = bpy.props.StringProperty(name="Color Set", default=" ") - active = bpy.props.FloatVectorProperty( - name="object_color", - subtype='COLOR', - default=(1.0, 1.0, 1.0), - min=0.0, max=1.0, - description="color picker" - ) - normal = bpy.props.FloatVectorProperty( - name="object_color", - subtype='COLOR', - default=(1.0, 1.0, 1.0), - min=0.0, max=1.0, - description="color picker" - ) - select = bpy.props.FloatVectorProperty( - name="object_color", - subtype='COLOR', - default=(1.0, 1.0, 1.0), - min=0.0, max=1.0, - description="color picker" - ) - standard_colors_lock = bpy.props.BoolProperty(default=True) + name: StringProperty(name="Color Set", default=" ") + active: FloatVectorProperty( + name="object_color", + subtype='COLOR', + default=(1.0, 1.0, 1.0), + min=0.0, max=1.0, + description="color picker" + ) + normal: FloatVectorProperty( + name="object_color", + subtype='COLOR', + default=(1.0, 1.0, 1.0), + min=0.0, max=1.0, + description="color picker" + ) + select: FloatVectorProperty( + name="object_color", + subtype='COLOR', + default=(1.0, 1.0, 1.0), + min=0.0, max=1.0, + description="color picker" + ) + standard_colors_lock: BoolProperty(default=True) class RigifySelectionColors(bpy.types.PropertyGroup): - select = bpy.props.FloatVectorProperty( - name="object_color", - subtype='COLOR', - default=(0.314, 0.784, 1.0), - min=0.0, max=1.0, - description="color picker" - ) + select: FloatVectorProperty( + name="object_color", + subtype='COLOR', + default=(0.314, 0.784, 1.0), + min=0.0, max=1.0, + description="color picker" + ) - active = bpy.props.FloatVectorProperty( - name="object_color", - subtype='COLOR', - default=(0.549, 1.0, 1.0), - min=0.0, max=1.0, - description="color picker" - ) + active: FloatVectorProperty( + name="object_color", + subtype='COLOR', + default=(0.549, 1.0, 1.0), + min=0.0, max=1.0, + description="color picker" + ) class RigifyParameters(bpy.types.PropertyGroup): - name = bpy.props.StringProperty() + name: StringProperty() class RigifyArmatureLayer(bpy.types.PropertyGroup): @@ -225,104 +232,123 @@ class RigifyArmatureLayer(bpy.types.PropertyGroup): else: self['group_prop'] = value - name = bpy.props.StringProperty(name="Layer Name", default=" ") - row = bpy.props.IntProperty(name="Layer Row", default=1, min=1, max=32, description='UI row for this layer') - set = bpy.props.BoolProperty(name="Selection Set", default=False, description='Add Selection Set for this layer') - group = bpy.props.IntProperty(name="Bone Group", default=0, min=0, max=32, - get=get_group, set=set_group, description='Assign Bone Group to this layer') + name: StringProperty(name="Layer Name", default=" ") + row: IntProperty(name="Layer Row", default=1, min=1, max=32, description='UI row for this layer') + selset: BoolProperty(name="Selection Set", default=False, description='Add Selection Set for this layer') + group: IntProperty(name="Bone Group", default=0, min=0, max=32, + get=get_group, set=set_group, description='Assign Bone Group to this layer') + ##### REGISTER ##### +classes = ( + RigifyName, + RigifyParameters, + RigifyColorSet, + RigifySelectionColors, + RigifyArmatureLayer, + RigifyPreferences, +) + + def register(): + from bpy.utils import register_class + + # Sub-modules. ui.register() metarig_menu.register() - bpy.utils.register_class(RigifyName) - bpy.utils.register_class(RigifyParameters) - - bpy.utils.register_class(RigifyColorSet) - bpy.utils.register_class(RigifySelectionColors) - bpy.utils.register_class(RigifyArmatureLayer) - bpy.utils.register_class(RigifyPreferences) - bpy.types.Armature.rigify_layers = bpy.props.CollectionProperty(type=RigifyArmatureLayer) - - bpy.types.PoseBone.rigify_type = bpy.props.StringProperty(name="Rigify Type", description="Rig type for this bone") - bpy.types.PoseBone.rigify_parameters = bpy.props.PointerProperty(type=RigifyParameters) - - bpy.types.Armature.rigify_colors = bpy.props.CollectionProperty(type=RigifyColorSet) - - bpy.types.Armature.rigify_selection_colors = bpy.props.PointerProperty(type=RigifySelectionColors) - - bpy.types.Armature.rigify_colors_index = bpy.props.IntProperty(default=-1) - bpy.types.Armature.rigify_colors_lock = bpy.props.BoolProperty(default=True) - bpy.types.Armature.rigify_theme_to_add = bpy.props.EnumProperty(items=(('THEME01', 'THEME01', ''), - ('THEME02', 'THEME02', ''), - ('THEME03', 'THEME03', ''), - ('THEME04', 'THEME04', ''), - ('THEME05', 'THEME05', ''), - ('THEME06', 'THEME06', ''), - ('THEME07', 'THEME07', ''), - ('THEME08', 'THEME08', ''), - ('THEME09', 'THEME09', ''), - ('THEME10', 'THEME10', ''), - ('THEME11', 'THEME11', ''), - ('THEME12', 'THEME12', ''), - ('THEME13', 'THEME13', ''), - ('THEME14', 'THEME14', ''), - ('THEME15', 'THEME15', ''), - ('THEME16', 'THEME16', ''), - ('THEME17', 'THEME17', ''), - ('THEME18', 'THEME18', ''), - ('THEME19', 'THEME19', ''), - ('THEME20', 'THEME20', '') - ), name='Theme') + # Classes. + for cls in classes: + register_class(cls) + + # Properties. + bpy.types.Armature.rigify_layers = CollectionProperty(type=RigifyArmatureLayer) + + bpy.types.PoseBone.rigify_type = StringProperty(name="Rigify Type", description="Rig type for this bone") + bpy.types.PoseBone.rigify_parameters = PointerProperty(type=RigifyParameters) + + bpy.types.Armature.rigify_colors = CollectionProperty(type=RigifyColorSet) + + bpy.types.Armature.rigify_selection_colors = PointerProperty(type=RigifySelectionColors) + + bpy.types.Armature.rigify_colors_index = IntProperty(default=-1) + bpy.types.Armature.rigify_colors_lock = BoolProperty(default=True) + bpy.types.Armature.rigify_theme_to_add = EnumProperty(items=( + ('THEME01', 'THEME01', ''), + ('THEME02', 'THEME02', ''), + ('THEME03', 'THEME03', ''), + ('THEME04', 'THEME04', ''), + ('THEME05', 'THEME05', ''), + ('THEME06', 'THEME06', ''), + ('THEME07', 'THEME07', ''), + ('THEME08', 'THEME08', ''), + ('THEME09', 'THEME09', ''), + ('THEME10', 'THEME10', ''), + ('THEME11', 'THEME11', ''), + ('THEME12', 'THEME12', ''), + ('THEME13', 'THEME13', ''), + ('THEME14', 'THEME14', ''), + ('THEME15', 'THEME15', ''), + ('THEME16', 'THEME16', ''), + ('THEME17', 'THEME17', ''), + ('THEME18', 'THEME18', ''), + ('THEME19', 'THEME19', ''), + ('THEME20', 'THEME20', '') + ), name='Theme') IDStore = bpy.types.WindowManager - IDStore.rigify_collection = bpy.props.EnumProperty(items=rig_lists.col_enum_list, default="All", - name="Rigify Active Collection", - description="The selected rig collection") + IDStore.rigify_collection = EnumProperty(items=rig_lists.col_enum_list, default="All", + name="Rigify Active Collection", + description="The selected rig collection") - IDStore.rigify_types = bpy.props.CollectionProperty(type=RigifyName) - IDStore.rigify_active_type = bpy.props.IntProperty(name="Rigify Active Type", description="The selected rig type") + IDStore.rigify_types = CollectionProperty(type=RigifyName) + IDStore.rigify_active_type = IntProperty(name="Rigify Active Type", description="The selected rig type") - IDStore.rigify_advanced_generation = bpy.props.BoolProperty(name="Advanced Options", - description="Enables/disables advanced options for Rigify rig generation", - default=False) + IDStore.rigify_advanced_generation = BoolProperty(name="Advanced Options", + description="Enables/disables advanced options for Rigify rig generation", + default=False) def update_mode(self, context): if self.rigify_generate_mode == 'new': self.rigify_force_widget_update = False - IDStore.rigify_generate_mode = bpy.props.EnumProperty(name="Rigify Generate Rig Mode", - description="'Generate Rig' mode. In 'overwrite' mode the features of the target rig will be updated as defined by the metarig. In 'new' mode a new rig will be created as defined by the metarig. Current mode", - update=update_mode, - items=(('overwrite', 'overwrite', ''), - ('new', 'new', ''))) - - IDStore.rigify_force_widget_update = bpy.props.BoolProperty(name="Force Widget Update", - description="Forces Rigify to delete and rebuild all the rig widgets. if unset, only missing widgets will be created", - default=False) - - IDStore.rigify_target_rigs = bpy.props.CollectionProperty(type=RigifyName) - IDStore.rigify_target_rig = bpy.props.StringProperty(name="Rigify Target Rig", - description="Defines which rig to overwrite. If unset, a new one called 'rig' will be created", - default="") - - IDStore.rigify_rig_uis = bpy.props.CollectionProperty(type=RigifyName) - IDStore.rigify_rig_ui = bpy.props.StringProperty(name="Rigify Target Rig UI", - description="Defines the UI to overwrite. It should always be the same as the target rig. If unset, 'rig_ui.py' will be used", - default="") - - IDStore.rigify_rig_basename = bpy.props.StringProperty(name="Rigify Rig Name", - description="Defines the name of the Rig. If unset, in 'new' mode 'rig' will be used, in 'overwrite' mode the target rig name will be used", - default="") - - IDStore.rigify_transfer_only_selected = bpy.props.BoolProperty(name="Transfer Only Selected", description="Transfer selected bones only", default=True) - IDStore.rigify_transfer_start_frame = bpy.props.IntProperty(name="Start Frame", description="First Frame to Transfer", default=0, min= 0) - IDStore.rigify_transfer_end_frame = bpy.props.IntProperty(name="End Frame", description="Last Frame to Transfer", default=0, min= 0) - + IDStore.rigify_generate_mode = EnumProperty(name="Rigify Generate Rig Mode", + description="'Generate Rig' mode. In 'overwrite' mode the features of the target rig will be updated as defined by the metarig. In 'new' mode a new rig will be created as defined by the metarig. Current mode", + update=update_mode, + items=( ('overwrite', 'overwrite', ''), + ('new', 'new', ''))) + + IDStore.rigify_force_widget_update = BoolProperty(name="Force Widget Update", + description="Forces Rigify to delete and rebuild all the rig widgets. if unset, only missing widgets will be created", + default=False) + + IDStore.rigify_target_rigs = CollectionProperty(type=RigifyName) + IDStore.rigify_target_rig = StringProperty(name="Rigify Target Rig", + description="Defines which rig to overwrite. If unset, a new one called 'rig' will be created", + default="") + + IDStore.rigify_rig_uis = CollectionProperty(type=RigifyName) + IDStore.rigify_rig_ui = StringProperty(name="Rigify Target Rig UI", + description="Defines the UI to overwrite. It should always be the same as the target rig. If unset, 'rig_ui.py' will be used", + default="") + + IDStore.rigify_rig_basename = StringProperty(name="Rigify Rig Name", + description="Defines the name of the Rig. If unset, in 'new' mode 'rig' will be used, in 'overwrite' mode the target rig name will be used", + default="") + + IDStore.rigify_transfer_only_selected = BoolProperty( + name="Transfer Only Selected", + description="Transfer selected bones only", default=True) + IDStore.rigify_transfer_start_frame = IntProperty( + name="Start Frame", + description="First Frame to Transfer", default=0, min= 0) + IDStore.rigify_transfer_end_frame = IntProperty( + name="End Frame", + description="Last Frame to Transfer", default=0, min= 0) + + # Update legacy on restart or reload. if (ui and 'legacy' in str(ui)) or bpy.context.user_preferences.addons['rigify'].preferences.legacy_mode: - # update legacy on restart or reload bpy.context.user_preferences.addons['rigify'].preferences.legacy_mode = True # Add rig parameters @@ -335,6 +361,9 @@ def register(): def unregister(): + from bpy.utils import unregister_class + + # Properties. del bpy.types.PoseBone.rigify_type del bpy.types.PoseBone.rigify_parameters @@ -354,14 +383,10 @@ def unregister(): del IDStore.rigify_transfer_start_frame del IDStore.rigify_transfer_end_frame - bpy.utils.unregister_class(RigifyName) - bpy.utils.unregister_class(RigifyParameters) - - bpy.utils.unregister_class(RigifyColorSet) - bpy.utils.unregister_class(RigifySelectionColors) - - bpy.utils.unregister_class(RigifyArmatureLayer) - bpy.utils.unregister_class(RigifyPreferences) + # Classes. + for cls in classes: + unregister_class(cls) + # Sub-modules. metarig_menu.unregister() ui.unregister() diff --git a/rigify/generate.py b/rigify/generate.py index e2492708..948ece11 100644 --- a/rigify/generate.py +++ b/rigify/generate.py @@ -29,6 +29,7 @@ from .utils import MetarigError, new_bone, get_rig_type from .utils import ORG_PREFIX, MCH_PREFIX, DEF_PREFIX, WGT_PREFIX, ROOT_NAME, make_original_name from .utils import RIG_DIR from .utils import create_root_widget +from .utils import ensure_widget_collection from .utils import random_id from .utils import copy_attributes from .utils import gamma_correct @@ -40,7 +41,6 @@ ORG_LAYER = [n == 31 for n in range(0, 32)] # Armature layer that original bone MCH_LAYER = [n == 30 for n in range(0, 32)] # Armature layer that mechanism bones should be moved to. DEF_LAYER = [n == 29 for n in range(0, 32)] # Armature layer that deformation bones should be moved to. ROOT_LAYER = [n == 28 for n in range(0, 32)] # Armature layer that root bone should be moved to. -WGT_LAYERS = [x == 19 for x in range(0, 20)] # Widgets go on the last scene layer. class Timer: @@ -72,7 +72,11 @@ def generate_rig(context, metarig): bpy.ops.object.mode_set(mode='OBJECT') scene = context.scene + view_layer = context.view_layer + collection = context.collection + layer_collection = context.layer_collection id_store = context.window_manager + #------------------------------------------ # Create/find the rig object and set it up @@ -96,13 +100,13 @@ def generate_rig(context, metarig): rig_old_name = name name = rig_new_name or name obj = bpy.data.objects.new(name, bpy.data.armatures.new(name)) - obj.draw_type = 'WIRE' - scene.objects.link(obj) + obj.display_type = 'WIRE' + collection.objects.link(obj) else: name = rig_new_name or "rig" obj = bpy.data.objects.new(name, bpy.data.armatures.new(name)) # in case name 'rig' exists it will be rig.001 - obj.draw_type = 'WIRE' - scene.objects.link(obj) + obj.display_type = 'WIRE' + collection.objects.link(obj) id_store.rigify_target_rig = obj.name obj.data.pose_position = 'POSE' @@ -112,23 +116,17 @@ def generate_rig(context, metarig): obj.animation_data_clear() # Select generated rig object - metarig.select = False - obj.select = True - scene.objects.active = obj + metarig.select_set('DESELECT') + obj.select_set('SELECT') + view_layer.objects.active = obj # Remove wgts if force update is set wgts_group_name = "WGTS_" + (rig_old_name or obj.name) if wgts_group_name in scene.objects and id_store.rigify_force_widget_update: bpy.ops.object.select_all(action='DESELECT') - for i, lyr in enumerate(WGT_LAYERS): - if lyr: - context.scene.layers[i] = True for wgt in bpy.data.objects[wgts_group_name].children: - wgt.select = True + wgt.select_set('SELECT') bpy.ops.object.delete(use_global=False) - for i, lyr in enumerate(WGT_LAYERS): - if lyr: - context.scene.layers[i] = False if rig_old_name: bpy.data.objects[wgts_group_name].name = "WGTS_" + obj.name @@ -148,18 +146,18 @@ def generate_rig(context, metarig): # Create temporary duplicates for merging temp_rig_1 = metarig.copy() temp_rig_1.data = metarig.data.copy() - scene.objects.link(temp_rig_1) + collection.objects.link(temp_rig_1) temp_rig_2 = metarig.copy() temp_rig_2.data = obj.data - scene.objects.link(temp_rig_2) + collection.objects.link(temp_rig_2) # Select the temp rigs for merging for objt in scene.objects: - objt.select = False # deselect all objects - temp_rig_1.select = True - temp_rig_2.select = True - scene.objects.active = temp_rig_2 + objt.select_set('DESELECT') # deselect all objects + temp_rig_1.select_set('SELECT') + temp_rig_2.select_set('SELECT') + view_layer.objects.active = temp_rig_2 # Merge the temporary rigs bpy.ops.object.join() @@ -169,9 +167,9 @@ def generate_rig(context, metarig): # Select the generated rig for objt in scene.objects: - objt.select = False # deselect all objects - obj.select = True - scene.objects.active = obj + objt.select_set('DESELECT') # deselect all objects + obj.select_set('SELECT') + view_layer.objects.active = obj # Copy over bone properties for bone in metarig.data.bones: @@ -303,7 +301,8 @@ def generate_rig(context, metarig): rna_idprop_ui_prop_get(obj.data, "rig_id", create=True) obj.data["rig_id"] = rig_id - t.tick("Create root bone: ") + # Create/find widge collection + widget_collection = ensure_widget_collection(context) # Create Group widget # wgts_group_name = "WGTS" @@ -313,21 +312,14 @@ def generate_rig(context, metarig): bpy.data.objects.remove(bpy.data.objects[wgts_group_name]) mesh = bpy.data.meshes.new(wgts_group_name) wgts_obj = bpy.data.objects.new(wgts_group_name, mesh) - scene.objects.link(wgts_obj) - wgts_obj.layers = WGT_LAYERS + widget_collection.objects.link(wgts_obj) t.tick("Create main WGTS: ") # # if id_store.rigify_generate_mode == 'new': # bpy.ops.object.select_all(action='DESELECT') # for wgt in bpy.data.objects[wgts_group_name].children: - # wgt.select = True - # for i, lyr in enumerate(WGT_LAYERS): - # if lyr: - # context.scene.layers[i] = True + # wgt.select_set('SELECT') # bpy.ops.object.make_single_user(obdata=True) - # for i, lyr in enumerate(WGT_LAYERS): - # if lyr: - # context.scene.layers[i] = False #---------------------------------- try: @@ -343,8 +335,8 @@ def generate_rig(context, metarig): for rig in rigs: # Go into editmode in the rig armature bpy.ops.object.mode_set(mode='OBJECT') - context.scene.objects.active = obj - obj.select = True + context.view_layer.objects.active = obj + obj.select_set('SELECT') bpy.ops.object.mode_set(mode='EDIT') scripts = rig.generate() if scripts is not None: @@ -511,18 +503,7 @@ def generate_rig(context, metarig): create_bone_groups(obj, metarig) # Add rig_ui to logic - skip = False - ctrls = obj.game.controllers - - for c in ctrls: - if 'Python' in c.name and c.text.name == script.name: - skip = True - break - if not skip: - bpy.ops.logic.controller_add(type='PYTHON', object=obj.name) - ctrl = obj.game.controllers[-1] - ctrl.text = bpy.data.texts[script.name] - + create_persistent_rig_ui(obj, script) t.tick("The rest: ") #---------------------------------- @@ -538,6 +519,11 @@ def generate_rig(context, metarig): child.parent_bone = sub_parent child.matrix_world = mat + #---------------------------------- + # Restore active collection + view_layer.collections.active = layer_collection + + def create_selection_sets(obj, metarig): # Check if selection sets addon is installed @@ -547,13 +533,13 @@ def create_selection_sets(obj, metarig): bpy.ops.object.mode_set(mode='POSE') - bpy.context.scene.objects.active = obj - obj.select = True - metarig.select = False + bpy.context.view_layer.objects.active = obj + obj.select_set('SELECT') + metarig.select_set('DESELECT') pbones = obj.pose.bones for i, name in enumerate(metarig.data.rigify_layers.keys()): - if name == '' or not metarig.data.rigify_layers[i].set: + if name == '' or not metarig.data.rigify_layers[i].selset: continue bpy.ops.pose.select_all(action='DESELECT') @@ -588,7 +574,7 @@ def create_bone_groups(obj, metarig): g_id = l.group - 1 name = groups[g_id].name if name not in obj.pose.bone_groups.keys(): - bg = obj.pose.bone_groups.new(name) + bg = obj.pose.bone_groups.new(name=name) bg.color_set = 'CUSTOM' bg.colors.normal = gamma_correct(groups[g_id].normal) bg.colors.select = gamma_correct(groups[g_id].select) @@ -607,6 +593,31 @@ def create_bone_groups(obj, metarig): b.bone_group = obj.pose.bone_groups[name] +def create_persistent_rig_ui(obj, script): + """Make sure the ui script always follows the rig around""" + skip = False + driver = None + + for fcurve in obj.animation_data.drivers: + if fcurve.data_path == 'pass_index': + driver = fcurve.driver + for variable in driver.variables: + if variable.name == script.name: + skip = True + break + break + + if not skip: + if not driver: + fcurve = obj.driver_add("pass_index") + driver = fcurve.driver + + variable = driver.variables.new() + variable.name = script.name + variable.targets[0].id_type = 'TEXT' + variable.targets[0].id = script + + def get_bone_rigs(obj, bone_name, halt_on_missing=False): """ Fetch all the rigs specified on a bone. """ diff --git a/rigify/legacy/__init__.py b/rigify/legacy/__init__.py index 6e6f751c..029d877e 100644 --- a/rigify/legacy/__init__.py +++ b/rigify/legacy/__init__.py @@ -45,16 +45,16 @@ import bpy class RigifyName(bpy.types.PropertyGroup): - name = bpy.props.StringProperty() + name: bpy.props.StringProperty() class RigifyParameters(bpy.types.PropertyGroup): - name = bpy.props.StringProperty() + name: bpy.props.StringProperty() class RigifyArmatureLayer(bpy.types.PropertyGroup): - name = bpy.props.StringProperty(name="Layer Name", default=" ") - row = bpy.props.IntProperty(name="Layer Row", default=1, min=1, max=32) + name: bpy.props.StringProperty(name="Layer Name", default=" ") + row: bpy.props.IntProperty(name="Layer Row", default=1, min=1, max=32) ##### REGISTER ##### diff --git a/rigify/legacy/generate.py b/rigify/legacy/generate.py index ec822b9e..9a39e333 100644 --- a/rigify/legacy/generate.py +++ b/rigify/legacy/generate.py @@ -28,7 +28,7 @@ from rna_prop_ui import rna_idprop_ui_prop_get from .utils import MetarigError, new_bone, get_rig_type from .utils import ORG_PREFIX, MCH_PREFIX, DEF_PREFIX, WGT_PREFIX, ROOT_NAME, make_original_name from .utils import RIG_DIR -from .utils import create_root_widget +from .utils import create_root_widget, ensure_widget_collection from .utils import random_id from .utils import copy_attributes from .rig_ui_template import UI_SLIDERS, layers_ui, UI_REGISTER @@ -71,6 +71,9 @@ def generate_rig(context, metarig): bpy.ops.object.mode_set(mode='OBJECT') scene = context.scene + view_layer = context.view_layer + collection = scene.collection + layer_collection = context.layer_collection #------------------------------------------ # Create/find the rig object and set it up @@ -88,8 +91,8 @@ def generate_rig(context, metarig): obj = scene.objects[name] except KeyError: obj = bpy.data.objects.new(name, bpy.data.armatures.new(name)) - obj.draw_type = 'WIRE' - scene.objects.link(obj) + obj.display_type = 'WIRE' + collection.objects.link(obj) obj.data.pose_position = 'POSE' @@ -98,9 +101,9 @@ def generate_rig(context, metarig): obj.animation_data_clear() # Select generated rig object - metarig.select = False - obj.select = True - scene.objects.active = obj + metarig.select_set('DESELECT') + obj.select_set('SELECT') + view_layer.objects.active = obj # Remove all bones from the generated rig armature. bpy.ops.object.mode_set(mode='EDIT') @@ -111,18 +114,18 @@ def generate_rig(context, metarig): # Create temporary duplicates for merging temp_rig_1 = metarig.copy() temp_rig_1.data = metarig.data.copy() - scene.objects.link(temp_rig_1) + collection.objects.link(temp_rig_1) temp_rig_2 = metarig.copy() temp_rig_2.data = obj.data - scene.objects.link(temp_rig_2) + collection.objects.link(temp_rig_2) # Select the temp rigs for merging for objt in scene.objects: - objt.select = False # deselect all objects - temp_rig_1.select = True - temp_rig_2.select = True - scene.objects.active = temp_rig_2 + objt.select_set('DESELECT') # deselect all objects + temp_rig_1.select_set('SELECT') + temp_rig_2.select_set('SELECT') + view_layer.objects.active = temp_rig_2 # Merge the temporary rigs bpy.ops.object.join() @@ -132,9 +135,9 @@ def generate_rig(context, metarig): # Select the generated rig for objt in scene.objects: - objt.select = False # deselect all objects - obj.select = True - scene.objects.active = obj + objt.select_set('DESELECT') # deselect all objects + obj.select_set('SELECT') + view_layer.objects.active = obj # Copy over bone properties for bone in metarig.data.bones: @@ -277,8 +280,8 @@ def generate_rig(context, metarig): for rig in rigs: # Go into editmode in the rig armature bpy.ops.object.mode_set(mode='OBJECT') - context.scene.objects.active = obj - obj.select = True + context.view_layer.objects.active = obj + obj.select_set('SELECT') bpy.ops.object.mode_set(mode='EDIT') scripts = rig.generate() if scripts is not None: @@ -353,7 +356,10 @@ def generate_rig(context, metarig): if obj.data.bones[bone].name.startswith(DEF_PREFIX): obj.data.bones[bone].layers = DEF_LAYER - # Create root bone widget + # Create/find widge collection + ensure_widget_collection(context) + + # Create root bone widget create_root_widget(obj, "root") # Assign shapes to bones @@ -427,6 +433,10 @@ def generate_rig(context, metarig): metarig.data.pose_position = rest_backup obj.data.pose_position = 'POSE' + #---------------------------------- + # Restore active collection + view_layer.collections.active = layer_collection + def get_bone_rigs(obj, bone_name, halt_on_missing=False): """ Fetch all the rigs specified on a bone. diff --git a/rigify/legacy/metarig_menu.py b/rigify/legacy/metarig_menu.py index 4bdf2701..c0c20955 100644 --- a/rigify/legacy/metarig_menu.py +++ b/rigify/legacy/metarig_menu.py @@ -114,7 +114,7 @@ def register(): bpy.utils.register_class(mop) for mf in menu_funcs: - bpy.types.INFO_MT_armature_add.append(mf) + bpy.types.VIEW3D_MT_armature_add.append(mf) def unregister(): @@ -122,4 +122,4 @@ def unregister(): bpy.utils.unregister_class(mop) for mf in menu_funcs: - bpy.types.INFO_MT_armature_add.remove(mf) + bpy.types.VIEW3D_MT_armature_add.remove(mf) diff --git a/rigify/legacy/rigs/basic/copy.py b/rigify/legacy/rigs/basic/copy.py index 50a25767..65c5ff31 100644 --- a/rigify/legacy/rigs/basic/copy.py +++ b/rigify/legacy/rigs/basic/copy.py @@ -88,8 +88,8 @@ def add_parameters(params): """ Add the parameters of this rig type to the RigifyParameters PropertyGroup """ - params.make_control = bpy.props.BoolProperty(name="Control", default=True, description="Create a control bone for the copy") - params.make_deform = bpy.props.BoolProperty(name="Deform", default=True, description="Create a deform bone for the copy") + params.make_control: bpy.props.BoolProperty(name="Control", default=True, description="Create a control bone for the copy") + params.make_deform: bpy.props.BoolProperty(name="Deform", default=True, description="Create a deform bone for the copy") def parameters_ui(layout, params): diff --git a/rigify/legacy/rigs/basic/copy_chain.py b/rigify/legacy/rigs/basic/copy_chain.py index 4e426284..25013c0e 100644 --- a/rigify/legacy/rigs/basic/copy_chain.py +++ b/rigify/legacy/rigs/basic/copy_chain.py @@ -127,8 +127,8 @@ def add_parameters(params): """ Add the parameters of this rig type to the RigifyParameters PropertyGroup """ - params.make_controls = bpy.props.BoolProperty(name="Controls", default=True, description="Create control bones for the copy") - params.make_deforms = bpy.props.BoolProperty(name="Deform", default=True, description="Create deform bones for the copy") + params.make_controls: bpy.props.BoolProperty(name="Controls", default=True, description="Create control bones for the copy") + params.make_deforms: bpy.props.BoolProperty(name="Deform", default=True, description="Create deform bones for the copy") def parameters_ui(layout, params): diff --git a/rigify/legacy/rigs/pitchipoy/limbs/limb_utils.py b/rigify/legacy/rigs/pitchipoy/limbs/limb_utils.py index b0b62d79..69449bb7 100644 --- a/rigify/legacy/rigs/pitchipoy/limbs/limb_utils.py +++ b/rigify/legacy/rigs/pitchipoy/limbs/limb_utils.py @@ -11,11 +11,11 @@ def orient_bone( cls, eb, axis, scale = 1.0, reverse = False ): setattr(v,axis,scale) if reverse: - tail_vec = v * cls.obj.matrix_world + tail_vec = v @ cls.obj.matrix_world eb.head[:] = eb.tail eb.tail[:] = eb.head + tail_vec else: - tail_vec = v * cls.obj.matrix_world + tail_vec = v @ cls.obj.matrix_world eb.tail[:] = eb.head + tail_vec eb.roll = 0.0 diff --git a/rigify/legacy/rigs/pitchipoy/super_copy.py b/rigify/legacy/rigs/pitchipoy/super_copy.py index 27e88775..5a60ed04 100644 --- a/rigify/legacy/rigs/pitchipoy/super_copy.py +++ b/rigify/legacy/rigs/pitchipoy/super_copy.py @@ -91,7 +91,7 @@ def add_parameters(params): """ Add the parameters of this rig type to the RigifyParameters PropertyGroup """ - params.make_control = bpy.props.BoolProperty( + params.make_control: bpy.props.BoolProperty( name = "Control", default = True, description = "Create a control bone for the copy" diff --git a/rigify/legacy/rigs/pitchipoy/super_face.py b/rigify/legacy/rigs/pitchipoy/super_face.py index c999ae9a..919f8439 100644 --- a/rigify/legacy/rigs/pitchipoy/super_face.py +++ b/rigify/legacy/rigs/pitchipoy/super_face.py @@ -1016,26 +1016,26 @@ def add_parameters(params): """ #Setting up extra layers for the tweak bones - params.primary_layers_extra = bpy.props.BoolProperty( + params.primary_layers_extra: bpy.props.BoolProperty( name = "primary_layers_extra", default = True, description = "" - ) - params.primary_layers = bpy.props.BoolVectorProperty( + ) + params.primary_layers: bpy.props.BoolVectorProperty( size = 32, description = "Layers for the 1st tweak controls to be on", default = tuple( [ i == 1 for i in range(0, 32) ] ) - ) - params.secondary_layers_extra = bpy.props.BoolProperty( + ) + params.secondary_layers_extra: bpy.props.BoolProperty( name = "secondary_layers_extra", default = True, description = "" - ) - params.secondary_layers = bpy.props.BoolVectorProperty( + ) + params.secondary_layers: bpy.props.BoolVectorProperty( size = 32, description = "Layers for the 2nd tweak controls to be on", default = tuple( [ i == 1 for i in range(0, 32) ] ) - ) + ) def parameters_ui(layout, params): diff --git a/rigify/legacy/rigs/pitchipoy/super_torso_turbo.py b/rigify/legacy/rigs/pitchipoy/super_torso_turbo.py index 38d5887b..d9645adb 100644 --- a/rigify/legacy/rigs/pitchipoy/super_torso_turbo.py +++ b/rigify/legacy/rigs/pitchipoy/super_torso_turbo.py @@ -99,11 +99,11 @@ class Rig: setattr(v,axis,scale) if reverse: - tail_vec = v * self.obj.matrix_world + tail_vec = v @ self.obj.matrix_world eb.head[:] = eb.tail eb.tail[:] = eb.head + tail_vec else: - tail_vec = v * self.obj.matrix_world + tail_vec = v @ self.obj.matrix_world eb.tail[:] = eb.head + tail_vec diff --git a/rigify/legacy/rigs/pitchipoy/super_widgets.py b/rigify/legacy/rigs/pitchipoy/super_widgets.py index 72384a7c..f442c590 100644 --- a/rigify/legacy/rigs/pitchipoy/super_widgets.py +++ b/rigify/legacy/rigs/pitchipoy/super_widgets.py @@ -3,7 +3,6 @@ import importlib import importlib from ...utils import create_widget -WGT_LAYERS = [x == 19 for x in range(0, 20)] # Widgets go on the last scene layer. MODULE_NAME = "super_widgets" # Windows/Mac blender is weird, so __package__ doesn't work diff --git a/rigify/legacy/ui.py b/rigify/legacy/ui.py index dec5b73c..f04ec335 100644 --- a/rigify/legacy/ui.py +++ b/rigify/legacy/ui.py @@ -124,7 +124,7 @@ class DATA_PT_rigify_layer_names(bpy.types.Panel): col = layout.column(align=True) row = col.row() row.prop(arm, "layers", index=i, text="", toggle=True) - split = row.split(percentage=0.8) + split = row.split(factor=0.8) split.prop(rigify_layer, "name", text="Layer %d" % (i + 1)) split.prop(rigify_layer, "row", text="") @@ -200,9 +200,9 @@ class BONE_PT_rigify_buttons(bpy.types.Panel): class VIEW3D_PT_tools_rigify_dev(bpy.types.Panel): bl_label = "Rigify Dev Tools" - bl_category = 'Tools' bl_space_type = 'VIEW_3D' - bl_region_type = 'TOOLS' + bl_region_type = 'UI' + bl_category = 'View' @classmethod def poll(cls, context): @@ -221,8 +221,8 @@ class VIEW3D_PT_tools_rigify_dev(bpy.types.Panel): r = self.layout.row() r.operator("mesh.rigify_encode_mesh_widget", text="Encode Mesh Widget to Python") -#~ class INFO_MT_armature_metarig_add(bpy.types.Menu): - #~ bl_idname = "INFO_MT_armature_metarig_add" +#~ class VIEW3D_MT_armature_metarig_add(bpy.types.Menu): + #~ bl_idname = "VIEW3D_MT_armature_metarig_add" #~ bl_label = "Meta-Rig" #~ def draw(self, context): @@ -304,11 +304,11 @@ class Sample(bpy.types.Operator): bl_label = "Add a sample metarig for a rig type" bl_options = {'UNDO'} - metarig_type = StringProperty( - name="Type", - description="Name of the rig type to generate a sample of", - maxlen=128, - ) + metarig_type: StringProperty( + name="Type", + description="Name of the rig type to generate a sample of", + maxlen=128, + ) def execute(self, context): if context.mode == 'EDIT_ARMATURE' and self.metarig_type != "": @@ -410,7 +410,7 @@ class EncodeWidget(bpy.types.Operator): return {'FINISHED'} -#menu_func = (lambda self, context: self.layout.menu("INFO_MT_armature_metarig_add", icon='OUTLINER_OB_ARMATURE')) +#menu_func = (lambda self, context: self.layout.menu("VIEW3D_MT_armature_metarig_add", icon='OUTLINER_OB_ARMATURE')) #from bl_ui import space_info # ensure the menu is loaded first @@ -425,7 +425,7 @@ def register(): bpy.utils.register_class(EncodeMetarig) bpy.utils.register_class(EncodeMetarigSample) bpy.utils.register_class(EncodeWidget) - #space_info.INFO_MT_armature_add.append(ui.menu_func) + #space_info.VIEW3D_MT_armature_add.append(ui.menu_func) def unregister(): diff --git a/rigify/legacy/utils.py b/rigify/legacy/utils.py index e3927ac3..0f3a092e 100644 --- a/rigify/legacy/utils.py +++ b/rigify/legacy/utils.py @@ -36,8 +36,6 @@ DEF_PREFIX = "DEF-" # Prefix of deformation bones. WGT_PREFIX = "WGT-" # Prefix for widget objects ROOT_NAME = "root" # Name of the root bone. -WGT_LAYERS = [x == 19 for x in range(0, 20)] # Widgets go on the last scene layer. - MODULE_NAME = "rigify" # Windows/Mac blender is weird, so __package__ doesn't work @@ -342,7 +340,7 @@ def obj_to_bone(obj, rig, bone_name): bone = rig.data.bones[bone_name] - mat = rig.matrix_world * bone.matrix_local + mat = rig.matrix_world @ bone.matrix_local obj.location = mat.to_translation() @@ -397,6 +395,7 @@ def create_widget(rig, bone_name, bone_transform_name=None): obj_name = WGT_PREFIX + bone_name scene = bpy.context.scene + collection = bpy.context.collection # Check if it already exists in the scene if obj_name in scene.objects: @@ -416,11 +415,10 @@ def create_widget(rig, bone_name, bone_transform_name=None): # Create mesh object mesh = bpy.data.meshes.new(obj_name) obj = bpy.data.objects.new(obj_name, mesh) - scene.objects.link(obj) + collection.objects.link(obj) # Move object to bone position and set layers obj_to_bone(obj, rig, bone_transform_name) - obj.layers = WGT_LAYERS return obj @@ -606,8 +604,8 @@ def align_bone_roll(obj, bone1, bone2): rot_mat = Matrix.Rotation(angle, 3, axis) # Roll factor - x3 = rot_mat * x1 - dot = x2 * x3 + x3 = rot_mat @ x1 + dot = x2 @ x3 if dot > 1.0: dot = 1.0 elif dot < -1.0: @@ -618,7 +616,7 @@ def align_bone_roll(obj, bone1, bone2): bone1_e.roll = roll # Check if we rolled in the right direction - x3 = rot_mat * bone1_e.x_axis + x3 = rot_mat @ bone1_e.x_axis check = x2 * x3 # If not, reverse @@ -937,3 +935,39 @@ def random_id(length=8): text += random.choice(chars) text += str(hex(int(time.time())))[2:][-tlength:].rjust(tlength, '0')[::-1] return text + + +def get_layer_collection_from_collection(children, collection): + for layer_collection in children: + if collection == layer_collection.collection: + return layer_collection + + # go recursive + layer_collection = get_layer_collection_from_collection(layer_collection.children, collection) + if layer_collection: + return layer_collection + + +def ensure_widget_collection(context): + wgts_collection_name = "Widgets" + + view_layer = context.view_layer + layer_collection = bpy.context.layer_collection + collection = layer_collection.collection + + widget_collection = bpy.data.collections.get(wgts_collection_name) + if not widget_collection: + # ------------------------------------------ + # Create the widget collection + widget_collection = bpy.data.collections.new(wgts_collection_name) + widget_collection.hide_viewport = True + widget_collection.hide_render = True + + collection.children.link(widget_collection) + widget_layer_collection = [c for c in layer_collection.children if c.collection == widget_collection][0] + else: + widget_layer_collection = get_layer_collection_from_collection(view_layer.collections, widget_collection) + + # Make the widget the active collection for the upcoming added (widget) objects + view_layer.collections.active = widget_layer_collection + return widget_collection diff --git a/rigify/metarig_menu.py b/rigify/metarig_menu.py index 6b12abad..102d366d 100644 --- a/rigify/metarig_menu.py +++ b/rigify/metarig_menu.py @@ -31,7 +31,7 @@ class ArmatureSubMenu(bpy.types.Menu): def draw(self, context): layout = self.layout - layout.label(self.bl_label) + layout.label(text=self.bl_label) for op, name in self.operators: text = capwords(name.replace("_", " ")) + " (Meta-Rig)" layout.operator(op, icon='OUTLINER_OB_ARMATURE', text=text) @@ -159,25 +159,33 @@ for metarig_class in metarig_classes: arm_sub = next((e for e in armature_submenus if e.bl_label == metarig_class + ' (submenu)'), '') arm_sub.operators.append((mop.bl_idname, name,)) + +### Registering ### + + def register(): + from bpy.utils import register_class + for cl in metarig_ops: for mop, name in metarig_ops[cl]: - bpy.utils.register_class(mop) + register_class(mop) for arm_sub in armature_submenus: - bpy.utils.register_class(arm_sub) + register_class(arm_sub) for mf in menu_funcs: - bpy.types.INFO_MT_armature_add.append(mf) + bpy.types.VIEW3D_MT_armature_add.append(mf) def unregister(): + from bpy.utils import unregister_class + for cl in metarig_ops: for mop, name in metarig_ops[cl]: - bpy.utils.unregister_class(mop) + unregister_class(mop) for arm_sub in armature_submenus: - bpy.utils.unregister_class(arm_sub) + unregister_class(arm_sub) for mf in menu_funcs: - bpy.types.INFO_MT_armature_add.remove(mf) + bpy.types.VIEW3D_MT_armature_add.remove(mf) diff --git a/rigify/metarigs/Animals/bird.py b/rigify/metarigs/Animals/bird.py index e31ce7fe..a3331c29 100644 --- a/rigify/metarigs/Animals/bird.py +++ b/rigify/metarigs/Animals/bird.py @@ -48,119 +48,119 @@ def create(obj): arm.rigify_layers[0].name = "Face" arm.rigify_layers[0].row = 1 - arm.rigify_layers[0].set = False + arm.rigify_layers[0].selset = False arm.rigify_layers[0].group = 6 arm.rigify_layers[1].name = "Face (Tweak)" arm.rigify_layers[1].row = 2 - arm.rigify_layers[1].set = False + arm.rigify_layers[1].selset = False arm.rigify_layers[1].group = 4 arm.rigify_layers[2].name = " " arm.rigify_layers[2].row = 1 - arm.rigify_layers[2].set = False + arm.rigify_layers[2].selset = False arm.rigify_layers[2].group = 0 arm.rigify_layers[3].name = "Spine" arm.rigify_layers[3].row = 3 - arm.rigify_layers[3].set = False + arm.rigify_layers[3].selset = False arm.rigify_layers[3].group = 3 arm.rigify_layers[4].name = "Spine (Tweak)" arm.rigify_layers[4].row = 4 - arm.rigify_layers[4].set = False + arm.rigify_layers[4].selset = False arm.rigify_layers[4].group = 4 arm.rigify_layers[5].name = " " arm.rigify_layers[5].row = 1 - arm.rigify_layers[5].set = False + arm.rigify_layers[5].selset = False arm.rigify_layers[5].group = 0 arm.rigify_layers[6].name = " " arm.rigify_layers[6].row = 1 - arm.rigify_layers[6].set = False + arm.rigify_layers[6].selset = False arm.rigify_layers[6].group = 0 arm.rigify_layers[7].name = "Wing.L" arm.rigify_layers[7].row = 6 - arm.rigify_layers[7].set = False + arm.rigify_layers[7].selset = False arm.rigify_layers[7].group = 5 arm.rigify_layers[8].name = "" arm.rigify_layers[8].row = 8 - arm.rigify_layers[8].set = False + arm.rigify_layers[8].selset = False arm.rigify_layers[8].group = 0 arm.rigify_layers[9].name = "Wing.L (Tweak)" arm.rigify_layers[9].row = 7 - arm.rigify_layers[9].set = False + arm.rigify_layers[9].selset = False arm.rigify_layers[9].group = 4 arm.rigify_layers[10].name = "Wing.R" arm.rigify_layers[10].row = 6 - arm.rigify_layers[10].set = False + arm.rigify_layers[10].selset = False arm.rigify_layers[10].group = 5 arm.rigify_layers[11].name = "" arm.rigify_layers[11].row = 8 - arm.rigify_layers[11].set = False + arm.rigify_layers[11].selset = False arm.rigify_layers[11].group = 0 arm.rigify_layers[12].name = "Wing.R (Tweak)" arm.rigify_layers[12].row = 7 - arm.rigify_layers[12].set = False + arm.rigify_layers[12].selset = False arm.rigify_layers[12].group = 4 arm.rigify_layers[13].name = "Leg.L (IK)" arm.rigify_layers[13].row = 10 - arm.rigify_layers[13].set = False + arm.rigify_layers[13].selset = False arm.rigify_layers[13].group = 2 arm.rigify_layers[14].name = "Leg.L (FK)" arm.rigify_layers[14].row = 11 - arm.rigify_layers[14].set = False + arm.rigify_layers[14].selset = False arm.rigify_layers[14].group = 5 arm.rigify_layers[15].name = "Leg.L (Tweak)" arm.rigify_layers[15].row = 12 - arm.rigify_layers[15].set = False + arm.rigify_layers[15].selset = False arm.rigify_layers[15].group = 4 arm.rigify_layers[16].name = " Leg.R (IK)" arm.rigify_layers[16].row = 10 - arm.rigify_layers[16].set = False + arm.rigify_layers[16].selset = False arm.rigify_layers[16].group = 2 arm.rigify_layers[17].name = " Leg.R (FK)" arm.rigify_layers[17].row = 11 - arm.rigify_layers[17].set = False + arm.rigify_layers[17].selset = False arm.rigify_layers[17].group = 5 arm.rigify_layers[18].name = " Leg.R (Tweak)" arm.rigify_layers[18].row = 12 - arm.rigify_layers[18].set = False + arm.rigify_layers[18].selset = False arm.rigify_layers[18].group = 4 arm.rigify_layers[19].name = " " arm.rigify_layers[19].row = 1 - arm.rigify_layers[19].set = False + arm.rigify_layers[19].selset = False arm.rigify_layers[19].group = 0 arm.rigify_layers[20].name = " " arm.rigify_layers[20].row = 1 - arm.rigify_layers[20].set = False + arm.rigify_layers[20].selset = False arm.rigify_layers[20].group = 0 arm.rigify_layers[21].name = "Claws" arm.rigify_layers[21].row = 13 - arm.rigify_layers[21].set = False + arm.rigify_layers[21].selset = False arm.rigify_layers[21].group = 6 arm.rigify_layers[22].name = "Claws (Tweak)" arm.rigify_layers[22].row = 14 - arm.rigify_layers[22].set = False + arm.rigify_layers[22].selset = False arm.rigify_layers[22].group = 4 arm.rigify_layers[23].name = " " arm.rigify_layers[23].row = 1 - arm.rigify_layers[23].set = False + arm.rigify_layers[23].selset = False arm.rigify_layers[23].group = 0 arm.rigify_layers[24].name = "Feathers" arm.rigify_layers[24].row = 8 - arm.rigify_layers[24].set = False + arm.rigify_layers[24].selset = False arm.rigify_layers[24].group = 6 arm.rigify_layers[25].name = " " arm.rigify_layers[25].row = 1 - arm.rigify_layers[25].set = False + arm.rigify_layers[25].selset = False arm.rigify_layers[25].group = 0 arm.rigify_layers[26].name = " " arm.rigify_layers[26].row = 1 - arm.rigify_layers[26].set = False + arm.rigify_layers[26].selset = False arm.rigify_layers[26].group = 0 arm.rigify_layers[27].name = " " arm.rigify_layers[27].row = 1 - arm.rigify_layers[27].set = False + arm.rigify_layers[27].selset = False arm.rigify_layers[27].group = 0 arm.rigify_layers[28].name = "Root" arm.rigify_layers[28].row = 14 - arm.rigify_layers[28].set = False + arm.rigify_layers[28].selset = False arm.rigify_layers[28].group = 1 bones = {} diff --git a/rigify/metarigs/Animals/cat.py b/rigify/metarigs/Animals/cat.py index 836c9794..d3de1192 100644 --- a/rigify/metarigs/Animals/cat.py +++ b/rigify/metarigs/Animals/cat.py @@ -48,119 +48,119 @@ def create(obj): arm.rigify_layers[0].name = "Face" arm.rigify_layers[0].row = 1 - arm.rigify_layers[0].set = False + arm.rigify_layers[0].selset = False arm.rigify_layers[0].group = 5 arm.rigify_layers[1].name = "Face (Primary)" arm.rigify_layers[1].row = 2 - arm.rigify_layers[1].set = False + arm.rigify_layers[1].selset = False arm.rigify_layers[1].group = 2 arm.rigify_layers[2].name = "Face (Secondary)" arm.rigify_layers[2].row = 2 - arm.rigify_layers[2].set = False + arm.rigify_layers[2].selset = False arm.rigify_layers[2].group = 3 arm.rigify_layers[3].name = "Spine" arm.rigify_layers[3].row = 3 - arm.rigify_layers[3].set = False + arm.rigify_layers[3].selset = False arm.rigify_layers[3].group = 3 arm.rigify_layers[4].name = "Spine (Tweak)" arm.rigify_layers[4].row = 4 - arm.rigify_layers[4].set = False + arm.rigify_layers[4].selset = False arm.rigify_layers[4].group = 4 arm.rigify_layers[5].name = "Paws" arm.rigify_layers[5].row = 5 - arm.rigify_layers[5].set = False + arm.rigify_layers[5].selset = False arm.rigify_layers[5].group = 6 arm.rigify_layers[6].name = "Paws (Tweak)" arm.rigify_layers[6].row = 6 - arm.rigify_layers[6].set = False + arm.rigify_layers[6].selset = False arm.rigify_layers[6].group = 4 arm.rigify_layers[7].name = "Arm.L (IK)" arm.rigify_layers[7].row = 7 - arm.rigify_layers[7].set = False + arm.rigify_layers[7].selset = False arm.rigify_layers[7].group = 2 arm.rigify_layers[8].name = "Arm.L (FK)" arm.rigify_layers[8].row = 8 - arm.rigify_layers[8].set = False + arm.rigify_layers[8].selset = False arm.rigify_layers[8].group = 5 arm.rigify_layers[9].name = "Arm,L (Tweak)" arm.rigify_layers[9].row = 9 - arm.rigify_layers[9].set = False + arm.rigify_layers[9].selset = False arm.rigify_layers[9].group = 4 arm.rigify_layers[10].name = "Arm.R (IK)" arm.rigify_layers[10].row = 7 - arm.rigify_layers[10].set = False + arm.rigify_layers[10].selset = False arm.rigify_layers[10].group = 2 arm.rigify_layers[11].name = "Arm.R (FK)" arm.rigify_layers[11].row = 8 - arm.rigify_layers[11].set = False + arm.rigify_layers[11].selset = False arm.rigify_layers[11].group = 5 arm.rigify_layers[12].name = "Arm.R (Tweak)" arm.rigify_layers[12].row = 9 - arm.rigify_layers[12].set = False + arm.rigify_layers[12].selset = False arm.rigify_layers[12].group = 4 arm.rigify_layers[13].name = "Leg.L (IK)" arm.rigify_layers[13].row = 10 - arm.rigify_layers[13].set = False + arm.rigify_layers[13].selset = False arm.rigify_layers[13].group = 2 arm.rigify_layers[14].name = "Leg.L (FK)" arm.rigify_layers[14].row = 11 - arm.rigify_layers[14].set = False + arm.rigify_layers[14].selset = False arm.rigify_layers[14].group = 5 arm.rigify_layers[15].name = "Leg.L (Tweak)" arm.rigify_layers[15].row = 12 - arm.rigify_layers[15].set = False + arm.rigify_layers[15].selset = False arm.rigify_layers[15].group = 4 arm.rigify_layers[16].name = "Leg.R (IK)" arm.rigify_layers[16].row = 10 - arm.rigify_layers[16].set = False + arm.rigify_layers[16].selset = False arm.rigify_layers[16].group = 2 arm.rigify_layers[17].name = "Leg.R (FK)" arm.rigify_layers[17].row = 11 - arm.rigify_layers[17].set = False + arm.rigify_layers[17].selset = False arm.rigify_layers[17].group = 5 arm.rigify_layers[18].name = "Leg.R (Tweak)" arm.rigify_layers[18].row = 12 - arm.rigify_layers[18].set = False + arm.rigify_layers[18].selset = False arm.rigify_layers[18].group = 4 arm.rigify_layers[19].name = "Tail" arm.rigify_layers[19].row = 13 - arm.rigify_layers[19].set = False + arm.rigify_layers[19].selset = False arm.rigify_layers[19].group = 3 arm.rigify_layers[20].name = "Tail (Tweaks)" arm.rigify_layers[20].row = 14 - arm.rigify_layers[20].set = False + arm.rigify_layers[20].selset = False arm.rigify_layers[20].group = 4 arm.rigify_layers[21].name = " " arm.rigify_layers[21].row = 1 - arm.rigify_layers[21].set = False + arm.rigify_layers[21].selset = False arm.rigify_layers[21].group = 0 arm.rigify_layers[22].name = " " arm.rigify_layers[22].row = 1 - arm.rigify_layers[22].set = False + arm.rigify_layers[22].selset = False arm.rigify_layers[22].group = 0 arm.rigify_layers[23].name = " " arm.rigify_layers[23].row = 1 - arm.rigify_layers[23].set = False + arm.rigify_layers[23].selset = False arm.rigify_layers[23].group = 0 arm.rigify_layers[24].name = " " arm.rigify_layers[24].row = 1 - arm.rigify_layers[24].set = False + arm.rigify_layers[24].selset = False arm.rigify_layers[24].group = 0 arm.rigify_layers[25].name = " " arm.rigify_layers[25].row = 1 - arm.rigify_layers[25].set = False + arm.rigify_layers[25].selset = False arm.rigify_layers[25].group = 0 arm.rigify_layers[26].name = " " arm.rigify_layers[26].row = 1 - arm.rigify_layers[26].set = False + arm.rigify_layers[26].selset = False arm.rigify_layers[26].group = 0 arm.rigify_layers[27].name = " " arm.rigify_layers[27].row = 1 - arm.rigify_layers[27].set = False + arm.rigify_layers[27].selset = False arm.rigify_layers[27].group = 0 arm.rigify_layers[28].name = "Root" arm.rigify_layers[28].row = 16 - arm.rigify_layers[28].set = False + arm.rigify_layers[28].selset = False arm.rigify_layers[28].group = 1 bones = {} diff --git a/rigify/metarigs/Animals/horse.py b/rigify/metarigs/Animals/horse.py index 72ed1de2..358a9ceb 100644 --- a/rigify/metarigs/Animals/horse.py +++ b/rigify/metarigs/Animals/horse.py @@ -48,119 +48,119 @@ def create(obj): arm.rigify_layers[0].name = "Face" arm.rigify_layers[0].row = 1 - arm.rigify_layers[0].set = False + arm.rigify_layers[0].selset = False arm.rigify_layers[0].group = 5 arm.rigify_layers[1].name = "Face (Primary)" arm.rigify_layers[1].row = 2 - arm.rigify_layers[1].set = False + arm.rigify_layers[1].selset = False arm.rigify_layers[1].group = 4 arm.rigify_layers[2].name = " " arm.rigify_layers[2].row = 3 - arm.rigify_layers[2].set = False + arm.rigify_layers[2].selset = False arm.rigify_layers[2].group = 0 arm.rigify_layers[3].name = "Spine" arm.rigify_layers[3].row = 4 - arm.rigify_layers[3].set = False + arm.rigify_layers[3].selset = False arm.rigify_layers[3].group = 3 arm.rigify_layers[4].name = "Spine (Tweak)" arm.rigify_layers[4].row = 5 - arm.rigify_layers[4].set = False + arm.rigify_layers[4].selset = False arm.rigify_layers[4].group = 4 arm.rigify_layers[5].name = " " arm.rigify_layers[5].row = 1 - arm.rigify_layers[5].set = False + arm.rigify_layers[5].selset = False arm.rigify_layers[5].group = 0 arm.rigify_layers[6].name = " " arm.rigify_layers[6].row = 1 - arm.rigify_layers[6].set = False + arm.rigify_layers[6].selset = False arm.rigify_layers[6].group = 0 arm.rigify_layers[7].name = "Arm.L (IK)" arm.rigify_layers[7].row = 7 - arm.rigify_layers[7].set = False + arm.rigify_layers[7].selset = False arm.rigify_layers[7].group = 2 arm.rigify_layers[8].name = "Arm.L (FK)" arm.rigify_layers[8].row = 8 - arm.rigify_layers[8].set = False + arm.rigify_layers[8].selset = False arm.rigify_layers[8].group = 5 arm.rigify_layers[9].name = "Arm.L (Tweak)" arm.rigify_layers[9].row = 9 - arm.rigify_layers[9].set = False + arm.rigify_layers[9].selset = False arm.rigify_layers[9].group = 4 arm.rigify_layers[10].name = "Arm.R (IK)" arm.rigify_layers[10].row = 7 - arm.rigify_layers[10].set = False + arm.rigify_layers[10].selset = False arm.rigify_layers[10].group = 2 arm.rigify_layers[11].name = "Arm.R (FK)" arm.rigify_layers[11].row = 8 - arm.rigify_layers[11].set = False + arm.rigify_layers[11].selset = False arm.rigify_layers[11].group = 5 arm.rigify_layers[12].name = "Arm.R (Tweak)" arm.rigify_layers[12].row = 9 - arm.rigify_layers[12].set = False + arm.rigify_layers[12].selset = False arm.rigify_layers[12].group = 4 arm.rigify_layers[13].name = "Leg.L (IK)" arm.rigify_layers[13].row = 10 - arm.rigify_layers[13].set = False + arm.rigify_layers[13].selset = False arm.rigify_layers[13].group = 2 arm.rigify_layers[14].name = "Leg.L (FK)" arm.rigify_layers[14].row = 11 - arm.rigify_layers[14].set = False + arm.rigify_layers[14].selset = False arm.rigify_layers[14].group = 5 arm.rigify_layers[15].name = "Leg.L (Tweak)" arm.rigify_layers[15].row = 12 - arm.rigify_layers[15].set = False + arm.rigify_layers[15].selset = False arm.rigify_layers[15].group = 4 arm.rigify_layers[16].name = "Leg.R (IK)" arm.rigify_layers[16].row = 10 - arm.rigify_layers[16].set = False + arm.rigify_layers[16].selset = False arm.rigify_layers[16].group = 2 arm.rigify_layers[17].name = "Leg.R (FK)" arm.rigify_layers[17].row = 11 - arm.rigify_layers[17].set = False + arm.rigify_layers[17].selset = False arm.rigify_layers[17].group = 5 arm.rigify_layers[18].name = "Leg.R (Tweak)" arm.rigify_layers[18].row = 12 - arm.rigify_layers[18].set = False + arm.rigify_layers[18].selset = False arm.rigify_layers[18].group = 4 arm.rigify_layers[19].name = "Tail" arm.rigify_layers[19].row = 13 - arm.rigify_layers[19].set = False + arm.rigify_layers[19].selset = False arm.rigify_layers[19].group = 6 arm.rigify_layers[20].name = " " arm.rigify_layers[20].row = 1 - arm.rigify_layers[20].set = False + arm.rigify_layers[20].selset = False arm.rigify_layers[20].group = 4 arm.rigify_layers[21].name = "Hair" arm.rigify_layers[21].row = 14 - arm.rigify_layers[21].set = False + arm.rigify_layers[21].selset = False arm.rigify_layers[21].group = 6 arm.rigify_layers[22].name = " " arm.rigify_layers[22].row = 1 - arm.rigify_layers[22].set = False + arm.rigify_layers[22].selset = False arm.rigify_layers[22].group = 0 arm.rigify_layers[23].name = " " arm.rigify_layers[23].row = 1 - arm.rigify_layers[23].set = False + arm.rigify_layers[23].selset = False arm.rigify_layers[23].group = 0 arm.rigify_layers[24].name = " " arm.rigify_layers[24].row = 1 - arm.rigify_layers[24].set = False + arm.rigify_layers[24].selset = False arm.rigify_layers[24].group = 0 arm.rigify_layers[25].name = " " arm.rigify_layers[25].row = 1 - arm.rigify_layers[25].set = False + arm.rigify_layers[25].selset = False arm.rigify_layers[25].group = 0 arm.rigify_layers[26].name = " " arm.rigify_layers[26].row = 1 - arm.rigify_layers[26].set = False + arm.rigify_layers[26].selset = False arm.rigify_layers[26].group = 0 arm.rigify_layers[27].name = " " arm.rigify_layers[27].row = 1 - arm.rigify_layers[27].set = False + arm.rigify_layers[27].selset = False arm.rigify_layers[27].group = 0 arm.rigify_layers[28].name = "Root" arm.rigify_layers[28].row = 14 - arm.rigify_layers[28].set = False + arm.rigify_layers[28].selset = False arm.rigify_layers[28].group = 1 diff --git a/rigify/metarigs/Animals/shark.py b/rigify/metarigs/Animals/shark.py index bcc53df3..1ee1d0d9 100644 --- a/rigify/metarigs/Animals/shark.py +++ b/rigify/metarigs/Animals/shark.py @@ -48,119 +48,119 @@ def create(obj): arm.rigify_layers[0].name = "Face" arm.rigify_layers[0].row = 1 - arm.rigify_layers[0].set = False + arm.rigify_layers[0].selset = False arm.rigify_layers[0].group = 5 arm.rigify_layers[1].name = "Face (Tweak)" arm.rigify_layers[1].row = 2 - arm.rigify_layers[1].set = False + arm.rigify_layers[1].selset = False arm.rigify_layers[1].group = 4 arm.rigify_layers[2].name = " " arm.rigify_layers[2].row = 1 - arm.rigify_layers[2].set = False + arm.rigify_layers[2].selset = False arm.rigify_layers[2].group = 0 arm.rigify_layers[3].name = "Spine" arm.rigify_layers[3].row = 3 - arm.rigify_layers[3].set = False + arm.rigify_layers[3].selset = False arm.rigify_layers[3].group = 3 arm.rigify_layers[4].name = "Spine (Tweak)" arm.rigify_layers[4].row = 4 - arm.rigify_layers[4].set = False + arm.rigify_layers[4].selset = False arm.rigify_layers[4].group = 4 arm.rigify_layers[5].name = "Tail" arm.rigify_layers[5].row = 5 - arm.rigify_layers[5].set = False + arm.rigify_layers[5].selset = False arm.rigify_layers[5].group = 6 arm.rigify_layers[6].name = "Fins.L" arm.rigify_layers[6].row = 6 - arm.rigify_layers[6].set = False + arm.rigify_layers[6].selset = False arm.rigify_layers[6].group = 5 arm.rigify_layers[7].name = "Fins.L (Tweak)" arm.rigify_layers[7].row = 7 - arm.rigify_layers[7].set = False + arm.rigify_layers[7].selset = False arm.rigify_layers[7].group = 4 arm.rigify_layers[8].name = "Fins.R" arm.rigify_layers[8].row = 6 - arm.rigify_layers[8].set = False + arm.rigify_layers[8].selset = False arm.rigify_layers[8].group = 5 arm.rigify_layers[9].name = "Fins.R (Tweak)" arm.rigify_layers[9].row = 7 - arm.rigify_layers[9].set = False + arm.rigify_layers[9].selset = False arm.rigify_layers[9].group = 4 arm.rigify_layers[10].name = "Fins" arm.rigify_layers[10].row = 8 - arm.rigify_layers[10].set = False + arm.rigify_layers[10].selset = False arm.rigify_layers[10].group = 3 arm.rigify_layers[11].name = "Fins (Tweak)" arm.rigify_layers[11].row = 9 - arm.rigify_layers[11].set = False + arm.rigify_layers[11].selset = False arm.rigify_layers[11].group = 4 arm.rigify_layers[12].name = " " arm.rigify_layers[12].row = 1 - arm.rigify_layers[12].set = False + arm.rigify_layers[12].selset = False arm.rigify_layers[12].group = 0 arm.rigify_layers[13].name = " " arm.rigify_layers[13].row = 1 - arm.rigify_layers[13].set = False + arm.rigify_layers[13].selset = False arm.rigify_layers[13].group = 6 arm.rigify_layers[14].name = " " arm.rigify_layers[14].row = 1 - arm.rigify_layers[14].set = False + arm.rigify_layers[14].selset = False arm.rigify_layers[14].group = 0 arm.rigify_layers[15].name = " " arm.rigify_layers[15].row = 1 - arm.rigify_layers[15].set = False + arm.rigify_layers[15].selset = False arm.rigify_layers[15].group = 0 arm.rigify_layers[16].name = " " arm.rigify_layers[16].row = 1 - arm.rigify_layers[16].set = False + arm.rigify_layers[16].selset = False arm.rigify_layers[16].group = 0 arm.rigify_layers[17].name = " " arm.rigify_layers[17].row = 1 - arm.rigify_layers[17].set = False + arm.rigify_layers[17].selset = False arm.rigify_layers[17].group = 0 arm.rigify_layers[18].name = " " arm.rigify_layers[18].row = 1 - arm.rigify_layers[18].set = False + arm.rigify_layers[18].selset = False arm.rigify_layers[18].group = 0 arm.rigify_layers[19].name = " " arm.rigify_layers[19].row = 1 - arm.rigify_layers[19].set = False + arm.rigify_layers[19].selset = False arm.rigify_layers[19].group = 0 arm.rigify_layers[20].name = " " arm.rigify_layers[20].row = 1 - arm.rigify_layers[20].set = False + arm.rigify_layers[20].selset = False arm.rigify_layers[20].group = 0 arm.rigify_layers[21].name = " " arm.rigify_layers[21].row = 1 - arm.rigify_layers[21].set = False + arm.rigify_layers[21].selset = False arm.rigify_layers[21].group = 0 arm.rigify_layers[22].name = " " arm.rigify_layers[22].row = 1 - arm.rigify_layers[22].set = False + arm.rigify_layers[22].selset = False arm.rigify_layers[22].group = 0 arm.rigify_layers[23].name = " " arm.rigify_layers[23].row = 1 - arm.rigify_layers[23].set = False + arm.rigify_layers[23].selset = False arm.rigify_layers[23].group = 0 arm.rigify_layers[24].name = " " arm.rigify_layers[24].row = 1 - arm.rigify_layers[24].set = False + arm.rigify_layers[24].selset = False arm.rigify_layers[24].group = 0 arm.rigify_layers[25].name = " " arm.rigify_layers[25].row = 1 - arm.rigify_layers[25].set = False + arm.rigify_layers[25].selset = False arm.rigify_layers[25].group = 0 arm.rigify_layers[26].name = " " arm.rigify_layers[26].row = 1 - arm.rigify_layers[26].set = False + arm.rigify_layers[26].selset = False arm.rigify_layers[26].group = 0 arm.rigify_layers[27].name = " " arm.rigify_layers[27].row = 1 - arm.rigify_layers[27].set = False + arm.rigify_layers[27].selset = False arm.rigify_layers[27].group = 0 arm.rigify_layers[28].name = "Root" arm.rigify_layers[28].row = 14 - arm.rigify_layers[28].set = False + arm.rigify_layers[28].selset = False arm.rigify_layers[28].group = 1 bones = {} diff --git a/rigify/metarigs/Animals/wolf.py b/rigify/metarigs/Animals/wolf.py index 20aa121c..4cccf085 100644 --- a/rigify/metarigs/Animals/wolf.py +++ b/rigify/metarigs/Animals/wolf.py @@ -48,119 +48,119 @@ def create(obj): arm.rigify_layers[0].name = "Face" arm.rigify_layers[0].row = 1 - arm.rigify_layers[0].set = False + arm.rigify_layers[0].selset = False arm.rigify_layers[0].group = 5 arm.rigify_layers[1].name = "Face (Primary)" arm.rigify_layers[1].row = 2 - arm.rigify_layers[1].set = False + arm.rigify_layers[1].selset = False arm.rigify_layers[1].group = 2 arm.rigify_layers[2].name = "Face (Secondary)" arm.rigify_layers[2].row = 2 - arm.rigify_layers[2].set = False + arm.rigify_layers[2].selset = False arm.rigify_layers[2].group = 3 arm.rigify_layers[3].name = "Spine" arm.rigify_layers[3].row = 3 - arm.rigify_layers[3].set = False + arm.rigify_layers[3].selset = False arm.rigify_layers[3].group = 3 arm.rigify_layers[4].name = "Spine (Tweak)" arm.rigify_layers[4].row = 4 - arm.rigify_layers[4].set = False + arm.rigify_layers[4].selset = False arm.rigify_layers[4].group = 4 arm.rigify_layers[5].name = "Paws" arm.rigify_layers[5].row = 5 - arm.rigify_layers[5].set = False + arm.rigify_layers[5].selset = False arm.rigify_layers[5].group = 6 arm.rigify_layers[6].name = "Paws (Tweak)" arm.rigify_layers[6].row = 6 - arm.rigify_layers[6].set = False + arm.rigify_layers[6].selset = False arm.rigify_layers[6].group = 4 arm.rigify_layers[7].name = "Arm.L (IK)" arm.rigify_layers[7].row = 7 - arm.rigify_layers[7].set = False + arm.rigify_layers[7].selset = False arm.rigify_layers[7].group = 2 arm.rigify_layers[8].name = "Arm.L (FK)" arm.rigify_layers[8].row = 8 - arm.rigify_layers[8].set = False + arm.rigify_layers[8].selset = False arm.rigify_layers[8].group = 5 arm.rigify_layers[9].name = "Arm.L (Tweak)" arm.rigify_layers[9].row = 9 - arm.rigify_layers[9].set = False + arm.rigify_layers[9].selset = False arm.rigify_layers[9].group = 4 arm.rigify_layers[10].name = "Arm.R (IK)" arm.rigify_layers[10].row = 7 - arm.rigify_layers[10].set = False + arm.rigify_layers[10].selset = False arm.rigify_layers[10].group = 2 arm.rigify_layers[11].name = "Arm.R (FK)" arm.rigify_layers[11].row = 8 - arm.rigify_layers[11].set = False + arm.rigify_layers[11].selset = False arm.rigify_layers[11].group = 5 arm.rigify_layers[12].name = "Arm.R (Tweak)" arm.rigify_layers[12].row = 9 - arm.rigify_layers[12].set = False + arm.rigify_layers[12].selset = False arm.rigify_layers[12].group = 4 arm.rigify_layers[13].name = "Leg.L (IK)" arm.rigify_layers[13].row = 10 - arm.rigify_layers[13].set = False + arm.rigify_layers[13].selset = False arm.rigify_layers[13].group = 2 arm.rigify_layers[14].name = "Leg.L (FK)" arm.rigify_layers[14].row = 11 - arm.rigify_layers[14].set = False + arm.rigify_layers[14].selset = False arm.rigify_layers[14].group = 5 arm.rigify_layers[15].name = "Leg.L (Tweak)" arm.rigify_layers[15].row = 12 - arm.rigify_layers[15].set = False + arm.rigify_layers[15].selset = False arm.rigify_layers[15].group = 4 arm.rigify_layers[16].name = "Leg.R (IK)" arm.rigify_layers[16].row = 10 - arm.rigify_layers[16].set = False + arm.rigify_layers[16].selset = False arm.rigify_layers[16].group = 2 arm.rigify_layers[17].name = "Leg.R (FK)" arm.rigify_layers[17].row = 11 - arm.rigify_layers[17].set = False + arm.rigify_layers[17].selset = False arm.rigify_layers[17].group = 5 arm.rigify_layers[18].name = "Leg.R (Tweak)" arm.rigify_layers[18].row = 12 - arm.rigify_layers[18].set = False + arm.rigify_layers[18].selset = False arm.rigify_layers[18].group = 4 arm.rigify_layers[19].name = "Tail" arm.rigify_layers[19].row = 13 - arm.rigify_layers[19].set = False + arm.rigify_layers[19].selset = False arm.rigify_layers[19].group = 6 arm.rigify_layers[20].name = "" arm.rigify_layers[20].row = 1 - arm.rigify_layers[20].set = False + arm.rigify_layers[20].selset = False arm.rigify_layers[20].group = 0 arm.rigify_layers[21].name = "" arm.rigify_layers[21].row = 13 - arm.rigify_layers[21].set = False + arm.rigify_layers[21].selset = False arm.rigify_layers[21].group = 0 arm.rigify_layers[22].name = "" arm.rigify_layers[22].row = 13 - arm.rigify_layers[22].set = False + arm.rigify_layers[22].selset = False arm.rigify_layers[22].group = 0 arm.rigify_layers[23].name = "" arm.rigify_layers[23].row = 1 - arm.rigify_layers[23].set = False + arm.rigify_layers[23].selset = False arm.rigify_layers[23].group = 0 arm.rigify_layers[24].name = "" arm.rigify_layers[24].row = 1 - arm.rigify_layers[24].set = False + arm.rigify_layers[24].selset = False arm.rigify_layers[24].group = 0 arm.rigify_layers[25].name = "" arm.rigify_layers[25].row = 1 - arm.rigify_layers[25].set = False + arm.rigify_layers[25].selset = False arm.rigify_layers[25].group = 0 arm.rigify_layers[26].name = "" arm.rigify_layers[26].row = 1 - arm.rigify_layers[26].set = False + arm.rigify_layers[26].selset = False arm.rigify_layers[26].group = 0 arm.rigify_layers[27].name = "" arm.rigify_layers[27].row = 1 - arm.rigify_layers[27].set = False + arm.rigify_layers[27].selset = False arm.rigify_layers[27].group = 0 arm.rigify_layers[28].name = "Root" arm.rigify_layers[28].row = 14 - arm.rigify_layers[28].set = False + arm.rigify_layers[28].selset = False arm.rigify_layers[28].group = 1 bones = {} diff --git a/rigify/metarigs/Basic/basic_human.py b/rigify/metarigs/Basic/basic_human.py index 5b1a401d..01367a7b 100644 --- a/rigify/metarigs/Basic/basic_human.py +++ b/rigify/metarigs/Basic/basic_human.py @@ -48,119 +48,119 @@ def create(obj): arm.rigify_layers[0].name = " " arm.rigify_layers[0].row = 1 - arm.rigify_layers[0].set = False + arm.rigify_layers[0].selset = False arm.rigify_layers[0].group = 0 arm.rigify_layers[1].name = " " arm.rigify_layers[1].row = 1 - arm.rigify_layers[1].set = False + arm.rigify_layers[1].selset = False arm.rigify_layers[1].group = 0 arm.rigify_layers[2].name = " " arm.rigify_layers[2].row = 1 - arm.rigify_layers[2].set = False + arm.rigify_layers[2].selset = False arm.rigify_layers[2].group = 0 arm.rigify_layers[3].name = "Torso" arm.rigify_layers[3].row = 3 - arm.rigify_layers[3].set = False + arm.rigify_layers[3].selset = False arm.rigify_layers[3].group = 3 arm.rigify_layers[4].name = "Torso (Tweak)" arm.rigify_layers[4].row = 4 - arm.rigify_layers[4].set = False + arm.rigify_layers[4].selset = False arm.rigify_layers[4].group = 4 arm.rigify_layers[5].name = " " arm.rigify_layers[5].row = 1 - arm.rigify_layers[5].set = False + arm.rigify_layers[5].selset = False arm.rigify_layers[5].group = 0 arm.rigify_layers[6].name = " " arm.rigify_layers[6].row = 1 - arm.rigify_layers[6].set = False + arm.rigify_layers[6].selset = False arm.rigify_layers[6].group = 0 arm.rigify_layers[7].name = "Arm.L (IK)" arm.rigify_layers[7].row = 7 - arm.rigify_layers[7].set = False + arm.rigify_layers[7].selset = False arm.rigify_layers[7].group = 2 arm.rigify_layers[8].name = "Arm.L (FK)" arm.rigify_layers[8].row = 8 - arm.rigify_layers[8].set = False + arm.rigify_layers[8].selset = False arm.rigify_layers[8].group = 5 arm.rigify_layers[9].name = "Arm.L (Tweak)" arm.rigify_layers[9].row = 9 - arm.rigify_layers[9].set = False + arm.rigify_layers[9].selset = False arm.rigify_layers[9].group = 4 arm.rigify_layers[10].name = "Arm.R (IK)" arm.rigify_layers[10].row = 7 - arm.rigify_layers[10].set = False + arm.rigify_layers[10].selset = False arm.rigify_layers[10].group = 2 arm.rigify_layers[11].name = "Arm.R (FK)" arm.rigify_layers[11].row = 8 - arm.rigify_layers[11].set = False + arm.rigify_layers[11].selset = False arm.rigify_layers[11].group = 5 arm.rigify_layers[12].name = "Arm.R (Tweak)" arm.rigify_layers[12].row = 9 - arm.rigify_layers[12].set = False + arm.rigify_layers[12].selset = False arm.rigify_layers[12].group = 4 arm.rigify_layers[13].name = "Leg.L (IK)" arm.rigify_layers[13].row = 10 - arm.rigify_layers[13].set = False + arm.rigify_layers[13].selset = False arm.rigify_layers[13].group = 2 arm.rigify_layers[14].name = "Leg.L (FK)" arm.rigify_layers[14].row = 11 - arm.rigify_layers[14].set = False + arm.rigify_layers[14].selset = False arm.rigify_layers[14].group = 5 arm.rigify_layers[15].name = "Leg.L (Tweak)" arm.rigify_layers[15].row = 12 - arm.rigify_layers[15].set = False + arm.rigify_layers[15].selset = False arm.rigify_layers[15].group = 4 arm.rigify_layers[16].name = "Leg.R (IK)" arm.rigify_layers[16].row = 10 - arm.rigify_layers[16].set = False + arm.rigify_layers[16].selset = False arm.rigify_layers[16].group = 2 arm.rigify_layers[17].name = "Leg.R (FK)" arm.rigify_layers[17].row = 11 - arm.rigify_layers[17].set = False + arm.rigify_layers[17].selset = False arm.rigify_layers[17].group = 5 arm.rigify_layers[18].name = "Leg.R (Tweak)" arm.rigify_layers[18].row = 12 - arm.rigify_layers[18].set = False + arm.rigify_layers[18].selset = False arm.rigify_layers[18].group = 4 arm.rigify_layers[19].name = "" arm.rigify_layers[19].row = 1 - arm.rigify_layers[19].set = False + arm.rigify_layers[19].selset = False arm.rigify_layers[19].group = 0 arm.rigify_layers[20].name = "" arm.rigify_layers[20].row = 1 - arm.rigify_layers[20].set = False + arm.rigify_layers[20].selset = False arm.rigify_layers[20].group = 0 arm.rigify_layers[21].name = "" arm.rigify_layers[21].row = 1 - arm.rigify_layers[21].set = False + arm.rigify_layers[21].selset = False arm.rigify_layers[21].group = 0 arm.rigify_layers[22].name = "" arm.rigify_layers[22].row = 1 - arm.rigify_layers[22].set = False + arm.rigify_layers[22].selset = False arm.rigify_layers[22].group = 0 arm.rigify_layers[23].name = "" arm.rigify_layers[23].row = 1 - arm.rigify_layers[23].set = False + arm.rigify_layers[23].selset = False arm.rigify_layers[23].group = 0 arm.rigify_layers[24].name = "" arm.rigify_layers[24].row = 1 - arm.rigify_layers[24].set = False + arm.rigify_layers[24].selset = False arm.rigify_layers[24].group = 0 arm.rigify_layers[25].name = "" arm.rigify_layers[25].row = 1 - arm.rigify_layers[25].set = False + arm.rigify_layers[25].selset = False arm.rigify_layers[25].group = 0 arm.rigify_layers[26].name = "" arm.rigify_layers[26].row = 1 - arm.rigify_layers[26].set = False + arm.rigify_layers[26].selset = False arm.rigify_layers[26].group = 0 arm.rigify_layers[27].name = "" arm.rigify_layers[27].row = 1 - arm.rigify_layers[27].set = False + arm.rigify_layers[27].selset = False arm.rigify_layers[27].group = 0 arm.rigify_layers[28].name = "Root" arm.rigify_layers[28].row = 14 - arm.rigify_layers[28].set = False + arm.rigify_layers[28].selset = False arm.rigify_layers[28].group = 1 bones = {} diff --git a/rigify/metarigs/Basic/basic_quadruped.py b/rigify/metarigs/Basic/basic_quadruped.py index c46743c7..5aa9f657 100644 --- a/rigify/metarigs/Basic/basic_quadruped.py +++ b/rigify/metarigs/Basic/basic_quadruped.py @@ -48,119 +48,119 @@ def create(obj): arm.rigify_layers[0].name = " " arm.rigify_layers[0].row = 1 - arm.rigify_layers[0].set = False + arm.rigify_layers[0].selset = False arm.rigify_layers[0].group = 0 arm.rigify_layers[1].name = " " arm.rigify_layers[1].row = 2 - arm.rigify_layers[1].set = False + arm.rigify_layers[1].selset = False arm.rigify_layers[1].group = 0 arm.rigify_layers[2].name = " " arm.rigify_layers[2].row = 2 - arm.rigify_layers[2].set = False + arm.rigify_layers[2].selset = False arm.rigify_layers[2].group = 0 arm.rigify_layers[3].name = "Spine" arm.rigify_layers[3].row = 3 - arm.rigify_layers[3].set = False + arm.rigify_layers[3].selset = False arm.rigify_layers[3].group = 3 arm.rigify_layers[4].name = "Spine (Tweak)" arm.rigify_layers[4].row = 4 - arm.rigify_layers[4].set = False + arm.rigify_layers[4].selset = False arm.rigify_layers[4].group = 4 arm.rigify_layers[5].name = " " arm.rigify_layers[5].row = 5 - arm.rigify_layers[5].set = False + arm.rigify_layers[5].selset = False arm.rigify_layers[5].group = 0 arm.rigify_layers[6].name = " " arm.rigify_layers[6].row = 6 - arm.rigify_layers[6].set = False + arm.rigify_layers[6].selset = False arm.rigify_layers[6].group = 0 arm.rigify_layers[7].name = "Arm.L (IK)" arm.rigify_layers[7].row = 7 - arm.rigify_layers[7].set = False + arm.rigify_layers[7].selset = False arm.rigify_layers[7].group = 2 arm.rigify_layers[8].name = "Arm.L (FK)" arm.rigify_layers[8].row = 8 - arm.rigify_layers[8].set = False + arm.rigify_layers[8].selset = False arm.rigify_layers[8].group = 5 arm.rigify_layers[9].name = "Arm.L (Tweak)" arm.rigify_layers[9].row = 9 - arm.rigify_layers[9].set = False + arm.rigify_layers[9].selset = False arm.rigify_layers[9].group = 4 arm.rigify_layers[10].name = "Arm.R (IK)" arm.rigify_layers[10].row = 7 - arm.rigify_layers[10].set = False + arm.rigify_layers[10].selset = False arm.rigify_layers[10].group = 2 arm.rigify_layers[11].name = "Arm.R (FK)" arm.rigify_layers[11].row = 8 - arm.rigify_layers[11].set = False + arm.rigify_layers[11].selset = False arm.rigify_layers[11].group = 5 arm.rigify_layers[12].name = "Arm.R (Tweak)" arm.rigify_layers[12].row = 9 - arm.rigify_layers[12].set = False + arm.rigify_layers[12].selset = False arm.rigify_layers[12].group = 4 arm.rigify_layers[13].name = "Leg.L (IK)" arm.rigify_layers[13].row = 10 - arm.rigify_layers[13].set = False + arm.rigify_layers[13].selset = False arm.rigify_layers[13].group = 2 arm.rigify_layers[14].name = "Leg.L (FK)" arm.rigify_layers[14].row = 11 - arm.rigify_layers[14].set = False + arm.rigify_layers[14].selset = False arm.rigify_layers[14].group = 5 arm.rigify_layers[15].name = "Leg.L (Tweak)" arm.rigify_layers[15].row = 12 - arm.rigify_layers[15].set = False + arm.rigify_layers[15].selset = False arm.rigify_layers[15].group = 4 arm.rigify_layers[16].name = "Leg.R (IK)" arm.rigify_layers[16].row = 10 - arm.rigify_layers[16].set = False + arm.rigify_layers[16].selset = False arm.rigify_layers[16].group = 2 arm.rigify_layers[17].name = "Leg.R (FK)" arm.rigify_layers[17].row = 11 - arm.rigify_layers[17].set = False + arm.rigify_layers[17].selset = False arm.rigify_layers[17].group = 5 arm.rigify_layers[18].name = "Leg.R (Tweak)" arm.rigify_layers[18].row = 12 - arm.rigify_layers[18].set = False + arm.rigify_layers[18].selset = False arm.rigify_layers[18].group = 4 arm.rigify_layers[19].name = "Tail" arm.rigify_layers[19].row = 13 - arm.rigify_layers[19].set = False + arm.rigify_layers[19].selset = False arm.rigify_layers[19].group = 6 arm.rigify_layers[20].name = "" arm.rigify_layers[20].row = 1 - arm.rigify_layers[20].set = False + arm.rigify_layers[20].selset = False arm.rigify_layers[20].group = 0 arm.rigify_layers[21].name = "" arm.rigify_layers[21].row = 13 - arm.rigify_layers[21].set = False + arm.rigify_layers[21].selset = False arm.rigify_layers[21].group = 0 arm.rigify_layers[22].name = "" arm.rigify_layers[22].row = 13 - arm.rigify_layers[22].set = False + arm.rigify_layers[22].selset = False arm.rigify_layers[22].group = 0 arm.rigify_layers[23].name = "" arm.rigify_layers[23].row = 1 - arm.rigify_layers[23].set = False + arm.rigify_layers[23].selset = False arm.rigify_layers[23].group = 0 arm.rigify_layers[24].name = "" arm.rigify_layers[24].row = 1 - arm.rigify_layers[24].set = False + arm.rigify_layers[24].selset = False arm.rigify_layers[24].group = 0 arm.rigify_layers[25].name = "" arm.rigify_layers[25].row = 1 - arm.rigify_layers[25].set = False + arm.rigify_layers[25].selset = False arm.rigify_layers[25].group = 0 arm.rigify_layers[26].name = "" arm.rigify_layers[26].row = 1 - arm.rigify_layers[26].set = False + arm.rigify_layers[26].selset = False arm.rigify_layers[26].group = 0 arm.rigify_layers[27].name = "" arm.rigify_layers[27].row = 1 - arm.rigify_layers[27].set = False + arm.rigify_layers[27].selset = False arm.rigify_layers[27].group = 0 arm.rigify_layers[28].name = "Root" arm.rigify_layers[28].row = 14 - arm.rigify_layers[28].set = False + arm.rigify_layers[28].selset = False arm.rigify_layers[28].group = 1 bones = {} diff --git a/rigify/metarigs/human.py b/rigify/metarigs/human.py index a31a107c..bbba8eed 100644 --- a/rigify/metarigs/human.py +++ b/rigify/metarigs/human.py @@ -48,119 +48,119 @@ def create(obj): arm.rigify_layers[0].name = "Face" arm.rigify_layers[0].row = 1 - arm.rigify_layers[0].set = False + arm.rigify_layers[0].selset = False arm.rigify_layers[0].group = 5 arm.rigify_layers[1].name = "Face (Primary)" arm.rigify_layers[1].row = 2 - arm.rigify_layers[1].set = False + arm.rigify_layers[1].selset = False arm.rigify_layers[1].group = 2 arm.rigify_layers[2].name = "Face (Secondary)" arm.rigify_layers[2].row = 2 - arm.rigify_layers[2].set = False + arm.rigify_layers[2].selset = False arm.rigify_layers[2].group = 3 arm.rigify_layers[3].name = "Torso" arm.rigify_layers[3].row = 3 - arm.rigify_layers[3].set = False + arm.rigify_layers[3].selset = False arm.rigify_layers[3].group = 3 arm.rigify_layers[4].name = "Torso (Tweak)" arm.rigify_layers[4].row = 4 - arm.rigify_layers[4].set = False + arm.rigify_layers[4].selset = False arm.rigify_layers[4].group = 4 arm.rigify_layers[5].name = "Fingers" arm.rigify_layers[5].row = 5 - arm.rigify_layers[5].set = False + arm.rigify_layers[5].selset = False arm.rigify_layers[5].group = 6 arm.rigify_layers[6].name = "Fingers (Tweak)" arm.rigify_layers[6].row = 6 - arm.rigify_layers[6].set = False + arm.rigify_layers[6].selset = False arm.rigify_layers[6].group = 4 arm.rigify_layers[7].name = "Arm.L (IK)" arm.rigify_layers[7].row = 7 - arm.rigify_layers[7].set = False + arm.rigify_layers[7].selset = False arm.rigify_layers[7].group = 2 arm.rigify_layers[8].name = "Arm.L (FK)" arm.rigify_layers[8].row = 8 - arm.rigify_layers[8].set = False + arm.rigify_layers[8].selset = False arm.rigify_layers[8].group = 5 arm.rigify_layers[9].name = "Arm.L (Tweak)" arm.rigify_layers[9].row = 9 - arm.rigify_layers[9].set = False + arm.rigify_layers[9].selset = False arm.rigify_layers[9].group = 4 arm.rigify_layers[10].name = "Arm.R (IK)" arm.rigify_layers[10].row = 7 - arm.rigify_layers[10].set = False + arm.rigify_layers[10].selset = False arm.rigify_layers[10].group = 2 arm.rigify_layers[11].name = "Arm.R (FK)" arm.rigify_layers[11].row = 8 - arm.rigify_layers[11].set = False + arm.rigify_layers[11].selset = False arm.rigify_layers[11].group = 5 arm.rigify_layers[12].name = "Arm.R (Tweak)" arm.rigify_layers[12].row = 9 - arm.rigify_layers[12].set = False + arm.rigify_layers[12].selset = False arm.rigify_layers[12].group = 4 arm.rigify_layers[13].name = "Leg.L (IK)" arm.rigify_layers[13].row = 10 - arm.rigify_layers[13].set = False + arm.rigify_layers[13].selset = False arm.rigify_layers[13].group = 2 arm.rigify_layers[14].name = "Leg.L (FK)" arm.rigify_layers[14].row = 11 - arm.rigify_layers[14].set = False + arm.rigify_layers[14].selset = False arm.rigify_layers[14].group = 5 arm.rigify_layers[15].name = "Leg.L (Tweak)" arm.rigify_layers[15].row = 12 - arm.rigify_layers[15].set = False + arm.rigify_layers[15].selset = False arm.rigify_layers[15].group = 4 arm.rigify_layers[16].name = "Leg.R (IK)" arm.rigify_layers[16].row = 10 - arm.rigify_layers[16].set = False + arm.rigify_layers[16].selset = False arm.rigify_layers[16].group = 2 arm.rigify_layers[17].name = "Leg.R (FK)" arm.rigify_layers[17].row = 11 - arm.rigify_layers[17].set = False + arm.rigify_layers[17].selset = False arm.rigify_layers[17].group = 5 arm.rigify_layers[18].name = "Leg.R (Tweak)" arm.rigify_layers[18].row = 12 - arm.rigify_layers[18].set = False + arm.rigify_layers[18].selset = False arm.rigify_layers[18].group = 4 arm.rigify_layers[19].name = "" arm.rigify_layers[19].row = 1 - arm.rigify_layers[19].set = False + arm.rigify_layers[19].selset = False arm.rigify_layers[19].group = 0 arm.rigify_layers[20].name = "" arm.rigify_layers[20].row = 1 - arm.rigify_layers[20].set = False + arm.rigify_layers[20].selset = False arm.rigify_layers[20].group = 0 arm.rigify_layers[21].name = "" arm.rigify_layers[21].row = 1 - arm.rigify_layers[21].set = False + arm.rigify_layers[21].selset = False arm.rigify_layers[21].group = 0 arm.rigify_layers[22].name = "" arm.rigify_layers[22].row = 1 - arm.rigify_layers[22].set = False + arm.rigify_layers[22].selset = False arm.rigify_layers[22].group = 0 arm.rigify_layers[23].name = "" arm.rigify_layers[23].row = 1 - arm.rigify_layers[23].set = False + arm.rigify_layers[23].selset = False arm.rigify_layers[23].group = 0 arm.rigify_layers[24].name = "" arm.rigify_layers[24].row = 1 - arm.rigify_layers[24].set = False + arm.rigify_layers[24].selset = False arm.rigify_layers[24].group = 0 arm.rigify_layers[25].name = "" arm.rigify_layers[25].row = 1 - arm.rigify_layers[25].set = False + arm.rigify_layers[25].selset = False arm.rigify_layers[25].group = 0 arm.rigify_layers[26].name = "" arm.rigify_layers[26].row = 1 - arm.rigify_layers[26].set = False + arm.rigify_layers[26].selset = False arm.rigify_layers[26].group = 0 arm.rigify_layers[27].name = "" arm.rigify_layers[27].row = 1 - arm.rigify_layers[27].set = False + arm.rigify_layers[27].selset = False arm.rigify_layers[27].group = 0 arm.rigify_layers[28].name = "Root" arm.rigify_layers[28].row = 14 - arm.rigify_layers[28].set = False + arm.rigify_layers[28].selset = False arm.rigify_layers[28].group = 1 bones = {} diff --git a/rigify/rig_ui_template.py b/rigify/rig_ui_template.py index 3cdda311..8031ff3b 100644 --- a/rigify/rig_ui_template.py +++ b/rigify/rig_ui_template.py @@ -20,6 +20,7 @@ UI_SLIDERS = ''' import bpy +from bpy.props import StringProperty from mathutils import Matrix, Vector from math import acos, pi, radians @@ -135,11 +136,11 @@ def get_pose_matrix_in_other_space(mat, pose_bone): par_rest = Matrix() # Get matrix in bone's current transform space - smat = rest_inv * (par_rest * (par_inv * mat)) + smat = rest_inv @ (par_rest @ (par_inv @ mat)) # Compensate for non-local location #if not pose_bone.bone.use_local_location: - # loc = smat.to_translation() * (par_rest.inverted() * rest).to_quaternion() + # loc = smat.to_translation() @ (par_rest.inverted() @ rest).to_quaternion() # smat.translation = loc return smat @@ -166,8 +167,8 @@ def set_pose_translation(pose_bone, mat): else: par_rest = Matrix() - q = (par_rest.inverted() * rest).to_quaternion() - pose_bone.location = q * loc + q = (par_rest.inverted() @ rest).to_quaternion() + pose_bone.location = q @ loc def set_pose_rotation(pose_bone, mat): @@ -283,11 +284,11 @@ def match_pole_target(ik_first, ik_last, pole, match_bone, length): angle = rotation_difference(ik_first.matrix, match_bone.matrix) # Try compensating for the rotation difference in both directions - pv1 = Matrix.Rotation(angle, 4, ikv) * pv + pv1 = Matrix.Rotation(angle, 4, ikv) @ pv set_pole(pv1) ang1 = rotation_difference(ik_first.matrix, match_bone.matrix) - pv2 = Matrix.Rotation(-angle, 4, ikv) * pv + pv2 = Matrix.Rotation(-angle, 4, ikv) @ pv set_pole(pv2) ang2 = rotation_difference(ik_first.matrix, match_bone.matrix) @@ -424,8 +425,8 @@ def fk2ik_leg(obj, fk, ik): match_pose_scale(shin, shini) # Foot position - mat = mfoot.bone.matrix_local.inverted() * foot.bone.matrix_local - footmat = get_pose_matrix_in_other_space(mfooti.matrix, foot) * mat + mat = mfoot.bone.matrix_local.inverted() @ foot.bone.matrix_local + footmat = get_pose_matrix_in_other_space(mfooti.matrix, foot) @ mat set_pose_rotation(foot, footmat) set_pose_scale(foot, footmat) bpy.ops.object.mode_set(mode='OBJECT') @@ -442,8 +443,8 @@ def fk2ik_leg(obj, fk, ik): match_pose_scale(shin, shini) # Foot position - mat = mfoot.bone.matrix_local.inverted() * foot.bone.matrix_local - footmat = get_pose_matrix_in_other_space(mfooti.matrix, foot) * mat + mat = mfoot.bone.matrix_local.inverted() @ foot.bone.matrix_local + footmat = get_pose_matrix_in_other_space(mfooti.matrix, foot) @ mat set_pose_rotation(foot, footmat) set_pose_scale(foot, footmat) bpy.ops.object.mode_set(mode='OBJECT') @@ -482,8 +483,8 @@ def ik2fk_leg(obj, fk, ik): set_pose_rotation(footroll, Matrix()) # Foot position - mat = mfooti.bone.matrix_local.inverted() * footi.bone.matrix_local - footmat = get_pose_matrix_in_other_space(foot.matrix, footi) * mat + mat = mfooti.bone.matrix_local.inverted() @ footi.bone.matrix_local + footmat = get_pose_matrix_in_other_space(foot.matrix, footi) @ mat set_pose_translation(footi, footmat) set_pose_rotation(footi, footmat) set_pose_scale(footi, footmat) @@ -508,8 +509,8 @@ def ik2fk_leg(obj, fk, ik): set_pose_rotation(footroll, Matrix()) # Foot position - mat = mfooti.bone.matrix_local.inverted() * footi.bone.matrix_local - footmat = get_pose_matrix_in_other_space(mfoot.matrix, footi) * mat + mat = mfooti.bone.matrix_local.inverted() @ footi.bone.matrix_local + footmat = get_pose_matrix_in_other_space(mfoot.matrix, footi) @ mat set_pose_translation(footi, footmat) set_pose_rotation(footi, footmat) set_pose_scale(footi, footmat) @@ -600,13 +601,13 @@ class Rigify_Arm_FK2IK(bpy.types.Operator): bl_label = "Rigify Snap FK arm to IK" bl_options = {'UNDO'} - uarm_fk = bpy.props.StringProperty(name="Upper Arm FK Name") - farm_fk = bpy.props.StringProperty(name="Forerm FK Name") - hand_fk = bpy.props.StringProperty(name="Hand FK Name") + uarm_fk: StringProperty(name="Upper Arm FK Name") + farm_fk: StringProperty(name="Forerm FK Name") + hand_fk: StringProperty(name="Hand FK Name") - uarm_ik = bpy.props.StringProperty(name="Upper Arm IK Name") - farm_ik = bpy.props.StringProperty(name="Forearm IK Name") - hand_ik = bpy.props.StringProperty(name="Hand IK Name") + uarm_ik: StringProperty(name="Upper Arm IK Name") + farm_ik: StringProperty(name="Forearm IK Name") + hand_ik: StringProperty(name="Hand IK Name") @classmethod def poll(cls, context): @@ -629,16 +630,16 @@ class Rigify_Arm_IK2FK(bpy.types.Operator): bl_label = "Rigify Snap IK arm to FK" bl_options = {'UNDO'} - uarm_fk = bpy.props.StringProperty(name="Upper Arm FK Name") - farm_fk = bpy.props.StringProperty(name="Forerm FK Name") - hand_fk = bpy.props.StringProperty(name="Hand FK Name") + uarm_fk: StringProperty(name="Upper Arm FK Name") + farm_fk: StringProperty(name="Forerm FK Name") + hand_fk: StringProperty(name="Hand FK Name") - uarm_ik = bpy.props.StringProperty(name="Upper Arm IK Name") - farm_ik = bpy.props.StringProperty(name="Forearm IK Name") - hand_ik = bpy.props.StringProperty(name="Hand IK Name") - pole = bpy.props.StringProperty(name="Pole IK Name") + uarm_ik: StringProperty(name="Upper Arm IK Name") + farm_ik: StringProperty(name="Forearm IK Name") + hand_ik: StringProperty(name="Hand IK Name") + pole : StringProperty(name="Pole IK Name") - main_parent = bpy.props.StringProperty(name="Main Parent", default="") + main_parent: StringProperty(name="Main Parent", default="") @classmethod def poll(cls, context): @@ -661,15 +662,15 @@ class Rigify_Leg_FK2IK(bpy.types.Operator): bl_label = "Rigify Snap FK leg to IK" bl_options = {'UNDO'} - thigh_fk = bpy.props.StringProperty(name="Thigh FK Name") - shin_fk = bpy.props.StringProperty(name="Shin FK Name") - foot_fk = bpy.props.StringProperty(name="Foot FK Name") - mfoot_fk = bpy.props.StringProperty(name="MFoot FK Name") + thigh_fk: StringProperty(name="Thigh FK Name") + shin_fk: StringProperty(name="Shin FK Name") + foot_fk: StringProperty(name="Foot FK Name") + mfoot_fk: StringProperty(name="MFoot FK Name") - thigh_ik = bpy.props.StringProperty(name="Thigh IK Name") - shin_ik = bpy.props.StringProperty(name="Shin IK Name") - foot_ik = bpy.props.StringProperty(name="Foot IK Name") - mfoot_ik = bpy.props.StringProperty(name="MFoot IK Name") + thigh_ik: StringProperty(name="Thigh IK Name") + shin_ik: StringProperty(name="Shin IK Name") + foot_ik: StringProperty(name="Foot IK Name") + mfoot_ik: StringProperty(name="MFoot IK Name") @classmethod def poll(cls, context): @@ -692,18 +693,18 @@ class Rigify_Leg_IK2FK(bpy.types.Operator): bl_label = "Rigify Snap IK leg to FK" bl_options = {'UNDO'} - thigh_fk = bpy.props.StringProperty(name="Thigh FK Name") - shin_fk = bpy.props.StringProperty(name="Shin FK Name") - mfoot_fk = bpy.props.StringProperty(name="MFoot FK Name") - foot_fk = bpy.props.StringProperty(name="Foot FK Name", default="") - thigh_ik = bpy.props.StringProperty(name="Thigh IK Name") - shin_ik = bpy.props.StringProperty(name="Shin IK Name") - foot_ik = bpy.props.StringProperty(name="Foot IK Name") - footroll = bpy.props.StringProperty(name="Foot Roll Name") - pole = bpy.props.StringProperty(name="Pole IK Name") - mfoot_ik = bpy.props.StringProperty(name="MFoot IK Name") + thigh_fk: StringProperty(name="Thigh FK Name") + shin_fk: StringProperty(name="Shin FK Name") + mfoot_fk: StringProperty(name="MFoot FK Name") + foot_fk: StringProperty(name="Foot FK Name", default="") + thigh_ik: StringProperty(name="Thigh IK Name") + shin_ik: StringProperty(name="Shin IK Name") + foot_ik: StringProperty(name="Foot IK Name") + footroll: StringProperty(name="Foot Roll Name") + pole: StringProperty(name="Pole IK Name") + mfoot_ik: StringProperty(name="MFoot IK Name") - main_parent = bpy.props.StringProperty(name="Main Parent", default="") + main_parent: StringProperty(name="Main Parent", default="") @classmethod def poll(cls, context): @@ -726,13 +727,14 @@ class Rigify_Rot2PoleSwitch(bpy.types.Operator): bl_idname = "pose.rigify_rot2pole_" + rig_id bl_label = "Rotation - Pole toggle" bl_description = "Toggles IK chain between rotation and pole target" - bone_name = bpy.props.StringProperty(default='') - limb_type = bpy.props.StringProperty(name="Limb Type") - controls = bpy.props.StringProperty(name="Controls string") - ik_ctrl = bpy.props.StringProperty(name="IK Controls string") - fk_ctrl = bpy.props.StringProperty(name="FK Controls string") - parent = bpy.props.StringProperty(name="Parent name") - pole = bpy.props.StringProperty(name="Pole name") + + bone_name: StringProperty(default='') + limb_type: StringProperty(name="Limb Type") + controls: StringProperty(name="Controls string") + ik_ctrl: StringProperty(name="IK Controls string") + fk_ctrl: StringProperty(name="FK Controls string") + parent: StringProperty(name="Parent name") + pole: StringProperty(name="Pole name") def execute(self, context): rig = context.object @@ -841,23 +843,26 @@ class RigLayers(bpy.types.Panel): UI_REGISTER = ''' +classes = ( + Rigify_Arm_FK2IK, + Rigify_Arm_IK2FK, + Rigify_Leg_FK2IK, + Rigify_Leg_IK2FK, + Rigify_Rot2PoleSwitch, + RigUI, + RigLayers, +) + def register(): - bpy.utils.register_class(Rigify_Arm_FK2IK) - bpy.utils.register_class(Rigify_Arm_IK2FK) - bpy.utils.register_class(Rigify_Leg_FK2IK) - bpy.utils.register_class(Rigify_Leg_IK2FK) - bpy.utils.register_class(Rigify_Rot2PoleSwitch) - bpy.utils.register_class(RigUI) - bpy.utils.register_class(RigLayers) + from bpy.utils import register_class + for cls in classes: + register_class(cls) + def unregister(): - bpy.utils.unregister_class(Rigify_Arm_FK2IK) - bpy.utils.unregister_class(Rigify_Arm_IK2FK) - bpy.utils.unregister_class(Rigify_Leg_FK2IK) - bpy.utils.unregister_class(Rigify_Leg_IK2FK) - bpy.utils.register_class(Rigify_Rot2PoleSwitch) - bpy.utils.unregister_class(RigUI) - bpy.utils.unregister_class(RigLayers) + from bpy.utils import unregister_class + for cls in classes: + unregister_class(cls) register() ''' diff --git a/rigify/rigs/experimental/super_chain.py b/rigify/rigs/experimental/super_chain.py index 408bce3f..2b2c472b 100644 --- a/rigify/rigs/experimental/super_chain.py +++ b/rigify/rigs/experimental/super_chain.py @@ -115,11 +115,11 @@ class Rig: setattr(v,axis,scale) if reverse: - tail_vec = v * self.obj.matrix_world + tail_vec = v @ self.obj.matrix_world eb.head[:] = eb.tail eb.tail[:] = eb.head + tail_vec else: - tail_vec = v * self.obj.matrix_world + tail_vec = v @ self.obj.matrix_world eb.tail[:] = eb.head + tail_vec def create_pivot(self, bones=None, pivot=None): diff --git a/rigify/rigs/limbs/limb_utils.py b/rigify/rigs/limbs/limb_utils.py index 80588516..609da256 100644 --- a/rigify/rigs/limbs/limb_utils.py +++ b/rigify/rigs/limbs/limb_utils.py @@ -11,11 +11,11 @@ def orient_bone( cls, eb, axis, scale = 1.0, reverse = False ): setattr(v,axis,scale) if reverse: - tail_vec = v * cls.obj.matrix_world + tail_vec = v @ cls.obj.matrix_world eb.head[:] = eb.tail eb.tail[:] = eb.head + tail_vec else: - tail_vec = v * cls.obj.matrix_world + tail_vec = v @ cls.obj.matrix_world eb.tail[:] = eb.head + tail_vec eb.roll = 0.0 diff --git a/rigify/rigs/spines/super_spine.py b/rigify/rigs/spines/super_spine.py index 115d0450..6d28de69 100644 --- a/rigify/rigs/spines/super_spine.py +++ b/rigify/rigs/spines/super_spine.py @@ -123,11 +123,11 @@ class Rig: setattr(v, axis, scale) if reverse: - tail_vec = v * self.obj.matrix_world + tail_vec = v @ self.obj.matrix_world eb.head[:] = eb.tail eb.tail[:] = eb.head + tail_vec else: - tail_vec = v * self.obj.matrix_world + tail_vec = v @ self.obj.matrix_world eb.tail[:] = eb.head + tail_vec def create_pivot(self, pivot): diff --git a/rigify/rigs/widgets.py b/rigify/rigs/widgets.py index 8461d82a..aebe7139 100644 --- a/rigify/rigs/widgets.py +++ b/rigify/rigs/widgets.py @@ -4,7 +4,6 @@ import importlib from mathutils import Matrix from ..utils import create_widget -WGT_LAYERS = [x == 19 for x in range(0, 20)] # Widgets go on the last scene layer. MODULE_NAME = "super_widgets" # Windows/Mac blender is weird, so __package__ doesn't work diff --git a/rigify/rot_mode.py b/rigify/rot_mode.py index e30e28d1..9abfecea 100644 --- a/rigify/rot_mode.py +++ b/rigify/rot_mode.py @@ -38,8 +38,10 @@ blender.stackexchange.com/questions/40711/how-to-convert-quaternions-keyframes-t # "category": "Animation"} import bpy - -order_list = ['QUATERNION', 'XYZ', 'XZY', 'YXZ', 'YZX', 'ZXY', 'ZYX'] +from bpy.props import ( + BoolProperty, + EnumProperty, +) class convert(): @@ -219,32 +221,10 @@ class convert(): convert = convert() -# def initSceneProperties(scn): -# -# bpy.types.Scene.order_list = bpy.props.EnumProperty( -# items = [('QUATERNION', 'QUATERNION', 'QUATERNION' ), -# ('XYZ', 'XYZ', 'XYZ' ), -# ('XZY', 'XZY', 'XZY' ), -# ('YXZ', 'YXZ', 'YXZ' ), -# ('YZX', 'YZX', 'YZX' ), -# ('ZXY', 'ZXY', 'ZXY' ), -# ('ZYX', 'ZYX', 'ZYX' ) ], -# name = "Order", -# description = "The target rotation mode") -# -# scn['order_list'] = 0 -# -# return -# -# initSceneProperties(bpy.context.scene) - - -# GUI (Panel) -# class ToolsPanel(bpy.types.Panel): bl_space_type = 'VIEW_3D' - bl_region_type = 'TOOLS' - bl_category = "Tools" + bl_region_type = 'UI' + bl_category = 'View' bl_context = "posemode" bl_label = 'Rigify Quat/Euler Converter' @@ -290,7 +270,7 @@ class CONVERT_OT_quat2eu_current_action(bpy.types.Operator): obj = bpy.context.active_object pose_bones = bpy.context.selected_pose_bones action = obj.animation_data.action - order = order_list[bpy.context.scene['order_list']] + order = bpy.context.scene.order_list id_store = context.window_manager if id_store.rigify_convert_only_selected: @@ -315,7 +295,7 @@ class CONVERT_OT_quat2eu_all_actions(bpy.types.Operator): def execute(op, context): obj = bpy.context.active_object pose_bones = bpy.context.selected_pose_bones - order = order_list[bpy.context.scene['order_list']] + order = bpy.context.scene.order_list id_store = context.window_manager if id_store.rigify_convert_only_selected: @@ -326,9 +306,19 @@ class CONVERT_OT_quat2eu_all_actions(bpy.types.Operator): return {'FINISHED'} +### Registering ### + +classes = ( + ToolsPanel, + CONVERT_OT_quat2eu_current_action, + CONVERT_OT_quat2eu_all_actions, +) + + def register(): - IDStore = bpy.types.WindowManager + from bpy.utils import register_class + # Properties. items = [('QUATERNION', 'QUATERNION', 'QUATERNION'), ('XYZ', 'XYZ', 'XYZ'), ('XZY', 'XZY', 'XZY'), @@ -336,24 +326,27 @@ def register(): ('YZX', 'YZX', 'YZX'), ('ZXY', 'ZXY', 'ZXY'), ('ZYX', 'ZYX', 'ZYX')] + bpy.types.Scene.order_list = EnumProperty( + items=items, name='Convert to', + description="The target rotation mode", default='QUATERNION') - bpy.types.Scene.order_list = bpy.props.EnumProperty(items=items, name='Convert to', - description="The target rotation mode", default='QUATERNION') + IDStore = bpy.types.WindowManager + IDStore.rigify_convert_only_selected = BoolProperty( + name="Convert Only Selected", + description="Convert selected bones only", default=True) - IDStore.rigify_convert_only_selected = bpy.props.BoolProperty( - name="Convert Only Selected", description="Convert selected bones only", default=True) + # Classes. + for cls in classes: + register_class(cls) - bpy.utils.register_class(ToolsPanel) - bpy.utils.register_class(CONVERT_OT_quat2eu_current_action) - bpy.utils.register_class(CONVERT_OT_quat2eu_all_actions) def unregister(): - IDStore = bpy.types.WindowManager + from bpy.utils import unregister_class - bpy.utils.unregister_class(ToolsPanel) - bpy.utils.unregister_class(CONVERT_OT_quat2eu_current_action) - bpy.utils.unregister_class(CONVERT_OT_quat2eu_all_actions) + # Classes. + for cls in classes: + unregister_class(cls) + # Properties. + IDStore = bpy.types.WindowManager del IDStore.rigify_convert_only_selected - -# bpy.utils.register_module(__name__) diff --git a/rigify/ui.py b/rigify/ui.py index 76b1fd23..77398ff0 100644 --- a/rigify/ui.py +++ b/rigify/ui.py @@ -19,7 +19,13 @@ # <pep8 compliant> import bpy -from bpy.props import StringProperty +from bpy.props import ( + BoolProperty, + IntProperty, + EnumProperty, + StringProperty +) + from mathutils import Color from .utils import get_rig_type, MetarigError @@ -89,7 +95,7 @@ class DATA_PT_rigify_buttons(bpy.types.Panel): if show_update_metarig: layout.label(text="This metarig contains old rig-types that can be automatically upgraded to benefit of rigify's new features.", icon='ERROR') - layout.label(text= "To use it as-is you need to enable legacy mode.",) + layout.label(text="To use it as-is you need to enable legacy mode.",) layout.operator("pose.rigify_upgrade_types", text="Upgrade Metarig") row = layout.row() @@ -111,7 +117,7 @@ class DATA_PT_rigify_buttons(bpy.types.Panel): row = col.row(align=True) row.prop(id_store, "rigify_generate_mode", expand=True) - main_row = col.row(align=True).split(percentage=0.3) + main_row = col.row(align=True).split(factor=0.3) col1 = main_row.column() col2 = main_row.column() col1.label(text="Rig Name") @@ -208,14 +214,14 @@ class DATA_PT_rigify_layer_names(bpy.types.Panel): return # UI - main_row = layout.row(align=True).split(0.05) + main_row = layout.row(align=True).split(factor=0.05) col1 = main_row.column() col2 = main_row.column() col1.label() for i in range(32): if i == 16 or i == 29: col1.label() - col1.label(str(i+1) + '.') + col1.label(text=str(i+1) + '.') for i, rigify_layer in enumerate(arm.rigify_layers): # note: rigify_layer == arm.rigify_layers[i] @@ -234,8 +240,8 @@ class DATA_PT_rigify_layer_names(bpy.types.Panel): #row.prop(arm, "layers", index=i, text="Layer %d" % (i + 1), toggle=True, icon=icon) row.prop(rigify_layer, "name", text="") row.prop(rigify_layer, "row", text="UI Row") - icon = 'RADIOBUT_ON' if rigify_layer.set else 'RADIOBUT_OFF' - row.prop(rigify_layer, "set", text="", toggle=True, icon=icon) + icon = 'RADIOBUT_ON' if rigify_layer.selset else 'RADIOBUT_OFF' + row.prop(rigify_layer, "selset", text="", toggle=True, icon=icon) row.prop(rigify_layer, "group", text="Bone Group") else: row = col.row(align=True) @@ -247,8 +253,8 @@ class DATA_PT_rigify_layer_names(bpy.types.Panel): row1.prop(rigify_layer, "name", text="") row1.prop(rigify_layer, "row", text="UI Row") row1.enabled = False - icon = 'RADIOBUT_ON' if rigify_layer.set else 'RADIOBUT_OFF' - row.prop(rigify_layer, "set", text="", toggle=True, icon=icon) + icon = 'RADIOBUT_ON' if rigify_layer.selset else 'RADIOBUT_OFF' + row.prop(rigify_layer, "selset", text="", toggle=True, icon=icon) row.prop(rigify_layer, "group", text="Bone Group") if rigify_layer.group == 0: row.label(text='None') @@ -395,28 +401,29 @@ class DATA_OT_rigify_bone_group_add_theme(bpy.types.Operator): bl_label = "Rigify Add Bone Group color set from Theme" bl_options = {"REGISTER", "UNDO"} - theme = bpy.props.EnumProperty(items=(('THEME01', 'THEME01', ''), - ('THEME02', 'THEME02', ''), - ('THEME03', 'THEME03', ''), - ('THEME04', 'THEME04', ''), - ('THEME05', 'THEME05', ''), - ('THEME06', 'THEME06', ''), - ('THEME07', 'THEME07', ''), - ('THEME08', 'THEME08', ''), - ('THEME09', 'THEME09', ''), - ('THEME10', 'THEME10', ''), - ('THEME11', 'THEME11', ''), - ('THEME12', 'THEME12', ''), - ('THEME13', 'THEME13', ''), - ('THEME14', 'THEME14', ''), - ('THEME15', 'THEME15', ''), - ('THEME16', 'THEME16', ''), - ('THEME17', 'THEME17', ''), - ('THEME18', 'THEME18', ''), - ('THEME19', 'THEME19', ''), - ('THEME20', 'THEME20', '') - ), - name='Theme') + theme: EnumProperty(items=( + ('THEME01', 'THEME01', ''), + ('THEME02', 'THEME02', ''), + ('THEME03', 'THEME03', ''), + ('THEME04', 'THEME04', ''), + ('THEME05', 'THEME05', ''), + ('THEME06', 'THEME06', ''), + ('THEME07', 'THEME07', ''), + ('THEME08', 'THEME08', ''), + ('THEME09', 'THEME09', ''), + ('THEME10', 'THEME10', ''), + ('THEME11', 'THEME11', ''), + ('THEME12', 'THEME12', ''), + ('THEME13', 'THEME13', ''), + ('THEME14', 'THEME14', ''), + ('THEME15', 'THEME15', ''), + ('THEME16', 'THEME16', ''), + ('THEME17', 'THEME17', ''), + ('THEME18', 'THEME18', ''), + ('THEME19', 'THEME19', ''), + ('THEME20', 'THEME20', '') + ), + name='Theme') @classmethod def poll(cls, context): @@ -448,7 +455,7 @@ class DATA_OT_rigify_bone_group_remove(bpy.types.Operator): bl_idname = "armature.rigify_bone_group_remove" bl_label = "Rigify Remove Bone Group color set" - idx = bpy.props.IntProperty() + idx: IntProperty() @classmethod def poll(cls, context): @@ -492,9 +499,9 @@ class DATA_OT_rigify_bone_group_remove_all(bpy.types.Operator): class DATA_UL_rigify_bone_groups(bpy.types.UIList): def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index): row = layout.row(align=True) - row = row.split(percentage=0.1) + row = row.split(factor=0.1) row.label(text=str(index+1)) - row = row.split(percentage=0.7) + row = row.split(factor=0.7) row.prop(item, "name", text='', emboss=False) row = row.row(align=True) icon = 'LOCKED' if item.standard_colors_lock else 'UNLOCKED' @@ -547,8 +554,8 @@ class DATA_PT_rigify_bone_groups(bpy.types.Panel): row.template_list("DATA_UL_rigify_bone_groups", "", obj.data, "rigify_colors", obj.data, "rigify_colors_index") col = row.column(align=True) - col.operator("armature.rigify_bone_group_add", icon='ZOOMIN', text="") - col.operator("armature.rigify_bone_group_remove", icon='ZOOMOUT', text="").idx = obj.data.rigify_colors_index + col.operator("armature.rigify_bone_group_add", icon='ZOOM_IN', text="") + col.operator("armature.rigify_bone_group_remove", icon='ZOOM_OUT', text="").idx = obj.data.rigify_colors_index col.menu("DATA_MT_rigify_bone_groups_specials", icon='DOWNARROW_HLT', text="") row = layout.row() row.prop(armature, 'rigify_theme_to_add', text = 'Theme') @@ -626,9 +633,9 @@ class BONE_PT_rigify_buttons(bpy.types.Panel): class VIEW3D_PT_tools_rigify_dev(bpy.types.Panel): bl_label = "Rigify Dev Tools" - bl_category = 'Tools' bl_space_type = 'VIEW_3D' - bl_region_type = 'TOOLS' + bl_region_type = 'UI' + bl_category = 'View' @classmethod def poll(cls, context): @@ -650,10 +657,10 @@ class VIEW3D_PT_tools_rigify_dev(bpy.types.Panel): class VIEW3D_PT_rigify_animation_tools(bpy.types.Panel): bl_label = "Rigify Animation Tools" - bl_category = 'Tools' bl_context = "posemode" bl_space_type = 'VIEW_3D' - bl_region_type = 'TOOLS' + bl_region_type = 'UI' + bl_category = 'View' @classmethod def poll(cls, context): @@ -681,8 +688,8 @@ class VIEW3D_PT_rigify_animation_tools(bpy.types.Panel): row.operator("rigify.transfer_ik_to_fk", text='FK2IK Action', icon='ACTION_TWEAK') row = self.layout.row(align=True) - row.operator("rigify.clear_animation", text="Clear IK Action", icon='CANCEL').type = "IK" - row.operator("rigify.clear_animation", text="Clear FK Action", icon='CANCEL').type = "FK" + row.operator("rigify.clear_animation", text="Clear IK Action", icon='CANCEL').anim_type = "IK" + row.operator("rigify.clear_animation", text="Clear FK Action", icon='CANCEL').anim_type = "FK" row = self.layout.row(align=True) op = row.operator("rigify.rotation_pole", icon='FORCE_HARMONIC', text='Switch to pole') @@ -794,18 +801,17 @@ class SwitchToLegacy(bpy.types.Operator): class Sample(bpy.types.Operator): - """Create a sample metarig to be modified before generating """ \ - """the final rig""" + """Create a sample metarig to be modified before generating the final rig""" bl_idname = "armature.metarig_sample_add" bl_label = "Add a sample metarig for a rig type" bl_options = {'UNDO'} - metarig_type = StringProperty( - name="Type", - description="Name of the rig type to generate a sample of", - maxlen=128, - ) + metarig_type: StringProperty( + name="Type", + description="Name of the rig type to generate a sample of", + maxlen=128, + ) def execute(self, context): if context.mode == 'EDIT_ARMATURE' and self.metarig_type != "": @@ -1074,20 +1080,20 @@ def IktoFk(rig, window='ALL'): break -def clearAnimation(act, type, names): +def clearAnimation(act, anim_type, names): bones = [] for group in names: if names[group]['limb_type'] == 'arm': - if type == 'IK': + if anim_type == 'IK': bones.extend([names[group]['controls'][0], names[group]['controls'][4]]) - elif type == 'FK': + elif anim_type == 'FK': bones.extend([names[group]['controls'][1], names[group]['controls'][2], names[group]['controls'][3]]) else: - if type == 'IK': + if anim_type == 'IK': bones.extend([names[group]['controls'][0], names[group]['controls'][6], names[group]['controls'][5], names[group]['controls'][4]]) - elif type == 'FK': + elif anim_type == 'FK': bones.extend([names[group]['controls'][1], names[group]['controls'][2], names[group]['controls'][3], names[group]['controls'][4]]) FCurves = [] @@ -1271,7 +1277,8 @@ class OBJECT_OT_ClearAnimation(bpy.types.Operator): bl_idname = "rigify.clear_animation" bl_label = "Clear Animation" bl_description = "Clear Animation For FK or IK Bones" - type = StringProperty() + + anim_type: StringProperty() def execute(self, context): @@ -1286,7 +1293,7 @@ class OBJECT_OT_ClearAnimation(bpy.types.Operator): if not act: return {'FINISHED'} - clearAnimation(act, self.type, names=get_limb_generated_names(rig)) + clearAnimation(act, self.anim_type, names=get_limb_generated_names(rig)) finally: context.user_preferences.edit.use_global_undo = use_global_undo return {'FINISHED'} @@ -1296,11 +1303,12 @@ class OBJECT_OT_Rot2Pole(bpy.types.Operator): bl_idname = "rigify.rotation_pole" bl_label = "Rotation - Pole toggle" bl_description = "Toggles IK chain between rotation and pole target" - bone_name = bpy.props.StringProperty(default='') - window = bpy.props.StringProperty(default='ALL') - toggle = bpy.props.BoolProperty(default=True) - value = bpy.props.BoolProperty(default=True) - bake = bpy.props.BoolProperty(default=True) + + bone_name: StringProperty(default='') + window: StringProperty(default='ALL') + toggle: BoolProperty(default=True) + value: BoolProperty(default=True) + bake: BoolProperty(default=True) def execute(self, context): rig = context.object @@ -1313,73 +1321,60 @@ class OBJECT_OT_Rot2Pole(bpy.types.Operator): return {'FINISHED'} +### Registering ### + + +classes = ( + DATA_OT_rigify_add_bone_groups, + DATA_OT_rigify_use_standard_colors, + DATA_OT_rigify_apply_selection_colors, + DATA_OT_rigify_bone_group_add, + DATA_OT_rigify_bone_group_add_theme, + DATA_OT_rigify_bone_group_remove, + DATA_OT_rigify_bone_group_remove_all, + DATA_UL_rigify_bone_groups, + DATA_MT_rigify_bone_groups_specials, + DATA_PT_rigify_bone_groups, + DATA_PT_rigify_layer_names, + DATA_PT_rigify_buttons, + BONE_PT_rigify_buttons, + VIEW3D_PT_rigify_animation_tools, + VIEW3D_PT_tools_rigify_dev, + LayerInit, + Generate, + UpgradeMetarigTypes, + SwitchToLegacy, + Sample, + EncodeMetarig, + EncodeMetarigSample, + EncodeWidget, + OBJECT_OT_GetFrameRange, + OBJECT_OT_FK2IK, + OBJECT_OT_IK2FK, + OBJECT_OT_TransferFKtoIK, + OBJECT_OT_TransferIKtoFK, + OBJECT_OT_ClearAnimation, + OBJECT_OT_Rot2Pole, +) + + def register(): + from bpy.utils import register_class - bpy.utils.register_class(DATA_OT_rigify_add_bone_groups) - bpy.utils.register_class(DATA_OT_rigify_use_standard_colors) - bpy.utils.register_class(DATA_OT_rigify_apply_selection_colors) - bpy.utils.register_class(DATA_OT_rigify_bone_group_add) - bpy.utils.register_class(DATA_OT_rigify_bone_group_add_theme) - bpy.utils.register_class(DATA_OT_rigify_bone_group_remove) - bpy.utils.register_class(DATA_OT_rigify_bone_group_remove_all) - bpy.utils.register_class(DATA_UL_rigify_bone_groups) - bpy.utils.register_class(DATA_MT_rigify_bone_groups_specials) - bpy.utils.register_class(DATA_PT_rigify_bone_groups) - bpy.utils.register_class(DATA_PT_rigify_layer_names) - bpy.utils.register_class(DATA_PT_rigify_buttons) - bpy.utils.register_class(BONE_PT_rigify_buttons) - bpy.utils.register_class(VIEW3D_PT_rigify_animation_tools) - bpy.utils.register_class(VIEW3D_PT_tools_rigify_dev) - bpy.utils.register_class(LayerInit) - bpy.utils.register_class(Generate) - bpy.utils.register_class(UpgradeMetarigTypes) - bpy.utils.register_class(SwitchToLegacy) - bpy.utils.register_class(Sample) - bpy.utils.register_class(EncodeMetarig) - bpy.utils.register_class(EncodeMetarigSample) - bpy.utils.register_class(EncodeWidget) - bpy.utils.register_class(OBJECT_OT_GetFrameRange) - bpy.utils.register_class(OBJECT_OT_FK2IK) - bpy.utils.register_class(OBJECT_OT_IK2FK) - bpy.utils.register_class(OBJECT_OT_TransferFKtoIK) - bpy.utils.register_class(OBJECT_OT_TransferIKtoFK) - bpy.utils.register_class(OBJECT_OT_ClearAnimation) - bpy.utils.register_class(OBJECT_OT_Rot2Pole) + # Classes. + for cls in classes: + register_class(cls) + # Sub-modules. rot_mode.register() def unregister(): + from bpy.utils import unregister_class - bpy.utils.unregister_class(DATA_OT_rigify_add_bone_groups) - bpy.utils.unregister_class(DATA_OT_rigify_use_standard_colors) - bpy.utils.unregister_class(DATA_OT_rigify_apply_selection_colors) - bpy.utils.unregister_class(DATA_OT_rigify_bone_group_add) - bpy.utils.unregister_class(DATA_OT_rigify_bone_group_add_theme) - bpy.utils.unregister_class(DATA_OT_rigify_bone_group_remove) - bpy.utils.unregister_class(DATA_OT_rigify_bone_group_remove_all) - bpy.utils.unregister_class(DATA_UL_rigify_bone_groups) - bpy.utils.unregister_class(DATA_MT_rigify_bone_groups_specials) - bpy.utils.unregister_class(DATA_PT_rigify_bone_groups) - bpy.utils.unregister_class(DATA_PT_rigify_layer_names) - bpy.utils.unregister_class(DATA_PT_rigify_buttons) - bpy.utils.unregister_class(BONE_PT_rigify_buttons) - bpy.utils.unregister_class(VIEW3D_PT_rigify_animation_tools) - bpy.utils.unregister_class(VIEW3D_PT_tools_rigify_dev) - bpy.utils.unregister_class(LayerInit) - bpy.utils.unregister_class(Generate) - bpy.utils.unregister_class(UpgradeMetarigTypes) - bpy.utils.unregister_class(SwitchToLegacy) - bpy.utils.unregister_class(Sample) - bpy.utils.unregister_class(EncodeMetarig) - bpy.utils.unregister_class(EncodeMetarigSample) - bpy.utils.unregister_class(EncodeWidget) - bpy.utils.unregister_class(OBJECT_OT_GetFrameRange) - bpy.utils.unregister_class(OBJECT_OT_FK2IK) - bpy.utils.unregister_class(OBJECT_OT_IK2FK) - bpy.utils.unregister_class(OBJECT_OT_TransferFKtoIK) - bpy.utils.unregister_class(OBJECT_OT_TransferIKtoFK) - bpy.utils.unregister_class(OBJECT_OT_ClearAnimation) - bpy.utils.unregister_class(OBJECT_OT_Rot2Pole) - + # Sub-modules. rot_mode.unregister() + + # Classes. + for cls in classes: + unregister_class(cls) diff --git a/rigify/utils.py b/rigify/utils.py index 1a711a3d..23596b3c 100644 --- a/rigify/utils.py +++ b/rigify/utils.py @@ -38,8 +38,6 @@ DEF_PREFIX = "DEF-" # Prefix of deformation bones. WGT_PREFIX = "WGT-" # Prefix for widget objects ROOT_NAME = "root" # Name of the root bone. -WGT_LAYERS = [x == 19 for x in range(0, 20)] # Widgets go on the last scene layer. - MODULE_NAME = "rigify" # Windows/Mac blender is weird, so __package__ doesn't work outdated_types = {"pitchipoy.limbs.super_limb": "limbs.super_limb", @@ -420,7 +418,7 @@ def obj_to_bone(obj, rig, bone_name): bone = rig.data.bones[bone_name] - mat = rig.matrix_world * bone.matrix_local + mat = rig.matrix_world @ bone.matrix_local obj.location = mat.to_translation() @@ -440,6 +438,7 @@ def create_widget(rig, bone_name, bone_transform_name=None): obj_name = WGT_PREFIX + rig.name + '_' + bone_name scene = bpy.context.scene + collection = bpy.context.collection id_store = bpy.context.window_manager # Check if it already exists in the scene @@ -460,14 +459,13 @@ def create_widget(rig, bone_name, bone_transform_name=None): # Create mesh object mesh = bpy.data.meshes.new(obj_name) obj = bpy.data.objects.new(obj_name, mesh) - scene.objects.link(obj) + collection.objects.link(obj) # Move object to bone position and set layers obj_to_bone(obj, rig, bone_transform_name) wgts_group_name = 'WGTS_' + rig.name if wgts_group_name in bpy.data.objects.keys(): obj.parent = bpy.data.objects[wgts_group_name] - obj.layers = WGT_LAYERS return obj @@ -814,8 +812,8 @@ def align_bone_roll(obj, bone1, bone2): bone1_e.roll = roll # Check if we rolled in the right direction - x3 = rot_mat * bone1_e.x_axis - check = x2 * x3 + x3 = rot_mat @ bone1_e.x_axis + check = x2 @ x3 # If not, reverse if check < 0.9999: @@ -1026,11 +1024,11 @@ def write_metarig(obj, layers=False, func_name="create", groups=False): for i in range(len(arm.rigify_layers)): name = arm.rigify_layers[i].name row = arm.rigify_layers[i].row - set = arm.rigify_layers[i].set + selset = arm.rigify_layers[i].selset group = arm.rigify_layers[i].group code.append(' arm.rigify_layers[' + str(i) + '].name = "' + name + '"') code.append(' arm.rigify_layers[' + str(i) + '].row = ' + str(row)) - code.append(' arm.rigify_layers[' + str(i) + '].set = ' + str(set)) + code.append(' arm.rigify_layers[' + str(i) + '].selset = ' + str(selset)) code.append(' arm.rigify_layers[' + str(i) + '].group = ' + str(group)) # write parents first @@ -1262,3 +1260,39 @@ def overwrite_prop_animation(rig, bone, prop_name, value, frames): for kp in curve.keyframe_points: if kp.co[0] in frames: kp.co[1] = value + + +def get_layer_collection_from_collection(children, collection): + for layer_collection in children: + if collection == layer_collection.collection: + return layer_collection + + # go recursive + layer_collection = get_layer_collection_from_collection(layer_collection.children, collection) + if layer_collection: + return layer_collection + + +def ensure_widget_collection(context): + wgts_collection_name = "Widgets" + + view_layer = context.view_layer + layer_collection = bpy.context.layer_collection + collection = layer_collection.collection + + widget_collection = bpy.data.collections.get(wgts_collection_name) + if not widget_collection: + # ------------------------------------------ + # Create the widget collection + widget_collection = bpy.data.collections.new(wgts_collection_name) + widget_collection.hide_viewport = True + widget_collection.hide_render = True + + collection.children.link(widget_collection) + widget_layer_collection = [c for c in layer_collection.children if c.collection == widget_collection][0] + else: + widget_layer_collection = get_layer_collection_from_collection(view_layer.collections, widget_collection) + + # Make the widget the active collection for the upcoming added (widget) objects + view_layer.collections.active = widget_layer_collection + return widget_collection diff --git a/space_clip_editor_refine_solution.py b/space_clip_editor_refine_solution.py index a3287b78..2287714b 100644 --- a/space_clip_editor_refine_solution.py +++ b/space_clip_editor_refine_solution.py @@ -18,12 +18,14 @@ # # ##### END GPL LICENSE BLOCK ##### +# <pep8 compliant> + bl_info = { "name": "Refine tracking solution", "author": "Stephen Leger", "license": "GPL", - "version": (1, 1, 3), - "blender": (2, 7, 8), + "version": (1, 1, 4), + "blender": (2, 80, 0), "location": "Clip Editor > Tools > Solve > Refine Solution", "description": "Refine motion solution by setting track weight according" " to reprojection error", @@ -70,10 +72,9 @@ class OP_Tracking_refine_solution(Operator): marker_position = Vector() for frame in range(start, end): - camera = tracking.reconstruction.cameras.find_frame(frame) + camera = tracking.reconstruction.cameras.find_frame(frame=frame) if camera is not None: - imat = camera.matrix.inverted() - projection_matrix = imat.transposed() + camera_invert = camera.matrix.inverted() else: continue @@ -102,7 +103,7 @@ class OP_Tracking_refine_solution(Operator): else: tw = 1.0 - reprojected_position = track.bundle * projection_matrix + reprojected_position = camera_invert @ track.bundle if reprojected_position.z == 0: track.weight = 0 track.keyframe_insert("weight", frame=frame) @@ -152,11 +153,11 @@ class OP_Tracking_reset_solution(Operator): start = tracking.reconstruction.cameras[0].frame end = tracking.reconstruction.cameras[-1].frame for frame in range(start, end): - camera = tracking.reconstruction.cameras.find_frame(frame) + camera = tracking.reconstruction.cameras.find_frame(frame=frame) if camera is None: continue for track in tracking.tracks: - marker = track.markers.find_frame(frame) + marker = track.markers.find_frame(frame=frame) if marker is None: continue track.weight = 1.0 @@ -191,6 +192,13 @@ class RefineMotionTrackingPanel(Panel): row.operator("tracking.reset_solution") +classes =( + OP_Tracking_refine_solution, + OP_Tracking_reset_solution, + RefineMotionTrackingPanel + ) + + def register(): bpy.types.WindowManager.TrackingTargetError = FloatProperty( name="Target Error", @@ -204,11 +212,13 @@ def register(): default=25, min=1 ) - bpy.utils.register_module(__name__) + for cls in classes: + bpy.utils.register_class(cls) def unregister(): - bpy.utils.unregister_module(__name__) + for cls in reversed(classes): + bpy.utils.unregister_class(cls) del bpy.types.WindowManager.TrackingTargetError del bpy.types.WindowManager.TrackingSmooth diff --git a/space_view3d_3d_navigation.py b/space_view3d_3d_navigation.py index a4c359cc..adf0c8d8 100644 --- a/space_view3d_3d_navigation.py +++ b/space_view3d_3d_navigation.py @@ -252,7 +252,7 @@ class VIEW3D_PT_3dnavigationPanel(Panel): col.operator("view3d.view_selected", text="View to Selected") col = layout.column(align=True) - col.label(text="Cursor:", icon="CURSOR") + col.label(text="Cursor:", icon='PIVOT_CURSOR') row = col.row(align=True) row.operator("view3d.snap_cursor_to_center", text="Center") row.operator("view3d.view_center_cursor", text="View") @@ -299,8 +299,8 @@ class VIEW3D_PT_pan_navigation1(Panel): row = layout.row() row.label(text="Zoom:") row = layout.row() - row.operator("opr.zoom_in_view1", text="In", icon="ZOOMIN") - row.operator("opr.zoom_out_view1", text="Out", icon="ZOOMOUT") + row.operator("opr.zoom_in_view1", text="In", icon='ADD') + row.operator("opr.zoom_out_view1", text="Out", icon='REMOVE') row = layout.row() row.label(text="Roll:") diff --git a/space_view3d_copy_attributes.py b/space_view3d_copy_attributes.py index 762eb953..9063bc89 100644 --- a/space_view3d_copy_attributes.py +++ b/space_view3d_copy_attributes.py @@ -22,7 +22,7 @@ bl_info = { "name": "Copy Attributes Menu", "author": "Bassam Kurdali, Fabian Fricke, Adam Wiseman", "version": (0, 4, 8), - "blender": (2, 63, 0), + "blender": (2, 80, 0), "location": "View3D > Ctrl-C", "description": "Copy Attributes Menu from Blender 2.4", "wiki_url": "https://wiki.blender.org/index.php/Extensions:2.6/Py/" @@ -33,13 +33,13 @@ bl_info = { import bpy from mathutils import Matrix from bpy.types import ( - Operator, - Menu, - ) + Operator, + Menu, +) from bpy.props import ( - BoolVectorProperty, - StringProperty, - ) + BoolVectorProperty, + StringProperty, +) # First part of the operator Info message INFO_MESSAGE = "Copy Attributes: " @@ -82,7 +82,7 @@ def genops(copylist, oplist, prefix, poll_func, loopfunc): exec_func = build_exec(loopfunc, op[3]) invoke_func = build_invoke(loopfunc, op[3]) opclass = build_op(prefix + op[0], "Copy " + op[1], op[2], - poll_func, exec_func, invoke_func) + poll_func, exec_func, invoke_func) oplist.append(opclass) @@ -101,22 +101,25 @@ def getmat(bone, active, context, ignoreparent): """Helper function for visual transform copy, gets the active transform in bone space """ - obj_act = context.active_object - data_bone = obj_act.data.bones[bone.name] + obj_bone = bone.id_data + obj_active = active.id_data + data_bone = obj_bone.data.bones[bone.name] # all matrices are in armature space unless commented otherwise - otherloc = active.matrix # final 4x4 mat of target, location. + active_to_selected = obj_bone.matrix_world.inverted() @ obj_active.matrix_world + active_matrix = active_to_selected @ active.matrix + otherloc = active_matrix # final 4x4 mat of target, location. bonemat_local = data_bone.matrix_local.copy() # self rest matrix if data_bone.parent: - parentposemat = obj_act.pose.bones[data_bone.parent.name].matrix.copy() + parentposemat = obj_bone.pose.bones[data_bone.parent.name].matrix.copy() parentbonemat = data_bone.parent.matrix_local.copy() else: parentposemat = parentbonemat = Matrix() if parentbonemat == parentposemat or ignoreparent: - newmat = bonemat_local.inverted() * otherloc + newmat = bonemat_local.inverted() @ otherloc else: - bonemat = parentbonemat.inverted() * bonemat_local + bonemat = parentbonemat.inverted() @ bonemat_local - newmat = bonemat.inverted() * parentposemat.inverted() * otherloc + newmat = bonemat.inverted() @ parentposemat.inverted() @ otherloc return newmat @@ -160,14 +163,16 @@ def pVisLocExec(bone, active, context): def pVisRotExec(bone, active, context): + obj_bone = bone.id_data rotcopy(bone, getmat(bone, active, - context, not context.active_object.data.bones[bone.name].use_inherit_rotation)) + context, not obj_bone.data.bones[bone.name].use_inherit_rotation)) def pVisScaExec(bone, active, context): + obj_bone = bone.id_data bone.scale = getmat(bone, active, context, - not context.active_object.data.bones[bone.name].use_inherit_scale)\ - .to_scale() + not obj_bone.data.bones[bone.name].use_inherit_scale)\ + .to_scale() def pDrwExec(bone, active, context): @@ -207,30 +212,29 @@ def pBBonesExec(bone, active, context): pose_copies = ( - ('pose_loc_loc', "Local Location", - "Copy Location from Active to Selected", pLocLocExec), - ('pose_loc_rot', "Local Rotation", - "Copy Rotation from Active to Selected", pLocRotExec), - ('pose_loc_sca', "Local Scale", - "Copy Scale from Active to Selected", pLocScaExec), - ('pose_vis_loc', "Visual Location", - "Copy Location from Active to Selected", pVisLocExec), - ('pose_vis_rot', "Visual Rotation", - "Copy Rotation from Active to Selected", pVisRotExec), - ('pose_vis_sca', "Visual Scale", - "Copy Scale from Active to Selected", pVisScaExec), - ('pose_drw', "Bone Shape", - "Copy Bone Shape from Active to Selected", pDrwExec), - ('pose_lok', "Protected Transform", - "Copy Protected Transforms from Active to Selected", pLokExec), - ('pose_con', "Bone Constraints", - "Copy Object Constraints from Active to Selected", pConExec), - ('pose_iks', "IK Limits", - "Copy IK Limits from Active to Selected", pIKsExec), - ('bbone_settings', "BBone Settings", - "Copy BBone Settings from Active to Selected", pBBonesExec), - ) - + ('pose_loc_loc', "Local Location", + "Copy Location from Active to Selected", pLocLocExec), + ('pose_loc_rot', "Local Rotation", + "Copy Rotation from Active to Selected", pLocRotExec), + ('pose_loc_sca', "Local Scale", + "Copy Scale from Active to Selected", pLocScaExec), + ('pose_vis_loc', "Visual Location", + "Copy Location from Active to Selected", pVisLocExec), + ('pose_vis_rot', "Visual Rotation", + "Copy Rotation from Active to Selected", pVisRotExec), + ('pose_vis_sca', "Visual Scale", + "Copy Scale from Active to Selected", pVisScaExec), + ('pose_drw', "Bone Shape", + "Copy Bone Shape from Active to Selected", pDrwExec), + ('pose_lok', "Protected Transform", + "Copy Protected Transforms from Active to Selected", pLokExec), + ('pose_con', "Bone Constraints", + "Copy Object Constraints from Active to Selected", pConExec), + ('pose_iks', "IK Limits", + "Copy IK Limits from Active to Selected", pIKsExec), + ('bbone_settings', "BBone Settings", + "Copy BBone Settings from Active to Selected", pBBonesExec), +) @classmethod def pose_poll_func(cls, context): @@ -248,10 +252,10 @@ class CopySelectedPoseConstraints(Operator): bl_idname = "pose.copy_selected_constraints" bl_label = "Copy Selected Constraints" - selection = BoolVectorProperty( - size=32, - options={'SKIP_SAVE'} - ) + selection: BoolVectorProperty( + size=32, + options={'SKIP_SAVE'} + ) poll = pose_poll_func invoke = pose_invoke_func @@ -260,7 +264,7 @@ class CopySelectedPoseConstraints(Operator): layout = self.layout for idx, const in enumerate(context.active_pose_bone.constraints): layout.prop(self, "selection", index=idx, text=const.name, - toggle=True) + toggle=True) def execute(self, context): active = context.active_pose_bone @@ -271,8 +275,8 @@ class CopySelectedPoseConstraints(Operator): if flag: old_constraint = active.constraints[index] new_constraint = bone.constraints.new( - active.constraints[index].type - ) + active.constraints[index].type + ) generic_copy(old_constraint, new_constraint) return {'FINISHED'} @@ -306,9 +310,9 @@ def obLoopExec(self, context, funk): def world_to_basis(active, ob, context): """put world coords of active as basis coords of ob""" - local = ob.parent.matrix_world.inverted() * active.matrix_world - P = ob.matrix_basis * ob.matrix_local.inverted() - mat = P * local + local = ob.parent.matrix_world.inverted() @ active.matrix_world + P = ob.matrix_basis @ ob.matrix_local.inverted() + mat = P @ local return(mat) @@ -355,17 +359,17 @@ def obVisSca(ob, active, context): def obDrw(ob, active, context): - ob.draw_type = active.draw_type + ob.display_type = active.display_type ob.show_axis = active.show_axis ob.show_bounds = active.show_bounds - ob.draw_bounds_type = active.draw_bounds_type + ob.display_bounds_type = active.display_bounds_type ob.show_name = active.show_name ob.show_texture_space = active.show_texture_space ob.show_transparent = active.show_transparent ob.show_wire = active.show_wire - ob.show_x_ray = active.show_x_ray - ob.empty_draw_type = active.empty_draw_type - ob.empty_draw_size = active.empty_draw_size + ob.show_in_front = active.show_in_front + ob.empty_display_type = active.empty_display_type + ob.empty_display_size = active.empty_display_size def obOfs(ob, active, context): @@ -382,11 +386,6 @@ def obCol(ob, active, context): ob.color = active.color -def obMas(ob, active, context): - ob.game.mass = active.game.mass - return('INFO', "Mass copied") - - def obLok(ob, active, context): for index, state in enumerate(active.lock_location): ob.lock_location[index] = state @@ -429,7 +428,7 @@ def obMod(ob, active, context): ob.modifiers.remove(modifier) for old_modifier in active.modifiers.values(): new_modifier = ob.modifiers.new(name=old_modifier.name, - type=old_modifier.type) + type=old_modifier.type) generic_copy(old_modifier, new_modifier) return('INFO', "Modifiers copied") @@ -483,62 +482,60 @@ def obWei(ob, active, context): for vgs in range(0, len(groups)): if groups[vgs].name == groupName: groups[vgs].add((v.index,), - vgroupIndex_weight[i][1], "REPLACE") + vgroupIndex_weight[i][1], "REPLACE") return('INFO', "Weights copied") object_copies = ( - # ('obj_loc', "Location", - # "Copy Location from Active to Selected", obLoc), - # ('obj_rot', "Rotation", - # "Copy Rotation from Active to Selected", obRot), - # ('obj_sca', "Scale", - # "Copy Scale from Active to Selected", obSca), - ('obj_vis_loc', "Location", - "Copy Location from Active to Selected", obVisLoc), - ('obj_vis_rot', "Rotation", - "Copy Rotation from Active to Selected", obVisRot), - ('obj_vis_sca', "Scale", - "Copy Scale from Active to Selected", obVisSca), - ('obj_drw', "Draw Options", - "Copy Draw Options from Active to Selected", obDrw), - ('obj_ofs', "Time Offset", - "Copy Time Offset from Active to Selected", obOfs), - ('obj_dup', "Dupli", - "Copy Dupli from Active to Selected", obDup), - ('obj_col', "Object Color", - "Copy Object Color from Active to Selected", obCol), - ('obj_mas', "Mass", - "Copy Mass from Active to Selected", obMas), - # ('obj_dmp', "Damping", - # "Copy Damping from Active to Selected"), - # ('obj_all', "All Physical Attributes", - # "Copy Physical Attributes from Active to Selected"), - # ('obj_prp', "Properties", - # "Copy Properties from Active to Selected"), - # ('obj_log', "Logic Bricks", - # "Copy Logic Bricks from Active to Selected"), - ('obj_lok', "Protected Transform", - "Copy Protected Transforms from Active to Selected", obLok), - ('obj_con', "Object Constraints", - "Copy Object Constraints from Active to Selected", obCon), - # ('obj_nla', "NLA Strips", - # "Copy NLA Strips from Active to Selected"), - # ('obj_tex', "Texture Space", - # "Copy Texture Space from Active to Selected", obTex), - # ('obj_sub', "Subsurf Settings", - # "Copy Subsurf Settings from Active to Selected"), - # ('obj_smo', "AutoSmooth", - # "Copy AutoSmooth from Active to Selected"), - ('obj_idx', "Pass Index", - "Copy Pass Index from Active to Selected", obIdx), - ('obj_mod', "Modifiers", - "Copy Modifiers from Active to Selected", obMod), - ('obj_wei', "Vertex Weights", - "Copy vertex weights based on indices", obWei), - ('obj_grp', "Group Links", - "Copy selected into active object's groups", obGrp) - ) + # ('obj_loc', "Location", + # "Copy Location from Active to Selected", obLoc), + # ('obj_rot', "Rotation", + # "Copy Rotation from Active to Selected", obRot), + # ('obj_sca', "Scale", + # "Copy Scale from Active to Selected", obSca), + ('obj_vis_loc', "Location", + "Copy Location from Active to Selected", obVisLoc), + ('obj_vis_rot', "Rotation", + "Copy Rotation from Active to Selected", obVisRot), + ('obj_vis_sca', "Scale", + "Copy Scale from Active to Selected", obVisSca), + ('obj_drw', "Draw Options", + "Copy Draw Options from Active to Selected", obDrw), + ('obj_ofs', "Time Offset", + "Copy Time Offset from Active to Selected", obOfs), + ('obj_dup', "Dupli", + "Copy Dupli from Active to Selected", obDup), + ('obj_col', "Object Color", + "Copy Object Color from Active to Selected", obCol), + # ('obj_dmp', "Damping", + # "Copy Damping from Active to Selected"), + # ('obj_all', "All Physical Attributes", + # "Copy Physical Attributes from Active to Selected"), + # ('obj_prp', "Properties", + # "Copy Properties from Active to Selected"), + # ('obj_log', "Logic Bricks", + # "Copy Logic Bricks from Active to Selected"), + ('obj_lok', "Protected Transform", + "Copy Protected Transforms from Active to Selected", obLok), + ('obj_con', "Object Constraints", + "Copy Object Constraints from Active to Selected", obCon), + # ('obj_nla', "NLA Strips", + # "Copy NLA Strips from Active to Selected"), + # ('obj_tex', "Texture Space", + # "Copy Texture Space from Active to Selected", obTex), + # ('obj_sub', "Subsurf Settings", + # "Copy Subsurf Settings from Active to Selected"), + # ('obj_smo', "AutoSmooth", + # "Copy AutoSmooth from Active to Selected"), + ('obj_idx', "Pass Index", + "Copy Pass Index from Active to Selected", obIdx), + ('obj_mod', "Modifiers", + "Copy Modifiers from Active to Selected", obMod), + ('obj_wei', "Vertex Weights", + "Copy vertex weights based on indices", obWei), + ('obj_grp', "Group Links", + "Copy selected into active object's groups", obGrp) +) @classmethod @@ -557,10 +554,10 @@ class CopySelectedObjectConstraints(Operator): bl_idname = "object.copy_selected_constraints" bl_label = "Copy Selected Constraints" - selection = BoolVectorProperty( - size=32, - options={'SKIP_SAVE'} - ) + selection: BoolVectorProperty( + size=32, + options={'SKIP_SAVE'} + ) poll = object_poll_func invoke = object_invoke_func @@ -569,7 +566,7 @@ class CopySelectedObjectConstraints(Operator): layout = self.layout for idx, const in enumerate(context.active_object.constraints): layout.prop(self, "selection", index=idx, text=const.name, - toggle=True) + toggle=True) def execute(self, context): active = context.active_object @@ -580,8 +577,8 @@ class CopySelectedObjectConstraints(Operator): if flag: old_constraint = active.constraints[index] new_constraint = obj.constraints.new( - active.constraints[index].type - ) + active.constraints[index].type + ) generic_copy(old_constraint, new_constraint) return{'FINISHED'} @@ -591,10 +588,10 @@ class CopySelectedObjectModifiers(Operator): bl_idname = "object.copy_selected_modifiers" bl_label = "Copy Selected Modifiers" - selection = BoolVectorProperty( - size=32, - options={'SKIP_SAVE'} - ) + selection: BoolVectorProperty( + size=32, + options={'SKIP_SAVE'} + ) poll = object_poll_func invoke = object_invoke_func @@ -603,7 +600,7 @@ class CopySelectedObjectModifiers(Operator): layout = self.layout for idx, const in enumerate(context.active_object.modifiers): layout.prop(self, 'selection', index=idx, text=const.name, - toggle=True) + toggle=True) def execute(self, context): active = context.active_object @@ -614,9 +611,9 @@ class CopySelectedObjectModifiers(Operator): if flag: old_modifier = active.modifiers[index] new_modifier = obj.modifiers.new( - type=active.modifiers[index].type, - name=active.modifiers[index].name - ) + type=active.modifiers[index].type, + name=active.modifiers[index].name + ) generic_copy(old_modifier, new_modifier) return{'FINISHED'} @@ -664,23 +661,23 @@ class MESH_MT_CopyFaceSettings(Menu): layout = self.layout op = layout.operator(MESH_OT_CopyFaceSettings.bl_idname, - text="Copy Material") + text="Copy Material") op['layer'] = '' op['mode'] = 'MAT' if mesh.uv_textures.active: op = layout.operator(MESH_OT_CopyFaceSettings.bl_idname, - text="Copy Active UV Image") + text="Copy Active UV Image") op['layer'] = '' op['mode'] = 'IMAGE' op = layout.operator(MESH_OT_CopyFaceSettings.bl_idname, - text="Copy Active UV Coords") + text="Copy Active UV Coords") op['layer'] = '' op['mode'] = 'UV' if mesh.vertex_colors.active: op = layout.operator(MESH_OT_CopyFaceSettings.bl_idname, - text="Copy Active Vertex Colors") + text="Copy Active Vertex Colors") op['layer'] = '' op['mode'] = 'VCOL' @@ -704,7 +701,7 @@ class MESH_MT_CopyImagesFromLayer(Menu): def poll(cls, context): obj = context.active_object return obj and obj.mode == "EDIT_MESH" and len( - obj.data.uv_layers) > 1 + obj.data.uv_layers) > 1 def draw(self, context): mesh = context.active_object.data @@ -718,7 +715,7 @@ class MESH_MT_CopyUVCoordsFromLayer(Menu): def poll(cls, context): obj = context.active_object return obj and obj.mode == "EDIT_MESH" and len( - obj.data.uv_layers) > 1 + obj.data.uv_layers) > 1 def draw(self, context): mesh = context.active_object.data @@ -732,7 +729,7 @@ class MESH_MT_CopyVertexColorsFromLayer(Menu): def poll(cls, context): obj = context.active_object return obj and obj.mode == "EDIT_MESH" and len( - obj.data.vertex_colors) > 1 + obj.data.vertex_colors) > 1 def draw(self, context): mesh = context.active_object.data @@ -759,14 +756,14 @@ class MESH_OT_CopyFaceSettings(Operator): bl_label = "Copy Face Settings" bl_options = {'REGISTER', 'UNDO'} - mode = StringProperty( - name="Mode", - options={"HIDDEN"}, - ) - layer = StringProperty( - name="Layer", - options={"HIDDEN"}, - ) + mode: StringProperty( + name="Mode", + options={"HIDDEN"}, + ) + layer: StringProperty( + name="Layer", + options={"HIDDEN"}, + ) @classmethod def poll(cls, context): @@ -838,8 +835,25 @@ class MESH_OT_CopyFaceSettings(Operator): return(retval) +classes = ( + CopySelectedPoseConstraints, + VIEW3D_MT_posecopypopup, + CopySelectedObjectConstraints, + CopySelectedObjectModifiers, + VIEW3D_MT_copypopup, + MESH_MT_CopyFaceSettings, + MESH_MT_CopyImagesFromLayer, + MESH_MT_CopyUVCoordsFromLayer, + MESH_MT_CopyVertexColorsFromLayer, + MESH_OT_CopyFaceSettings, + *pose_ops, + *object_ops, +) + def register(): - bpy.utils.register_module(__name__) + from bpy.utils import register_class + for cls in classes: + register_class(cls) # mostly to get the keymap working kc = bpy.context.window_manager.keyconfigs.addon @@ -888,7 +902,9 @@ def unregister(): if kmi.properties.name == 'VIEW3D_MT_copypopup': km.keymap_items.remove(kmi) - bpy.utils.unregister_module(__name__) + from bpy.utils import unregister_class + for cls in classes: + unregister_class(cls) if __name__ == "__main__": diff --git a/space_view3d_display_tools/__init__.py b/space_view3d_display_tools/__init__.py index 58699f98..462f417e 100644 --- a/space_view3d_display_tools/__init__.py +++ b/space_view3d_display_tools/__init__.py @@ -80,7 +80,7 @@ class DisplayToolsPanel(Panel): bl_category = "Display" bl_options = {'DEFAULT_CLOSED'} - draw_type_icons = { + display_type_icons = { 'BOUNDS': 'BBOX', 'WIRE': 'WIRE', 'SOLID': 'SOLID', @@ -142,7 +142,7 @@ class DisplayToolsPanel(Panel): col.prop(view, "show_all_objects_origin", toggle=True) col.prop(view, "show_backface_culling", toggle=True) if obj: - col.prop(obj, "show_x_ray", text="X-Ray", toggle=True) + col.prop(obj, "show_in_front", text="X-Ray", toggle=True) if obj and obj_type == 'MESH': col.prop(obj, "show_transparent", text="Transparency", toggle=True) @@ -176,8 +176,8 @@ class DisplayToolsPanel(Panel): if obj: col = layout.column(align=True) col.alignment = 'EXPAND' - col.label(text="Maximum:") - col.prop(obj, "draw_type", text="", icon=self.draw_type_icons[obj.draw_type]) + col.label(text="Display As:") + col.prop(obj, "display_type", text="", icon=self.display_type_icons[obj.display_type]) col = layout.column(align=True) col.alignment = 'CENTER' @@ -394,7 +394,7 @@ class DisplayToolsPanel(Panel): row.prop(display_tools, "UiTabDrop", index=4, text="Selection", icon=icon_active_4) if not SELECT2DROP: - row.operator("view3d.select_border", text="", icon="MESH_PLANE") + row.operator("view3d.select_box", text="", icon="MESH_PLANE") row.operator("view3d.select_circle", text="", icon="MESH_CIRCLE") row.label(text="", icon="BLANK1") else: diff --git a/space_view3d_display_tools/display.py b/space_view3d_display_tools/display.py index d0310ee8..6c1c6796 100644 --- a/space_view3d_display_tools/display.py +++ b/space_view3d_display_tools/display.py @@ -82,10 +82,10 @@ class DisplayDrawChange(Operator, BasePollCheck): if not selection: for obj in bpy.data.objects: - obj.draw_type = self.drawing + obj.display_type = self.drawing else: for obj in selection: - obj.draw_type = self.drawing + obj.display_type = self.drawing except: self.report({'ERROR'}, "Setting Draw Type could not be applied") return {'CANCELLED'} @@ -110,12 +110,12 @@ class DisplayBoundsSwitch(Operator, BasePollCheck): for obj in bpy.data.objects: obj.show_bounds = self.bounds if self.bounds: - obj.draw_bounds_type = scene.BoundingMode + obj.display_bounds_type = scene.BoundingMode else: for obj in selection: obj.show_bounds = self.bounds if self.bounds: - obj.draw_bounds_type = scene.BoundingMode + obj.display_bounds_type = scene.BoundingMode except: self.report({'ERROR'}, "Display/Hide Bounding box overlay failed") return {'CANCELLED'} @@ -164,10 +164,10 @@ class DisplayXRayOn(Operator, BasePollCheck): if not selection: for obj in bpy.data.objects: - obj.show_x_ray = self.xrays + obj.show_in_front = self.xrays else: for obj in selection: - obj.show_x_ray = self.xrays + obj.show_in_front = self.xrays except: self.report({'ERROR'}, "Turn on/off X-ray mode failed") return {'CANCELLED'} diff --git a/space_view3d_display_tools/fast_navigate.py b/space_view3d_display_tools/fast_navigate.py index 269aec2c..5d61138a 100644 --- a/space_view3d_display_tools/fast_navigate.py +++ b/space_view3d_display_tools/fast_navigate.py @@ -43,14 +43,14 @@ def display_particles(mode, dis_particles): for particles in bpy.data.particles: if scene.ShowParticles is False: - particles.draw_method = 'NONE' + particles.display_method = 'NONE' else: if particles.type == 'EMITTER': - particles.draw_method = 'DOT' - particles.draw_percentage = 100 + particles.display_method = 'DOT' + particles.display_percentage = 100 else: - particles.draw_method = 'RENDER' - particles.draw_percentage = dis_particles + particles.display_method = 'RENDER' + particles.display_percentage = dis_particles return dis_particles @@ -149,15 +149,15 @@ class FastNavigate(Operator): self.store_viewport_shade = shade for particle in bpy.data.particles: self.store_init_particles[particle.name] = \ - [particle.draw_method, particle.draw_percentage] + [particle.display_method, particle.display_percentage] else: if not shade: self.store_fail = True else: shade = self.store_viewport_shade or 'SOLID' for particle in bpy.data.particles: - particle.draw_method = self.store_init_particles[particle.name][0] - particle.draw_percentage = self.store_init_particles[particle.name][1] + particle.display_method = self.store_init_particles[particle.name][0] + particle.display_percentage = self.store_init_particles[particle.name][1] except: self.store_fail = True diff --git a/space_view3d_display_tools/select_tools.py b/space_view3d_display_tools/select_tools.py index 95dc4ff2..2eb79dfc 100644 --- a/space_view3d_display_tools/select_tools.py +++ b/space_view3d_display_tools/select_tools.py @@ -65,7 +65,7 @@ class ShowHideObject(Operator): i.hide = True i.select = False - if i.type not in ['CAMERA', 'LAMP']: + if i.type not in ['CAMERA', 'LIGHT']: i.hide_render = True except: continue @@ -103,7 +103,7 @@ class HideAllObjects(Operator): i.hide = True i.select = False - if i.type not in ['CAMERA', 'LAMP']: + if i.type not in ['CAMERA', 'LIGHT']: i.hide_render = True else: obj_name = context.object.name @@ -113,7 +113,7 @@ class HideAllObjects(Operator): i.hide = True i.select = False - if i.type not in ['CAMERA', 'LAMP']: + if i.type not in ['CAMERA', 'LIGHT']: i.hide_render = True return {'FINISHED'} @@ -232,11 +232,11 @@ class OBJECT_OT_HideShowByTypeTemplate(): ('LATTICE', 'Lattice', ''), ('EMPTY', 'Empty', ''), ('CAMERA', 'Camera', ''), - ('LAMP', 'Lamp', ''), + ('LIGHT', 'Lamp', ''), ('ALL', 'All', '')), name="Type", description="Type", - default='LAMP', + default='LIGHT', options={'ANIMATABLE'} ) diff --git a/space_view3d_display_tools/selection_restrictor.py b/space_view3d_display_tools/selection_restrictor.py index feb3b8b8..71561bfe 100644 --- a/space_view3d_display_tools/selection_restrictor.py +++ b/space_view3d_display_tools/selection_restrictor.py @@ -45,7 +45,7 @@ curve = 'OUTLINER_OB_CURVE' arm = 'OUTLINER_OB_ARMATURE' empty = 'OUTLINER_OB_EMPTY' cam = 'OUTLINER_OB_CAMERA' -lamp = 'OUTLINER_OB_LAMP' +lamp = 'OUTLINER_OB_LIGHT' lat = 'OUTLINER_OB_LATTICE' font = 'OUTLINER_OB_FONT' meta = 'OUTLINER_OB_META' @@ -135,10 +135,10 @@ def check_restrictors(dummy): # lamp if bpy.context.scene.get('lamprestrictor') is None: lamprestrictorenabled = True - lamp = 'OUTLINER_OB_LAMP' + lamp = 'OUTLINER_OB_LIGHT' else: lamprestrictorenabled = False - lamp = 'LAMP_DATA' + lamp = 'LIGHT_DATA' # lattice if bpy.context.scene.get('latrestrictor') is None: @@ -408,7 +408,7 @@ class RestrictorCam(Operator): # Restrictor for Lamps class RestrictorLamp(Operator): - bl_idname = "restrictor.lamp" + bl_idname = "restrictor.light" bl_label = "Restrictor Lamps" bl_option = {'REGISTER', 'UNDO'} bl_description = "Lamps selection restrictor" @@ -421,18 +421,18 @@ class RestrictorLamp(Operator): lamprestrictorenabled = True if bpy.context.scene.get('lamprestrictor') is not None: del bpy.context.scene['lamprestrictor'] - lamp = 'OUTLINER_OB_LAMP' + lamp = 'OUTLINER_OB_LIGHT' for ob in bpy.context.scene.objects: - if ob.type == 'LAMP': + if ob.type == 'LIGHT': if ob.get('ignore_restrictors') is None: ob.hide_select = False else: lamprestrictorenabled = False bpy.context.scene['lamprestrictor'] = 1 - lamp = 'LAMP_DATA' + lamp = 'LIGHT_DATA' for ob in bpy.context.scene.objects: - if ob.type == 'LAMP': + if ob.type == 'LIGHT': if ob.get('ignore_restrictors') is None: ob.hide_select = True ob.select = False @@ -638,7 +638,7 @@ class RefreshRestrictors(Operator): 'armrestrictor': ("OUTLINER_OB_ARMATURE", "ARMATURE_DATA", "ARMATURE"), 'emptyrestrictor': ("OUTLINER_OB_EMPTY", "EMPTY_DATA", "EMPTY"), 'camrestrictor': ("OUTLINER_OB_CAMERA", "CAMERA_DATA", "CAMERA"), - 'lamprestrictor': ("OUTLINER_OB_LAMP", "LAMP_DATA", "LAMP"), + 'lamprestrictor': ("OUTLINER_OB_LIGHT", "LIGHT_DATA", "LIGHT"), 'latrestrictor': ("OUTLINER_OB_LATTICE", "LATTICE", "LATTICE"), 'fontrestrictor': ("OUTLINER_OB_FONT", "FONT", "FONT"), 'metarestrictor': ("OUTLINER_OB_META", "META_DATA", "META"), @@ -664,7 +664,7 @@ class RefreshRestrictors(Operator): arm = gl_icon if types == "ARMATURE" else arm empty = gl_icon if types == "EMPTY" else empty cam = gl_icon if types == "CAMERA" else cam - lamp = gl_icon if types == "LAMP" else lamp + lamp = gl_icon if types == "LIGHT" else lamp lat = gl_icon if types == "LATTICE" else lat font = gl_icon if types == "FONT" else font meta = gl_icon if types == "META" else meta @@ -701,7 +701,7 @@ class RestrictorSelection(Menu): layout.operator("restrictor.arm", icon=arm, text="Armature") layout.operator("restrictor.empty", icon=empty, text="Empty") layout.operator("restrictor.cam", icon=cam, text="Camera") - layout.operator("restrictor.lamp", icon=lamp, text="Lamp") + layout.operator("restrictor.light", icon=lamp, text="Lamp") layout.operator("restrictor.lat", icon=lat, text="Lattice") layout.operator("restrictor.font", icon=font, text="Font") layout.operator("restrictor.meta", icon=meta, text="MetaBall") diff --git a/space_view3d_display_tools/useless_tools.py b/space_view3d_display_tools/useless_tools.py index 512fcf2d..22931423 100644 --- a/space_view3d_display_tools/useless_tools.py +++ b/space_view3d_display_tools/useless_tools.py @@ -204,7 +204,7 @@ class UTSubsurfHideSelAll(Operator): objects = bpy.context.selected_objects if self.selected else bpy.data.objects for e in objects: try: - if e.type not in {"LAMP", "CAMERA", "EMPTY"}: + if e.type not in {"LIGHT", "CAMERA", "EMPTY"}: e.modifiers['Subsurf'].show_viewport = self.show except Exception as k: name = getattr(e, "name", "Nameless") @@ -233,7 +233,7 @@ class UTOptimalDisplaySelAll(Operator): objects = bpy.context.selected_objects if self.selected else bpy.data.objects for e in objects: try: - if e.type not in {"LAMP", "CAMERA", "EMPTY"}: + if e.type not in {"LIGHT", "CAMERA", "EMPTY"}: e.modifiers['Subsurf'].show_only_control_edges = self.on except Exception as k: name = getattr(e, "name", "Nameless") diff --git a/space_view3d_pie_menus/__init__.py b/space_view3d_pie_menus/__init__.py index 486d538f..e725995f 100644 --- a/space_view3d_pie_menus/__init__.py +++ b/space_view3d_pie_menus/__init__.py @@ -21,20 +21,20 @@ import bpy from bpy.props import ( - BoolProperty, - PointerProperty, - ) + BoolProperty, + PointerProperty, +) from bpy.types import ( - PropertyGroup, - AddonPreferences, - ) + PropertyGroup, + AddonPreferences, +) bl_info = { "name": "3D Viewport Pie Menus", "author": "meta-androcto, pitiwazou, chromoly, italic", "version": (1, 1, 8), - "blender": (2, 7, 7), + "blender": (2, 80, 0), "description": "Individual Pie Menu Activation List", "location": "Addons Preferences", "warning": "", @@ -149,32 +149,32 @@ def disable_all_modules(self, context): class PieToolsPreferences(AddonPreferences): bl_idname = __name__ - enable_all = BoolProperty( - name="Enable all", - description="Enable all Pie Modules", - default=False, - update=enable_all_modules - ) - disable_all = BoolProperty( - name="Disable all", - description="Disable all Pie Modules", - default=False, - update=disable_all_modules - ) + enable_all: BoolProperty( + name="Enable all", + description="Enable all Pie Modules", + default=False, + update=enable_all_modules + ) + disable_all: BoolProperty( + name="Disable all", + description="Disable all Pie Modules", + default=False, + update=disable_all_modules + ) def draw(self, context): layout = self.layout - split = layout.split(percentage=0.5, align=True) + split = layout.split(factor=0.5, align=True) row = split.row() row.alignment = "LEFT" sub_box = row.box() sub_box.prop(self, "enable_all", emboss=False, icon="VISIBLE_IPO_ON", icon_only=True) - row.label("Enable All") + row.label(text="Enable All") row = split.row() row.alignment = "RIGHT" - row.label("Disable All") + row.label(text="Disable All") sub_box = row.box() sub_box.prop(self, "disable_all", emboss=False, icon="VISIBLE_IPO_OFF", icon_only=True) @@ -195,42 +195,42 @@ class PieToolsPreferences(AddonPreferences): op = sub.operator('wm.context_toggle', text='', icon=icon, emboss=False) op.data_path = 'addon_prefs.show_expanded_' + mod_name - sub.label('{}: {}'.format(info['category'], info['name'])) + sub.label(text='{}: {}'.format(info['category'], info['name'])) sub = row.row() sub.alignment = 'RIGHT' if info.get('warning'): - sub.label('', icon='ERROR') + sub.label(text='', icon='ERROR') sub.prop(self, 'use_' + mod_name, text='') # The second stage if expand: if info.get('description'): - split = col.row().split(percentage=0.15) - split.label('Description:') - split.label(info['description']) + split = col.row().split(factor=0.15) + split.label(text='Description:') + split.label(text=info['description']) if info.get('location'): - split = col.row().split(percentage=0.15) - split.label('Location:') - split.label(info['location']) + split = col.row().split(factor=0.15) + split.label(text='Location:') + split.label(text=info['location']) """ if info.get('author'): - split = col.row().split(percentage=0.15) - split.label('Author:') + split = col.row().split(factor=0.15) + split.label(text='Author:') split.label(info['author']) """ if info.get('version'): - split = col.row().split(percentage=0.15) - split.label('Version:') - split.label('.'.join(str(x) for x in info['version']), + split = col.row().split(factor=0.15) + split.label(text='Version:') + split.label(text='.'.join(str(x) for x in info['version']), translate=False) if info.get('warning'): - split = col.row().split(percentage=0.15) - split.label('Warning:') - split.label(' ' + info['warning'], icon='ERROR') + split = col.row().split(factor=0.15) + split.label(text='Warning:') + split.label(text=' ' + info['warning'], icon='ERROR') tot_row = int(bool(info.get('wiki_url'))) if tot_row: - split = col.row().split(percentage=0.15) + split = col.row().split(factor=0.15) split.label(text='Internet:') if info.get('wiki_url'): op = split.operator('wm.url_open', @@ -274,17 +274,17 @@ for mod in sub_modules: return update prop = BoolProperty( - name=info['name'], - description=info.get('description', ''), - update=gen_update(mod), - ) + name=info['name'], + description=info.get('description', ''), + update=gen_update(mod), + ) setattr(PieToolsPreferences, 'use_' + mod_name, prop) prop = BoolProperty() setattr(PieToolsPreferences, 'show_expanded_' + mod_name, prop) classes = ( PieToolsPreferences, - ) +) def register(): diff --git a/space_view3d_pie_menus/pie_align_menu.py b/space_view3d_pie_menus/pie_align_menu.py index c8ce2e15..39315137 100644 --- a/space_view3d_pie_menus/pie_align_menu.py +++ b/space_view3d_pie_menus/pie_align_menu.py @@ -102,7 +102,7 @@ class AlignSelectedXYZ(Operator): bl_description = "Align Selected Along the chosen axis" bl_options = {'REGISTER', 'UNDO'} - axis = EnumProperty( + axis: EnumProperty( name="Axis", items=[ ('X', "X", "X Axis"), @@ -147,7 +147,7 @@ class AlignToXYZ0(Operator): bl_description = "Align Active Object To a chosen X, Y or Z equals 0 Location" bl_options = {'REGISTER', 'UNDO'} - axis = EnumProperty( + axis: EnumProperty( name="Axis", items=[ ('0', "X", "X Axis"), @@ -181,7 +181,7 @@ class AlignXYZAll(Operator): bl_description = "Align to a Front or Back along the chosen Axis" bl_options = {'REGISTER', 'UNDO'} - axis = EnumProperty( + axis: EnumProperty( name="Axis", items=[ ('0', "X", "X Axis"), @@ -191,7 +191,7 @@ class AlignXYZAll(Operator): description="Choose an axis for alignment", default='0' ) - side = EnumProperty( + side: EnumProperty( name="Side", items=[ ('POSITIVE', "Front", "Align on the positive chosen axis"), diff --git a/space_view3d_pie_menus/pie_apply_transform_menu.py b/space_view3d_pie_menus/pie_apply_transform_menu.py index e22f23b4..268ee550 100644 --- a/space_view3d_pie_menus/pie_apply_transform_menu.py +++ b/space_view3d_pie_menus/pie_apply_transform_menu.py @@ -71,7 +71,7 @@ class ApplyTransLocRotPie(Operator): bl_description = "Apply Transform: Location, Rotation or Scale" bl_options = {'REGISTER', 'UNDO'} - option = EnumProperty( + option: EnumProperty( name="Type", items=[ ("LOC", "Location", "Apply Location"), diff --git a/space_view3d_pie_menus/pie_cursor.py b/space_view3d_pie_menus/pie_cursor.py index 568cdd6d..e598943f 100644 --- a/space_view3d_pie_menus/pie_cursor.py +++ b/space_view3d_pie_menus/pie_cursor.py @@ -69,7 +69,7 @@ class Snap_CursorMenu(Menu): icon='CLIPUV_HLT').use_offset = False # 6 - RIGHT pie.operator("view3d.snap_selected_to_cursor", - text="Selection to Cursor (Offset)", icon='CURSOR').use_offset = True + text="Selection to Cursor (Keep Offset)", icon='CURSOR').use_offset = True # 2 - BOTTOM pie.operator("view3d.snap_cursor_selected_to_center1", text="Selected & Cursor to Center", icon='ALIGN') diff --git a/space_view3d_pie_menus/pie_editor_switch_menu.py b/space_view3d_pie_menus/pie_editor_switch_menu.py index 67f40ff8..adbab7c2 100644 --- a/space_view3d_pie_menus/pie_editor_switch_menu.py +++ b/space_view3d_pie_menus/pie_editor_switch_menu.py @@ -41,7 +41,7 @@ from bpy.props import ( class AreaPieMenu(Menu): - bl_idname = "INFO_MT_window_pie" + bl_idname = "TOPBAR_MT_window_pie" bl_label = "Pie Menu" bl_description = "Window Pie Menus" @@ -87,7 +87,7 @@ class AreaPieEditor(Menu): class AreaTypePieOther(Menu): - bl_idname = "INFO_MT_window_pie_area_type_other" + bl_idname = "TOPBAR_MT_window_pie_area_type_other" bl_label = "Editor Type (other)" bl_description = "Is pie menu change editor type (other)" @@ -95,7 +95,7 @@ class AreaTypePieOther(Menu): # 4 - LEFT self.layout.operator(SetAreaType.bl_idname, text="Logic Editor", icon="LOGIC").types = "LOGIC_EDITOR" # 6 - RIGHT - self.layout.operator(SetAreaType.bl_idname, text="File Browser", icon="FILESEL").types = "FILE_BROWSER" + self.layout.operator(SetAreaType.bl_idname, text="File Browser", icon="FILEBROWSER").types = "FILE_BROWSER" # 2 - BOTTOM self.layout.operator(SetAreaType.bl_idname, text="Python Console", icon="CONSOLE").types = "CONSOLE" # 8 - TOP @@ -114,7 +114,7 @@ class SetAreaType(Operator): bl_description = "Change Editor Type" bl_options = {'REGISTER'} - types = StringProperty(name="Area Type") + types: StringProperty(name="Area Type") def execute(self, context): context.area.type = self.types @@ -122,7 +122,7 @@ class SetAreaType(Operator): class AreaTypePieAnim(Menu): - bl_idname = "INFO_MT_window_pie_area_type_anim" + bl_idname = "TOPBAR_MT_window_pie_area_type_anim" bl_label = "Editor Type (Animation)" bl_description = "Menu for changing editor type (animation related)" diff --git a/space_view3d_pie_menus/pie_manipulator_menu.py b/space_view3d_pie_menus/pie_manipulator_menu.py index 2690c094..3a599483 100644 --- a/space_view3d_pie_menus/pie_manipulator_menu.py +++ b/space_view3d_pie_menus/pie_manipulator_menu.py @@ -37,111 +37,6 @@ from bpy.types import ( ) -class ManipTranslate(Operator): - bl_idname = "manip.translate" - bl_label = "Manip Translate" - bl_options = {'REGISTER', 'UNDO'} - bl_description = " Show Translate" - - def execute(self, context): - if context.space_data.show_manipulator is False: - context.space_data.show_manipulator = True - context.space_data.transform_manipulators = {'TRANSLATE'} - if context.space_data.transform_manipulators != {'TRANSLATE'}: - context.space_data.transform_manipulators = {'TRANSLATE'} - return {'FINISHED'} - - -class ManipRotate(Operator): - bl_idname = "manip.rotate" - bl_label = "Manip Rotate" - bl_options = {'REGISTER', 'UNDO'} - bl_description = " Show Rotate" - - def execute(self, context): - if context.space_data.show_manipulator is False: - context.space_data.show_manipulator = True - context.space_data.transform_manipulators = {'ROTATE'} - if context.space_data.transform_manipulators != {'ROTATE'}: - context.space_data.transform_manipulators = {'ROTATE'} - return {'FINISHED'} - - -class ManipScale(Operator): - bl_idname = "manip.scale" - bl_label = "Manip Scale" - bl_options = {'REGISTER', 'UNDO'} - bl_description = " Show Scale" - - def execute(self, context): - if context.space_data.show_manipulator is False: - context.space_data.show_manipulator = True - context.space_data.transform_manipulators = {'SCALE'} - if context.space_data.transform_manipulators != {'SCALE'}: - context.space_data.transform_manipulators = {'SCALE'} - return {'FINISHED'} - - -class TranslateRotate(Operator): - bl_idname = "translate.rotate" - bl_label = "Translate Rotate" - bl_options = {'REGISTER', 'UNDO'} - bl_description = " Show Translate/Rotate" - - def execute(self, context): - if context.space_data.show_manipulator is False: - context.space_data.show_manipulator = True - context.space_data.transform_manipulators = {'TRANSLATE', 'ROTATE'} - if context.space_data.transform_manipulators != {'TRANSLATE', 'ROTATE'}: - context.space_data.transform_manipulators = {'TRANSLATE', 'ROTATE'} - return {'FINISHED'} - - -class TranslateScale(Operator): - bl_idname = "translate.scale" - bl_label = "Translate Scale" - bl_options = {'REGISTER', 'UNDO'} - bl_description = " Show Translate/Scale" - - def execute(self, context): - if context.space_data.show_manipulator is False: - context.space_data.show_manipulator = True - context.space_data.transform_manipulators = {'TRANSLATE', 'SCALE'} - if context.space_data.transform_manipulators != {'TRANSLATE', 'SCALE'}: - context.space_data.transform_manipulators = {'TRANSLATE', 'SCALE'} - return {'FINISHED'} - - -class RotateScale(Operator): - bl_idname = "rotate.scale" - bl_label = "Rotate Scale" - bl_options = {'REGISTER', 'UNDO'} - bl_description = " Show Rotate/Scale" - - def execute(self, context): - if context.space_data.show_manipulator is False: - context.space_data.show_manipulator = True - context.space_data.transform_manipulators = {'ROTATE', 'SCALE'} - if context.space_data.transform_manipulators != {'ROTATE', 'SCALE'}: - context.space_data.transform_manipulators = {'ROTATE', 'SCALE'} - return {'FINISHED'} - - -class TranslateRotateScale(Operator): - bl_idname = "translate.rotatescale" - bl_label = "Translate Rotate Scale" - bl_options = {'REGISTER', 'UNDO'} - bl_description = "Show All" - - def execute(self, context): - if context.space_data.show_manipulator is False: - context.space_data.show_manipulator = True - context.space_data.transform_manipulators = {'TRANSLATE', 'ROTATE', 'SCALE'} - if context.space_data.transform_manipulators != {'TRANSLATE', 'ROTATE', 'SCALE'}: - context.space_data.transform_manipulators = {'TRANSLATE', 'ROTATE', 'SCALE'} - return {'FINISHED'} - - class WManupulators(Operator): bl_idname = "w.manupulators" bl_label = "W Manupulators" @@ -168,32 +63,17 @@ class PieManipulator(Menu): layout = self.layout pie = layout.menu_pie() # 4 - LEFT - pie.operator("rotate.scale", text="Rotate/Scale") + pie.operator("wm.tool_set_by_name", text="Translate", icon='MAN_TRANS').name = "Move" # 6 - RIGHT - pie.operator("manip.rotate", text="Rotate", icon='MAN_ROT') + pie.operator("wm.tool_set_by_name", text="Scale", icon='MAN_SCALE').name = "Scale" # 2 - BOTTOM - pie.operator("translate.rotatescale", text="Translate/Rotate/Scale") + pie.operator("wm.tool_set_by_name", text="Rotate", icon='MAN_ROT').name = "Rotate" # 8 - TOP pie.operator("w.manupulators", text="Show/Hide Toggle", icon='MANIPUL') - # 7 - TOP - LEFT - pie.operator("translate.rotate", text="Translate/Rotate") - # 9 - TOP - RIGHT - pie.operator("manip.translate", text="Translate", icon='MAN_TRANS') - # 1 - BOTTOM - LEFT - pie.operator("translate.scale", text="Translate/Scale") - # 3 - BOTTOM - RIGHT - pie.operator("manip.scale", text="Scale", icon='MAN_SCALE') classes = ( PieManipulator, - ManipTranslate, - ManipRotate, - ManipScale, - TranslateRotate, - TranslateScale, - RotateScale, - TranslateRotateScale, WManupulators, ) diff --git a/space_view3d_pie_menus/pie_modes_menu.py b/space_view3d_pie_menus/pie_modes_menu.py index 40f6ba4a..74c0b79d 100644 --- a/space_view3d_pie_menus/pie_modes_menu.py +++ b/space_view3d_pie_menus/pie_modes_menu.py @@ -163,7 +163,7 @@ class SetObjectModePie(Operator): bl_description = "I set the interactive mode of object" bl_options = {'REGISTER'} - mode = bpy.props.StringProperty(name="Interactive mode", default="OBJECT") + mode: bpy.props.StringProperty(name="Interactive mode", default="OBJECT") def execute(self, context): if (context.active_object): @@ -429,7 +429,7 @@ class PieObjectEditMode(Menu): pie.operator("view3d.pie_interactive_mode_grease_pencil", icon="GREASEPENCIL") else: message = "Active Object has only Object Mode available" if ob \ - and ob.type in {"LAMP", "CAMERA", "EMPTY", "SPEAKER"} else \ + and ob.type in {"LIGHT", "CAMERA", "EMPTY", "SPEAKER"} else \ "No active object found. Please select one first" pie = layout.menu_pie() pie.separator() diff --git a/space_view3d_pie_menus/pie_orientation_menu.py b/space_view3d_pie_menus/pie_orientation_menu.py index a9de9fa6..ea90862a 100644 --- a/space_view3d_pie_menus/pie_orientation_menu.py +++ b/space_view3d_pie_menus/pie_orientation_menu.py @@ -44,7 +44,7 @@ class OrientPoll(Operator): bl_label = "Orientation Poll" bl_options = {'INTERNAL'} - space = StringProperty() + space: StringProperty() @classmethod def poll(cls, context): diff --git a/space_view3d_pie_menus/pie_save_open_menu.py b/space_view3d_pie_menus/pie_save_open_menu.py index bdd9b63c..8b7e56e0 100644 --- a/space_view3d_pie_menus/pie_save_open_menu.py +++ b/space_view3d_pie_menus/pie_save_open_menu.py @@ -97,9 +97,9 @@ class pie_fileio(Menu): layout = self.layout pie = layout.menu_pie() box = pie.split().column() - box.menu("INFO_MT_file_import", icon='IMPORT') + box.menu("TOPBAR_MT_file_import", icon='IMPORT') box.separator() - box.menu("INFO_MT_file_export", icon='EXPORT') + box.menu("TOPBAR_MT_file_export", icon='EXPORT') class ExternalData(Menu): diff --git a/space_view3d_pie_menus/pie_select_menu.py b/space_view3d_pie_menus/pie_select_menu.py index 091e18ed..e0e492eb 100644 --- a/space_view3d_pie_menus/pie_select_menu.py +++ b/space_view3d_pie_menus/pie_select_menu.py @@ -70,7 +70,7 @@ class PieSelectionsOM(Menu): # 7 - TOP - LEFT pie.operator("view3d.select_circle", text="Circle Select", icon='BORDER_LASSO') # 9 - TOP - RIGHT - pie.operator("view3d.select_border", text="Border Select", icon='BORDER_RECT') + pie.operator("view3d.select_box", text="Box Select", icon='BORDER_RECT') # 1 - BOTTOM - LEFT pie.operator("object.select_camera", text="Select Camera", icon='CAMERA_DATA') # 3 - BOTTOM - RIGHT @@ -86,7 +86,7 @@ class PieSelectionsEM(Menu): layout = self.layout pie = layout.menu_pie() # 4 - LEFT - pie.operator("view3d.select_border", text="Border Select", + pie.operator("view3d.select_box", text="Box Select", icon='BORDER_RECT') # 6 - RIGHT pie.menu("object.selectloopselection", text="Select Loop Menu", icon='LOOPSEL') diff --git a/space_view3d_pie_menus/pie_snap_menu.py b/space_view3d_pie_menus/pie_snap_menu.py index b5ca502c..19b4464f 100644 --- a/space_view3d_pie_menus/pie_snap_menu.py +++ b/space_view3d_pie_menus/pie_snap_menu.py @@ -185,7 +185,8 @@ class SnapTargetVariable(Operator): bl_idname = "object.snaptargetvariable" bl_label = "Snap Target Variable" bl_options = {'REGISTER', 'UNDO'} - variable = bpy.props.StringProperty() + + variable: bpy.props.StringProperty() @classmethod def poll(cls, context): diff --git a/space_view3d_spacebar_menu.py b/space_view3d_spacebar_menu.py index 0831c0d5..e0dbf8a5 100644 --- a/space_view3d_spacebar_menu.py +++ b/space_view3d_spacebar_menu.py @@ -64,8 +64,8 @@ class VIEW3D_MT_Space_Dynamic_Menu(Menu): UseSeparator(self, context) layout.menu("VIEW3D_MT_AddMenu", icon='OBJECT_DATAMODE') layout.menu("VIEW3D_MT_View_Directions", icon='ZOOM_ALL') - layout.menu("VIEW3D_MT_View_Navigation", icon='ROTATE') - layout.menu("VIEW3D_MT_View_Toggle", icon='SPLITSCREEN') + layout.menu("VIEW3D_MT_View_Navigation", icon='PIVOT_BOUNDBOX') + layout.menu("VIEW3D_MT_View_Toggle", icon='WORKSPACE') layout.operator("view3d.snap_cursor_to_center", text="Cursor to Center") layout.operator("view3d.snap_cursor_to_grid", @@ -91,9 +91,9 @@ class VIEW3D_MT_Space_Dynamic_Menu(Menu): UseSeparator(self, context) layout.menu("VIEW3D_MT_TransformMenu", icon='MANIPUL') layout.menu("VIEW3D_MT_MirrorMenu", icon='MOD_MIRROR') - layout.menu("VIEW3D_MT_CursorMenu", icon='CURSOR') + layout.menu("VIEW3D_MT_CursorMenu", icon='PIVOT_CURSOR') UseSeparator(self, context) - layout.menu("VIEW3D_MT_ParentMenu", icon='ROTACTIVE') + layout.menu("VIEW3D_MT_ParentMenu", icon='PIVOT_ACTIVE') layout.menu("VIEW3D_MT_GroupMenu", icon='GROUP') UseSeparator(self, context) layout.menu("VIEW3D_MT_object_specials", text="Specials", icon='SOLO_OFF') @@ -121,16 +121,16 @@ class VIEW3D_MT_Space_Dynamic_Menu(Menu): layout.menu("VIEW3D_MT_Select_Edit_Mesh", icon='RESTRICT_SELECT_OFF') layout.menu("VIEW3D_MT_Edit_Multi", icon='VERTEXSEL') UseSeparator(self, context) - layout.menu("INFO_MT_mesh_add", text="Add Mesh", icon='OUTLINER_OB_MESH') + layout.menu("VIEW3D_MT_mesh_add", text="Add Mesh", icon='OUTLINER_OB_MESH') layout.menu("VIEW3D_MT_Edit_Mesh", text="Mesh", icon='MESH_DATA') UseSeparator(self, context) layout.menu("VIEW3D_MT_TransformMenuEdit", icon='MANIPUL') layout.menu("VIEW3D_MT_MirrorMenu", icon='MOD_MIRROR') - layout.menu("VIEW3D_MT_EditCursorMenu", icon='CURSOR') + layout.menu("VIEW3D_MT_EditCursorMenu", icon='PIVOT_CURSOR') UseSeparator(self, context) layout.menu("VIEW3D_MT_UV_Map", icon='MOD_UVPROJECT') layout.menu("VIEW3D_MT_edit_mesh_specials", icon='SOLO_OFF') - layout.menu("VIEW3D_MT_edit_mesh_extrude", icon='ORTHO') + layout.menu("VIEW3D_MT_edit_mesh_extrude", icon='XRAY') UseSeparator(self, context) layout.operator_menu_enum("object.modifier_add", "type", icon='MODIFIER') layout.operator_menu_enum("object.constraint_add", @@ -230,9 +230,9 @@ class VIEW3D_MT_Space_Dynamic_Menu(Menu): UseSeparator(self, context) layout.menu("VIEW3D_MT_TransformMenu", icon='MANIPUL') layout.menu("VIEW3D_MT_MirrorMenu", icon='MOD_MIRROR') - layout.menu("VIEW3D_MT_CursorMenu", icon='CURSOR') + layout.menu("VIEW3D_MT_CursorMenu", icon='PIVOT_CURSOR') UseSeparator(self, context) - layout.menu("VIEW3D_MT_ParentMenu", icon='ROTACTIVE') + layout.menu("VIEW3D_MT_ParentMenu", icon='PIVOT_ACTIVE') layout.menu("VIEW3D_MT_GroupMenu", icon='GROUP') UseSeparator(self, context) layout.menu("VIEW3D_MT_object_specials", text="Specials", icon='SOLO_OFF') @@ -259,13 +259,13 @@ class VIEW3D_MT_Space_Dynamic_Menu(Menu): layout.menu("VIEW3D_MT_Select_Edit_Curve", icon='RESTRICT_SELECT_OFF') UseSeparator(self, context) - layout.menu("INFO_MT_curve_add", text="Add Curve", + layout.menu("VIEW3D_MT_curve_add", text="Add Curve", icon='OUTLINER_OB_CURVE') layout.menu("VIEW3D_MT_Edit_Curve", icon='CURVE_DATA') UseSeparator(self, context) layout.menu("VIEW3D_MT_TransformMenu", icon='MANIPUL') layout.menu("VIEW3D_MT_MirrorMenu", icon='MOD_MIRROR') - layout.menu("VIEW3D_MT_CursorMenu", icon='CURSOR') + layout.menu("VIEW3D_MT_CursorMenu", icon='PIVOT_CURSOR') layout.menu("VIEW3D_MT_EditCurveCtrlpoints", icon='CURVE_BEZCURVE') layout.menu("VIEW3D_MT_EditCurveSpecials", @@ -294,9 +294,9 @@ class VIEW3D_MT_Space_Dynamic_Menu(Menu): UseSeparator(self, context) layout.menu("VIEW3D_MT_TransformMenu", icon='MANIPUL') layout.menu("VIEW3D_MT_MirrorMenu", icon='MOD_MIRROR') - layout.menu("VIEW3D_MT_CursorMenu", icon='CURSOR') + layout.menu("VIEW3D_MT_CursorMenu", icon='PIVOT_CURSOR') UseSeparator(self, context) - layout.menu("VIEW3D_MT_ParentMenu", icon='ROTACTIVE') + layout.menu("VIEW3D_MT_ParentMenu", icon='PIVOT_ACTIVE') layout.menu("VIEW3D_MT_GroupMenu", icon='GROUP') UseSeparator(self, context) layout.menu("VIEW3D_MT_object_specials", text="Specials", icon='SOLO_OFF') @@ -321,11 +321,11 @@ class VIEW3D_MT_Space_Dynamic_Menu(Menu): layout.menu("VIEW3D_MT_View_Menu", icon='ZOOM_ALL') layout.menu("VIEW3D_MT_Select_Edit_Surface", icon='RESTRICT_SELECT_OFF') UseSeparator(self, context) - layout.menu("INFO_MT_surface_add", text="Add Surface", + layout.menu("VIEW3D_MT_surface_add", text="Add Surface", icon='OUTLINER_OB_SURFACE') layout.menu("VIEW3D_MT_TransformMenu", icon='MANIPUL') layout.menu("VIEW3D_MT_MirrorMenu", icon='MOD_MIRROR') - layout.menu("VIEW3D_MT_CursorMenu", icon='CURSOR') + layout.menu("VIEW3D_MT_CursorMenu", icon='PIVOT_CURSOR') UseSeparator(self, context) layout.prop_menu_enum(settings, "proportional_edit", icon="PROP_CON") @@ -357,9 +357,9 @@ class VIEW3D_MT_Space_Dynamic_Menu(Menu): UseSeparator(self, context) layout.menu("VIEW3D_MT_TransformMenu", icon='MANIPUL') layout.menu("VIEW3D_MT_MirrorMenu", icon='MOD_MIRROR') - layout.menu("VIEW3D_MT_CursorMenu", icon='CURSOR') + layout.menu("VIEW3D_MT_CursorMenu", icon='PIVOT_CURSOR') UseSeparator(self, context) - layout.menu("VIEW3D_MT_ParentMenu", icon='ROTACTIVE') + layout.menu("VIEW3D_MT_ParentMenu", icon='PIVOT_ACTIVE') layout.menu("VIEW3D_MT_GroupMenu", icon='GROUP') UseSeparator(self, context) layout.menu("VIEW3D_MT_object_specials", text="Specials", icon='SOLO_OFF') @@ -388,7 +388,7 @@ class VIEW3D_MT_Space_Dynamic_Menu(Menu): icon='OUTLINER_OB_META') layout.menu("VIEW3D_MT_TransformMenu", icon='MANIPUL') layout.menu("VIEW3D_MT_MirrorMenu", icon='MOD_MIRROR') - layout.menu("VIEW3D_MT_CursorMenu", icon='CURSOR') + layout.menu("VIEW3D_MT_CursorMenu", icon='PIVOT_CURSOR') UseSeparator(self, context) layout.prop_menu_enum(settings, "proportional_edit", icon="PROP_CON") @@ -418,9 +418,9 @@ class VIEW3D_MT_Space_Dynamic_Menu(Menu): UseSeparator(self, context) layout.menu("VIEW3D_MT_TransformMenu", icon='MANIPUL') layout.menu("VIEW3D_MT_MirrorMenu", icon='MOD_MIRROR') - layout.menu("VIEW3D_MT_CursorMenu", icon='CURSOR') + layout.menu("VIEW3D_MT_CursorMenu", icon='PIVOT_CURSOR') UseSeparator(self, context) - layout.menu("VIEW3D_MT_ParentMenu", icon='ROTACTIVE') + layout.menu("VIEW3D_MT_ParentMenu", icon='PIVOT_ACTIVE') layout.menu("VIEW3D_MT_GroupMenu", icon='GROUP') UseSeparator(self, context) layout.menu("VIEW3D_MT_object_specials", text="Specials", icon='SOLO_OFF') @@ -470,9 +470,9 @@ class VIEW3D_MT_Space_Dynamic_Menu(Menu): layout.menu("VIEW3D_MT_Object", icon='VIEW3D') UseSeparator(self, context) layout.menu("VIEW3D_MT_TransformMenu", icon='MANIPUL') - layout.menu("VIEW3D_MT_CursorMenuLite", icon='CURSOR') + layout.menu("VIEW3D_MT_CursorMenuLite", icon='PIVOT_CURSOR') UseSeparator(self, context) - layout.menu("VIEW3D_MT_ParentMenu", icon='ROTACTIVE') + layout.menu("VIEW3D_MT_ParentMenu", icon='PIVOT_ACTIVE') layout.menu("VIEW3D_MT_GroupMenu", icon='GROUP') UseSeparator(self, context) layout.menu("VIEW3D_MT_object_specials", text="Specials", icon='SOLO_OFF') @@ -489,7 +489,7 @@ class VIEW3D_MT_Space_Dynamic_Menu(Menu): layout.operator("view3d.properties", icon='MENU_PANEL') # Lamp Object Mode # - if obj and obj.type == 'LAMP' and obj.mode in {'OBJECT'}: + if obj and obj.type == 'LIGHT' and obj.mode in {'OBJECT'}: layout.operator_context = 'INVOKE_REGION_WIN' layout.operator("wm.search_menu", text="Search", icon='VIEWZOOM') @@ -501,9 +501,9 @@ class VIEW3D_MT_Space_Dynamic_Menu(Menu): layout.menu("VIEW3D_MT_Object", icon='VIEW3D') UseSeparator(self, context) layout.menu("VIEW3D_MT_TransformMenuLite", icon='MANIPUL') - layout.menu("VIEW3D_MT_CursorMenuLite", icon='CURSOR') + layout.menu("VIEW3D_MT_CursorMenuLite", icon='PIVOT_CURSOR') UseSeparator(self, context) - layout.menu("VIEW3D_MT_ParentMenu", icon='ROTACTIVE') + layout.menu("VIEW3D_MT_ParentMenu", icon='PIVOT_ACTIVE') layout.menu("VIEW3D_MT_GroupMenu", icon='GROUP') UseSeparator(self, context) layout.menu("VIEW3D_MT_object_specials", text="Specials", icon='SOLO_OFF') @@ -533,9 +533,9 @@ class VIEW3D_MT_Space_Dynamic_Menu(Menu): UseSeparator(self, context) layout.menu("VIEW3D_MT_TransformMenuArmature", icon='MANIPUL') layout.menu("VIEW3D_MT_MirrorMenu", icon='MOD_MIRROR') - layout.menu("VIEW3D_MT_CursorMenuLite", icon='CURSOR') + layout.menu("VIEW3D_MT_CursorMenuLite", icon='PIVOT_CURSOR') UseSeparator(self, context) - layout.menu("VIEW3D_MT_ParentMenu", icon='ROTACTIVE') + layout.menu("VIEW3D_MT_ParentMenu", icon='PIVOT_ACTIVE') layout.menu("VIEW3D_MT_GroupMenu", icon='GROUP') UseSeparator(self, context) layout.menu("VIEW3D_MT_object_specials", text="Specials", icon='SOLO_OFF') @@ -561,7 +561,7 @@ class VIEW3D_MT_Space_Dynamic_Menu(Menu): layout.menu("VIEW3D_MT_Select_Edit_Armature", icon='RESTRICT_SELECT_OFF') UseSeparator(self, context) - layout.menu("INFO_MT_armature_add", text="Add Armature", + layout.menu("VIEW3D_MT_armature_add", text="Add Armature", icon='OUTLINER_OB_ARMATURE') layout.menu("VIEW3D_MT_Edit_Armature", text="Armature", icon='OUTLINER_DATA_ARMATURE') @@ -570,8 +570,8 @@ class VIEW3D_MT_Space_Dynamic_Menu(Menu): UseSeparator(self, context) layout.menu("VIEW3D_MT_TransformMenuArmatureEdit", icon='MANIPUL') layout.menu("VIEW3D_MT_MirrorMenu", icon='MOD_MIRROR') - layout.menu("VIEW3D_MT_CursorMenuLite", icon='CURSOR') - layout.menu("VIEW3D_MT_ParentMenu", icon='ROTACTIVE') + layout.menu("VIEW3D_MT_CursorMenuLite", icon='PIVOT_CURSOR') + layout.menu("VIEW3D_MT_ParentMenu", icon='PIVOT_ACTIVE') layout.menu("VIEW3D_MT_armature_specials", icon='SOLO_OFF') layout.menu("VIEW3D_MT_edit_armature_roll", icon='BONE_DATA') @@ -599,10 +599,10 @@ class VIEW3D_MT_Space_Dynamic_Menu(Menu): layout.menu("VIEW3D_MT_TransformMenuArmaturePose", icon='MANIPUL') layout.menu("VIEW3D_MT_pose_transform", icon='EMPTY_DATA') UseSeparator(self, context) - layout.menu("VIEW3D_MT_CursorMenuLite", icon='CURSOR') + layout.menu("VIEW3D_MT_CursorMenuLite", icon='PIVOT_CURSOR') layout.menu("VIEW3D_MT_PoseCopy", icon='FILE') - if arm.draw_type in {'BBONE', 'ENVELOPE'}: + if arm.display_type in {'BBONE', 'ENVELOPE'}: layout.operator("transform.transform", text="Scale Envelope Distance").mode = 'BONE_SIZE' @@ -635,9 +635,9 @@ class VIEW3D_MT_Space_Dynamic_Menu(Menu): UseSeparator(self, context) layout.menu("VIEW3D_MT_TransformMenu", icon='MANIPUL') layout.menu("VIEW3D_MT_MirrorMenu", icon='MOD_MIRROR') - layout.menu("VIEW3D_MT_CursorMenu", icon='CURSOR') + layout.menu("VIEW3D_MT_CursorMenu", icon='PIVOT_CURSOR') UseSeparator(self, context) - layout.menu("VIEW3D_MT_ParentMenu", icon='ROTACTIVE') + layout.menu("VIEW3D_MT_ParentMenu", icon='PIVOT_ACTIVE') layout.menu("VIEW3D_MT_GroupMenu", icon='GROUP') UseSeparator(self, context) layout.menu("VIEW3D_MT_object_specials", text="Specials", icon='SOLO_OFF') @@ -666,7 +666,7 @@ class VIEW3D_MT_Space_Dynamic_Menu(Menu): UseSeparator(self, context) layout.menu("VIEW3D_MT_TransformMenu", icon='MANIPUL') layout.menu("VIEW3D_MT_MirrorMenu", icon='MOD_MIRROR') - layout.menu("VIEW3D_MT_CursorMenu", icon='CURSOR') + layout.menu("VIEW3D_MT_CursorMenu", icon='PIVOT_CURSOR') UseSeparator(self, context) layout.prop_menu_enum(settings, "proportional_edit", icon="PROP_CON") @@ -695,9 +695,9 @@ class VIEW3D_MT_Space_Dynamic_Menu(Menu): UseSeparator(self, context) layout.menu("VIEW3D_MT_TransformMenuLite", icon='MANIPUL') layout.menu("VIEW3D_MT_MirrorMenu", icon='MOD_MIRROR') - layout.menu("VIEW3D_MT_CursorMenuLite", icon='CURSOR') + layout.menu("VIEW3D_MT_CursorMenuLite", icon='PIVOT_CURSOR') UseSeparator(self, context) - layout.menu("VIEW3D_MT_ParentMenu", icon='ROTACTIVE') + layout.menu("VIEW3D_MT_ParentMenu", icon='PIVOT_ACTIVE') layout.menu("VIEW3D_MT_GroupMenu", icon='GROUP') UseSeparator(self, context) layout.menu("VIEW3D_MT_object_specials", text="Specials", icon='SOLO_OFF') @@ -726,9 +726,9 @@ class VIEW3D_MT_Space_Dynamic_Menu(Menu): layout.menu("VIEW3D_MT_Object", icon='VIEW3D') UseSeparator(self, context) layout.menu("VIEW3D_MT_TransformMenuLite", icon='MANIPUL') - layout.menu("VIEW3D_MT_CursorMenuLite", icon='CURSOR') + layout.menu("VIEW3D_MT_CursorMenuLite", icon='PIVOT_CURSOR') UseSeparator(self, context) - layout.menu("VIEW3D_MT_ParentMenu", icon='ROTACTIVE') + layout.menu("VIEW3D_MT_ParentMenu", icon='PIVOT_ACTIVE') layout.menu("VIEW3D_MT_GroupMenu", icon='GROUP') UseSeparator(self, context) layout.operator_menu_enum("object.constraint_add", @@ -754,7 +754,7 @@ class VIEW3D_MT_Space_Dynamic_Menu(Menu): UseSeparator(self, context) layout.menu("VIEW3D_MT_TransformMenu", icon='MANIPUL') layout.menu("VIEW3D_MT_MirrorMenu", icon='MOD_MIRROR') - layout.menu("VIEW3D_MT_CursorMenuLite", icon='CURSOR') + layout.menu("VIEW3D_MT_CursorMenuLite", icon='PIVOT_CURSOR') UseSeparator(self, context) layout.prop_menu_enum(settings, "proportional_edit", icon="PROP_CON") @@ -807,7 +807,6 @@ class VIEW3D_MT_Object(Menu): layout.menu("VIEW3D_MT_object_track") layout.menu("VIEW3D_MT_object_animation") UseSeparator(self, context) - layout.menu("VIEW3D_MT_object_game") layout.menu("VIEW3D_MT_object_showhide") UseSeparator(self, context) layout.operator_menu_enum("object.convert", "target") @@ -821,18 +820,18 @@ class VIEW3D_MT_AddMenu(Menu): layout = self.layout layout.operator_context = 'INVOKE_REGION_WIN' - layout.menu("INFO_MT_mesh_add", text="Add Mesh", + layout.menu("VIEW3D_MT_mesh_add", text="Add Mesh", icon='OUTLINER_OB_MESH') - layout.menu("INFO_MT_curve_add", text="Add Curve", + layout.menu("VIEW3D_MT_curve_add", text="Add Curve", icon='OUTLINER_OB_CURVE') - layout.menu("INFO_MT_surface_add", text="Add Surface", + layout.menu("VIEW3D_MT_surface_add", text="Add Surface", icon='OUTLINER_OB_SURFACE') layout.operator_menu_enum("object.metaball_add", "type", icon='OUTLINER_OB_META') layout.operator("object.text_add", text="Add Text", icon='OUTLINER_OB_FONT') UseSeparator(self, context) - layout.menu("INFO_MT_armature_add", text="Add Armature", + layout.menu("VIEW3D_MT_armature_add", text="Add Armature", icon='OUTLINER_OB_ARMATURE') layout.operator("object.add", text="Lattice", icon='OUTLINER_OB_LATTICE').type = 'LATTICE' @@ -842,8 +841,8 @@ class VIEW3D_MT_AddMenu(Menu): UseSeparator(self, context) layout.operator("object.camera_add", text="Camera", icon='OUTLINER_OB_CAMERA') - layout.operator_menu_enum("object.lamp_add", "type", - icon="OUTLINER_OB_LAMP") + layout.operator_menu_enum("object.light_add", "type", + icon="OUTLINER_OB_LIGHT") UseSeparator(self, context) layout.operator_menu_enum("object.effector_add", "type", text="Force Field", @@ -981,8 +980,10 @@ class VIEW3D_MT_CursorMenu(Menu): layout.operator("view3d.snap_cursor_to_active", text="Cursor to Active") UseSeparator(self, context) - layout.operator("view3d.snap_selected_to_cursor", text="Selection to Cursor").use_offset = False - layout.operator("view3d.snap_selected_to_cursor", text="Selection to Cursor (Offset)").use_offset = True + layout.operator("view3d.snap_selected_to_cursor", + text="Selection to Cursor").use_offset = False + layout.operator("view3d.snap_selected_to_cursor", + text="Selection to Cursor (Keep Offset)").use_offset = True layout.operator("view3d.snap_selected_to_grid", text="Selection to Grid") layout.operator("view3d.snap_cursor_selected_to_center", @@ -1012,8 +1013,10 @@ class VIEW3D_MT_CursorMenuLite(Menu): layout.operator("view3d.snap_cursor_to_active", text="Cursor to Active") UseSeparator(self, context) - layout.operator("view3d.snap_selected_to_cursor", text="Selection to Cursor").use_offset = False - layout.operator("view3d.snap_selected_to_cursor", text="Selection to Cursor (Offset)").use_offset = True + layout.operator("view3d.snap_selected_to_cursor", + text="Selection to Cursor").use_offset = False + layout.operator("view3d.snap_selected_to_cursor", + text="Selection to Cursor (Keep Offset)").use_offset = True layout.operator("view3d.snap_selected_to_grid", text="Selection to Grid") layout.operator("view3d.snap_cursor_selected_to_center", @@ -1348,7 +1351,7 @@ class VIEW3D_MT_Edit_Multi(Menu): prop = layout.operator("wm.context_set_value", text="Vertex & Face Select", - icon='ORTHO') + icon='XRAY') prop.value = "(True, False, True)" prop.data_path = "tool_settings.mesh_select_mode" @@ -1420,8 +1423,10 @@ class VIEW3D_MT_EditCursorMenu(Menu): layout.operator("view3d.snap_cursor_to_edge_intersection", text="Cursor to Edge Intersection") UseSeparator(self, context) - layout.operator("view3d.snap_selected_to_cursor", text="Selection to Cursor").use_offset = False - layout.operator("view3d.snap_selected_to_cursor", text="Selection to Cursor (Offset)").use_offset = True + layout.operator("view3d.snap_selected_to_cursor", + text="Selection to Cursor").use_offset = False + layout.operator("view3d.snap_selected_to_cursor", + text="Selection to Cursor (Keep Offset)").use_offset = True layout.operator("view3d.snap_selected_to_grid", text="Selection to Grid") UseSeparator(self, context) @@ -1648,7 +1653,7 @@ class VIEW3D_MT_Hide_Masks(Menu): props = layout.operator("paint.mask_lasso_gesture", text="Lasso Mask") UseSeparator(self, context) - props = layout.operator("view3d.select_border", text="Box Mask", icon="BORDER_RECT") + props = layout.operator("view3d.select_box", text="Box Mask", icon="BORDER_RECT") props = layout.operator("paint.hide_show", text="Box Hide") props.action = 'HIDE' props.area = 'INSIDE' @@ -1890,7 +1895,7 @@ class VIEW3D_MT_TransformMenu(Menu): layout = self.layout layout.menu("VIEW3D_MT_ManipulatorMenu1") UseSeparator(self, context) - layout.operator("transform.translate", text="Grab/Move") + layout.operator("transform.translate", text="Move") layout.operator("transform.rotate", text="Rotate") layout.operator("transform.resize", text="Scale") UseSeparator(self, context) @@ -1920,7 +1925,7 @@ class VIEW3D_MT_TransformMenuEdit(Menu): layout = self.layout layout.menu("VIEW3D_MT_ManipulatorMenu1") UseSeparator(self, context) - layout.operator("transform.translate", text="Grab/Move") + layout.operator("transform.translate", text="Move") layout.operator("transform.rotate", text="Rotate") layout.operator("transform.resize", text="Scale") UseSeparator(self, context) @@ -1950,7 +1955,7 @@ class VIEW3D_MT_TransformMenuLite(Menu): layout = self.layout layout.menu("VIEW3D_MT_ManipulatorMenu1") UseSeparator(self, context) - layout.operator("transform.translate", text="Grab/Move") + layout.operator("transform.translate", text="Move") layout.operator("transform.rotate", text="Rotate") layout.operator("transform.resize", text="Scale") UseSeparator(self, context) @@ -1971,7 +1976,7 @@ class VIEW3D_MT_TransformMenuCamera(Menu): layout.menu("VIEW3D_MT_ManipulatorMenu1") layout.menu("VIEW3D_MT_object_clear") layout.menu("VIEW3D_MT_object_apply") - layout.operator("transform.translate", text="Grab/Move") + layout.operator("transform.translate", text="Move") layout.operator("transform.rotate", text="Rotate") layout.operator("transform.resize", text="Scale") layout.operator("object.align") @@ -1990,7 +1995,7 @@ class VIEW3D_MT_TransformMenuArmature(Menu): layout.menu("VIEW3D_MT_ManipulatorMenu1") UseSeparator(self, context) - layout.operator("transform.translate", text="Grab/Move") + layout.operator("transform.translate", text="Move") layout.operator("transform.rotate", text="Rotate") layout.operator("transform.resize", text="Scale") UseSeparator(self, context) @@ -2016,7 +2021,7 @@ class VIEW3D_MT_TransformMenuArmatureEdit(Menu): layout = self.layout layout.menu("VIEW3D_MT_ManipulatorMenu1") UseSeparator(self, context) - layout.operator("transform.translate", text="Grab/Move") + layout.operator("transform.translate", text="Move") layout.operator("transform.rotate", text="Rotate") layout.operator("transform.resize", text="Scale") UseSeparator(self, context) @@ -2038,7 +2043,7 @@ class VIEW3D_MT_TransformMenuArmaturePose(Menu): def draw(self, context): layout = self.layout layout.menu("VIEW3D_MT_ManipulatorMenu1") - layout.operator("transform.translate", text="Grab/Move") + layout.operator("transform.translate", text="Move") layout.operator("transform.rotate", text="Rotate") layout.operator("transform.resize", text="Scale") UseSeparator(self, context) @@ -2052,9 +2057,9 @@ class VIEW3D_MT_TransformMenuArmaturePose(Menu): layout.operator("pose.user_transforms_clear", text="Reset unkeyed") obj = context.object if obj.type == 'ARMATURE' and obj.mode in {'EDIT', 'POSE'}: - if obj.data.draw_type == 'BBONE': + if obj.data.display_type == 'BBONE': layout.operator("transform.transform", text="Scale BBone").mode = 'BONE_SIZE' - elif obj.data.draw_type == 'ENVELOPE': + elif obj.data.display_type == 'ENVELOPE': layout.operator("transform.transform", text="Scale Envelope Distance").mode = 'BONE_SIZE' layout.operator("transform.transform", text="Scale Radius").mode = 'BONE_ENVELOPE' @@ -2086,7 +2091,7 @@ class VIEW3D_MT_View_Border(Menu): layout.operator_context = 'INVOKE_REGION_WIN' layout.operator("view3d.clip_border", text="Clipping Border...") layout.operator("view3d.zoom_border", text="Zoom Border...") - layout.operator("view3d.render_border", text="Render Border...").camera_only = False + layout.operator("view3d.render_border", text="Render Border...") class VIEW3D_MT_View_Toggle(Menu): @@ -2223,8 +2228,8 @@ class VIEW3D_MT_Shade(Menu): layout.operator("OBJECT_OT_shade_flat") UseSeparator(self, context) - layout.operator("view3d.display_wire_all", text="Wire all", icon='WIRE') - layout.prop(context.object, "show_x_ray", text="X-Ray", icon="META_CUBE") + layout.operator("view3d.display_wire_all", text="Wire all", icon='SHADING_WIRE') + layout.prop(context.object, "show_in_front", text="X-Ray", icon="META_CUBE") UseSeparator(self, context) layout.prop(context.space_data.fx_settings, "use_ssao", @@ -2267,7 +2272,7 @@ class VIEW3D_MT_Select_Object(Menu): def draw(self, context): layout = self.layout layout.operator_context = 'INVOKE_REGION_WIN' - layout.operator("view3d.select_border") + layout.operator("view3d.select_box") layout.operator("view3d.select_circle") UseSeparator(self, context) layout.operator("object.select_all").action = 'TOGGLE' @@ -2317,7 +2322,7 @@ class VIEW3D_MT_Select_Edit_Mesh(Menu): def draw(self, context): layout = self.layout - layout.operator("view3d.select_border") + layout.operator("view3d.select_box") layout.operator("view3d.select_circle") UseSeparator(self, context) layout.operator("mesh.select_all").action = 'TOGGLE' @@ -2383,7 +2388,7 @@ class VIEW3D_MT_Select_Edit_Curve(Menu): def draw(self, context): layout = self.layout - layout.operator("view3d.select_border") + layout.operator("view3d.select_box") layout.operator("view3d.select_circle") UseSeparator(self, context) layout.operator("curve.select_all").action = 'TOGGLE' @@ -2408,7 +2413,7 @@ class VIEW3D_MT_SelectArmatureMenu(Menu): def draw(self, context): layout = self.layout - layout.operator("view3d.select_border") + layout.operator("view3d.select_box") layout.operator("armature.select_all") layout.operator("armature.select_inverse", text="Inverse") layout.operator("armature.select_hierarchy", @@ -2432,7 +2437,7 @@ class VIEW3D_MT_Select_Edit_Armature(Menu): def draw(self, context): layout = self.layout - layout.operator("view3d.select_border") + layout.operator("view3d.select_box") layout.operator("view3d.select_circle") UseSeparator(self, context) @@ -2475,7 +2480,7 @@ class VIEW3D_MT_Select_Pose(Menu): def draw(self, context): layout = self.layout - layout.operator("view3d.select_border") + layout.operator("view3d.select_box") layout.operator("view3d.select_circle") UseSeparator(self, context) layout.operator("pose.select_all").action = 'TOGGLE' @@ -2556,7 +2561,7 @@ class VIEW3D_MT_Select_Edit_Surface(Menu): def draw(self, context): layout = self.layout - layout.operator("view3d.select_border") + layout.operator("view3d.select_box") layout.operator("view3d.select_circle") UseSeparator(self, context) layout.operator("curve.select_all").action = 'TOGGLE' @@ -2577,7 +2582,7 @@ class VIEW3D_MT_SelectMetaball(Menu): def draw(self, context): layout = self.layout - layout.operator("view3d.select_border") + layout.operator("view3d.select_box") layout.operator("view3d.select_circle") UseSeparator(self, context) layout.operator("mball.select_all").action = 'TOGGLE' @@ -2590,7 +2595,7 @@ class VIEW3D_MT_Select_Edit_Metaball(Menu): def draw(self, context): layout = self.layout - layout.operator("view3d.select_border") + layout.operator("view3d.select_box") layout.operator("view3d.select_circle") layout.operator("mball.select_all").action = 'TOGGLE' layout.operator("mball.select_all", text="Inverse").action = 'INVERT' @@ -2615,7 +2620,7 @@ class VIEW3D_MT_Select_Particle(Menu): def draw(self, context): layout = self.layout - layout.operator("view3d.select_border") + layout.operator("view3d.select_box") layout.operator("view3d.select_circle") UseSeparator(self, context) @@ -2642,7 +2647,7 @@ class VIEW3D_MT_Select_Edit_Lattice(Menu): def draw(self, context): layout = self.layout - layout.operator("view3d.select_border") + layout.operator("view3d.select_box") layout.operator("view3d.select_circle") UseSeparator(self, context) layout.operator("lattice.select_mirror") @@ -2662,7 +2667,7 @@ class VIEW3D_MT_Select_Gpencil(Menu): def draw(self, context): layout = self.layout - layout.operator("gpencil.select_border") + layout.operator("gpencil.select_box") layout.operator("gpencil.select_circle") UseSeparator(self, context) @@ -2700,7 +2705,7 @@ class VIEW3D_MT_Select_Paint_Mask(Menu): def draw(self, context): layout = self.layout - layout.operator("view3d.select_border") + layout.operator("view3d.select_box") layout.operator("view3d.select_circle") layout.operator("paint.face_select_all").action = 'TOGGLE' layout.operator("paint.face_select_all", text="Inverse").action = 'INVERT' @@ -2712,7 +2717,7 @@ class VIEW3D_MT_Select_Paint_Mask_Vertex(Menu): def draw(self, context): layout = self.layout - layout.operator("view3d.select_border") + layout.operator("view3d.select_box") layout.operator("view3d.select_circle") layout.operator("paint.vert_select_all").action = 'TOGGLE' layout.operator("paint.vert_select_all", text="Inverse").action = 'INVERT' diff --git a/system_blend_info.py b/system_blend_info.py index 8b2a0939..65b1d9f9 100644 --- a/system_blend_info.py +++ b/system_blend_info.py @@ -102,10 +102,10 @@ class OBJECT_PT_blendinfo(bpy.types.Panel): icon='CAMERA_DATA') row = ob_cols[1].row() - lamps = [o for o in objects.values() if o.type == 'LAMP'] + lamps = [o for o in objects.values() if o.type == 'LIGHT'] num = len(lamps) row.label(text=quantity_string(num, "Lamp", "Lamps"), - icon='LAMP_DATA') + icon='LIGHT_DATA') row = ob_cols[0].row() armatures = [o for o in objects.values() if o.type == 'ARMATURE'] @@ -159,9 +159,9 @@ class OBJECT_PT_blendinfo(bpy.types.Panel): icon='CAMERA_DATA') row = db_cols[1].row() - num = len(bpy.data.lamps) + num = len(bpy.data.lights) row.label(text=quantity_string(num, "Lamp", "Lamps"), - icon='LAMP_DATA') + icon='LIGHT_DATA') row = db_cols[0].row() num = len(bpy.data.armatures) diff --git a/system_demo_mode/__init__.py b/system_demo_mode/__init__.py index 000fcef1..75eb38ba 100644 --- a/system_demo_mode/__init__.py +++ b/system_demo_mode/__init__.py @@ -21,7 +21,7 @@ bl_info = { "name": "Demo Mode", "author": "Campbell Barton", - "blender": (2, 57, 0), + "blender": (2, 80, 0), "location": "Demo Menu", "description": "Demo mode lets you select multiple blend files and loop over them.", "warning": "", @@ -39,12 +39,12 @@ if "bpy" in locals(): import bpy from bpy.props import ( - StringProperty, - BoolProperty, - IntProperty, - FloatProperty, - EnumProperty, - ) + StringProperty, + BoolProperty, + IntProperty, + FloatProperty, + EnumProperty, +) class DemoModeSetup(bpy.types.Operator): @@ -57,85 +57,84 @@ class DemoModeSetup(bpy.types.Operator): # to the class instance from the operator settings before calling. # these are used to create the file list. - directory = StringProperty( - name="Search Path", - description="Directory used for importing the file", - maxlen=1024, - subtype='DIR_PATH', - ) - random_order = BoolProperty( - name="Random Order", - description="Select files randomly", - default=False, - ) - mode = EnumProperty( - name="Method", - items=(('AUTO', "Auto", ""), - ('PLAY', "Play", ""), - ('RENDER', "Render", ""), - ), - ) - - run = BoolProperty( - name="Run Immediately!", - description="Run demo immediately", - default=True, - ) - exit = BoolProperty( - name="Exit", - description="Run once and exit", - default=False, - ) + directory: StringProperty( + name="Search Path", + description="Directory used for importing the file", + maxlen=1024, + subtype='DIR_PATH', + ) + random_order: BoolProperty( + name="Random Order", + description="Select files randomly", + default=False, + ) + mode: EnumProperty( + name="Method", + items=(('AUTO', "Auto", ""), + ('PLAY', "Play", ""), + ('RENDER', "Render", "")) + ) + + run: BoolProperty( + name="Run Immediately!", + description="Run demo immediately", + default=True, + ) + exit: BoolProperty( + name="Exit", + description="Run once and exit", + default=False, + ) # these are mapped directly to the config! # # anim # ==== - anim_cycles = IntProperty( - name="Cycles", - description="Number of times to play the animation", - min=1, max=1000, - default=2, - ) - anim_time_min = FloatProperty( - name="Time Min", - description="Minimum number of seconds to show the animation for " - "(for small loops)", - min=0.0, max=1000.0, - soft_min=1.0, soft_max=1000.0, - default=4.0, - ) - anim_time_max = FloatProperty( - name="Time Max", - description="Maximum number of seconds to show the animation for " - "(in case the end frame is very high for no reason)", - min=0.0, max=100000000.0, - soft_min=1.0, soft_max=100000000.0, - default=8.0, - ) - anim_screen_switch = FloatProperty( - name="Screen Switch", - description="Time between switching screens (in seconds) " - "or 0 to disable", - min=0.0, max=100000000.0, - soft_min=1.0, soft_max=60.0, - default=0.0, - ) + anim_cycles: IntProperty( + name="Cycles", + description="Number of times to play the animation", + min=1, max=1000, + default=2, + ) + anim_time_min: FloatProperty( + name="Time Min", + description="Minimum number of seconds to show the animation for " + "(for small loops)", + min=0.0, max=1000.0, + soft_min=1.0, soft_max=1000.0, + default=4.0, + ) + anim_time_max: FloatProperty( + name="Time Max", + description="Maximum number of seconds to show the animation for " + "(in case the end frame is very high for no reason)", + min=0.0, max=100000000.0, + soft_min=1.0, soft_max=100000000.0, + default=8.0, + ) + anim_screen_switch: FloatProperty( + name="Screen Switch", + description="Time between switching screens (in seconds) " + "or 0 to disable", + min=0.0, max=100000000.0, + soft_min=1.0, soft_max=60.0, + default=0.0, + ) # # render # ====== - display_render = FloatProperty( - name="Render Delay", - description="Time to display the rendered image before moving on " - "(in seconds)", - min=0.0, max=60.0, - default=4.0, - ) - anim_render = BoolProperty( - name="Render Anim", - description="Render entire animation (render mode only)", - default=False, - ) + display_render: FloatProperty( + name="Render Delay", + description="Time to display the rendered image before moving on " + "(in seconds)", + min=0.0, max=60.0, + default=4.0, + ) + anim_render: BoolProperty( + name="Render Anim", + description="Render entire animation (render mode only)", + default=False, + ) def execute(self, context): from . import config @@ -168,13 +167,13 @@ class DemoModeSetup(bpy.types.Operator): layout = self.layout box = layout.box() - box.label("Search *.blend recursively") - box.label("Writes: demo.py config text") + box.label(text="Search *.blend recursively") + box.label(text="Writes: demo.py config text") layout.prop(self, "run") layout.prop(self, "exit") - layout.label("Generate Settings:") + layout.label(text="Generate Settings:") row = layout.row() row.prop(self, "mode", expand=True) layout.prop(self, "random_order") @@ -184,7 +183,7 @@ class DemoModeSetup(bpy.types.Operator): layout.separator() sub = layout.column() sub.active = (mode in {'AUTO', 'PLAY'}) - sub.label("Animate Settings:") + sub.label(text="Animate Settings:") sub.prop(self, "anim_cycles") sub.prop(self, "anim_time_min") sub.prop(self, "anim_time_max") @@ -193,7 +192,7 @@ class DemoModeSetup(bpy.types.Operator): layout.separator() sub = layout.column() sub.active = (mode in {'AUTO', 'RENDER'}) - sub.label("Render Settings:") + sub.label(text="Render Settings:") sub.prop(self, "display_render") @@ -248,7 +247,7 @@ def register(): bpy.utils.register_class(DemoModeSetup) bpy.utils.register_class(DemoModeRun) - bpy.types.INFO_MT_file.prepend(menu_func) + bpy.types.TOPBAR_MT_file.prepend(menu_func) extern_demo_mode_register() @@ -257,7 +256,7 @@ def unregister(): bpy.utils.unregister_class(DemoModeSetup) bpy.utils.unregister_class(DemoModeRun) - bpy.types.INFO_MT_file.remove(menu_func) + bpy.types.TOPBAR_MT_file.remove(menu_func) extern_demo_mode_unregister() diff --git a/system_demo_mode/demo_mode.py b/system_demo_mode/demo_mode.py index 9b94378c..1a717a5e 100644 --- a/system_demo_mode/demo_mode.py +++ b/system_demo_mode/demo_mode.py @@ -154,7 +154,7 @@ def demo_mode_next_file(step=1): def demo_mode_timer_add(): - global_state["timer"] = bpy.context.window_manager.event_timer_add(0.8, bpy.context.window) + global_state["timer"] = bpy.context.window_manager.event_timer_add(0.8, window=bpy.context.window) def demo_mode_timer_remove(): @@ -418,12 +418,12 @@ class DemoModeControl(bpy.types.Operator): bl_idname = "wm.demo_mode_control" bl_label = "Control" - mode = bpy.props.EnumProperty(items=( - ('PREV', "Prev", ""), - ('PAUSE', "Pause", ""), - ('NEXT', "Next", ""), - ), - name="Mode") + mode: bpy.props.EnumProperty( + items=(('PREV', "Prev", ""), + ('PAUSE', "Pause", ""), + ('NEXT', "Next", "")), + name="Mode" + ) def execute(self, context): mode = self.mode @@ -441,7 +441,7 @@ def menu_func(self, context): layout = self.layout layout.operator_context = 'EXEC_DEFAULT' row = layout.row(align=True) - row.label("Demo Mode:") + row.label(text="Demo Mode:") if not DemoMode.enabled: row.operator("wm.demo_mode", icon='PLAY', text="") else: diff --git a/system_property_chart.py b/system_property_chart.py index 028786c9..3fc5ff13 100644 --- a/system_property_chart.py +++ b/system_property_chart.py @@ -179,8 +179,8 @@ def _property_chart_draw(self, context): col.label(text="Properties") row = col.row(align=True) row.menu("SCENE_MT_properties_presets", text=bpy.types.SCENE_MT_properties_presets.bl_label) - row.operator("scene.properties_preset_add", text="", icon="ZOOMIN") - row.operator("scene.properties_preset_add", text="", icon="ZOOMOUT").remove_active = True + row.operator("scene.properties_preset_add", text="", icon='ADD') + row.operator("scene.properties_preset_add", text="", icon='REMOVE').remove_active = True # edit the display props col.prop(id_storage, self._PROP_STORAGE_ID, text="") diff --git a/ui_layer_manager.py b/ui_layer_manager.py index 018aad26..d3e20e69 100644 --- a/ui_layer_manager.py +++ b/ui_layer_manager.py @@ -277,11 +277,11 @@ class SCENE_OT_namedlayer_toggle_wire(Operator): group_layers = scene.layergroups[group_idx].layers layers = obj.layers if True in {layer and group_layer for layer, group_layer in zip(layers, group_layers)}: - obj.draw_type = display + obj.display_type = display scene.layergroups[group_idx].use_wire = use_wire else: if obj.layers[layer_idx]: - obj.draw_type = display + obj.display_type = display scene.namedlayers.layers[layer_idx].use_wire = use_wire return {'FINISHED'} @@ -580,8 +580,8 @@ class SCENE_PT_namedlayer_groups(Panel): row.template_list("SCENE_UL_namedlayer_groups", "", scene, "layergroups", scene, "layergroups_index") col = row.column(align=True) - col.operator("scene.namedlayer_group_add", icon='ZOOMIN', text="").layers = scene.layers - col.operator("scene.namedlayer_group_remove", icon='ZOOMOUT', text="").group_idx = group_idx + col.operator("scene.namedlayer_group_add", icon='ADD', text="").layers = scene.layers + col.operator("scene.namedlayer_group_remove", icon='REMOVE', text="").group_idx = group_idx if bool(scene.layergroups): layout.prop(scene.layergroups[group_idx], "layers", text="", toggle=True) diff --git a/uv_texture_atlas.py b/uv_texture_atlas.py index b655c83c..debd4418 100644 --- a/uv_texture_atlas.py +++ b/uv_texture_atlas.py @@ -95,8 +95,8 @@ class TexAtl_Main(Panel): row.template_list("UI_UL_list", "template_list_controls", scene, "ms_lightmap_groups", scene, "ms_lightmap_groups_index", rows=2, maxrows=5) col = row.column(align=True) - col.operator("scene.ms_add_lightmap_group", icon='ZOOMIN', text="") - col.operator("scene.ms_del_lightmap_group", icon='ZOOMOUT', text="") + col.operator("scene.ms_add_lightmap_group", icon='ADD', text="") + col.operator("scene.ms_del_lightmap_group", icon='REMOVE', text="") row = self.layout.row(align=True) @@ -127,15 +127,15 @@ class TexAtl_Main(Panel): self.layout.prop(group, 'unwrap_type', text='Lightmap', expand=True) row = self.layout.row() row.operator( - "object.ms_auto", text="Auto Unwrap", icon="LAMP_SPOT") + "object.ms_auto", text="Auto Unwrap", icon="LIGHT_SPOT") row.prop(group, 'autoUnwrapPrecision', text='') self.layout.label(text="Manual Unwrap:") row = self.layout.row() row.operator( - "object.ms_run", text="StartManualUnwrap", icon="LAMP_SPOT") + "object.ms_run", text="StartManualUnwrap", icon="LIGHT_SPOT") row.operator( - "object.ms_run_remove", text="FinishManualUnwrap", icon="LAMP_SPOT") + "object.ms_run_remove", text="FinishManualUnwrap", icon="LIGHT_SPOT") class TexAtl_RunAuto(Operator): |