Fix #105009: AnimAll: Error when inserting key on string attribute
[blender-addons.git] / add_mesh_BoltFactory / Boltfactory.py
blob8fc5e1e80bb8672bc5a965bedd412b52a6f5572d
1 # SPDX-FileCopyrightText: 2010-2022 Blender Foundation
3 # SPDX-License-Identifier: GPL-2.0-or-later
6 import bpy
7 import bmesh
8 from mathutils import Matrix
9 from bpy.types import Operator
10 from bpy_extras.object_utils import AddObjectHelper
11 from bpy.props import (
12 BoolProperty,
13 EnumProperty,
14 FloatProperty,
15 IntProperty,
16 FloatVectorProperty,
17 StringProperty,
19 from . import createMesh
20 from bpy_extras import object_utils
23 class add_mesh_bolt(Operator, AddObjectHelper):
24 bl_idname = "mesh.bolt_add"
25 bl_label = "Add Bolt"
26 bl_options = {'REGISTER', 'UNDO', 'PRESET'}
27 bl_description = "Construct many types of Bolts"
30 MAX_INPUT_NUMBER = 50
32 Bolt : BoolProperty(name = "Bolt",
33 default = True,
34 description = "Bolt")
35 change : BoolProperty(name = "Change",
36 default = False,
37 description = "change Bolt")
39 # Model Types
40 Model_Type_List = [('bf_Model_Bolt', 'BOLT', 'Bolt Model'),
41 ('bf_Model_Nut', 'NUT', 'Nut Model')]
42 bf_Model_Type: EnumProperty(
43 attr='bf_Model_Type',
44 name='Model',
45 description='Choose the type off model you would like',
46 items=Model_Type_List, default='bf_Model_Bolt'
48 # Head Types
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(
56 attr='bf_Head_Type',
57 name='Head',
58 description='Choose the type off Head you would like',
59 items=Model_Type_List, default='bf_Head_Hex'
61 # Bit Types
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(
67 attr='bf_Bit_Type',
68 name='Bit Type',
69 description='Choose the type of bit to you would like',
70 items=Bit_Type_List, default='bf_Bit_None'
72 # Nut Types
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(
77 attr='bf_Nut_Type',
78 name='Nut Type',
79 description='Choose the type of nut you would like',
80 items=Nut_Type_List, default='bf_Nut_Hex'
82 # Shank Types
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',
88 unit='LENGTH',
90 bf_Shank_Dia: FloatProperty(
91 attr='bf_Shank_Dia',
92 name='Shank Dia', default=3,
93 min=0, soft_min=0,
94 max=MAX_INPUT_NUMBER,
95 description='Diameter of the shank',
96 unit='LENGTH',
98 bf_Phillips_Bit_Depth: FloatProperty(
99 attr='bf_Phillips_Bit_Depth',
100 name='Bit Depth', default=1.1431535482406616,
101 min=0, soft_min=0,
102 max=MAX_INPUT_NUMBER,
103 description='Depth of the Phillips Bit',
104 unit='LENGTH',
106 bf_Allen_Bit_Depth: FloatProperty(
107 attr='bf_Allen_Bit_Depth',
108 name='Bit Depth', default=1.5,
109 min=0, soft_min=0,
110 max=MAX_INPUT_NUMBER,
111 description='Depth of the Allen Bit',
112 unit='LENGTH',
114 bf_Allen_Bit_Flat_Distance: FloatProperty(
115 attr='bf_Allen_Bit_Flat_Distance',
116 name='Flat Dist', default=2.5,
117 min=0, soft_min=0,
118 max=MAX_INPUT_NUMBER,
119 description='Flat Distance of the Allen Bit',
120 unit='LENGTH',
122 # Torx Size Types
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',
134 name='Torx Size',
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,
141 min=0, soft_min=0,
142 max=MAX_INPUT_NUMBER,
143 description='Depth of the Torx Bit',
144 unit='LENGTH',
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',
151 unit='LENGTH',
153 bf_Hex_Head_Flat_Distance: FloatProperty(
154 attr='bf_Hex_Head_Flat_Distance',
155 name='Flat Dist', default=5.5,
156 min=0, soft_min=0,
157 max=MAX_INPUT_NUMBER,
158 description='Flat Distance of the Hex Head',
159 unit='LENGTH',
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',
166 unit='LENGTH',
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',
174 unit='LENGTH',
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,
179 min=0, soft_min=0,
180 max=MAX_INPUT_NUMBER,
181 description='Flange diameter of the 12 point Head',
182 unit='LENGTH',
184 bf_CounterSink_Head_Dia: FloatProperty(
185 attr='bf_CounterSink_Head_Dia',
186 name='Head Dia', default=6.300000190734863,
187 min=0, soft_min=0,
188 max=MAX_INPUT_NUMBER,
189 description='Diameter of the Counter Sink Head',
190 unit='LENGTH',
192 bf_Cap_Head_Height: FloatProperty(
193 attr='bf_Cap_Head_Height',
194 name='Head Height', default=3,
195 min=0, soft_min=0,
196 max=MAX_INPUT_NUMBER,
197 description='Height of the Cap Head',
198 unit='LENGTH',
200 bf_Cap_Head_Dia: FloatProperty(
201 attr='bf_Cap_Head_Dia',
202 name='Head Dia', default=5.5,
203 min=0, soft_min=0,
204 max=MAX_INPUT_NUMBER,
205 description='Diameter of the Cap Head',
206 unit='LENGTH',
208 bf_Dome_Head_Dia: FloatProperty(
209 attr='bf_Dome_Head_Dia',
210 name='Dome Head Dia', default=5.599999904632568,
211 min=0, soft_min=0,
212 max=MAX_INPUT_NUMBER,
213 description='Length of the unthreaded shank',
214 unit='LENGTH',
216 bf_Pan_Head_Dia: FloatProperty(
217 attr='bf_Pan_Head_Dia',
218 name='Pan Head Dia', default=5.599999904632568,
219 min=0, soft_min=0,
220 max=MAX_INPUT_NUMBER,
221 description='Diameter of the Pan Head',
222 unit='LENGTH',
225 bf_Philips_Bit_Dia: FloatProperty(
226 attr='bf_Philips_Bit_Dia',
227 name='Bit Dia', default=1.8199999332427979,
228 min=0, soft_min=0,
229 max=MAX_INPUT_NUMBER,
230 description='Diameter of the Philips Bit',
231 unit='LENGTH',
234 bf_Thread_Length: FloatProperty(
235 attr='bf_Thread_Length',
236 name='Thread Length', default=6,
237 min=0, soft_min=0,
238 max=MAX_INPUT_NUMBER,
239 description='Length of the Thread',
240 unit='LENGTH',
243 bf_Major_Dia: FloatProperty(
244 attr='bf_Major_Dia',
245 name='Major Dia', default=3,
246 min=0, soft_min=0,
247 max=MAX_INPUT_NUMBER,
248 description='Outside diameter of the Thread',
249 unit='LENGTH',
252 bf_Pitch: FloatProperty(
253 attr='bf_Pitch',
254 name='Pitch', default=0.3499999940395355,
255 min=0.1, soft_min=0.1,
256 max=7.0,
257 description='Pitch if the thread',
258 unit='LENGTH',
260 bf_Minor_Dia: FloatProperty(
261 attr='bf_Minor_Dia',
262 name='Minor Dia', default=2.6211137771606445,
263 min=0, soft_min=0,
264 max=MAX_INPUT_NUMBER,
265 description='Inside diameter of the Thread',
266 unit='LENGTH',
268 bf_Crest_Percent: IntProperty(
269 attr='bf_Crest_Percent',
270 name='Crest Percent', default=10,
271 min=1, soft_min=1,
272 max=90,
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,
278 min=1, soft_min=1,
279 max=90,
280 description='Percent of the pitch that makes up the Root',
282 bf_Div_Count: IntProperty(
283 attr='bf_Div_Count',
284 name='Div count', default=36,
285 min=4, soft_min=4,
286 max=4096,
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,
292 min=0, soft_min=0,
293 max=MAX_INPUT_NUMBER,
294 description='Height of the Hex Nut',
295 unit='LENGTH',
297 bf_Hex_Nut_Flat_Distance: FloatProperty(
298 attr='bf_Hex_Nut_Flat_Distance',
299 name='Hex Nut Flat Dist', default=5.5,
300 min=0, soft_min=0,
301 max=MAX_INPUT_NUMBER,
302 description='Flat distance of the Hex Nut',
303 unit='LENGTH',
305 bf_12_Point_Nut_Height: FloatProperty(
306 attr='bf_12_Point_Nut_Height',
307 name='12 Point Nut Height', default=2.4000000953674316,
308 min=0, soft_min=0,
309 max=MAX_INPUT_NUMBER,
310 description='Height of the 12 Point Nut',
311 unit='LENGTH',
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',
320 unit='LENGTH',
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,
325 min=0, soft_min=0,
326 max=MAX_INPUT_NUMBER,
327 description='Flange diameter of the 12 point Nut',
328 unit='LENGTH',
330 def draw(self, context):
331 layout = self.layout
332 col = layout.column()
334 # ENUMS
335 col.prop(self, 'bf_Model_Type')
336 col.separator()
338 # Bit
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':
342 pass
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')
352 col.separator()
353 # Head
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')
372 col.separator()
373 # Shank
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')
378 col.separator()
379 # Nut
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')
386 else:
387 col.prop(self, 'bf_Hex_Nut_Height')
388 col.prop(self, 'bf_Hex_Nut_Flat_Distance')
392 # Thread
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
405 col.separator()
406 col.prop(self, 'align')
407 col.prop(self, 'location')
408 col.prop(self, 'rotation')
410 @classmethod
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)
426 bm = bmesh.new()
427 bm.from_mesh(mesh)
428 bm.to_mesh(obj.data)
429 bm.free()
431 # Preserve flat/smooth choice. New mesh is flat by default
432 if use_smooth:
433 bpy.ops.object.shade_smooth()
434 else:
435 bpy.ops.object.shade_flat()
437 bpy.data.meshes.remove(mesh)
439 try:
440 bpy.ops.object.vertex_group_remove(all=True)
441 except:
442 pass
444 else:
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
463 return {'FINISHED'}
465 def invoke(self, context, event):
466 self.execute(context)
468 return {'FINISHED'}
470 # Register:
471 def Bolt_contex_menu(self, context):
472 bl_label = 'Change'
474 obj = context.object
475 layout = self.layout
477 if obj.data is not None and 'Bolt' in obj.data.keys():
478 props = layout.operator("mesh.bolt_add", text="Change Bolt")
479 props.change = True
480 for prm in BoltParameters():
481 setattr(props, prm, obj.data[prm])
482 layout.separator()
484 def menu_func_bolt(self, context):
485 layout = self.layout
486 layout.separator()
487 oper = self.layout.operator(add_mesh_bolt.bl_idname, text="Bolt", icon="MOD_SCREW")
488 oper.change = False
490 classes = (
491 add_mesh_bolt,
496 def register():
497 for cls in classes:
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)
503 def unregister():
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():
510 BoltParameters = [
511 "bf_Model_Type",
512 "bf_Head_Type",
513 "bf_Bit_Type",
514 "bf_Nut_Type",
515 "bf_Shank_Length",
516 "bf_Shank_Dia",
517 "bf_Phillips_Bit_Depth",
518 "bf_Allen_Bit_Depth",
519 "bf_Allen_Bit_Flat_Distance",
520 "bf_Torx_Bit_Depth",
521 "bf_Torx_Size_Type",
522 "bf_Hex_Head_Height",
523 "bf_Hex_Head_Flat_Distance",
524 "bf_CounterSink_Head_Dia",
525 "bf_Cap_Head_Height",
526 "bf_Cap_Head_Dia",
527 "bf_Dome_Head_Dia",
528 "bf_Pan_Head_Dia",
529 "bf_Philips_Bit_Dia",
530 "bf_Thread_Length",
531 "bf_Major_Dia",
532 "bf_Pitch",
533 "bf_Minor_Dia",
534 "bf_Crest_Percent",
535 "bf_Root_Percent",
536 "bf_Div_Count",
537 "bf_Hex_Nut_Height",
538 "bf_Hex_Nut_Flat_Distance",
540 return BoltParameters