1 # SPDX-License-Identifier: GPL-2.0-or-later
6 from mathutils
import Matrix
7 from bpy
.types
import Operator
8 from bpy_extras
.object_utils
import AddObjectHelper
9 from bpy
.props
import (
17 from . import createMesh
18 from bpy_extras
import object_utils
21 class add_mesh_bolt(Operator
, AddObjectHelper
):
22 bl_idname
= "mesh.bolt_add"
24 bl_options
= {'REGISTER', 'UNDO', 'PRESET'}
25 bl_description
= "Construct many types of Bolts"
30 Bolt
: BoolProperty(name
= "Bolt",
33 change
: BoolProperty(name
= "Change",
35 description
= "change Bolt")
38 Model_Type_List
= [('bf_Model_Bolt', 'BOLT', 'Bolt Model'),
39 ('bf_Model_Nut', 'NUT', 'Nut Model')]
40 bf_Model_Type
: EnumProperty(
43 description
='Choose the type off model you would like',
44 items
=Model_Type_List
, default
='bf_Model_Bolt'
47 Model_Type_List
= [('bf_Head_Hex', 'HEX', 'Hex Head'),
48 ('bf_Head_12Pnt', '12 POINT', '12 Point Head'),
49 ('bf_Head_Cap', 'CAP', 'Cap Head'),
50 ('bf_Head_Dome', 'DOME', 'Dome Head'),
51 ('bf_Head_Pan', 'PAN', 'Pan Head'),
52 ('bf_Head_CounterSink', 'COUNTER SINK', 'Counter Sink Head')]
53 bf_Head_Type
: EnumProperty(
56 description
='Choose the type off Head you would like',
57 items
=Model_Type_List
, default
='bf_Head_Hex'
60 Bit_Type_List
= [('bf_Bit_None', 'NONE', 'No Bit Type'),
61 ('bf_Bit_Allen', 'ALLEN', 'Allen Bit Type'),
62 ('bf_Bit_Torx', 'TORX', 'Torx Bit Type'),
63 ('bf_Bit_Philips', 'PHILLIPS', 'Phillips Bit Type')]
64 bf_Bit_Type
: EnumProperty(
67 description
='Choose the type of bit to you would like',
68 items
=Bit_Type_List
, default
='bf_Bit_None'
71 Nut_Type_List
= [('bf_Nut_Hex', 'HEX', 'Hex Nut'),
72 ('bf_Nut_Lock', 'LOCK', 'Lock Nut'),
73 ('bf_Nut_12Pnt', '12 POINT', '12 Point Nut')]
74 bf_Nut_Type
: EnumProperty(
77 description
='Choose the type of nut you would like',
78 items
=Nut_Type_List
, default
='bf_Nut_Hex'
81 bf_Shank_Length
: FloatProperty(
82 attr
='bf_Shank_Length',
83 name
='Shank Length', default
=0,
84 min=0, soft_min
=0, max=MAX_INPUT_NUMBER
,
85 description
='Length of the unthreaded shank',
88 bf_Shank_Dia
: FloatProperty(
90 name
='Shank Dia', default
=3,
93 description
='Diameter of the shank',
96 bf_Phillips_Bit_Depth
: FloatProperty(
97 attr
='bf_Phillips_Bit_Depth',
98 name
='Bit Depth', default
=1.1431535482406616,
100 max=MAX_INPUT_NUMBER
,
101 description
='Depth of the Phillips Bit',
104 bf_Allen_Bit_Depth
: FloatProperty(
105 attr
='bf_Allen_Bit_Depth',
106 name
='Bit Depth', default
=1.5,
108 max=MAX_INPUT_NUMBER
,
109 description
='Depth of the Allen Bit',
112 bf_Allen_Bit_Flat_Distance
: FloatProperty(
113 attr
='bf_Allen_Bit_Flat_Distance',
114 name
='Flat Dist', default
=2.5,
116 max=MAX_INPUT_NUMBER
,
117 description
='Flat Distance of the Allen Bit',
121 Torx_Size_Type_List
= [('bf_Torx_T10', 'T10', 'T10'),
122 ('bf_Torx_T20', 'T20', 'T20'),
123 ('bf_Torx_T25', 'T25', 'T25'),
124 ('bf_Torx_T30', 'T30', 'T30'),
125 ('bf_Torx_T40', 'T40', 'T40'),
126 ('bf_Torx_T50', 'T50', 'T50'),
127 ('bf_Torx_T55', 'T55', 'T55'),
130 bf_Torx_Size_Type
: EnumProperty(
131 attr
='bf_Torx_Size_Type',
133 description
='Size of the Torx Bit',
134 items
=Torx_Size_Type_List
, default
='bf_Torx_T20'
136 bf_Torx_Bit_Depth
: FloatProperty(
137 attr
='bf_Torx_Bit_Depth',
138 name
='Bit Depth', default
=1.5,
140 max=MAX_INPUT_NUMBER
,
141 description
='Depth of the Torx Bit',
144 bf_Hex_Head_Height
: FloatProperty(
145 attr
='bf_Hex_Head_Height',
146 name
='Head Height', default
=2,
147 min=0, soft_min
=0, max=MAX_INPUT_NUMBER
,
148 description
='Height of the Hex Head',
151 bf_Hex_Head_Flat_Distance
: FloatProperty(
152 attr
='bf_Hex_Head_Flat_Distance',
153 name
='Flat Dist', default
=5.5,
155 max=MAX_INPUT_NUMBER
,
156 description
='Flat Distance of the Hex Head',
159 bf_12_Point_Head_Height
: FloatProperty(
160 attr
='bf_12_Point_Head_Height',
161 name
='Head Height', default
=3.0,
162 min=0, soft_min
=0, max=MAX_INPUT_NUMBER
,
163 description
='Height of the 12 Point Head',
166 bf_12_Point_Head_Flat_Distance
: FloatProperty(
167 attr
='bf_12_Point_Head_Flat_Distance',
168 name
='Flat Dist', default
=3.0,
169 min=0.001, soft_min
=0, #limit to 0.001 to avoid calculation error
170 max=MAX_INPUT_NUMBER
,
171 description
='Flat Distance of the 12 Point Head',
174 bf_12_Point_Head_Flange_Dia
: FloatProperty(
175 attr
='bf_12_Point_Head_Flange_Dia',
176 name
='12 Point Head Flange Dia', default
=5.5,
178 max=MAX_INPUT_NUMBER
,
179 description
='Flange diameter of the 12 point Head',
182 bf_CounterSink_Head_Dia
: FloatProperty(
183 attr
='bf_CounterSink_Head_Dia',
184 name
='Head Dia', default
=6.300000190734863,
186 max=MAX_INPUT_NUMBER
,
187 description
='Diameter of the Counter Sink Head',
190 bf_Cap_Head_Height
: FloatProperty(
191 attr
='bf_Cap_Head_Height',
192 name
='Head Height', default
=3,
194 max=MAX_INPUT_NUMBER
,
195 description
='Height of the Cap Head',
198 bf_Cap_Head_Dia
: FloatProperty(
199 attr
='bf_Cap_Head_Dia',
200 name
='Head Dia', default
=5.5,
202 max=MAX_INPUT_NUMBER
,
203 description
='Diameter of the Cap Head',
206 bf_Dome_Head_Dia
: FloatProperty(
207 attr
='bf_Dome_Head_Dia',
208 name
='Dome Head Dia', default
=5.599999904632568,
210 max=MAX_INPUT_NUMBER
,
211 description
='Length of the unthreaded shank',
214 bf_Pan_Head_Dia
: FloatProperty(
215 attr
='bf_Pan_Head_Dia',
216 name
='Pan Head Dia', default
=5.599999904632568,
218 max=MAX_INPUT_NUMBER
,
219 description
='Diameter of the Pan Head',
223 bf_Philips_Bit_Dia
: FloatProperty(
224 attr
='bf_Philips_Bit_Dia',
225 name
='Bit Dia', default
=1.8199999332427979,
227 max=MAX_INPUT_NUMBER
,
228 description
='Diameter of the Philips Bit',
232 bf_Thread_Length
: FloatProperty(
233 attr
='bf_Thread_Length',
234 name
='Thread Length', default
=6,
236 max=MAX_INPUT_NUMBER
,
237 description
='Length of the Thread',
241 bf_Major_Dia
: FloatProperty(
243 name
='Major Dia', default
=3,
245 max=MAX_INPUT_NUMBER
,
246 description
='Outside diameter of the Thread',
250 bf_Pitch
: FloatProperty(
252 name
='Pitch', default
=0.3499999940395355,
253 min=0.1, soft_min
=0.1,
255 description
='Pitch if the thread',
258 bf_Minor_Dia
: FloatProperty(
260 name
='Minor Dia', default
=2.6211137771606445,
262 max=MAX_INPUT_NUMBER
,
263 description
='Inside diameter of the Thread',
266 bf_Crest_Percent
: IntProperty(
267 attr
='bf_Crest_Percent',
268 name
='Crest Percent', default
=10,
271 description
='Percent of the pitch that makes up the Crest',
273 bf_Root_Percent
: IntProperty(
274 attr
='bf_Root_Percent',
275 name
='Root Percent', default
=10,
278 description
='Percent of the pitch that makes up the Root',
280 bf_Div_Count
: IntProperty(
282 name
='Div count', default
=36,
285 description
='Div count determine circle resolution',
287 bf_Hex_Nut_Height
: FloatProperty(
288 attr
='bf_Hex_Nut_Height',
289 name
='Hex Nut Height', default
=2.4000000953674316,
291 max=MAX_INPUT_NUMBER
,
292 description
='Height of the Hex Nut',
295 bf_Hex_Nut_Flat_Distance
: FloatProperty(
296 attr
='bf_Hex_Nut_Flat_Distance',
297 name
='Hex Nut Flat Dist', default
=5.5,
299 max=MAX_INPUT_NUMBER
,
300 description
='Flat distance of the Hex Nut',
303 bf_12_Point_Nut_Height
: FloatProperty(
304 attr
='bf_12_Point_Nut_Height',
305 name
='12 Point Nut Height', default
=2.4000000953674316,
307 max=MAX_INPUT_NUMBER
,
308 description
='Height of the 12 Point Nut',
312 bf_12_Point_Nut_Flat_Distance
: FloatProperty(
313 attr
='bf_12_Point_Nut_Flat_Distance',
314 name
='12 Point Nut Flat Dist', default
=3.0,
315 min=0.001, soft_min
=0, #limit to 0.001 to avoid calculation error
316 max=MAX_INPUT_NUMBER
,
317 description
='Flat distance of the 12 point Nut',
320 bf_12_Point_Nut_Flange_Dia
: FloatProperty(
321 attr
='bf_12_Point_Nut_Flange_Dia',
322 name
='12 Point Nut Flange Dia', default
=5.5,
324 max=MAX_INPUT_NUMBER
,
325 description
='Flange diameter of the 12 point Nut',
328 def draw(self
, context
):
330 col
= layout
.column()
333 col
.prop(self
, 'bf_Model_Type')
337 if self
.bf_Model_Type
== 'bf_Model_Bolt':
338 col
.prop(self
, 'bf_Bit_Type')
339 if self
.bf_Bit_Type
== 'bf_Bit_None':
341 elif self
.bf_Bit_Type
== 'bf_Bit_Allen':
342 col
.prop(self
, 'bf_Allen_Bit_Depth')
343 col
.prop(self
, 'bf_Allen_Bit_Flat_Distance')
344 elif self
.bf_Bit_Type
== 'bf_Bit_Torx':
345 col
.prop(self
, 'bf_Torx_Bit_Depth')
346 col
.prop(self
, 'bf_Torx_Size_Type')
347 elif self
.bf_Bit_Type
== 'bf_Bit_Philips':
348 col
.prop(self
, 'bf_Phillips_Bit_Depth')
349 col
.prop(self
, 'bf_Philips_Bit_Dia')
352 if self
.bf_Model_Type
== 'bf_Model_Bolt':
353 col
.prop(self
, 'bf_Head_Type')
354 if self
.bf_Head_Type
== 'bf_Head_Hex':
355 col
.prop(self
, 'bf_Hex_Head_Height')
356 col
.prop(self
, 'bf_Hex_Head_Flat_Distance')
357 elif self
.bf_Head_Type
== 'bf_Head_12Pnt':
358 col
.prop(self
, 'bf_12_Point_Head_Height')
359 col
.prop(self
, 'bf_12_Point_Head_Flat_Distance')
360 col
.prop(self
, 'bf_12_Point_Head_Flange_Dia')
361 elif self
.bf_Head_Type
== 'bf_Head_Cap':
362 col
.prop(self
, 'bf_Cap_Head_Height')
363 col
.prop(self
, 'bf_Cap_Head_Dia')
364 elif self
.bf_Head_Type
== 'bf_Head_Dome':
365 col
.prop(self
, 'bf_Dome_Head_Dia')
366 elif self
.bf_Head_Type
== 'bf_Head_Pan':
367 col
.prop(self
, 'bf_Pan_Head_Dia')
368 elif self
.bf_Head_Type
== 'bf_Head_CounterSink':
369 col
.prop(self
, 'bf_CounterSink_Head_Dia')
372 if self
.bf_Model_Type
== 'bf_Model_Bolt':
373 col
.label(text
='Shank')
374 col
.prop(self
, 'bf_Shank_Length')
375 col
.prop(self
, 'bf_Shank_Dia')
378 if self
.bf_Model_Type
== 'bf_Model_Nut':
379 col
.prop(self
, 'bf_Nut_Type')
380 if self
.bf_Nut_Type
== "bf_Nut_12Pnt":
381 col
.prop(self
, 'bf_12_Point_Nut_Height')
382 col
.prop(self
, 'bf_12_Point_Nut_Flat_Distance')
383 col
.prop(self
, 'bf_12_Point_Nut_Flange_Dia')
385 col
.prop(self
, 'bf_Hex_Nut_Height')
386 col
.prop(self
, 'bf_Hex_Nut_Flat_Distance')
391 col
.label(text
='Thread')
392 if self
.bf_Model_Type
== 'bf_Model_Bolt':
393 col
.prop(self
, 'bf_Thread_Length')
394 col
.prop(self
, 'bf_Major_Dia')
395 col
.prop(self
, 'bf_Minor_Dia')
396 col
.prop(self
, 'bf_Pitch')
397 col
.prop(self
, 'bf_Crest_Percent')
398 col
.prop(self
, 'bf_Root_Percent')
399 col
.prop(self
, 'bf_Div_Count')
401 if self
.change
== False:
402 # generic transform props
404 col
.prop(self
, 'align')
405 col
.prop(self
, 'location')
406 col
.prop(self
, 'rotation')
409 def poll(cls
, context
):
410 return context
.scene
is not None
412 def execute(self
, context
):
414 if bpy
.context
.mode
== "OBJECT":
415 if context
.selected_objects
!= [] and context
.active_object
and \
416 (context
.active_object
.data
is not None) and ('Bolt' in context
.active_object
.data
.keys()) and \
417 (self
.change
== True):
418 obj
= context
.active_object
419 use_auto_smooth
= bool(obj
.data
.use_auto_smooth
) # Copy value, do not take a reference
420 use_smooth
= bool(obj
.data
.polygons
[0].use_smooth
) # Copy value, do not take a reference
422 mesh
= createMesh
.Create_New_Mesh(self
, context
)
424 # Modify existing mesh data object by replacing geometry (but leaving materials etc)
430 # Preserve flat/smooth choice. New mesh is flat by default
431 obj
.data
.use_auto_smooth
= use_auto_smooth
433 bpy
.ops
.object.shade_smooth()
435 bpy
.data
.meshes
.remove(mesh
)
438 bpy
.ops
.object.vertex_group_remove(all
=True)
443 mesh
= createMesh
.Create_New_Mesh(self
, context
)
444 obj
= object_utils
.object_data_add(context
, mesh
, operator
=self
)
446 obj
.data
["Bolt"] = True
447 obj
.data
["change"] = False
448 for prm
in BoltParameters():
449 obj
.data
[prm
] = getattr(self
, prm
)
451 if bpy
.context
.mode
== "EDIT_MESH":
452 obj
= context
.edit_object
453 mesh
= createMesh
.Create_New_Mesh(self
, context
)
455 bm
= bmesh
.from_edit_mesh(obj
.data
) # Access edit mode's mesh data
456 bm
.from_mesh(mesh
) # Append new mesh data
457 bmesh
.update_edit_mesh(obj
.data
) # Flush changes (update edit mode's view)
459 bpy
.data
.meshes
.remove(mesh
) # Remove temporary mesh
463 def invoke(self
, context
, event
):
464 self
.execute(context
)
469 def Bolt_contex_menu(self
, context
):
475 if obj
.data
is not None and 'Bolt' in obj
.data
.keys():
476 props
= layout
.operator("mesh.bolt_add", text
="Change Bolt")
478 for prm
in BoltParameters():
479 setattr(props
, prm
, obj
.data
[prm
])
482 def menu_func_bolt(self
, context
):
485 oper
= self
.layout
.operator(add_mesh_bolt
.bl_idname
, text
="Bolt", icon
="MOD_SCREW")
496 bpy
.utils
.register_class(cls
)
497 bpy
.types
.VIEW3D_MT_mesh_add
.append(menu_func_bolt
)
498 bpy
.types
.VIEW3D_MT_object_context_menu
.prepend(Bolt_contex_menu
)
502 bpy
.types
.VIEW3D_MT_object_context_menu
.remove(Bolt_contex_menu
)
503 bpy
.types
.VIEW3D_MT_mesh_add
.remove(menu_func_bolt
)
504 for cls
in reversed(classes
):
505 bpy
.utils
.unregister_class(cls
)
507 def BoltParameters():
515 "bf_Phillips_Bit_Depth",
516 "bf_Allen_Bit_Depth",
517 "bf_Allen_Bit_Flat_Distance",
520 "bf_Hex_Head_Height",
521 "bf_Hex_Head_Flat_Distance",
522 "bf_CounterSink_Head_Dia",
523 "bf_Cap_Head_Height",
527 "bf_Philips_Bit_Dia",
536 "bf_Hex_Nut_Flat_Distance",
538 return BoltParameters