FBX IO: Add support for armature data custom properties
[blender-addons.git] / precision_drawing_tools / __init__.py
blob6d6086c0804bd1fad7d611aa5b888bb082e7e5c0
1 # SPDX-FileCopyrightText: 2019-2022 Alan Odom (Clockmender)
2 # SPDX-FileCopyrightText: 2019-2022 Rune Morling (ermo)
4 # SPDX-License-Identifier: GPL-2.0-or-later
6 # ----------------------------------------------
7 # Define Addon info
8 # ----------------------------------------------
10 bl_info = {
11 "name": "Precision Drawing Tools (PDT)",
12 "author": "Alan Odom (Clockmender), Rune Morling (ermo)",
13 "version": (1, 5, 3),
14 "blender": (3, 0, 0),
15 "location": "View3D > UI > PDT",
16 "description": "Precision Drawing Tools for Accurate Modelling",
17 "warning": "",
18 "doc_url": "{BLENDER_MANUAL_URL}/addons/3d_view/precision_drawing_tools/index.html",
19 "category": "3D View",
23 # ----------------------------------------------
24 # Import modules
25 # ----------------------------------------------
26 if "bpy" in locals():
27 import importlib
29 importlib.reload(pdt_design)
30 importlib.reload(pdt_pivot_point)
31 importlib.reload(pdt_menus)
32 importlib.reload(pdt_library)
33 importlib.reload(pdt_view)
34 importlib.reload(pdt_xall)
35 importlib.reload(pdt_bix)
36 importlib.reload(pdt_etof)
37 importlib.reload(pdt_tangent)
38 importlib.reload(pdt_trig_waves)
39 else:
40 from . import pdt_design
41 from . import pdt_pivot_point
42 from . import pdt_menus
43 from . import pdt_library
44 from . import pdt_view
45 from . import pdt_xall
46 from . import pdt_bix
47 from . import pdt_etof
48 from . import pdt_tangent
49 from . import pdt_trig_waves
51 import bpy
52 import os
53 from pathlib import Path
54 from bpy.types import (
55 AddonPreferences,
56 PropertyGroup, Scene,
57 WindowManager,
58 Object,
60 from bpy.props import (
61 BoolProperty,
62 CollectionProperty,
63 EnumProperty,
64 FloatProperty,
65 FloatVectorProperty,
66 IntProperty,
67 PointerProperty,
68 StringProperty,
70 from .pdt_msg_strings import (
71 PDT_DES_COORDS,
72 PDT_DES_FILLETPROF,
73 PDT_DES_FILLETRAD,
74 PDT_DES_FILLETSEG,
75 PDT_DES_FILLETVERTS,
76 PDT_DES_FILLINT,
77 PDT_DES_FLIPANG,
78 PDT_DES_FLIPPER,
79 PDT_DES_LIBCOLS,
80 PDT_DES_LIBMATS,
81 PDT_DES_LIBMODE,
82 PDT_DES_LIBOBS,
83 PDT_DES_LIBSER,
84 PDT_DES_MOVESEL,
85 PDT_DES_OBORDER,
86 PDT_DES_OFFANG,
87 PDT_DES_OFFDIS,
88 PDT_DES_OFFPER,
89 PDT_DES_OPMODE,
90 PDT_DES_OUTPUT,
91 PDT_DES_PIVOTDIS,
92 PDT_DES_PPLOC,
93 PDT_DES_PPSCALEFAC,
94 PDT_DES_PPSIZE,
95 PDT_DES_PPTRANS,
96 PDT_DES_PPWIDTH,
97 PDT_DES_ROTMOVAX,
98 PDT_DES_TRIM,
99 PDT_DES_VALIDLET,
100 PDT_DES_WORPLANE,
101 PDT_DES_TANCEN1,
102 PDT_DES_TANCEN2,
103 PDT_DES_TANCEN3,
104 PDT_DES_RADIUS1,
105 PDT_DES_RADIUS2,
106 PDT_DES_TPOINT,
107 PDT_DES_EXPCOLL,
108 PDT_DES_TANMODE,
110 from .pdt_command import command_run
111 from .pdt_functions import scale_set
114 # Declare enum items variables
116 _pdt_obj_items = []
117 _pdt_col_items = []
118 _pdt_mat_items = []
121 class PDTPreferences(AddonPreferences):
122 # This must match the addon name, use '__package__'
123 # when defining this in a submodule of a python package.
125 bl_idname = __name__
127 debug: BoolProperty(
128 name="Enable console debug output from PDT scripts",
129 default=False,
130 description="NOTE: Does not enable debugging globally in Blender (only in PDT scripts)",
133 pdt_ui_width: IntProperty(
134 name="UI Width Cut-off",
135 default=350,
136 description="Cutoff width for shrinking items per line in menus",
139 pdt_input_round: IntProperty(
140 name="Input Rounding", default=5, description="Rounding Factor for Inputs"
143 def draw(self, context):
144 layout = self.layout
146 box = layout.box()
147 row1 = box.row()
148 row2 = box.row()
149 row1.prop(self, "debug")
150 row2.prop(self, "pdt_ui_width")
151 row2.prop(self, "pdt_input_round")
154 def enumlist_objects(self, context):
155 """Populate Objects List from Parts Library.
157 Creates list of objects that optionally have search string contained in them
158 to populate variable pdt_lib_objects enumerator.
160 Args:
161 context: Blender bpy.context instance.
163 Returns:
164 list of Object Names.
167 scene = context.scene
168 pg = scene.pdt_pg
169 file_path = pg.pdt_library_path
170 path = Path(bpy.path.abspath(file_path))
171 _pdt_obj_items.clear()
173 if path.is_file() and ".blend" in str(path):
174 with bpy.data.libraries.load(str(path)) as (data_from, _):
175 if len(pg.object_search_string) == 0:
176 object_names = [obj for obj in data_from.objects]
177 else:
178 object_names = [obj for obj in data_from.objects if pg.object_search_string in obj]
179 for object_name in object_names:
180 _pdt_obj_items.append((object_name, object_name, ""))
181 else:
182 _pdt_obj_items.append(("MISSING", "Library Not Set", ""))
183 return _pdt_obj_items
186 def enumlist_collections(self, context):
187 """Populate Collections List from Parts Library.
189 Creates list of collections that optionally have search string contained in them
190 to populate variable pg.lib_collections enumerator
192 Args:
193 context: Blender bpy.context instance.
195 Returns:
196 list of Collections Names.
199 scene = context.scene
200 pg = scene.pdt_pg
201 file_path = pg.pdt_library_path
202 path = Path(bpy.path.abspath(file_path))
203 _pdt_col_items.clear()
205 if path.is_file() and ".blend" in str(path):
206 with bpy.data.libraries.load(str(path)) as (data_from, _):
207 if len(pg.collection_search_string) == 0:
208 object_names = [obj for obj in data_from.collections]
209 else:
210 object_names = [
211 obj for obj in data_from.collections if pg.collection_search_string in obj
213 for object_name in object_names:
214 _pdt_col_items.append((object_name, object_name, ""))
215 else:
216 _pdt_col_items.append(("MISSING", "Library Not Set", ""))
217 return _pdt_col_items
220 def enumlist_materials(self, context):
221 """Populate Materials List from Parts Library.
223 Creates list of materials that optionally have search string contained in them
224 to populate variable pg.lib_materials enumerator.
226 Args:
227 context: Blender bpy.context instance.
229 Returns:
230 list of Object Names.
233 scene = context.scene
234 pg = scene.pdt_pg
235 file_path = pg.pdt_library_path
236 path = Path(bpy.path.abspath(file_path))
237 _pdt_mat_items.clear()
239 if path.is_file() and ".blend" in str(path):
240 with bpy.data.libraries.load(str(path)) as (data_from, _):
241 if len(pg.material_search_string) == 0:
242 object_names = [obj for obj in data_from.materials]
243 else:
244 object_names = [
245 obj for obj in data_from.materials if pg.material_search_string in obj
247 for object_name in object_names:
248 _pdt_mat_items.append((object_name, object_name, ""))
249 else:
250 _pdt_mat_items.append(("MISSING", "Library Not Set", ""))
251 return _pdt_mat_items
254 class PDTSceneProperties(PropertyGroup):
255 """Contains all PDT related properties."""
257 pdt_library_path: StringProperty(
258 name="Library",
259 default="",
260 description="Parts Library File",
261 maxlen=1024,
262 subtype="FILE_PATH",
265 object_search_string: StringProperty(name="Search", default="", description=PDT_DES_LIBSER)
266 collection_search_string: StringProperty(name="Search", default="", description=PDT_DES_LIBSER)
267 material_search_string: StringProperty(name="Search", default="", description=PDT_DES_LIBSER)
269 cartesian_coords: FloatVectorProperty(
270 name="Coords", default=(0.0, 0.0, 0.0), subtype="XYZ", description=PDT_DES_COORDS
272 distance: FloatProperty(
273 name="Distance", default=0.0, precision=5, description=PDT_DES_OFFDIS, unit="LENGTH"
275 angle: FloatProperty(
276 name="Angle", min=-180, max=180, default=0.0, precision=5, description=PDT_DES_OFFANG
278 percent: FloatProperty(name="Percent", default=0.0, precision=5, description=PDT_DES_OFFPER)
279 plane: EnumProperty(
280 items=(
281 ("XZ", "Front(X-Z)", "Use X-Z Plane"),
282 ("XY", "Top(X-Y)", "Use X-Y Plane"),
283 ("YZ", "Right(Y-Z)", "Use Y-Z Plane"),
284 ("LO", "View", "Use View Plane"),
286 name="Working Plane",
287 default="XZ",
288 description=PDT_DES_WORPLANE,
290 select: EnumProperty(
291 items=(
292 ("REL", "Current Pos.", "Move Relative to Current Position"),
294 "SEL",
295 "Selected Entities",
296 "Move Relative to Selected Object or Vertex (Cursor & Pivot Only)",
299 name="Move Mode",
300 default="SEL",
301 description=PDT_DES_MOVESEL,
303 operation: EnumProperty(
304 items=(
305 ("CU", "Move Cursor", "This function will Move the Cursor"),
306 ("PP", "Move Pivot Point", "This function will Move the Pivot Point"),
307 ("MV", "Move Entities", "This function will Move selected Vertices or Objects"),
308 ("NV", "Add New Vertex", "This function will Add a New Vertex"),
310 "EV",
311 "Extrude Vertex/Vertices",
312 "This function will Extrude Vertex/Vertices Only in EDIT Mode",
314 ("SE", "Split Edges", "This function will Split Edges Only in EDIT Mode"),
316 "DG",
317 "Duplicate Geometry",
318 "This function will Duplicate Geometry in EDIT Mode (Delta & Direction Only)",
321 "EG",
322 "Extrude Geometry",
323 "This function will Extrude Geometry in EDIT Mode (Delta & Direction Only)",
326 name="Operation",
327 default="CU",
328 description=PDT_DES_OPMODE,
330 taper: EnumProperty(
331 items=(
332 ("RX-MY", "RotX-MovY", "Rotate X - Move Y"),
333 ("RX-MZ", "RotX-MovZ", "Rotate X - Move Z"),
334 ("RY-MX", "RotY-MovX", "Rotate Y - Move X"),
335 ("RY-MZ", "RotY-MovZ", "Rotate Y - Move Z"),
336 ("RZ-MX", "RotZ-MovX", "Rotate Z - Move X"),
337 ("RZ-MY", "RotZ-MovY", "Rotate Z - Move Y"),
339 name="Axes",
340 default="RX-MY",
341 description=PDT_DES_ROTMOVAX,
344 flip_angle: BoolProperty(name="Flip Angle", default=False, description=PDT_DES_FLIPANG)
345 flip_percent: BoolProperty(name="Flip %", default=False, description=PDT_DES_FLIPPER)
347 extend: BoolProperty(name="Trim/Extend All", default=False, description=PDT_DES_TRIM)
349 lib_objects: EnumProperty(items=enumlist_objects, name="Objects", description=PDT_DES_LIBOBS)
350 lib_collections: EnumProperty(
351 items=enumlist_collections, name="Collections", description=PDT_DES_LIBCOLS
353 lib_materials: EnumProperty(
354 items=enumlist_materials, name="Materials", description=PDT_DES_LIBMATS
356 lib_mode: EnumProperty(
357 items=(
358 ("OBJECTS", "Objects", "Use Objects"),
359 ("COLLECTIONS", "Collections", "Use Collections"),
360 ("MATERIALS", "Materials", "Use Materials"),
362 name="Mode",
363 default="OBJECTS",
364 description=PDT_DES_LIBMODE,
367 rotation_coords: FloatVectorProperty(
368 name="Rotation", default=(0.0, 0.0, 0.0), subtype="XYZ", description="Rotation Coordinates"
371 object_order: EnumProperty(
372 items=(
373 ("1,2,3,4", "1,2,3,4", "Objects 1 & 2 are First Line"),
374 ("1,3,2,4", "1,3,2,4", "Objects 1 & 3 are First Line"),
375 ("1,4,2,3", "1,4,2,3", "Objects 1 & 4 are First Line"),
377 name="Order",
378 default="1,2,3,4",
379 description=PDT_DES_OBORDER,
381 vrotangle: FloatProperty(name="View Rotate Angle", default=10, max=180, min=-180)
382 command: StringProperty(
383 name="Command", default="CA0,0,0", update=command_run, description=PDT_DES_VALIDLET,
385 maths_output: FloatProperty(
386 name="Maths output", default=0, description=PDT_DES_OUTPUT,
388 error: StringProperty(name="Error", default="")
390 # Was pivot* -- is now pivot_*
391 pivot_loc: FloatVectorProperty(
392 name="Pivot Location", default=(0.0, 0.0, 0.0), subtype="XYZ", description=PDT_DES_PPLOC,
394 pivot_scale: FloatVectorProperty(
395 name="Pivot Scale", default=(1.0, 1.0, 1.0), subtype="XYZ", description=PDT_DES_PPSCALEFAC
397 pivot_size: FloatProperty(
398 name="Pivot Factor", min=0.4, max=10, default=2, precision=1, description=PDT_DES_PPSIZE
400 pivot_width: IntProperty(name="Width", min=1, max=5, default=2, description=PDT_DES_PPWIDTH)
402 pivot_ang: FloatProperty(name="Pivot Angle", min=-180, max=180, default=0.0)
404 pivot_dis: FloatProperty(
405 name="Pivot Dist", default=0.0, min=0, update=scale_set, description=PDT_DES_PIVOTDIS,
407 pivot_alpha: FloatProperty(
408 name="Alpha", min=0.2, max=1, default=0.6, precision=1, description=PDT_DES_PPTRANS,
410 pivot_show: BoolProperty()
412 # Was filletrad
413 fillet_radius: FloatProperty(
414 name="Fillet Radius", min=0.0, default=1.0, unit="LENGTH", description=PDT_DES_FILLETRAD
416 # Was filletnum
417 fillet_segments: IntProperty(
418 name="Fillet Segments", min=1, default=4, description=PDT_DES_FILLETSEG
420 # Was filletpro
421 fillet_profile: FloatProperty(
422 name="Fillet Profile", min=0.0, max=1.0, default=0.5, description=PDT_DES_FILLETPROF
424 # Was filletbool
425 fillet_vertices_only: BoolProperty(
426 name="Fillet Vertices Only", default=True, description=PDT_DES_FILLETVERTS,
428 fillet_intersect: BoolProperty(
429 name="Intersect", default=False, description=PDT_DES_FILLINT,
431 tangent_point0: FloatVectorProperty(
432 name="Coordst1", default=(0.0, 0.0, 0.0), subtype="XYZ", description=PDT_DES_TANCEN1
434 tangent_point1: FloatVectorProperty(
435 name="Coordst2", default=(0.0, 0.0, 0.0), subtype="XYZ", description=PDT_DES_TANCEN2
437 tangent_radius0: FloatProperty(
438 name="Arc Radius 1", min=0.00001, default=1, unit="LENGTH", description=PDT_DES_RADIUS1
440 tangent_radius1: FloatProperty(
441 name="Arc Radius 2", min=0.00001, default=1, unit="LENGTH", description=PDT_DES_RADIUS2
443 tangent_point2: FloatVectorProperty(
444 name="Coordst3", default=(0.0, 0.0, 0.0), subtype="XYZ", description=PDT_DES_TANCEN3
446 menu_expand: BoolProperty(
447 name="Expand", default=False, description=PDT_DES_EXPCOLL,
449 tangent_mode: EnumProperty(
450 items=(
451 ("inner", "Inner", "Inner Tangents"),
452 ("outer", "Outer", "Outer Tangents"),
453 ("both", "Inner & Outer", "Inner & Outer Tangents"),
454 ("point", "From Point", "Tangents from Point"),
456 name="Working Plane",
457 default="both",
458 description=PDT_DES_TANMODE,
461 # For Trig Waves
462 trig_type : EnumProperty(
463 items=(
464 ("sin", "Sine", "Sine Wave"),
465 ("cos", "Cosine", "Cosine Wave"),
466 ("tan", "Tangent", "Tangent Wave"),
468 name="Wave Form",
469 default="sin",
470 description="Trig. Wave Form",
472 trig_cycles : IntProperty(name="Cycles #", default=1, min=1,
473 description="1 Cycle = 180 Degrees")
474 trig_amp : FloatProperty(name="Amplitude", default=1, min=0.01,
475 description="Maximum Height of 1 Cycle (forms Basis for Tangents)")
476 trig_len : FloatProperty(name="Cycle Length", default=2, min=0.02,
477 description="Length in Blender Units of 1 Cycle")
478 trig_obj : PointerProperty(name="Object", type=Object)
479 trig_del : BoolProperty(name="Empty Object", default=False,
480 description="Delete ALL Vertices in Object First")
481 trig_res : IntProperty(name="Resolution", default=18, min=4, max=72,
482 description="Number of Vertices per Cycle (180 Degrees)")
483 trig_tanmax : FloatProperty(name="Tangent Max", default=10, min=0.1,
484 description="Maximum Permitted Tangent Value")
485 trig_off : FloatVectorProperty(name="Start Location", default=(0,0,0),
486 description="Location in World Space for Origin of Wave")
487 trig_abs : BoolProperty(name="Absolute", default=False,
488 description="Use Absolute Values Only")
491 # List of All Classes in the Add-on to register
493 # Due to the way PropertyGroups work, this needs to be listed/loaded first
494 # (and unloaded last)
496 classes = (
497 PDTPreferences,
498 PDTSceneProperties,
499 pdt_bix.PDT_OT_LineOnBisection,
500 pdt_command.PDT_OT_CommandReRun,
501 pdt_design.PDT_OT_PlacementAbs,
502 pdt_design.PDT_OT_PlacementDelta,
503 pdt_design.PDT_OT_PlacementDis,
504 pdt_design.PDT_OT_PlacementView,
505 pdt_design.PDT_OT_PlacementCen,
506 pdt_design.PDT_OT_PlacementPer,
507 pdt_design.PDT_OT_PlacementNormal,
508 pdt_design.PDT_OT_PlacementInt,
509 pdt_design.PDT_OT_JoinVerts,
510 pdt_design.PDT_OT_Angle2,
511 pdt_design.PDT_OT_Angle3,
512 pdt_design.PDT_OT_Origin,
513 pdt_design.PDT_OT_Taper,
514 pdt_design.PDT_OT_Fillet,
515 pdt_etof.PDT_OT_EdgeToFace,
516 pdt_library.PDT_OT_Append,
517 pdt_library.PDT_OT_Link,
518 pdt_library.PDT_OT_LibShow,
519 pdt_menus.PDT_PT_PanelDesign,
520 pdt_menus.PDT_PT_PanelTools,
521 pdt_menus.PDT_PT_PanelTangent,
522 pdt_menus.PDT_PT_PanelCommandLine,
523 pdt_menus.PDT_PT_PanelViewControl,
524 pdt_menus.PDT_PT_PanelPivotPoint,
525 pdt_menus.PDT_PT_PanelPartsLibrary,
526 pdt_menus.PDT_PT_PanelTrig,
527 pdt_pivot_point.PDT_OT_ModalDrawOperator,
528 pdt_pivot_point.PDT_OT_ViewPlaneRotate,
529 pdt_pivot_point.PDT_OT_ViewPlaneScale,
530 pdt_pivot_point.PDT_OT_PivotToCursor,
531 pdt_pivot_point.PDT_OT_CursorToPivot,
532 pdt_pivot_point.PDT_OT_PivotSelected,
533 pdt_pivot_point.PDT_OT_PivotOrigin,
534 pdt_pivot_point.PDT_OT_PivotWrite,
535 pdt_pivot_point.PDT_OT_PivotRead,
536 pdt_tangent.PDT_OT_TangentOperate,
537 pdt_tangent.PDT_OT_TangentOperateSel,
538 pdt_tangent.PDT_OT_TangentSet1,
539 pdt_tangent.PDT_OT_TangentSet2,
540 pdt_tangent.PDT_OT_TangentSet3,
541 pdt_tangent.PDT_OT_TangentSet4,
542 pdt_tangent.PDT_OT_TangentExpandMenu,
543 pdt_trig_waves.PDT_OT_WaveGenerator,
544 pdt_view.PDT_OT_ViewRot,
545 pdt_view.PDT_OT_ViewRotL,
546 pdt_view.PDT_OT_ViewRotR,
547 pdt_view.PDT_OT_ViewRotU,
548 pdt_view.PDT_OT_ViewRotD,
549 pdt_view.PDT_OT_ViewRoll,
550 pdt_view.PDT_OT_ViewIso,
551 pdt_view.PDT_OT_Reset3DView,
552 pdt_xall.PDT_OT_IntersectAllEdges,
556 def register():
557 """Register Classes and Create Scene Variables.
559 Operates on the classes list defined above.
562 from bpy.utils import register_class
564 for cls in classes:
565 register_class(cls)
567 # OpenGL flag
569 window_manager = WindowManager
570 # Register Internal OpenGL Property
572 window_manager.pdt_run_opengl = BoolProperty(default=False)
574 Scene.pdt_pg = PointerProperty(type=PDTSceneProperties)
577 def unregister():
578 """Unregister Classes and Delete Scene Variables.
580 Operates on the classes list defined above.
583 from bpy.utils import unregister_class
585 # remove OpenGL data
586 pdt_pivot_point.PDT_OT_ModalDrawOperator.handle_remove(
587 pdt_pivot_point.PDT_OT_ModalDrawOperator, bpy.context
589 window_manager = bpy.context.window_manager
590 pdt_wm = "pdt_run_opengl"
591 if pdt_wm in window_manager:
592 del window_manager[pdt_wm]
594 for cls in reversed(classes):
595 unregister_class(cls)
597 del Scene.pdt_pg
600 if __name__ == "__main__":
601 register()