1 # SPDX-FileCopyrightText: 2010-2022 Blender Foundation
3 # SPDX-License-Identifier: GPL-2.0-or-later
8 from mathutils
import Matrix
9 from bpy
.types
import Operator
10 from bpy_extras
.object_utils
import AddObjectHelper
11 from bpy
.props
import (
19 from . import createMesh
20 from bpy_extras
import object_utils
23 class add_mesh_bolt(Operator
, AddObjectHelper
):
24 bl_idname
= "mesh.bolt_add"
26 bl_options
= {'REGISTER', 'UNDO', 'PRESET'}
27 bl_description
= "Construct many types of Bolts"
32 Bolt
: BoolProperty(name
= "Bolt",
35 change
: BoolProperty(name
= "Change",
37 description
= "change Bolt")
40 Model_Type_List
= [('bf_Model_Bolt', 'BOLT', 'Bolt Model'),
41 ('bf_Model_Nut', 'NUT', 'Nut Model')]
42 bf_Model_Type
: EnumProperty(
45 description
='Choose the type off model you would like',
46 items
=Model_Type_List
, default
='bf_Model_Bolt'
49 Model_Type_List
= [('bf_Head_Hex', 'HEX', 'Hex Head'),
50 ('bf_Head_12Pnt', '12 POINT', '12 Point Head'),
51 ('bf_Head_Cap', 'CAP', 'Cap Head'),
52 ('bf_Head_Dome', 'DOME', 'Dome Head'),
53 ('bf_Head_Pan', 'PAN', 'Pan Head'),
54 ('bf_Head_CounterSink', 'COUNTER SINK', 'Counter Sink Head')]
55 bf_Head_Type
: EnumProperty(
58 description
='Choose the type off Head you would like',
59 items
=Model_Type_List
, default
='bf_Head_Hex'
62 Bit_Type_List
= [('bf_Bit_None', 'NONE', 'No Bit Type'),
63 ('bf_Bit_Allen', 'ALLEN', 'Allen Bit Type'),
64 ('bf_Bit_Torx', 'TORX', 'Torx Bit Type'),
65 ('bf_Bit_Philips', 'PHILLIPS', 'Phillips Bit Type')]
66 bf_Bit_Type
: EnumProperty(
69 description
='Choose the type of bit to you would like',
70 items
=Bit_Type_List
, default
='bf_Bit_None'
73 Nut_Type_List
= [('bf_Nut_Hex', 'HEX', 'Hex Nut'),
74 ('bf_Nut_Lock', 'LOCK', 'Lock Nut'),
75 ('bf_Nut_12Pnt', '12 POINT', '12 Point Nut')]
76 bf_Nut_Type
: EnumProperty(
79 description
='Choose the type of nut you would like',
80 items
=Nut_Type_List
, default
='bf_Nut_Hex'
83 bf_Shank_Length
: FloatProperty(
84 attr
='bf_Shank_Length',
85 name
='Shank Length', default
=0,
86 min=0, soft_min
=0, max=MAX_INPUT_NUMBER
,
87 description
='Length of the unthreaded shank',
90 bf_Shank_Dia
: FloatProperty(
92 name
='Shank Dia', default
=3,
95 description
='Diameter of the shank',
98 bf_Phillips_Bit_Depth
: FloatProperty(
99 attr
='bf_Phillips_Bit_Depth',
100 name
='Bit Depth', default
=1.1431535482406616,
102 max=MAX_INPUT_NUMBER
,
103 description
='Depth of the Phillips Bit',
106 bf_Allen_Bit_Depth
: FloatProperty(
107 attr
='bf_Allen_Bit_Depth',
108 name
='Bit Depth', default
=1.5,
110 max=MAX_INPUT_NUMBER
,
111 description
='Depth of the Allen Bit',
114 bf_Allen_Bit_Flat_Distance
: FloatProperty(
115 attr
='bf_Allen_Bit_Flat_Distance',
116 name
='Flat Dist', default
=2.5,
118 max=MAX_INPUT_NUMBER
,
119 description
='Flat Distance of the Allen Bit',
123 Torx_Size_Type_List
= [('bf_Torx_T10', 'T10', 'T10'),
124 ('bf_Torx_T20', 'T20', 'T20'),
125 ('bf_Torx_T25', 'T25', 'T25'),
126 ('bf_Torx_T30', 'T30', 'T30'),
127 ('bf_Torx_T40', 'T40', 'T40'),
128 ('bf_Torx_T50', 'T50', 'T50'),
129 ('bf_Torx_T55', 'T55', 'T55'),
132 bf_Torx_Size_Type
: EnumProperty(
133 attr
='bf_Torx_Size_Type',
135 description
='Size of the Torx Bit',
136 items
=Torx_Size_Type_List
, default
='bf_Torx_T20'
138 bf_Torx_Bit_Depth
: FloatProperty(
139 attr
='bf_Torx_Bit_Depth',
140 name
='Bit Depth', default
=1.5,
142 max=MAX_INPUT_NUMBER
,
143 description
='Depth of the Torx Bit',
146 bf_Hex_Head_Height
: FloatProperty(
147 attr
='bf_Hex_Head_Height',
148 name
='Head Height', default
=2,
149 min=0, soft_min
=0, max=MAX_INPUT_NUMBER
,
150 description
='Height of the Hex Head',
153 bf_Hex_Head_Flat_Distance
: FloatProperty(
154 attr
='bf_Hex_Head_Flat_Distance',
155 name
='Flat Dist', default
=5.5,
157 max=MAX_INPUT_NUMBER
,
158 description
='Flat Distance of the Hex Head',
161 bf_12_Point_Head_Height
: FloatProperty(
162 attr
='bf_12_Point_Head_Height',
163 name
='Head Height', default
=3.0,
164 min=0, soft_min
=0, max=MAX_INPUT_NUMBER
,
165 description
='Height of the 12 Point Head',
168 bf_12_Point_Head_Flat_Distance
: FloatProperty(
169 attr
='bf_12_Point_Head_Flat_Distance',
170 name
='Flat Dist', default
=3.0,
171 min=0.001, soft_min
=0, #limit to 0.001 to avoid calculation error
172 max=MAX_INPUT_NUMBER
,
173 description
='Flat Distance of the 12 Point Head',
176 bf_12_Point_Head_Flange_Dia
: FloatProperty(
177 attr
='bf_12_Point_Head_Flange_Dia',
178 name
='12 Point Head Flange Dia', default
=5.5,
180 max=MAX_INPUT_NUMBER
,
181 description
='Flange diameter of the 12 point Head',
184 bf_CounterSink_Head_Dia
: FloatProperty(
185 attr
='bf_CounterSink_Head_Dia',
186 name
='Head Dia', default
=6.300000190734863,
188 max=MAX_INPUT_NUMBER
,
189 description
='Diameter of the Counter Sink Head',
192 bf_Cap_Head_Height
: FloatProperty(
193 attr
='bf_Cap_Head_Height',
194 name
='Head Height', default
=3,
196 max=MAX_INPUT_NUMBER
,
197 description
='Height of the Cap Head',
200 bf_Cap_Head_Dia
: FloatProperty(
201 attr
='bf_Cap_Head_Dia',
202 name
='Head Dia', default
=5.5,
204 max=MAX_INPUT_NUMBER
,
205 description
='Diameter of the Cap Head',
208 bf_Dome_Head_Dia
: FloatProperty(
209 attr
='bf_Dome_Head_Dia',
210 name
='Dome Head Dia', default
=5.599999904632568,
212 max=MAX_INPUT_NUMBER
,
213 description
='Length of the unthreaded shank',
216 bf_Pan_Head_Dia
: FloatProperty(
217 attr
='bf_Pan_Head_Dia',
218 name
='Pan Head Dia', default
=5.599999904632568,
220 max=MAX_INPUT_NUMBER
,
221 description
='Diameter of the Pan Head',
225 bf_Philips_Bit_Dia
: FloatProperty(
226 attr
='bf_Philips_Bit_Dia',
227 name
='Bit Dia', default
=1.8199999332427979,
229 max=MAX_INPUT_NUMBER
,
230 description
='Diameter of the Philips Bit',
234 bf_Thread_Length
: FloatProperty(
235 attr
='bf_Thread_Length',
236 name
='Thread Length', default
=6,
238 max=MAX_INPUT_NUMBER
,
239 description
='Length of the Thread',
243 bf_Major_Dia
: FloatProperty(
245 name
='Major Dia', default
=3,
247 max=MAX_INPUT_NUMBER
,
248 description
='Outside diameter of the Thread',
252 bf_Pitch
: FloatProperty(
254 name
='Pitch', default
=0.3499999940395355,
255 min=0.1, soft_min
=0.1,
257 description
='Pitch if the thread',
260 bf_Minor_Dia
: FloatProperty(
262 name
='Minor Dia', default
=2.6211137771606445,
264 max=MAX_INPUT_NUMBER
,
265 description
='Inside diameter of the Thread',
268 bf_Crest_Percent
: IntProperty(
269 attr
='bf_Crest_Percent',
270 name
='Crest Percent', default
=10,
273 description
='Percent of the pitch that makes up the Crest',
275 bf_Root_Percent
: IntProperty(
276 attr
='bf_Root_Percent',
277 name
='Root Percent', default
=10,
280 description
='Percent of the pitch that makes up the Root',
282 bf_Div_Count
: IntProperty(
284 name
='Div count', default
=36,
287 description
='Div count determine circle resolution',
289 bf_Hex_Nut_Height
: FloatProperty(
290 attr
='bf_Hex_Nut_Height',
291 name
='Hex Nut Height', default
=2.4000000953674316,
293 max=MAX_INPUT_NUMBER
,
294 description
='Height of the Hex Nut',
297 bf_Hex_Nut_Flat_Distance
: FloatProperty(
298 attr
='bf_Hex_Nut_Flat_Distance',
299 name
='Hex Nut Flat Dist', default
=5.5,
301 max=MAX_INPUT_NUMBER
,
302 description
='Flat distance of the Hex Nut',
305 bf_12_Point_Nut_Height
: FloatProperty(
306 attr
='bf_12_Point_Nut_Height',
307 name
='12 Point Nut Height', default
=2.4000000953674316,
309 max=MAX_INPUT_NUMBER
,
310 description
='Height of the 12 Point Nut',
314 bf_12_Point_Nut_Flat_Distance
: FloatProperty(
315 attr
='bf_12_Point_Nut_Flat_Distance',
316 name
='12 Point Nut Flat Dist', default
=3.0,
317 min=0.001, soft_min
=0, #limit to 0.001 to avoid calculation error
318 max=MAX_INPUT_NUMBER
,
319 description
='Flat distance of the 12 point Nut',
322 bf_12_Point_Nut_Flange_Dia
: FloatProperty(
323 attr
='bf_12_Point_Nut_Flange_Dia',
324 name
='12 Point Nut Flange Dia', default
=5.5,
326 max=MAX_INPUT_NUMBER
,
327 description
='Flange diameter of the 12 point Nut',
330 def draw(self
, context
):
332 col
= layout
.column()
335 col
.prop(self
, 'bf_Model_Type')
339 if self
.bf_Model_Type
== 'bf_Model_Bolt':
340 col
.prop(self
, 'bf_Bit_Type')
341 if self
.bf_Bit_Type
== 'bf_Bit_None':
343 elif self
.bf_Bit_Type
== 'bf_Bit_Allen':
344 col
.prop(self
, 'bf_Allen_Bit_Depth')
345 col
.prop(self
, 'bf_Allen_Bit_Flat_Distance')
346 elif self
.bf_Bit_Type
== 'bf_Bit_Torx':
347 col
.prop(self
, 'bf_Torx_Bit_Depth')
348 col
.prop(self
, 'bf_Torx_Size_Type')
349 elif self
.bf_Bit_Type
== 'bf_Bit_Philips':
350 col
.prop(self
, 'bf_Phillips_Bit_Depth')
351 col
.prop(self
, 'bf_Philips_Bit_Dia')
354 if self
.bf_Model_Type
== 'bf_Model_Bolt':
355 col
.prop(self
, 'bf_Head_Type')
356 if self
.bf_Head_Type
== 'bf_Head_Hex':
357 col
.prop(self
, 'bf_Hex_Head_Height')
358 col
.prop(self
, 'bf_Hex_Head_Flat_Distance')
359 elif self
.bf_Head_Type
== 'bf_Head_12Pnt':
360 col
.prop(self
, 'bf_12_Point_Head_Height')
361 col
.prop(self
, 'bf_12_Point_Head_Flat_Distance')
362 col
.prop(self
, 'bf_12_Point_Head_Flange_Dia')
363 elif self
.bf_Head_Type
== 'bf_Head_Cap':
364 col
.prop(self
, 'bf_Cap_Head_Height')
365 col
.prop(self
, 'bf_Cap_Head_Dia')
366 elif self
.bf_Head_Type
== 'bf_Head_Dome':
367 col
.prop(self
, 'bf_Dome_Head_Dia')
368 elif self
.bf_Head_Type
== 'bf_Head_Pan':
369 col
.prop(self
, 'bf_Pan_Head_Dia')
370 elif self
.bf_Head_Type
== 'bf_Head_CounterSink':
371 col
.prop(self
, 'bf_CounterSink_Head_Dia')
374 if self
.bf_Model_Type
== 'bf_Model_Bolt':
375 col
.label(text
='Shank')
376 col
.prop(self
, 'bf_Shank_Length')
377 col
.prop(self
, 'bf_Shank_Dia')
380 if self
.bf_Model_Type
== 'bf_Model_Nut':
381 col
.prop(self
, 'bf_Nut_Type')
382 if self
.bf_Nut_Type
== "bf_Nut_12Pnt":
383 col
.prop(self
, 'bf_12_Point_Nut_Height')
384 col
.prop(self
, 'bf_12_Point_Nut_Flat_Distance')
385 col
.prop(self
, 'bf_12_Point_Nut_Flange_Dia')
387 col
.prop(self
, 'bf_Hex_Nut_Height')
388 col
.prop(self
, 'bf_Hex_Nut_Flat_Distance')
393 col
.label(text
='Thread')
394 if self
.bf_Model_Type
== 'bf_Model_Bolt':
395 col
.prop(self
, 'bf_Thread_Length')
396 col
.prop(self
, 'bf_Major_Dia')
397 col
.prop(self
, 'bf_Minor_Dia')
398 col
.prop(self
, 'bf_Pitch')
399 col
.prop(self
, 'bf_Crest_Percent')
400 col
.prop(self
, 'bf_Root_Percent')
401 col
.prop(self
, 'bf_Div_Count')
403 if self
.change
== False:
404 # generic transform props
406 col
.prop(self
, 'align')
407 col
.prop(self
, 'location')
408 col
.prop(self
, 'rotation')
411 def poll(cls
, context
):
412 return context
.scene
is not None
414 def execute(self
, context
):
416 if bpy
.context
.mode
== "OBJECT":
417 if context
.selected_objects
!= [] and context
.active_object
and \
418 (context
.active_object
.data
is not None) and ('Bolt' in context
.active_object
.data
.keys()) and \
419 (self
.change
== True):
420 obj
= context
.active_object
421 use_smooth
= bool(obj
.data
.polygons
[0].use_smooth
) # Copy value, do not take a reference
423 mesh
= createMesh
.Create_New_Mesh(self
, context
)
425 # Modify existing mesh data object by replacing geometry (but leaving materials etc)
431 # Preserve flat/smooth choice. New mesh is flat by default
433 bpy
.ops
.object.shade_smooth()
435 bpy
.ops
.object.shade_flat()
437 bpy
.data
.meshes
.remove(mesh
)
440 bpy
.ops
.object.vertex_group_remove(all
=True)
445 mesh
= createMesh
.Create_New_Mesh(self
, context
)
446 obj
= object_utils
.object_data_add(context
, mesh
, operator
=self
)
448 obj
.data
["Bolt"] = True
449 obj
.data
["change"] = False
450 for prm
in BoltParameters():
451 obj
.data
[prm
] = getattr(self
, prm
)
453 if bpy
.context
.mode
== "EDIT_MESH":
454 obj
= context
.edit_object
455 mesh
= createMesh
.Create_New_Mesh(self
, context
)
457 bm
= bmesh
.from_edit_mesh(obj
.data
) # Access edit mode's mesh data
458 bm
.from_mesh(mesh
) # Append new mesh data
459 bmesh
.update_edit_mesh(obj
.data
) # Flush changes (update edit mode's view)
461 bpy
.data
.meshes
.remove(mesh
) # Remove temporary mesh
465 def invoke(self
, context
, event
):
466 self
.execute(context
)
471 def Bolt_contex_menu(self
, context
):
477 if obj
.data
is not None and 'Bolt' in obj
.data
.keys():
478 props
= layout
.operator("mesh.bolt_add", text
="Change Bolt")
480 for prm
in BoltParameters():
481 setattr(props
, prm
, obj
.data
[prm
])
484 def menu_func_bolt(self
, context
):
487 oper
= self
.layout
.operator(add_mesh_bolt
.bl_idname
, text
="Bolt", icon
="MOD_SCREW")
498 bpy
.utils
.register_class(cls
)
499 bpy
.types
.VIEW3D_MT_mesh_add
.append(menu_func_bolt
)
500 bpy
.types
.VIEW3D_MT_object_context_menu
.prepend(Bolt_contex_menu
)
504 bpy
.types
.VIEW3D_MT_object_context_menu
.remove(Bolt_contex_menu
)
505 bpy
.types
.VIEW3D_MT_mesh_add
.remove(menu_func_bolt
)
506 for cls
in reversed(classes
):
507 bpy
.utils
.unregister_class(cls
)
509 def BoltParameters():
517 "bf_Phillips_Bit_Depth",
518 "bf_Allen_Bit_Depth",
519 "bf_Allen_Bit_Flat_Distance",
522 "bf_Hex_Head_Height",
523 "bf_Hex_Head_Flat_Distance",
524 "bf_CounterSink_Head_Dia",
525 "bf_Cap_Head_Height",
529 "bf_Philips_Bit_Dia",
538 "bf_Hex_Nut_Flat_Distance",
540 return BoltParameters