diff options
author | Spivak Vladimir (cwolf3d) <cwolf3d@gmail.com> | 2020-01-23 04:16:39 +0300 |
---|---|---|
committer | Spivak Vladimir (cwolf3d) <cwolf3d@gmail.com> | 2020-01-23 04:16:39 +0300 |
commit | 3049742f7ff91beaa0a0c7b05d62bf2e418fd264 (patch) | |
tree | 943adcc7f4d877ba24519a7d5a16d291e118f47d /mesh_auto_mirror.py | |
parent | 1e165b809b66fbf19778dbb6f1a3f4e64efef031 (diff) |
Fix T73326: Blender 2.81 - AutoMirror issue
Diffstat (limited to 'mesh_auto_mirror.py')
-rw-r--r-- | mesh_auto_mirror.py | 213 |
1 files changed, 122 insertions, 91 deletions
diff --git a/mesh_auto_mirror.py b/mesh_auto_mirror.py index 384fb37b..9585ee96 100644 --- a/mesh_auto_mirror.py +++ b/mesh_auto_mirror.py @@ -33,6 +33,7 @@ from bpy.types import ( Menu, Panel, AddonPreferences, + PropertyGroup, ) from bpy.props import ( BoolProperty, @@ -46,7 +47,7 @@ from bpy.props import ( # Operator -class AlignVertices(bpy.types.Operator): +class AlignVertices(Operator): """ Automatically cut an object along an axis """ @@ -59,6 +60,8 @@ class AlignVertices(bpy.types.Operator): return obj and obj.type == "MESH" def execute(self, context): + automirror = context.scene.automirror + bpy.ops.object.mode_set(mode = 'OBJECT') x1,y1,z1 = bpy.context.scene.cursor.location @@ -73,14 +76,14 @@ class AlignVertices(bpy.types.Operator): #Vertices coordinate to 0 (local coordinate, so on the origin) for vert in bpy.context.object.data.vertices: if vert.select: - if bpy.context.scene.AutoMirror_axis == 'x': + if automirror.axis == 'x': axis = 0 - elif bpy.context.scene.AutoMirror_axis == 'y': + elif automirror.axis == 'y': axis = 1 - elif bpy.context.scene.AutoMirror_axis == 'z': + elif automirror.axis == 'z': axis = 2 vert.co[axis] = 0 - # + bpy.context.scene.cursor.location = x2,y2,z2 bpy.ops.object.origin_set(type='ORIGIN_CURSOR') @@ -103,88 +106,98 @@ class AutoMirror(bpy.types.Operator): return obj and obj.type == "MESH" def draw(self, context): + automirror = context.scene.automirror + layout = self.layout if bpy.context.object and bpy.context.object.type == 'MESH': - layout.prop(context.scene, "AutoMirror_axis", text="Mirror axis") - layout.prop(context.scene, "AutoMirror_orientation", text="Orientation") - layout.prop(context.scene, "AutoMirror_threshold", text="Threshold") - layout.prop(context.scene, "AutoMirror_toggle_edit", text="Toggle edit") - layout.prop(context.scene, "AutoMirror_cut", text="Cut and mirror") - if bpy.context.scene.AutoMirror_cut: - layout.prop(context.scene, "AutoMirror_clipping", text="Clipping") - layout.prop(context.scene, "AutoMirror_apply_mirror", text="Apply mirror") + layout.prop(automirror, "axis", text = "Mirror axis") + layout.prop(automirror, "orientation", text = "Orientation") + layout.prop(automirror, "threshold", text = "Threshold") + layout.prop(automirror, "toggle_edit", text = "Toggle edit") + layout.prop(automirror, "cut", text = "Cut and mirror") + if automirror.cut: + layout.prop(automirror, "clipping", text = "Clipping") + layout.prop(automirror, "mirror", text = "Apply mirror") else: - layout.label(icon="ERROR", text="No mesh selected") + layout.label(icon = "ERROR", text = "No mesh selected") def get_local_axis_vector(self, context, X, Y, Z, orientation): loc = context.object.location - bpy.ops.object.mode_set(mode="OBJECT") # Needed to avoid to translate vertices + bpy.ops.object.mode_set(mode = "OBJECT") # Needed to avoid to translate vertices v1 = Vector((loc[0],loc[1],loc[2])) - bpy.ops.transform.translate(value=(X*orientation, Y*orientation, Z*orientation), - constraint_axis=((X==1), (Y==1), (Z==1)), - orient_type='LOCAL') + bpy.ops.transform.translate(value = (X*orientation, Y*orientation, Z*orientation), + constraint_axis = ((X==1), (Y==1), (Z==1)), + orient_type = 'LOCAL') v2 = Vector((loc[0],loc[1],loc[2])) - bpy.ops.transform.translate(value=(-X*orientation, -Y*orientation, -Z*orientation), - constraint_axis=((X==1), (Y==1), (Z==1)), - orient_type='LOCAL') + bpy.ops.transform.translate(value = (-X*orientation, -Y*orientation, -Z*orientation), + constraint_axis = ((X==1), (Y==1), (Z==1)), + orient_type = 'LOCAL') bpy.ops.object.mode_set(mode="EDIT") return v2-v1 def execute(self, context): + automirror = context.scene.automirror + X,Y,Z = 0,0,0 - if bpy.context.scene.AutoMirror_axis == 'x': + + if automirror.axis == 'x': X = 1 - elif bpy.context.scene.AutoMirror_axis == 'y': + elif automirror.axis == 'y': Y = 1 - elif bpy.context.scene.AutoMirror_axis == 'z': + elif automirror.axis == 'z': Z = 1 current_mode = bpy.context.object.mode # Save the current mode if bpy.context.object.mode != "EDIT": - bpy.ops.object.mode_set(mode="EDIT") # Go to edit mode - bpy.ops.mesh.select_all(action='SELECT') # Select all the vertices - if bpy.context.scene.AutoMirror_orientation == 'positive': + bpy.ops.object.mode_set(mode = "EDIT") # Go to edit mode + + bpy.ops.mesh.select_all(action = 'SELECT') # Select all the vertices + + if automirror.orientation == 'positive': orientation = 1 else: orientation = -1 + cut_normal = self.get_local_axis_vector(context, X, Y, Z, orientation) # Cut the mesh bpy.ops.mesh.bisect( - plane_co=( + plane_co = ( bpy.context.object.location[0], bpy.context.object.location[1], bpy.context.object.location[2] ), - plane_no=cut_normal, - use_fill= False, - clear_inner= bpy.context.scene.AutoMirror_cut, - clear_outer= 0, - threshold= bpy.context.scene.AutoMirror_threshold) + plane_no = cut_normal, + use_fill = False, + clear_inner = automirror.cut, + clear_outer = 0, + threshold = automirror.threshold + ) bpy.ops.object.align_vertices() # Use to align the vertices on the origin, needed by the "threshold" - if not bpy.context.scene.AutoMirror_toggle_edit: - bpy.ops.object.mode_set(mode=current_mode) # Reload previous mode + if not automirror.toggle_edit: + bpy.ops.object.mode_set(mode = current_mode) # Reload previous mode - if bpy.context.scene.AutoMirror_cut: - bpy.ops.object.modifier_add(type='MIRROR') # Add a mirror modifier + if automirror.cut: + bpy.ops.object.modifier_add(type = 'MIRROR') # Add a mirror modifier bpy.context.object.modifiers[-1].use_axis[0] = X # Choose the axis to use, based on the cut's axis bpy.context.object.modifiers[-1].use_axis[1] = Y bpy.context.object.modifiers[-1].use_axis[2] = Z - bpy.context.object.modifiers[-1].use_clip = context.scene.Use_Matcap - bpy.context.object.modifiers[-1].show_on_cage = context.scene.AutoMirror_show_on_cage - if bpy.context.scene.AutoMirror_apply_mirror: - bpy.ops.object.mode_set(mode='OBJECT') - bpy.ops.object.modifier_apply(apply_as= 'DATA', modifier= bpy.context.object.modifiers[-1].name) - if bpy.context.scene.AutoMirror_toggle_edit: - bpy.ops.object.mode_set(mode='EDIT') + bpy.context.object.modifiers[-1].use_clip = automirror.Use_Matcap + bpy.context.object.modifiers[-1].show_on_cage = automirror.show_on_cage + if automirror.apply_mirror: + bpy.ops.object.mode_set(mode = 'OBJECT') + bpy.ops.object.modifier_apply(apply_as = 'DATA', + modifier = bpy.context.object.modifiers[-1].name) + if automirror.toggle_edit: + bpy.ops.object.mode_set(mode = 'EDIT') else: - bpy.ops.object.mode_set(mode=current_mode) + bpy.ops.object.mode_set(mode = current_mode) return {'FINISHED'} @@ -198,62 +211,75 @@ class VIEW3D_PT_BisectMirror(Panel): bl_category = 'Edit' bl_options = {'DEFAULT_CLOSED'} - def draw(self, context): + automirror = context.scene.automirror + layout = self.layout col = layout.column(align=True) layout = self.layout - if bpy.context.object and bpy.context.object.type == 'MESH': + if bpy.context.object and bpy.context.object.type == 'MESH': layout.operator("object.automirror") - layout.prop(context.scene, "AutoMirror_axis", text="Mirror Axis", expand=True) - layout.prop(context.scene, "AutoMirror_orientation", text="Orientation") - layout.prop(context.scene, "AutoMirror_threshold", text="Threshold") - layout.prop(context.scene, "AutoMirror_toggle_edit", text="Toggle Edit") - layout.prop(context.scene, "AutoMirror_cut", text="Cut and Mirror") - if bpy.context.scene.AutoMirror_cut: - layout.prop(context.scene, "Use_Matcap", text="Use Clip") - layout.prop(context.scene, "AutoMirror_show_on_cage", text="Editable") - layout.prop(context.scene, "AutoMirror_apply_mirror", text="Apply Mirror") + layout.prop(automirror, "axis", text = "Mirror Axis", expand=True) + layout.prop(automirror, "orientation", text = "Orientation") + layout.prop(automirror, "threshold", text = "Threshold") + layout.prop(automirror, "toggle_edit", text = "Toggle Edit") + layout.prop(automirror, "cut", text = "Cut and Mirror") + if bpy.context.scene.automirror.cut: + layout.prop(automirror, "Use_Matcap", text = "Use Clip") + layout.prop(automirror, "show_on_cage", text = "Editable") + layout.prop(automirror, "apply_mirror", text = "Apply Mirror") else: - layout.label(icon="ERROR", text="No mesh selected") + layout.label(icon="ERROR", text = "No mesh selected") # Properties +class AutoMirrorProps(PropertyGroup): + axis : EnumProperty( + items = [("x", "X", "", 1), + ("y", "Y", "", 2), + ("z", "Z", "", 3)], + description="Axis used by the mirror modifier", + ) -bpy.types.Scene.AutoMirror_axis = bpy.props.EnumProperty( - items = [("x", "X", "", 1),("y", "Y", "", 2),("z", "Z", "", 3)], - description="Axis used by the mirror modifier") - -bpy.types.Scene.AutoMirror_orientation = bpy.props.EnumProperty( - items = [("positive", "Positive", "", 1),("negative", "Negative", "", 2)], - description="Choose the side along the axis of the editable part (+/- coordinates)") - -bpy.types.Scene.AutoMirror_threshold = bpy.props.FloatProperty( - default= 0.001, min= 0.001, - description="Vertices closer than this distance are merged on the loopcut") + orientation : EnumProperty( + items = [("positive", "Positive", "", 1),("negative", "Negative", "", 2)], + description="Choose the side along the axis of the editable part (+/- coordinates)", + ) -bpy.types.Scene.AutoMirror_toggle_edit = bpy.props.BoolProperty( - default= False, - description="If not in edit mode, change mode to edit") + threshold : FloatProperty( + default= 0.001, min= 0.001, + description="Vertices closer than this distance are merged on the loopcut", + ) -bpy.types.Scene.AutoMirror_cut = bpy.props.BoolProperty( - default= True, - description="If enabeled, cut the mesh in two parts and mirror it. If not, just make a loopcut") + toggle_edit : BoolProperty( + default= False, + description="If not in edit mode, change mode to edit", + ) -bpy.types.Scene.AutoMirror_clipping = bpy.props.BoolProperty( - default=True) -bpy.types.Scene.Use_Matcap = bpy.props.BoolProperty(default=True, -description="Use clipping for the mirror modifier") + cut : BoolProperty( + default= True, + description="If enabeled, cut the mesh in two parts and mirror it. If not, just make a loopcut", + ) -bpy.types.Scene.AutoMirror_show_on_cage = bpy.props.BoolProperty( - default=False, - description="Enable to edit the cage (it's the classical modifier's option)") + clipping : BoolProperty( + default=True, + ) + + Use_Matcap : BoolProperty( + default=True, + description="Use clipping for the mirror modifier", + ) -bpy.types.Scene.AutoMirror_apply_mirror = bpy.props.BoolProperty( + show_on_cage : BoolProperty( + default=False, + description="Enable to edit the cage (it's the classical modifier's option)", + ) - description="Apply the mirror modifier (useful to symmetrise the mesh)") + apply_mirror : BoolProperty( + description="Apply the mirror modifier (useful to symmetrise the mesh)", + ) # Add-ons Preferences Update Panel @@ -286,10 +312,10 @@ class AutoMirrorAddonPreferences(AddonPreferences): bl_idname = __name__ category: StringProperty( - name="Tab Category", - description="Choose a name for the category of the panel", - default="Edit", - update=update_panel + name = "Tab Category", + description = "Choose a name for the category of the panel", + default = "Edit", + update = update_panel ) def draw(self, context): @@ -297,15 +323,16 @@ class AutoMirrorAddonPreferences(AddonPreferences): row = layout.row() col = row.column() - col.label(text="Tab Category:") - col.prop(self, "category", text="") - + col.label(text = "Tab Category:") + col.prop(self, "category", text = "") + # define classes for registration classes = ( VIEW3D_PT_BisectMirror, AutoMirror, AlignVertices, - AutoMirrorAddonPreferences + AutoMirrorAddonPreferences, + AutoMirrorProps, ) @@ -313,12 +340,16 @@ classes = ( def register(): for cls in classes: bpy.utils.register_class(cls) + + bpy.types.Scene.automirror = PointerProperty(type = AutoMirrorProps) update_panel(None, bpy.context) # unregistering and removing menus def unregister(): for cls in reversed(classes): bpy.utils.unregister_class(cls) + + del bpy.types.Scene.automirror if __name__ == "__main__": register() |