Fix mesh_snap_utilities_line running without key-maps available
[blender-addons.git] / precision_drawing_tools / __init__.py
blob19b2b810caca0f22f05c30e9be5607a6677e50a5
1 # ##### BEGIN GPL LICENSE BLOCK #####
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU General Public License
5 # as published by the Free Software Foundation; either version 2
6 # of the License, or (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software Foundation,
15 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 # ##### END GPL LICENSE BLOCK #####
19 # <pep8 compliant>
21 # -----------------------------------------------------------------------
22 # Author: Alan Odom (Clockmender), Rune Morling (ermo) Copyright (c) 2019
23 # -----------------------------------------------------------------------
25 # ----------------------------------------------
26 # Define Addon info
27 # ----------------------------------------------
29 bl_info = {
30 "name": "Precision Drawing Tools (PDT)",
31 "author": "Alan Odom (Clockmender), Rune Morling (ermo)",
32 "version": (1, 4, 0),
33 "blender": (2, 83, 0),
34 "location": "View3D > UI > PDT",
35 "description": "Precision Drawing Tools for Acccurate Modelling",
36 "warning": "",
37 "doc_url": "https://github.com/Clockmender/Precision-Drawing-Tools/wiki",
38 "category": "3D View",
42 # ----------------------------------------------
43 # Import modules
44 # ----------------------------------------------
45 if "bpy" in locals():
46 import importlib
48 importlib.reload(pdt_design)
49 importlib.reload(pdt_pivot_point)
50 importlib.reload(pdt_menus)
51 importlib.reload(pdt_library)
52 importlib.reload(pdt_view)
53 importlib.reload(pdt_xall)
54 importlib.reload(pdt_bix)
55 importlib.reload(pdt_etof)
56 importlib.reload(pdt_tangent)
57 importlib.reload(pdt_trig_waves)
58 else:
59 from . import pdt_design
60 from . import pdt_pivot_point
61 from . import pdt_menus
62 from . import pdt_library
63 from . import pdt_view
64 from . import pdt_xall
65 from . import pdt_bix
66 from . import pdt_etof
67 from . import pdt_tangent
68 from . import pdt_trig_waves
70 import bpy
71 import os
72 from pathlib import Path
73 from bpy.types import (
74 AddonPreferences,
75 PropertyGroup, Scene,
76 WindowManager,
77 Object,
79 from bpy.props import (
80 BoolProperty,
81 CollectionProperty,
82 EnumProperty,
83 FloatProperty,
84 FloatVectorProperty,
85 IntProperty,
86 PointerProperty,
87 StringProperty,
89 from .pdt_msg_strings import (
90 PDT_DES_COORDS,
91 PDT_DES_FILLETPROF,
92 PDT_DES_FILLETRAD,
93 PDT_DES_FILLETSEG,
94 PDT_DES_FILLETVERTS,
95 PDT_DES_FILLINT,
96 PDT_DES_FLIPANG,
97 PDT_DES_FLIPPER,
98 PDT_DES_LIBCOLS,
99 PDT_DES_LIBMATS,
100 PDT_DES_LIBMODE,
101 PDT_DES_LIBOBS,
102 PDT_DES_LIBSER,
103 PDT_DES_MOVESEL,
104 PDT_DES_OBORDER,
105 PDT_DES_OFFANG,
106 PDT_DES_OFFDIS,
107 PDT_DES_OFFPER,
108 PDT_DES_OPMODE,
109 PDT_DES_OUTPUT,
110 PDT_DES_PIVOTDIS,
111 PDT_DES_PPLOC,
112 PDT_DES_PPSCALEFAC,
113 PDT_DES_PPSIZE,
114 PDT_DES_PPTRANS,
115 PDT_DES_PPWIDTH,
116 PDT_DES_ROTMOVAX,
117 PDT_DES_TRIM,
118 PDT_DES_VALIDLET,
119 PDT_DES_WORPLANE,
120 PDT_DES_TANCEN1,
121 PDT_DES_TANCEN2,
122 PDT_DES_TANCEN3,
123 PDT_DES_RADIUS1,
124 PDT_DES_RADIUS2,
125 PDT_DES_TPOINT,
126 PDT_DES_EXPCOLL,
127 PDT_DES_TANMODE,
129 from .pdt_command import command_run
130 from .pdt_functions import scale_set
133 # Declare enum items variables
135 _pdt_obj_items = []
136 _pdt_col_items = []
137 _pdt_mat_items = []
140 class PDTPreferences(AddonPreferences):
141 # This must match the addon name, use '__package__'
142 # when defining this in a submodule of a python package.
144 bl_idname = __name__
146 debug: BoolProperty(
147 name="Enable console debug output from PDT scripts",
148 default=False,
149 description="NOTE: Does not enable debugging globally in Blender (only in PDT scripts)",
152 pdt_ui_width: IntProperty(
153 name="UI Width Cut-off",
154 default=350,
155 description="Cutoff width for shrinking items per line in menus",
158 pdt_input_round: IntProperty(
159 name="Input Rounding", default=5, description="Rounding Factor for Inputs"
162 def draw(self, context):
163 layout = self.layout
165 box = layout.box()
166 row1 = box.row()
167 row2 = box.row()
168 row1.prop(self, "debug")
169 row2.prop(self, "pdt_ui_width")
170 row2.prop(self, "pdt_input_round")
173 def enumlist_objects(self, context):
174 """Populate Objects List from Parts Library.
176 Creates list of objects that optionally have search string contained in them
177 to populate variable pdt_lib_objects enumerator.
179 Args:
180 context: Blender bpy.context instance.
182 Returns:
183 list of Object Names.
186 scene = context.scene
187 pg = scene.pdt_pg
188 file_path = pg.pdt_library_path
189 path = Path(bpy.path.abspath(file_path))
190 _pdt_obj_items.clear()
192 if path.is_file() and ".blend" in str(path):
193 with bpy.data.libraries.load(str(path)) as (data_from, _):
194 if len(pg.object_search_string) == 0:
195 object_names = [obj for obj in data_from.objects]
196 else:
197 object_names = [obj for obj in data_from.objects if pg.object_search_string in obj]
198 for object_name in object_names:
199 _pdt_obj_items.append((object_name, object_name, ""))
200 else:
201 _pdt_obj_items.append(("MISSING", "Library Not Set", ""))
202 return _pdt_obj_items
205 def enumlist_collections(self, context):
206 """Populate Collections List from Parts Library.
208 Creates list of collections that optionally have search string contained in them
209 to populate variable pg.lib_collections enumerator
211 Args:
212 context: Blender bpy.context instance.
214 Returns:
215 list of Collections Names.
218 scene = context.scene
219 pg = scene.pdt_pg
220 file_path = pg.pdt_library_path
221 path = Path(bpy.path.abspath(file_path))
222 _pdt_col_items.clear()
224 if path.is_file() and ".blend" in str(path):
225 with bpy.data.libraries.load(str(path)) as (data_from, _):
226 if len(pg.collection_search_string) == 0:
227 object_names = [obj for obj in data_from.collections]
228 else:
229 object_names = [
230 obj for obj in data_from.collections if pg.collection_search_string in obj
232 for object_name in object_names:
233 _pdt_col_items.append((object_name, object_name, ""))
234 else:
235 _pdt_col_items.append(("MISSING", "Library Not Set", ""))
236 return _pdt_col_items
239 def enumlist_materials(self, context):
240 """Populate Materials List from Parts Library.
242 Creates list of materials that optionally have search string contained in them
243 to populate variable pg.lib_materials enumerator.
245 Args:
246 context: Blender bpy.context instance.
248 Returns:
249 list of Object Names.
252 scene = context.scene
253 pg = scene.pdt_pg
254 file_path = pg.pdt_library_path
255 path = Path(bpy.path.abspath(file_path))
256 _pdt_mat_items.clear()
258 if path.is_file() and ".blend" in str(path):
259 with bpy.data.libraries.load(str(path)) as (data_from, _):
260 if len(pg.material_search_string) == 0:
261 object_names = [obj for obj in data_from.materials]
262 else:
263 object_names = [
264 obj for obj in data_from.materials if pg.material_search_string in obj
266 for object_name in object_names:
267 _pdt_mat_items.append((object_name, object_name, ""))
268 else:
269 _pdt_mat_items.append(("MISSING", "Library Not Set", ""))
270 return _pdt_mat_items
273 class PDTSceneProperties(PropertyGroup):
274 """Contains all PDT related properties."""
276 pdt_library_path: StringProperty(
277 name="Library",
278 default="",
279 description="Parts Library File",
280 maxlen=1024,
281 subtype="FILE_PATH",
284 object_search_string: StringProperty(name="Search", default="", description=PDT_DES_LIBSER)
285 collection_search_string: StringProperty(name="Search", default="", description=PDT_DES_LIBSER)
286 material_search_string: StringProperty(name="Search", default="", description=PDT_DES_LIBSER)
288 cartesian_coords: FloatVectorProperty(
289 name="Coords", default=(0.0, 0.0, 0.0), subtype="XYZ", description=PDT_DES_COORDS
291 distance: FloatProperty(
292 name="Distance", default=0.0, precision=5, description=PDT_DES_OFFDIS, unit="LENGTH"
294 angle: FloatProperty(
295 name="Angle", min=-180, max=180, default=0.0, precision=5, description=PDT_DES_OFFANG
297 percent: FloatProperty(name="Percent", default=0.0, precision=5, description=PDT_DES_OFFPER)
298 plane: EnumProperty(
299 items=(
300 ("XZ", "Front(X-Z)", "Use X-Z Plane"),
301 ("XY", "Top(X-Y)", "Use X-Y Plane"),
302 ("YZ", "Right(Y-Z)", "Use Y-Z Plane"),
303 ("LO", "View", "Use View Plane"),
305 name="Working Plane",
306 default="XZ",
307 description=PDT_DES_WORPLANE,
309 select: EnumProperty(
310 items=(
311 ("REL", "Current Pos.", "Move Relative to Current Position"),
313 "SEL",
314 "Selected Entities",
315 "Move Relative to Selected Object or Vertex (Cursor & Pivot Only)",
318 name="Move Mode",
319 default="SEL",
320 description=PDT_DES_MOVESEL,
322 operation: EnumProperty(
323 items=(
324 ("CU", "Move Cursor", "This function will Move the Cursor"),
325 ("PP", "Move Pivot Point", "This function will Move the Pivot Point"),
326 ("MV", "Move Entities", "This function will Move selected Vertices or Objects"),
327 ("NV", "Add New Vertex", "This function will Add a New Vertex"),
329 "EV",
330 "Extrude Vertex/Vertices",
331 "This function will Extrude Vertex/Vertices Only in EDIT Mode",
333 ("SE", "Split Edges", "This function will Split Edges Only in EDIT Mode"),
335 "DG",
336 "Duplicate Geometry",
337 "This function will Duplicate Geometry in EDIT Mode (Delta & Direction Only)",
340 "EG",
341 "Extrude Geometry",
342 "This function will Extrude Geometry in EDIT Mode (Delta & Direction Only)",
345 name="Operation",
346 default="CU",
347 description=PDT_DES_OPMODE,
349 taper: EnumProperty(
350 items=(
351 ("RX-MY", "RotX-MovY", "Rotate X - Move Y"),
352 ("RX-MZ", "RotX-MovZ", "Rotate X - Move Z"),
353 ("RY-MX", "RotY-MovX", "Rotate Y - Move X"),
354 ("RY-MZ", "RotY-MovZ", "Rotate Y - Move Z"),
355 ("RZ-MX", "RotZ-MovX", "Rotate Z - Move X"),
356 ("RZ-MY", "RotZ-MovY", "Rotate Z - Move Y"),
358 name="Axes",
359 default="RX-MY",
360 description=PDT_DES_ROTMOVAX,
363 flip_angle: BoolProperty(name="Flip Angle", default=False, description=PDT_DES_FLIPANG)
364 flip_percent: BoolProperty(name="Flip %", default=False, description=PDT_DES_FLIPPER)
366 extend: BoolProperty(name="Trim/Extend All", default=False, description=PDT_DES_TRIM)
368 lib_objects: EnumProperty(items=enumlist_objects, name="Objects", description=PDT_DES_LIBOBS)
369 lib_collections: EnumProperty(
370 items=enumlist_collections, name="Collections", description=PDT_DES_LIBCOLS
372 lib_materials: EnumProperty(
373 items=enumlist_materials, name="Materials", description=PDT_DES_LIBMATS
375 lib_mode: EnumProperty(
376 items=(
377 ("OBJECTS", "Objects", "Use Objects"),
378 ("COLLECTIONS", "Collections", "Use Collections"),
379 ("MATERIALS", "Materials", "Use Materials"),
381 name="Mode",
382 default="OBJECTS",
383 description=PDT_DES_LIBMODE,
386 rotation_coords: FloatVectorProperty(
387 name="Rotation", default=(0.0, 0.0, 0.0), subtype="XYZ", description="Rotation Coordinates"
390 object_order: EnumProperty(
391 items=(
392 ("1,2,3,4", "1,2,3,4", "Objects 1 & 2 are First Line"),
393 ("1,3,2,4", "1,3,2,4", "Objects 1 & 3 are First Line"),
394 ("1,4,2,3", "1,4,2,3", "Objects 1 & 4 are First Line"),
396 name="Order",
397 default="1,2,3,4",
398 description=PDT_DES_OBORDER,
400 vrotangle: FloatProperty(name="View Rotate Angle", default=10, max=180, min=-180)
401 command: StringProperty(
402 name="Command", default="CA0,0,0", update=command_run, description=PDT_DES_VALIDLET,
404 maths_output: FloatProperty(
405 name="Maths output", default=0, description=PDT_DES_OUTPUT,
407 error: StringProperty(name="Error", default="")
409 # Was pivot* -- is now pivot_*
410 pivot_loc: FloatVectorProperty(
411 name="Pivot Location", default=(0.0, 0.0, 0.0), subtype="XYZ", description=PDT_DES_PPLOC,
413 pivot_scale: FloatVectorProperty(
414 name="Pivot Scale", default=(1.0, 1.0, 1.0), subtype="XYZ", description=PDT_DES_PPSCALEFAC
416 pivot_size: FloatProperty(
417 name="Pivot Factor", min=0.4, max=10, default=2, precision=1, description=PDT_DES_PPSIZE
419 pivot_width: IntProperty(name="Width", min=1, max=5, default=2, description=PDT_DES_PPWIDTH)
421 pivot_ang: FloatProperty(name="Pivot Angle", min=-180, max=180, default=0.0)
423 pivot_dis: FloatProperty(
424 name="Pivot Dist", default=0.0, min=0, update=scale_set, description=PDT_DES_PIVOTDIS,
426 pivot_alpha: FloatProperty(
427 name="Alpha", min=0.2, max=1, default=0.6, precision=1, description=PDT_DES_PPTRANS,
429 pivot_show: BoolProperty()
431 # Was filletrad
432 fillet_radius: FloatProperty(
433 name="Fillet Radius", min=0.0, default=1.0, description=PDT_DES_FILLETRAD
435 # Was filletnum
436 fillet_segments: IntProperty(
437 name="Fillet Segments", min=1, default=4, description=PDT_DES_FILLETSEG
439 # Was filletpro
440 fillet_profile: FloatProperty(
441 name="Fillet Profile", min=0.0, max=1.0, default=0.5, description=PDT_DES_FILLETPROF
443 # Was filletbool
444 fillet_vertices_only: BoolProperty(
445 name="Fillet Vertices Only", default=True, description=PDT_DES_FILLETVERTS,
447 fillet_intersect: BoolProperty(
448 name="Intersect", default=False, description=PDT_DES_FILLINT,
450 tangent_point0: FloatVectorProperty(
451 name="Coordst1", default=(0.0, 0.0, 0.0), subtype="XYZ", description=PDT_DES_TANCEN1
453 tangent_point1: FloatVectorProperty(
454 name="Coordst2", default=(0.0, 0.0, 0.0), subtype="XYZ", description=PDT_DES_TANCEN2
456 tangent_radius0: FloatProperty(
457 name="Arc Radius 1", min=0.00001, default=1, description=PDT_DES_RADIUS1
459 tangent_radius1: FloatProperty(
460 name="Arc Radius 2", min=0.00001, default=1, description=PDT_DES_RADIUS2
462 tangent_point2: FloatVectorProperty(
463 name="Coordst3", default=(0.0, 0.0, 0.0), subtype="XYZ", description=PDT_DES_TANCEN3
465 menu_expand: BoolProperty(
466 name="Expand", default=False, description=PDT_DES_EXPCOLL,
468 tangent_mode: EnumProperty(
469 items=(
470 ("inner", "Inner", "Inner Tangents"),
471 ("outer", "Outer", "Outer Tangents"),
472 ("both", "Inner & Outer", "Inner & Outer Tangents"),
473 ("point", "From Point", "Tangents from Point"),
475 name="Working Plane",
476 default="both",
477 description=PDT_DES_TANMODE,
480 # For Trig Waves
481 trig_type : EnumProperty(
482 items=(
483 ("sin", "Sine", "Sine Wave"),
484 ("cos", "Cosine", "Cosine Wave"),
485 ("tan", "Tangent", "Tangent Wave"),
487 name="Wave Form",
488 default="sin",
489 description="Trig. Wave Form",
491 trig_cycles : IntProperty(name="Cycles #", default=1, min=1,
492 description="1 Cycle = 180 Degrees")
493 trig_amp : FloatProperty(name="Amplitude", default=1, min=0.01,
494 description="Maximum Height of 1 Cycle (forms Basis for Tangents)")
495 trig_len : FloatProperty(name="Cycle Length", default=2, min=0.02,
496 description="Length in Blender Units of 1 Cycle")
497 trig_obj : PointerProperty(name="Object", type=Object)
498 trig_del : BoolProperty(name="Empty Object", default=False,
499 description="Delete ALL Vertices in Object First")
500 trig_res : IntProperty(name="Resolution", default=18, min=4, max=72,
501 description="Number of Vertices per Cycle (180 Degrees)")
502 trig_tanmax : FloatProperty(name="Tangent Max", default=10, min=0.1,
503 description="Maximum Permitted Tangent Value")
504 trig_off : FloatVectorProperty(name="Start Location", default=(0,0,0),
505 description="Location in World Space for Origin of Wave")
506 trig_abs : BoolProperty(name="Absolute", default=False,
507 description="Use Absolute Values Only")
510 # List of All Classes in the Add-on to register
512 # Due to the way PropertyGroups work, this needs to be listed/loaded first
513 # (and unloaded last)
515 classes = (
516 PDTPreferences,
517 PDTSceneProperties,
518 pdt_bix.PDT_OT_LineOnBisection,
519 pdt_command.PDT_OT_CommandReRun,
520 pdt_design.PDT_OT_PlacementAbs,
521 pdt_design.PDT_OT_PlacementDelta,
522 pdt_design.PDT_OT_PlacementDis,
523 pdt_design.PDT_OT_PlacementCen,
524 pdt_design.PDT_OT_PlacementPer,
525 pdt_design.PDT_OT_PlacementNormal,
526 pdt_design.PDT_OT_PlacementInt,
527 pdt_design.PDT_OT_JoinVerts,
528 pdt_design.PDT_OT_Angle2,
529 pdt_design.PDT_OT_Angle3,
530 pdt_design.PDT_OT_Origin,
531 pdt_design.PDT_OT_Taper,
532 pdt_design.PDT_OT_Fillet,
533 pdt_etof.PDT_OT_EdgeToFace,
534 pdt_library.PDT_OT_Append,
535 pdt_library.PDT_OT_Link,
536 pdt_library.PDT_OT_LibShow,
537 pdt_menus.PDT_PT_PanelDesign,
538 pdt_menus.PDT_PT_PanelTools,
539 pdt_menus.PDT_PT_PanelTangent,
540 pdt_menus.PDT_PT_PanelCommandLine,
541 pdt_menus.PDT_PT_PanelViewControl,
542 pdt_menus.PDT_PT_PanelPivotPoint,
543 pdt_menus.PDT_PT_PanelPartsLibrary,
544 pdt_menus.PDT_PT_PanelTrig,
545 pdt_pivot_point.PDT_OT_ModalDrawOperator,
546 pdt_pivot_point.PDT_OT_ViewPlaneRotate,
547 pdt_pivot_point.PDT_OT_ViewPlaneScale,
548 pdt_pivot_point.PDT_OT_PivotToCursor,
549 pdt_pivot_point.PDT_OT_CursorToPivot,
550 pdt_pivot_point.PDT_OT_PivotSelected,
551 pdt_pivot_point.PDT_OT_PivotOrigin,
552 pdt_pivot_point.PDT_OT_PivotWrite,
553 pdt_pivot_point.PDT_OT_PivotRead,
554 pdt_tangent.PDT_OT_TangentOperate,
555 pdt_tangent.PDT_OT_TangentOperateSel,
556 pdt_tangent.PDT_OT_TangentSet1,
557 pdt_tangent.PDT_OT_TangentSet2,
558 pdt_tangent.PDT_OT_TangentSet3,
559 pdt_tangent.PDT_OT_TangentSet4,
560 pdt_tangent.PDT_OT_TangentExpandMenu,
561 pdt_trig_waves.PDT_OT_WaveGenerator,
562 pdt_view.PDT_OT_ViewRot,
563 pdt_view.PDT_OT_ViewRotL,
564 pdt_view.PDT_OT_ViewRotR,
565 pdt_view.PDT_OT_ViewRotU,
566 pdt_view.PDT_OT_ViewRotD,
567 pdt_view.PDT_OT_ViewRoll,
568 pdt_view.PDT_OT_ViewIso,
569 pdt_view.PDT_OT_Reset3DView,
570 pdt_xall.PDT_OT_IntersectAllEdges,
574 def register():
575 """Register Classes and Create Scene Variables.
577 Operates on the classes list defined above.
580 from bpy.utils import register_class
582 for cls in classes:
583 register_class(cls)
585 # OpenGL flag
587 window_manager = WindowManager
588 # Register Internal OpenGL Property
590 window_manager.pdt_run_opengl = BoolProperty(default=False)
592 Scene.pdt_pg = PointerProperty(type=PDTSceneProperties)
595 def unregister():
596 """Unregister Classes and Delete Scene Variables.
598 Operates on the classes list defined above.
601 from bpy.utils import unregister_class
603 # remove OpenGL data
604 pdt_pivot_point.PDT_OT_ModalDrawOperator.handle_remove(
605 pdt_pivot_point.PDT_OT_ModalDrawOperator, bpy.context
607 window_manager = bpy.context.window_manager
608 pdt_wm = "pdt_run_opengl"
609 if pdt_wm in window_manager:
610 del window_manager[pdt_wm]
612 for cls in reversed(classes):
613 unregister_class(cls)
615 del Scene.pdt_pg
618 if __name__ == "__main__":
619 register()