diff --git a/add_mesh_BoltFactory/Boltfactory.py b/add_mesh_BoltFactory/Boltfactory.py index 67e46d8cbde0fb501bc22c8a12a27afda99e6e54..672633d39bf3ad779371403456e734b1e8361f24 100644 --- a/add_mesh_BoltFactory/Boltfactory.py +++ b/add_mesh_BoltFactory/Boltfactory.py @@ -20,44 +20,29 @@ import bpy from mathutils import Matrix from bpy.types import Operator +from bpy_extras.object_utils import AddObjectHelper from bpy.props import ( BoolProperty, EnumProperty, FloatProperty, IntProperty, + FloatVectorProperty, ) from . import createMesh -# ------------------------------------------------------------ -# calculates the matrix for the new object depending on user pref -def align_matrix(context): - loc = Matrix.Translation(context.scene.cursor_location) - obj_align = context.user_preferences.edit.object_align - if (context.space_data.type == 'VIEW_3D' and obj_align == 'VIEW'): - rot = context.space_data.region_3d.view_matrix.to_3x3().inverted().to_4x4() - else: - rot = Matrix() - align_matrix = loc * rot - return align_matrix -class add_mesh_bolt(Operator): +class add_mesh_bolt(Operator, AddObjectHelper): bl_idname = "mesh.bolt_add" bl_label = "Add Bolt" bl_options = {'REGISTER', 'UNDO', 'PRESET'} bl_description = "Construct many types of Bolts" - align_matrix = Matrix() + MAX_INPUT_NUMBER = 50 - # edit - Whether to add or update - edit = BoolProperty( - name="", - description="", - default=False, - options={'HIDDEN'} - ) + # Model Types Model_Type_List = [('bf_Model_Bolt', 'BOLT', 'Bolt Model'), ('bf_Model_Nut', 'NUT', 'Nut Model')] @@ -148,35 +133,35 @@ class add_mesh_bolt(Operator): ) bf_CounterSink_Head_Dia = FloatProperty( attr='bf_CounterSink_Head_Dia', - name='Head Dia', default=5.5, + name='Head Dia', default=6.300000190734863, min=0, soft_min=0, max=MAX_INPUT_NUMBER, description='Diameter of the Counter Sink Head' ) bf_Cap_Head_Height = FloatProperty( attr='bf_Cap_Head_Height', - name='Head Height', default=5.5, + name='Head Height', default=3, min=0, soft_min=0, max=MAX_INPUT_NUMBER, description='Height of the Cap Head' ) bf_Cap_Head_Dia = FloatProperty( attr='bf_Cap_Head_Dia', - name='Head Dia', default=3, + name='Head Dia', default=5.5, min=0, soft_min=0, max=MAX_INPUT_NUMBER, description='Diameter of the Cap Head' ) bf_Dome_Head_Dia = FloatProperty( attr='bf_Dome_Head_Dia', - name='Dome Head Dia', default=5.6, + name='Dome Head Dia', default=5.599999904632568, min=0, soft_min=0, max=MAX_INPUT_NUMBER, description='Length of the unthreaded shank' ) bf_Pan_Head_Dia = FloatProperty( attr='bf_Pan_Head_Dia', - name='Pan Head Dia', default=5.6, + name='Pan Head Dia', default=5.599999904632568, min=0, soft_min=0, max=MAX_INPUT_NUMBER, description='Diameter of the Pan Head') @@ -204,7 +189,7 @@ class add_mesh_bolt(Operator): bf_Pitch = FloatProperty( attr='bf_Pitch', - name='Pitch', default=0.35, + name='Pitch', default=0.3499999940395355, min=0.1, soft_min=0.1, max=7.0, description='Pitch if the thread' @@ -239,7 +224,7 @@ class add_mesh_bolt(Operator): ) bf_Hex_Nut_Height = FloatProperty( attr='bf_Hex_Nut_Height', - name='Hex Nut Height', default=2.4, + name='Hex Nut Height', default=2.4000000953674316, min=0, soft_min=0, max=MAX_INPUT_NUMBER, description='Height of the Hex Nut' @@ -251,6 +236,23 @@ class add_mesh_bolt(Operator): max=MAX_INPUT_NUMBER, description='Flat distance of the Hex Nut' ) + + # generic transform props + view_align = BoolProperty( + name="Align to View", + default=False, + update=AddObjectHelper.view_align_update_callback, + ) + + location = FloatVectorProperty( + name="Location", + subtype='TRANSLATION', + ) + + rotation = FloatVectorProperty( + name="Rotation", + subtype='EULER', + ) def draw(self, context): layout = self.layout @@ -309,18 +311,22 @@ class add_mesh_bolt(Operator): col.prop(self, 'bf_Crest_Percent') col.prop(self, 'bf_Root_Percent') col.prop(self, 'bf_Div_Count') + + # generic transform props + col.separator() + col.prop(self, 'view_align') + col.prop(self, 'location') + col.prop(self, 'rotation') @classmethod def poll(cls, context): return context.scene is not None def execute(self, context): - createMesh.Create_New_Mesh(self, context, self.align_matrix) + createMesh.Create_New_Mesh(self, context) return {'FINISHED'} def invoke(self, context, event): - # store creation_matrix - self.align_matrix = align_matrix(context) self.execute(context) return {'FINISHED'} diff --git a/add_mesh_BoltFactory/__init__.py b/add_mesh_BoltFactory/__init__.py index d4ad13c1ebc95c67e0c26b98e98c03ee4af4c0fb..46d250de92e44756a2e50c4d4da58d5a998bb4fb 100644 --- a/add_mesh_BoltFactory/__init__.py +++ b/add_mesh_BoltFactory/__init__.py @@ -19,7 +19,7 @@ bl_info = { "name": "BoltFactory", "author": "Aaron Keith", - "version": (0, 3, 3), + "version": (0, 3, 4), "blender": (2, 78, 0), "location": "View3D > Add > Mesh", "description": "Add a bolt or nut", diff --git a/add_mesh_BoltFactory/createMesh.py b/add_mesh_BoltFactory/createMesh.py index a211be2d5a4ccb3c9818cb49aa611ffbc08bfd08..31b74179ae1b785ffb93f7f8f0891822a2cf7487 100644 --- a/add_mesh_BoltFactory/createMesh.py +++ b/add_mesh_BoltFactory/createMesh.py @@ -26,6 +26,7 @@ from math import ( tan, radians, ) from random import triangular +from bpy_extras.object_utils import AddObjectHelper, object_data_add NARROW_UI = 180 MAX_INPUT_NUMBER = 50 @@ -69,7 +70,7 @@ Remove Doubles takes a list on Verts and a list of Faces and removes the doubles, much like Blender does in edit mode. It doesn’t have the range function but it will round the corrdinates and remove verts that are very close togther. The function -is useful because you can perform a “Remove Doubles” with out +is useful because you can perform a "Remove Doubles" with out having to enter Edit Mode. Having to enter edit mode has the disadvantage of not being able to interactively change the properties. """ @@ -1964,140 +1965,45 @@ def Bolt_Mesh(props, context): return Move_Verts_Up_Z(verts, Thread_Height), faces -# calculates the matrix for the new object -# depending on user pref -def align_matrix(context): - loc = Matrix.Translation(context.scene.cursor_location) - obj_align = context.user_preferences.edit.object_align - if (context.space_data.type == 'VIEW_3D' and obj_align == 'VIEW'): - rot = context.space_data.region_3d.view_matrix.to_3x3().inverted().to_4x4() - else: - rot = Matrix() - align_matrix = loc * rot - return align_matrix - - -# Create a new mesh (object) from verts/edges/faces. -# verts/edges/faces ... List of vertices/edges/faces for the -# new mesh (as used in from_pydata). -# name ... Name of the new mesh (& object). -# edit ... Replace existing mesh data. -# Note: Using "edit" will destroy/delete existing mesh data. -def create_mesh_object(context, verts, edges, faces, name, edit, align_matrix): - scene = context.scene - obj_act = scene.objects.active - - # Can't edit anything, unless we have an active obj. - if edit and not obj_act: - return None - - # Create new mesh - mesh = bpy.data.meshes.new(name) - - # Make a mesh from a list of verts/edges/faces. - mesh.from_pydata(verts, edges, faces) - - # Fix T51338 : Validate the mesh (the internal thread generator for the Nut - # should be more reliable now, however there could be other possible errors) - is_not_mesh_valid = mesh.validate() - - if is_not_mesh_valid: - print("\n[BoltFactory]\nFunction: create_mesh_object\n" - "Mesh is not Valid, correcting\n") - - # Update mesh geometry after adding stuff. - mesh.update() - - # Deselect all objects when in object mode - if bpy.ops.object.select_all.poll(): - bpy.ops.object.select_all(action='DESELECT') - - if edit: - # Replace geometry of existing object - - # Use the active obj and select it. - ob_new = obj_act - ob_new.select = True - - if obj_act.mode == 'OBJECT': - # Get existing mesh datablock. - old_mesh = ob_new.data - - # Set object data to nothing - ob_new.data = None - - # Clear users of existing mesh datablock. - old_mesh.user_clear() - # Remove old mesh datablock if no users are left. - if (old_mesh.users == 0): - bpy.data.meshes.remove(old_mesh) - # Assign new mesh datablock. - ob_new.data = mesh - else: - # Create new object - ob_new = bpy.data.objects.new(name, mesh) - - # Link new object to the given scene and select it. - scene.objects.link(ob_new) - ob_new.select = True - - # Place the object at the 3D cursor location. - # apply viewRotaion - ob_new.matrix_world = align_matrix - - if obj_act and obj_act.mode == 'EDIT': - if not edit: - # We are in EditMode, switch to ObjectMode. - bpy.ops.object.mode_set(mode='OBJECT') - - # Select the active object as well. - obj_act.select = True - # Apply location of new object. - scene.update() - - # Join new object into the active. - bpy.ops.object.join() - - # Switching back to EditMode. - bpy.ops.object.mode_set(mode='EDIT') - - ob_new = obj_act - - else: - # We are in ObjectMode. - # Make the new object the active one. - scene.objects.active = ob_new - return ob_new -def Create_New_Mesh(props, context, align_matrix): +def Create_New_Mesh(props, context): verts = [] faces = [] - # sMeshName ='' # UNUSED + edges = [] sObjName = '' if props.bf_Model_Type == 'bf_Model_Bolt': # print('Create Bolt') verts, faces = Bolt_Mesh(props, context) - # sMeshName = 'Bolt' # UNUSED sObjName = 'Bolt' if props.bf_Model_Type == 'bf_Model_Nut': # print('Create Nut') verts, faces = Nut_Mesh(props, context) - # sMeshName = 'Nut' # UNUSED sObjName = 'Nut' verts, faces = RemoveDoubles(verts, faces) verts = Scale_Mesh_Verts(verts, GLOBAL_SCALE) - obj = create_mesh_object(context, verts, [], faces, sObjName, - props.edit, align_matrix) + mesh = bpy.data.meshes.new(name=sObjName) + mesh.from_pydata(verts, edges, faces) + + # useful for development when the mesh may be invalid. + # Fix T51338 : Validate the mesh (the internal thread generator for the Nut + # should be more reliable now, however there could be other possible errors) + is_not_mesh_valid = mesh.validate() + + if is_not_mesh_valid: + print("\n[BoltFactory]\nFunction: create_mesh_object\n" + "Mesh is not Valid, correcting\n") + + object_data_add(context, mesh, operator=props) + - return obj