diff options
-rw-r--r-- | pdt_command_functions.py | 46 | ||||
-rw-r--r-- | pdt_exception.py | 7 | ||||
-rw-r--r-- | precision_drawing_tools/__init__.py | 203 | ||||
-rw-r--r-- | precision_drawing_tools/pdt_bix.py | 57 | ||||
-rw-r--r-- | precision_drawing_tools/pdt_cad_module.py | 92 | ||||
-rw-r--r-- | precision_drawing_tools/pdt_command.py | 197 | ||||
-rw-r--r-- | precision_drawing_tools/pdt_design.py | 46 | ||||
-rw-r--r-- | precision_drawing_tools/pdt_etof.py | 46 | ||||
-rw-r--r-- | precision_drawing_tools/pdt_functions.py | 344 | ||||
-rw-r--r-- | precision_drawing_tools/pdt_library.py | 69 | ||||
-rw-r--r-- | precision_drawing_tools/pdt_msg_strings.py | 256 | ||||
-rw-r--r-- | precision_drawing_tools/pdt_pivot_point.py | 71 | ||||
-rw-r--r-- | precision_drawing_tools/pdt_view.py | 46 | ||||
-rw-r--r-- | precision_drawing_tools/pdt_xall.py | 48 |
14 files changed, 809 insertions, 719 deletions
diff --git a/pdt_command_functions.py b/pdt_command_functions.py index 772f3fc0..f38ad1d0 100644 --- a/pdt_command_functions.py +++ b/pdt_command_functions.py @@ -21,11 +21,9 @@ # Author: Alan Odom (Clockmender), Rune Morling (ermo) Copyright (c) 2019 # ----------------------------------------------------------------------- # -import bpy import bmesh -import math -from math import sqrt, tan, pi import numpy as np +from math import sqrt, tan, pi from mathutils import Vector from mathutils.geometry import intersect_point_line from .pdt_functions import ( @@ -45,7 +43,7 @@ from .pdt_functions import ( from . import pdt_exception PDT_SelectionError = pdt_exception.SelectionError PDT_InvalidVector = pdt_exception.InvalidVector -PDT_ObjectMode = pdt_exception.ObjectMode +PDT_ObjectModeError = pdt_exception.ObjectModeError PDT_InfRadius = pdt_exception.InfRadius PDT_NoObjectError = pdt_exception.NoObjectError PDT_IntersectionError = pdt_exception.IntersectionError @@ -101,10 +99,13 @@ def vector_build(context, pg, obj, operation, values, num_values): flip_a = pg.flip_angle flip_p = pg.flip_percent + # Cartesian 3D coordinates if num_values == 3 and len(values) == 3: output_vector = Vector((float(values[0]), float(values[1]), float(values[2]))) + # Polar 2D coordinates elif num_values == 2 and len(values) == 2: output_vector = dis_ang(values, flip_a, plane, scene) + # Percentage of imaginary line between two 3D coordinates elif num_values == 1 and len(values) == 1: output_vector = get_percent(obj, flip_p, float(values[0]), operation, scene) else: @@ -115,7 +116,7 @@ def vector_build(context, pg, obj, operation, values, num_values): else: pg.error = PDT_ERR_BAD1VALS context.window_manager.popup_menu(oops, title="Error", icon="ERROR") - raise pdt_InvalidVector + raise PDT_InvalidVector return output_vector @@ -149,7 +150,7 @@ def placement_normal(context, operation): if obj is None: pg.error = PDT_ERR_NO_ACT_OBJ context.window_manager.popup_menu(oops, title="Error", icon="ERROR") - raise PDT_ObjectMode + raise PDT_ObjectModeError obj_loc = obj.matrix_world.decompose()[0] bm = bmesh.from_edit_mesh(obj.data) if len(bm.select_history) == 3: @@ -224,10 +225,9 @@ def placement_normal(context, operation): else: pg.error = f"{operation} {PDT_ERR_NON_VALID} {PDT_LAB_NOR}" context.window_manager.popup_menu(oops, title="Error", icon="ERROR") - return -def placement_centre(context, operation): +def placement_arc_centre(context, operation): """Manipulates Geometry, or Objects to an Arc Centre defined by 3 points on an Imaginary Arc. -- set position of CUrsor (CU) @@ -256,7 +256,7 @@ def placement_centre(context, operation): if obj is None: pg.error = PDT_ERR_NO_ACT_OBJ context.window_manager.popup_menu(oops, title="Error", icon="ERROR") - raise PDT_ObjectMode + raise PDT_ObjectModeError obj = context.view_layer.objects.active obj_loc = obj.matrix_world.decompose()[0] bm = bmesh.from_edit_mesh(obj.data) @@ -333,7 +333,6 @@ def placement_centre(context, operation): else: pg.error = f"{operation} {PDT_ERR_NON_VALID} {PDT_LAB_ARCCENTRE}" context.window_manager.popup_menu(oops, title="Error", icon="ERROR") - return def placement_intersect(context, operation): @@ -556,7 +555,7 @@ def join_two_vertices(context): else: pg.error = f"{PDT_ERR_EDOB_MODE},{obj.mode})" context.window_manager.popup_menu(oops, title="Error", icon="ERROR") - raise PDT_ObjectMode + raise PDT_ObjectModeError def set_angle_distance_two(context): @@ -631,15 +630,12 @@ def set_angle_distance_two(context): if plane == "LO": pg.distance = round(sqrt( (vector_a.x - vector_b.x) ** 2 + - (vector_a.y - vector_b.y) ** 2), val_round - ) + (vector_a.y - vector_b.y) ** 2), val_round) else: pg.distance = round(sqrt( (vector_a[a1] - vector_b[a1]) ** 2 + - (vector_a[a2] - vector_b[a2]) ** 2), val_round - ) - pg.cartesian_coords = Vector(([round(i, val_round) for i in (vector_b - vector_a)])) - return + (vector_a[a2] - vector_b[a2]) ** 2), val_round) + pg.cartesian_coords = Vector(([round(i, val_round) for i in vector_b - vector_a])) def set_angle_distance_three(context): @@ -672,7 +668,7 @@ def set_angle_distance_three(context): if vector_a is None: pg.error = PDT_ERR_VERT_MODE context.window_manager.popup_menu(oops, title="Error", icon="ERROR") - raise pdt_InvalidVector + raise PDT_InvalidVector else: pg.error = f"{PDT_ERR_SEL_3_VERTIO} {len(bm.select_history)})" context.window_manager.popup_menu(oops, title="Error", icon="ERROR") @@ -708,8 +704,7 @@ def set_angle_distance_three(context): else: pg.angle = round(ang, val_round) pg.distance = round((vector_a - vector_b).length, val_round) - pg.cartesian_coords = Vector(([round(i, val_round) for i in (vector_b - vector_a)])) - return + pg.cartesian_coords = Vector(([round(i, val_round) for i in vector_b - vector_a])) def origin_to_cursor(context): @@ -750,8 +745,7 @@ def origin_to_cursor(context): else: pg.error = f"{PDT_ERR_EDOB_MODE} {obj.mode})" context.window_manager.popup_menu(oops, title="Error", icon="ERROR") - raise PDT_ObjectMode - return + raise PDT_ObjectModeError def taper(context): @@ -809,7 +803,7 @@ def taper(context): v.co[a2] = v.co[a2] - (dis_v * tan(ang_v * pi / 180)) bmesh.update_edit_mesh(obj.data) bm.select_history.clear() - return - pg.error = f"{PDT_ERR_EDOB_MODE},{obj.mode})" - context.window_manager.popup_menu(oops, title="Error", icon="ERROR") - raise PDT_ObjectMode + else: + pg.error = f"{PDT_ERR_EDOB_MODE},{obj.mode})" + context.window_manager.popup_menu(oops, title="Error", icon="ERROR") + raise PDT_ObjectModeError diff --git a/pdt_exception.py b/pdt_exception.py index 4287974b..c33777ab 100644 --- a/pdt_exception.py +++ b/pdt_exception.py @@ -21,7 +21,7 @@ # Author: Alan Odom (Clockmender), Rune Morling (ermo) Copyright (c) 2019 # ----------------------------------------------------------------------- # -# Exception Routines +# Exceptions are used in the absence of nullable types in python class SelectionError(Exception): @@ -36,7 +36,7 @@ class CommandFailure(Exception): pass -class ObjectMode(Exception): +class ObjectModeError(Exception): pass @@ -66,3 +66,6 @@ class VerticesConnected(Exception): class InvalidAngle(Exception): pass + +class ShaderError(Exception): + pass diff --git a/precision_drawing_tools/__init__.py b/precision_drawing_tools/__init__.py index 81ef97e4..d3639acd 100644 --- a/precision_drawing_tools/__init__.py +++ b/precision_drawing_tools/__init__.py @@ -107,7 +107,7 @@ from .pdt_msg_strings import ( PDT_DES_ROTMOVAX, PDT_DES_TRIM, PDT_DES_VALIDLET, - PDT_DES_WORPLANE + PDT_DES_WORPLANE, ) from .pdt_command import command_run from .pdt_functions import scale_set @@ -176,7 +176,9 @@ def enumlist_collections(self, context): if len(pg.collection_search_string) == 0: object_names = [ob for ob in data_from.collections] else: - object_names = [ob for ob in data_from.collections if pg.collection_search_string in ob] + object_names = [ + ob for ob in data_from.collections if pg.collection_search_string in ob + ] for object_name in object_names: _pdt_col_items.append((object_name, object_name, "")) else: @@ -219,32 +221,21 @@ def enumlist_materials(self, context): class PDTSceneProperties(PropertyGroup): """Contains all PDT related properties.""" - object_search_string : StringProperty( - name="Search", default="", description=PDT_DES_LIBSER - ) - collection_search_string : StringProperty( - name="Search", default="", description=PDT_DES_LIBSER - ) - material_search_string : StringProperty( - name="Search", default="", description=PDT_DES_LIBSER - ) + object_search_string: StringProperty(name="Search", default="", description=PDT_DES_LIBSER) + collection_search_string: StringProperty(name="Search", default="", description=PDT_DES_LIBSER) + material_search_string: StringProperty(name="Search", default="", description=PDT_DES_LIBSER) - cartesian_coords : FloatVectorProperty( - name="Coords", - default=(0.0, 0.0, 0.0), - subtype="XYZ", - description=PDT_DES_COORDS + cartesian_coords: FloatVectorProperty( + name="Coords", default=(0.0, 0.0, 0.0), subtype="XYZ", description=PDT_DES_COORDS ) - distance : FloatProperty( + distance: FloatProperty( name="Distance", default=0.0, precision=5, description=PDT_DES_OFFDIS, unit="LENGTH" ) - angle : FloatProperty( + angle: FloatProperty( name="Angle", min=-180, max=180, default=0.0, precision=5, description=PDT_DES_OFFANG ) - percent : FloatProperty( - name="Percent", default=0.0, precision=5, description=PDT_DES_OFFPER - ) - plane : EnumProperty( + percent: FloatProperty(name="Percent", default=0.0, precision=5, description=PDT_DES_OFFPER) + plane: EnumProperty( items=( ("XZ", "Front(X-Z)", "Use X-Z Plane"), ("XY", "Top(X-Y)", "Use X-Y Plane"), @@ -255,7 +246,7 @@ class PDTSceneProperties(PropertyGroup): default="XZ", description=PDT_DES_WORPLANE, ) - select : EnumProperty( + select: EnumProperty( items=( ("REL", "Current Pos.", "Move Relative to Current Position"), ( @@ -268,13 +259,17 @@ class PDTSceneProperties(PropertyGroup): default="SEL", description=PDT_DES_MOVESEL, ) - operation : EnumProperty( + operation: EnumProperty( items=( ("CU", "Move Cursor", "This function will Move the Cursor"), ("PP", "Move Pivot Point", "This function will Move the Pivot Point"), ("MV", "Move Entities", "This function will Move selected Vertices or Objects"), ("NV", "Add New Vertex", "This function will Add a New Vertex"), - ("EV", "Extrude Vertex/Vertices", "This function will Extrude Vertex/Vertices Only in EDIT Mode"), + ( + "EV", + "Extrude Vertex/Vertices", + "This function will Extrude Vertex/Vertices Only in EDIT Mode", + ), ("SE", "Split Edges", "This function will Split Edges Only in EDIT Mode"), ( "DG", @@ -291,7 +286,7 @@ class PDTSceneProperties(PropertyGroup): default="CU", description=PDT_DES_OPMODE, ) - taper : EnumProperty( + taper: EnumProperty( items=( ("RX-MY", "RotX-MovY", "Rotate X - Move Y"), ("RX-MZ", "RotX-MovZ", "Rotate X - Move Z"), @@ -305,27 +300,19 @@ class PDTSceneProperties(PropertyGroup): description=PDT_DES_ROTMOVAX, ) - flip_angle : BoolProperty( - name="Flip Angle", default=False, description=PDT_DES_FLIPANG - ) - flip_percent : BoolProperty( - name="Flip %", default=False, description=PDT_DES_FLIPPER - ) + flip_angle: BoolProperty(name="Flip Angle", default=False, description=PDT_DES_FLIPANG) + flip_percent: BoolProperty(name="Flip %", default=False, description=PDT_DES_FLIPPER) - extend : BoolProperty( - name="Trim/Extend All", default=False, description=PDT_DES_TRIM - ) + extend: BoolProperty(name="Trim/Extend All", default=False, description=PDT_DES_TRIM) - lib_objects : EnumProperty( - items=enumlist_objects, name="Objects", description=PDT_DES_LIBOBS - ) - lib_collections : EnumProperty( + lib_objects: EnumProperty(items=enumlist_objects, name="Objects", description=PDT_DES_LIBOBS) + lib_collections: EnumProperty( items=enumlist_collections, name="Collections", description=PDT_DES_LIBCOLS ) - lib_materials : EnumProperty( + lib_materials: EnumProperty( items=enumlist_materials, name="Materials", description=PDT_DES_LIBMATS ) - lib_mode : EnumProperty( + lib_mode: EnumProperty( items=( ("OBJECTS", "Objects", "Use Objects"), ("COLLECTIONS", "Collections", "Use Collections"), @@ -336,14 +323,11 @@ class PDTSceneProperties(PropertyGroup): description=PDT_DES_LIBMODE, ) - rotation_coords : FloatVectorProperty( - name="Rotation", - default=(0.0, 0.0, 0.0), - subtype="XYZ", - description="Rotation Coordinates" + rotation_coords: FloatVectorProperty( + name="Rotation", default=(0.0, 0.0, 0.0), subtype="XYZ", description="Rotation Coordinates" ) - object_order : EnumProperty( + object_order: EnumProperty( items=( ("1,2,3,4", "1,2,3,4", "Objects 1 & 2 are First Line"), ("1,3,2,4", "1,3,2,4", "Objects 1 & 3 are First Line"), @@ -353,105 +337,86 @@ class PDTSceneProperties(PropertyGroup): default="1,2,3,4", description=PDT_DES_OBORDER, ) - vrotangle : FloatProperty(name="View Rotate Angle", default=10, max=180, min=-180) - command : StringProperty( - name="Command", - default="CA0,0,0", - update=command_run, - description=PDT_DES_VALIDLET, + vrotangle: FloatProperty(name="View Rotate Angle", default=10, max=180, min=-180) + command: StringProperty( + name="Command", default="CA0,0,0", update=command_run, description=PDT_DES_VALIDLET, ) - maths_output : FloatProperty( - name="Maths output", - default=0, - description=PDT_DES_OUTPUT, + maths_output: FloatProperty( + name="Maths output", default=0, description=PDT_DES_OUTPUT, ) - error : StringProperty(name="Error", default="") + error: StringProperty(name="Error", default="") # Was pivot* -- is now pivot_* - pivot_loc : FloatVectorProperty( - name="Pivot Location", - default=(0.0, 0.0, 0.0), - subtype="XYZ", - description=PDT_DES_PPLOC, + pivot_loc: FloatVectorProperty( + name="Pivot Location", default=(0.0, 0.0, 0.0), subtype="XYZ", description=PDT_DES_PPLOC, ) - pivot_scale : FloatVectorProperty( + pivot_scale: FloatVectorProperty( name="Pivot Scale", default=(1.0, 1.0, 1.0), subtype="XYZ", description=PDT_DES_PPSCALEFAC ) - pivot_size : FloatProperty( + pivot_size: FloatProperty( name="Pivot Factor", min=0.4, max=10, default=2, precision=1, description=PDT_DES_PPSIZE ) - pivot_width : IntProperty( - name="Width", min=1, max=5, default=2, description=PDT_DES_PPWIDTH - ) + pivot_width: IntProperty(name="Width", min=1, max=5, default=2, description=PDT_DES_PPWIDTH) # FIXME: might as well become pivot_angle - pivot_ang : FloatProperty(name="Pivot Angle", min=-180, max=180, default=0.0) + pivot_ang: FloatProperty(name="Pivot Angle", min=-180, max=180, default=0.0) # FIXME: pivot_dist for consistency? - pivot_dis : FloatProperty(name="Pivot Dist", - default=0.0, - min = 0, - update=scale_set, - description=PDT_DES_PIVOTDIS, + pivot_dis: FloatProperty( + name="Pivot Dist", default=0.0, min=0, update=scale_set, description=PDT_DES_PIVOTDIS, ) - pivot_alpha : FloatProperty( - name="Alpha", - min=0.2, - max=1, - default=0.6, - precision=1, - description=PDT_DES_PPTRANS, + pivot_alpha: FloatProperty( + name="Alpha", min=0.2, max=1, default=0.6, precision=1, description=PDT_DES_PPTRANS, ) - pivot_show : BoolProperty() + pivot_show: BoolProperty() # Was filletrad - fillet_radius : FloatProperty( + fillet_radius: FloatProperty( name="Fillet Radius", min=0.0, default=1.0, description=PDT_DES_FILLETRAD ) # Was filletnum - fillet_segments : IntProperty( + fillet_segments: IntProperty( name="Fillet Segments", min=1, default=4, description=PDT_DES_FILLETSEG ) # Was filletpro - fillet_profile : FloatProperty( + fillet_profile: FloatProperty( name="Fillet Profile", min=0.0, max=1.0, default=0.5, description=PDT_DES_FILLETPROF ) # Was filletbool - fillet_vertices_only : BoolProperty( - name="Fillet Vertices Only", - default=True, - description=PDT_DES_FILLETVERTS, + fillet_vertices_only: BoolProperty( + name="Fillet Vertices Only", default=True, description=PDT_DES_FILLETVERTS, ) - fillet_intersect : BoolProperty( - name="Intersect", - default=False, - description=PDT_DES_FILLINT, + fillet_intersect: BoolProperty( + name="Intersect", default=False, description=PDT_DES_FILLINT, ) class PDTPreferences(AddonPreferences): - # This must match the addon name, use '__package__' when defining this in a submodule of a python package. + # This must match the addon name, use '__package__' + # when defining this in a submodule of a python package. bl_idname = __name__ - pdt_library_path : StringProperty( - name="Parts Library", default="", description="Parts Library File", - maxlen=1024, subtype='FILE_PATH' + pdt_library_path: StringProperty( + name="Parts Library", + default="", + description="Parts Library File", + maxlen=1024, + subtype="FILE_PATH", ) - debug : BoolProperty( - name="Enable console debug output from PDT scripts", default=False, - description="NOTE: Does not enable debugging globally in Blender (only in PDT scripts)" + debug: BoolProperty( + name="Enable console debug output from PDT scripts", + default=False, + description="NOTE: Does not enable debugging globally in Blender (only in PDT scripts)", ) - pdt_ui_width : IntProperty( - name='UI Width Cut-off', + pdt_ui_width: IntProperty( + name="UI Width Cut-off", default=350, - description="Cutoff width for shrinking items per line in menus" + description="Cutoff width for shrinking items per line in menus", ) - pdt_input_round : IntProperty( - name='Input Rounding', - default=5, - description='Rounding Factor for Inputs' + pdt_input_round: IntProperty( + name="Input Rounding", default=5, description="Rounding Factor for Inputs" ) def draw(self, context): @@ -510,12 +475,12 @@ classes = ( pdt_pivot_point.PDT_OT_PivotWrite, pdt_pivot_point.PDT_OT_PivotRead, pdt_view.PDT_OT_ViewRot, - pdt_view.PDT_OT_vRotL, - pdt_view.PDT_OT_vRotR, - pdt_view.PDT_OT_vRotU, - pdt_view.PDT_OT_vRotD, - pdt_view.PDT_OT_vRoll, - pdt_view.PDT_OT_viso, + pdt_view.PDT_OT_ViewRotL, + pdt_view.PDT_OT_ViewRotR, + pdt_view.PDT_OT_ViewRotU, + pdt_view.PDT_OT_ViewRotD, + pdt_view.PDT_OT_ViewRoll, + pdt_view.PDT_OT_ViewIso, pdt_view.PDT_OT_Reset3DView, pdt_xall.PDT_OT_IntersectAllEdges, ) @@ -534,10 +499,10 @@ def register(): # OpenGL flag # - wm = WindowManager + window_manager = WindowManager # Register Internal OpenGL Property # - wm.pdt_run_opengl = BoolProperty(default=False) + window_manager.pdt_run_opengl = BoolProperty(default=False) Scene.pdt_pg = PointerProperty(type=PDTSceneProperties) @@ -554,10 +519,10 @@ def unregister(): pdt_pivot_point.PDT_OT_ModalDrawOperator.handle_remove( pdt_pivot_point.PDT_OT_ModalDrawOperator, bpy.context ) - wm = bpy.context.window_manager - p = "pdt_run_opengl" - if p in wm: - del wm[p] + window_manager = bpy.context.window_manager + pdt_wm = "pdt_run_opengl" + if pdt_wm in window_manager: + del window_manager[pdt_wm] for cls in reversed(classes): unregister_class(cls) diff --git a/precision_drawing_tools/pdt_bix.py b/precision_drawing_tools/pdt_bix.py index 0da468cb..f6b5cb66 100644 --- a/precision_drawing_tools/pdt_bix.py +++ b/precision_drawing_tools/pdt_bix.py @@ -34,6 +34,7 @@ from .pdt_msg_strings import ( ) from .pdt_functions import debug, oops + def add_line_to_bisection(context): """Computes Bisector of 2 Co-Planar Edges. @@ -47,8 +48,8 @@ def add_line_to_bisection(context): obj = context.object if all([bool(obj), obj.type == "MESH", obj.mode == "EDIT"]): pg = context.scene.pdt_pg - me = obj.data - bm = bmesh.from_edit_mesh(me) + obj_data = obj.data + bm = bmesh.from_edit_mesh(obj_data) bm.verts.ensure_lookup_table() bm.edges.ensure_lookup_table() @@ -60,39 +61,47 @@ def add_line_to_bisection(context): context.window_manager.popup_menu(oops, title="Error", icon="ERROR") return - [[v1, v2], [v3, v4]] = [[v.co for v in e.verts] for e in edges] - debug(f"vectors found:\n {v1}\n {v2}\n {v3}\n {v4}") + [[vector_a, vector_b], [vector_c, vector_d]] = [[v.co for v in e.verts] for e in edges] + debug(f"vectors found:\n {vector_a}\n {vector_b}\n {vector_c}\n {vector_d}") - dist1 = (v1 - v2).length - dist2 = (v3 - v4).length + dist1 = (vector_a - vector_b).length + dist2 = (vector_c - vector_d).length bdist = min([dist1, dist2]) - edge1 = (v1, v2) - edge2 = (v3, v4) + edge1 = (vector_a, vector_b) + edge2 = (vector_c, vector_d) if not cm.test_coplanar(edge1, edge2): pg.error = PDT_ERR_NCEDGES context.window_manager.popup_menu(oops, title="Error", icon="ERROR") return - # get pt and pick farthest vertex from (projected) intersections - pt = cm.get_intersection(edge1, edge2) - far1 = v2 if (v1 - pt).length < (v2 - pt).length else v1 - far2 = v4 if (v3 - pt).length < (v4 - pt).length else v3 - - dex1 = far1 - pt - dex2 = far2 - pt + # get intersect_point and pick farthest vertex from (projected) intersections + intersect_point = cm.get_intersection(edge1, edge2) + far1 = ( + vector_b + if (vector_a - intersect_point).length < (vector_b - intersect_point).length + else vector_a + ) + far2 = ( + vector_d + if (vector_c - intersect_point).length < (vector_d - intersect_point).length + else vector_c + ) + + dex1 = far1 - intersect_point + dex2 = far2 - intersect_point dex1 = dex1 * (bdist / dex1.length) dex2 = dex2 * (bdist / dex2.length) - pt2 = pt + (dex1).lerp(dex2, 0.5) - pt3 = pt2.lerp(pt, 2.0) + intersect_point2 = intersect_point + (dex1).lerp(dex2, 0.5) + intersect_point3 = intersect_point2.lerp(intersect_point, 2.0) - vec1 = bm.verts.new(pt2) - vec2 = bm.verts.new(pt) - vec3 = bm.verts.new(pt3) + vec1 = bm.verts.new(intersect_point2) + vec2 = bm.verts.new(intersect_point) + vec3 = bm.verts.new(intersect_point3) bm.edges.new((vec1, vec2)) bm.edges.new((vec2, vec3)) bmesh.ops.remove_doubles(bm, verts=bm.verts, dist=0.0001) - bmesh.update_edit_mesh(me) + bmesh.update_edit_mesh(obj_data) else: pg.error = f"{PDT_ERR_EDOB_MODE},{obj.mode})" context.window_manager.popup_menu(oops, title="Error", icon="ERROR") @@ -109,10 +118,10 @@ class PDT_OT_LineOnBisection(bpy.types.Operator): @classmethod def poll(cls, context): """Only allow operation on a mesh object in EDIT mode.""" - ob = context.active_object - if ob is None: + obj = context.active_object + if obj is None: return False - return all([ob is not None, ob.type == "MESH", ob.mode == "EDIT"]) + return all([obj is not None, obj.type == "MESH", obj.mode == "EDIT"]) def execute(self, context): """Computes Bisector of 2 Co-Planar Edges. diff --git a/precision_drawing_tools/pdt_cad_module.py b/precision_drawing_tools/pdt_cad_module.py index 21a5c6c7..6e6294e6 100644 --- a/precision_drawing_tools/pdt_cad_module.py +++ b/precision_drawing_tools/pdt_cad_module.py @@ -3,7 +3,7 @@ # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. +# of the License, or (at your ointersect_pointion) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -28,19 +28,20 @@ from mathutils import Vector from mathutils.geometry import intersect_line_line, intersect_point_line from .pdt_functions import debug -def point_on_edge(p, edge): + +def point_on_edge(point, edge): """Find Point on Edge. Args: - p: vector + point: vector edge: tuple containing 2 vectors. Returns: True if point p happens to lie on the edge, False otherwise. """ - pt, _percent = intersect_point_line(p, *edge) - on_line = (pt - p).length < 1.0e-5 + intersect_point, _percent = intersect_point_line(point, *edge) + on_line = (intersect_point - point).length < 1.0e-5 return on_line and (0.0 <= _percent <= 1.0) @@ -56,8 +57,10 @@ def line_from_edge_intersect(edge1, edge2): Output of intersect_line_line. """ - [p1, p2], [p3, p4] = edge1, edge2 - return intersect_line_line(p1, p2, p3, p4) + [intersect_point1, intersect_point2], [intersect_point3, intersect_point4] = edge1, edge2 + return intersect_line_line( + intersect_point1, intersect_point2, intersect_point3, intersect_point4 + ) def get_intersection(edge1, edge2): @@ -73,6 +76,7 @@ def get_intersection(edge1, edge2): line = line_from_edge_intersect(edge1, edge2) if line: return (line[0] + line[1]) / 2 + return None def test_coplanar(edge1, edge2): @@ -92,50 +96,53 @@ def test_coplanar(edge1, edge2): line = line_from_edge_intersect(edge1, edge2) if line: return (line[0] - line[1]).length < 1.0e-5 + return None -def closest_idx(pt, e): +def closest_idx(intersect_point, edge): """Get Closest Vertex to input point. - If both points in e are equally far from pt, then v1 is returned. + If both points in e are equally far from intersect_point, then v1 is returned. Args: - pt: vector - e: bmesh edge + intersect_point: vector + edge: bmesh edge Returns: - Index of vertex closest to pt. + Index of vertex closest to intersect_point. """ - if isinstance(e, bmesh.types.BMEdge): - ev = e.verts - v1 = ev[0].co - v2 = ev[1].co - distance_test = (v1 - pt).length <= (v2 - pt).length - return ev[0].index if distance_test else ev[1].index + if isinstance(edge, bmesh.types.BMEdge): + edge_verts = edge.verts + vector_a = edge_verts[0].co + vector_b = edge_verts[1].co + distance_test = (vector_a - intersect_point).length <= (vector_b - intersect_point).length + return edge_verts[0].index if distance_test else edge_verts[1].index - debug(f"Received {e}, check expected input in docstring ") + debug(f"Received {edge}, check expected input in docstring ") + return None -def closest_vector(pt, e): +def closest_vector(intersect_point, edge): """Return Closest Vector to input Point. - If both points in e are equally far from pt, then v1 is returned. + If both points in e are equally far from intersect_point, then v1 is returned. Args: - pt: vector - e: tuple containing 2 vectors + intersect_point: vector + edge: tuple containing 2 vectors Returns: - Vector closest to pt. + Vector closest to intersect_point. """ - if isinstance(e, tuple) and all([isinstance(co, Vector) for co in e]): - v1, v2 = e - distance_test = (v1 - pt).length <= (v2 - pt).length - return v1 if distance_test else v2 + if isinstance(edge, tuple) and all([isinstance(co, Vector) for co in edge]): + vector_a, vector_b = edge + distance_test = (vector_a - intersect_point).length <= (vector_b - intersect_point).length + return vector_a if distance_test else vector_b - debug(f"Received {e}, check expected input in docstring ") + debug(f"Received {edge}, check expected input in docstring ") + return None def coords_tuple_from_edge_idx(bm, idx): @@ -159,8 +166,8 @@ def vertex_indices_from_edges_tuple(bm, edge_tuple): The vertex indices of edge_tuple. """ - def k(v, w): - return bm.edges[edge_tuple[v]].verts[w].index + def k(ind_v, ind_w): + return bm.edges[edge_tuple[ind_v]].verts[ind_w].index return [k(i >> 1, i % 2) for i in range(4)] @@ -182,29 +189,38 @@ def get_vert_indices_from_bmedges(edges): return temp_edges -def num_edges_point_lies_on(pt, edges): +def num_edges_point_lies_on(intersect_point, edges): """Returns the number of edges that a point lies on.""" - res = [point_on_edge(pt, edge) for edge in [edges[:2], edges[2:]]] + res = [point_on_edge(intersect_point, edge) for edge in [edges[:2], edges[2:]]] return len([i for i in res if i]) -def find_intersecting_edges(bm, pt, idx1, idx2): +def find_intersecting_edges(bm, intersect_point, idx1, idx2): """Find Intercecting Edges. Args: - pt: Vector + intersect_point: Vector idx1, ix2: edge indices Returns: - The list of edge indices where pt is on those edges. + The list of edge indices where intersect_point is on those edges. """ - if not pt: + if not intersect_point: return [] idxs = [idx1, idx2] edges = [coords_tuple_from_edge_idx(bm, idx) for idx in idxs] - return [idx for edge, idx in zip(edges, idxs) if point_on_edge(pt, edge)] + return [idx for edge, idx in zip(edges, idxs) if point_on_edge(intersect_point, edge)] def vert_idxs_from_edge_idx(bm, idx): + """Find Vertex Indices form Edge Indices. + + Args: + Object Bmesh as bm + Selection Index as idx + + Returns: + Vertex Indices of Edge. + """ edge = bm.edges[idx] return edge.verts[0].index, edge.verts[1].index diff --git a/precision_drawing_tools/pdt_command.py b/precision_drawing_tools/pdt_command.py index 0776feb8..3aa7bafc 100644 --- a/precision_drawing_tools/pdt_command.py +++ b/precision_drawing_tools/pdt_command.py @@ -40,7 +40,7 @@ from .pdt_command_functions import ( origin_to_cursor, taper, placement_normal, - placement_centre, + placement_arc_centre, placement_intersect, ) from .pdt_msg_strings import ( @@ -59,6 +59,8 @@ from .pdt_msg_strings import ( PDT_ERR_BADMATHS, PDT_OBJ_MODE_ERROR, PDT_ERR_SEL_4_VERTS, + PDT_ERR_INT_LINES, + PDT_LAB_PLANE, ) from .pdt_bix import add_line_to_bisection from .pdt_etof import extend_vertex @@ -68,8 +70,9 @@ from . import pdt_exception PDT_SelectionError = pdt_exception.SelectionError PDT_InvalidVector = pdt_exception.InvalidVector PDT_CommandFailure = pdt_exception.CommandFailure -PDT_ObjectMode = pdt_exception.ObjectMode -PDT_MathError = pdt_exception.MathsError +PDT_ObjectModeError = pdt_exception.ObjectModeError +PDT_MathsError = pdt_exception.MathsError +PDT_IntersectionError = pdt_exception.IntersectionError class PDT_OT_CommandReRun(Operator): @@ -149,7 +152,7 @@ def command_run(self, context): if obj.mode not in {"OBJECT", "EDIT"} or obj.type != "MESH": pg.error = PDT_OBJ_MODE_ERROR context.window_manager.popup_menu(oops, title="Error", icon="ERROR") - raise PDT_ObjectMode + raise PDT_ObjectModeError # Special Cases of Command. if command == "?" or command.lower() == "help": @@ -157,52 +160,47 @@ def command_run(self, context): context.window_manager.popup_menu(pdt_help, title="PDT Command Line Help", icon="INFO") # fmt: on return - elif command == "": + if command == "": return - elif command.upper() == "J2V": + if command.upper() == "J2V": join_two_vertices(context) return - elif command.upper() == "AD2": + if command.upper() == "AD2": set_angle_distance_two(context) return - elif command.upper() == "AD3": + if command.upper() == "AD3": set_angle_distance_three(context) return - elif command.upper() == "OTC": + if command.upper() == "OTC": origin_to_cursor(context) return - elif command.upper() == "TAP": + if command.upper() == "TAP": taper(context) return - elif command.upper() == "BIS": + if command.upper() == "BIS": add_line_to_bisection(context) return - elif command.upper() == "ETF": + if command.upper() == "ETF": extend_vertex(context) return - elif command.upper() == "INTALL": + if command.upper() == "INTALL": intersect_all(context) return - elif command.upper()[1:] == "NML": + if command.upper()[1:] == "NML": placement_normal(context, command.upper()[0]) return - elif command.upper()[1:] == "CEN": - placement_centre(context, command.upper()[0]) + if command.upper()[1:] == "CEN": + placement_arc_centre(context, command.upper()[0]) return - elif command.upper()[1:] == "INT": + if command.upper()[1:] == "INT": placement_intersect(context, command.upper()[0]) return - # Check First Letter + # Check Command Length if len(command) < 3: pg.error = PDT_ERR_CHARS_NUM context.window_manager.popup_menu(oops, title="Error", icon="ERROR") return - operation = command[0].upper() - if operation not in {"C", "D", "E", "F", "G", "N", "M", "P", "V", "S"}: - pg.error = PDT_ERR_BADFLETTER - context.window_manager.popup_menu(oops, title="Error", icon="ERROR") - return # Check First Letter operation = command[0].upper() @@ -214,11 +212,11 @@ def command_run(self, context): # Check Second Letter. mode = command[1].lower() if ( - (operation == "F" and mode not in {"v", "e", "i"}) - or (operation in {"D", "E"} and mode not in {"d", "i"}) - or (operation == "M" and mode not in {"a", "d", "i", "p", "o", "x", "y", "z"}) - or (operation not in {"D", "E", "F", "M"} and mode not in {"a", "d", "i", "p"}) - ): + (operation == "F" and mode not in {"v", "e", "i"}) + or (operation in {"D", "E"} and mode not in {"d", "i"}) + or (operation == "M" and mode not in {"a", "d", "i", "p", "o", "x", "y", "z"}) + or (operation not in {"D", "E", "F", "M"} and mode not in {"a", "d", "i", "p"}) + ): pg.error = f"'{mode}' {PDT_ERR_NON_VALID} '{operation}'" context.window_manager.popup_menu(oops, title="Error", icon="ERROR") return @@ -249,7 +247,7 @@ def command_run(self, context): # ------------------------ # Move Vertices or Objects - elif operation == "G": + if operation == "G": try: move_entities(context, pg, operation, mode, obj, bm, verts, values) except PDT_CommandFailure: @@ -257,7 +255,7 @@ def command_run(self, context): # -------------- # Add New Vertex - elif operation == "N": + if operation == "N": try: add_new_vertex(context, pg, operation, mode, obj, bm, verts, values) except PDT_CommandFailure: @@ -265,7 +263,7 @@ def command_run(self, context): # ----------- # Split Edges - elif operation == "S": + if operation == "S": try: split_edges(context, pg, operation, mode, obj, obj_loc, bm, values) except PDT_CommandFailure: @@ -274,7 +272,7 @@ def command_run(self, context): # ---------------- # Extrude Vertices - elif operation == "V": + if operation == "V": try: extrude_vertices(context, pg, operation, mode, obj, obj_loc, bm, verts, values) except PDT_CommandFailure: @@ -282,7 +280,7 @@ def command_run(self, context): # ---------------- # Extrude Geometry - elif operation == "E": + if operation == "E": try: extrude_geometry(context, pg, operation, mode, obj, bm, values) except PDT_CommandFailure: @@ -290,7 +288,7 @@ def command_run(self, context): # ------------------ # Duplicate Geometry - elif operation == "D": + if operation == "D": try: duplicate_geometry(context, pg, operation, mode, obj, bm, values) except PDT_CommandFailure: @@ -298,18 +296,12 @@ def command_run(self, context): # --------------- # Fillet Geometry - elif operation == "F": + if operation == "F": try: fillet_geometry(context, pg, mode, obj, bm, verts, values) except PDT_CommandFailure: return - # ------------- - # Anything else - else: - # Trap all other value and allow for more options - return - def pdt_help(self, context): """Display PDT Command Line help in a pop-up.""" @@ -392,12 +384,19 @@ def command_maths(context, mode, pg, expression, output_target): elif output_target == "p": pg.percent = round(maths_result, val_round) else: - # Mst be "o" + # Must be "o" pg.maths_output = round(maths_result, val_round) - return def command_parse(context): + """Parse Command Input. + + Args: + context: Blender bpy.context instance. + + Returns: + pg, values_out, obj, obj_loc, bm, verts. + """ scene = context.scene pg = scene.pdt_pg command = pg.command.strip() @@ -418,7 +417,7 @@ def command_parse(context): val_round = context.preferences.addons[__package__].preferences.pdt_input_round values_out = [str(round(float(v), val_round)) for v in values] - bm, good = obj_check(context, obj, scene, operation) + bm, good = obj_check(obj, scene, operation) if good: obj_loc = obj.matrix_world.decompose()[0] else: @@ -426,12 +425,11 @@ def command_parse(context): if mode_s == 'SEL' and bm is not None and mode not in {"a"}: if len(bm.select_history) == 0: - if len([v for v in bm.verts if v.select]) == 0: + verts = [v for v in bm.verts if v.select] + if len(verts) == 0: pg.error = PDT_ERR_NO_SEL_GEOM context.window_manager.popup_menu(oops, title="Error", icon="ERROR") raise PDT_SelectionError - else: - verts = [v for v in bm.verts if v.select] else: verts = bm.select_history elif operation == "G" and mode == "a": @@ -446,6 +444,16 @@ def command_parse(context): def move_cursor_pivot(context, pg, operation, mode, obj, verts, values): + """Moves Cursor & Pivot Point. + + Args: + context: Blender bpy.context instance. + pg, operation, mode, obj, verts, values + + Returns: + Nothing. + """ + # Absolute/Global Coordinates, or Delta/Relative Coordinates if mode in {"a", "d"}: try: @@ -466,7 +474,7 @@ def move_cursor_pivot(context, pg, operation, mode, obj, verts, values): except: raise PDT_InvalidVector - if vector_delta == None: + if vector_delta is None: raise PDT_InvalidVector scene = context.scene @@ -507,10 +515,19 @@ def move_cursor_pivot(context, pg, operation, mode, obj, verts, values): scene.cursor.location = vector_delta else: pg.pivot_loc = vector_delta - return def move_entities(context, pg, operation, mode, obj, bm, verts, values): + """Moves Entities. + + Args: + context: Blender bpy.context instance. + pg, operation, mode, obj, bm, verts, values + + Returns: + Nothing. + """ + obj_loc = obj.matrix_world.decompose()[0] # Absolute/Global Coordinates @@ -562,10 +579,19 @@ def move_entities(context, pg, operation, mode, obj, bm, verts, values): if obj.mode == 'EDIT': bmesh.update_edit_mesh(obj.data) bm.select_history.clear() - return def add_new_vertex(context, pg, operation, mode, obj, bm, verts, values): + """Add New Vertex. + + Args: + context: Blender bpy.context instance. + pg, operation, mode, obj, bm, verts, values + + Returns: + Nothing. + """ + obj_loc = obj.matrix_world.decompose()[0] if not obj.mode == "EDIT": @@ -606,10 +632,19 @@ def add_new_vertex(context, pg, operation, mode, obj, bm, verts, values): new_vertex.select_set(True) bmesh.update_edit_mesh(obj.data) bm.select_history.clear() - return def split_edges(context, pg, operation, mode, obj, obj_loc, bm, values): + """Split Edges. + + Args: + context: Blender bpy.context instance. + pg, operation, mode, obj, obj_loc, bm, verts, values + + Returns: + Nothing. + """ + if not obj.mode == "EDIT": pg.error = PDT_ERR_SPLITEDIT context.window_manager.popup_menu(oops, title="Error", icon="ERROR") @@ -694,10 +729,19 @@ def split_edges(context, pg, operation, mode, obj, obj_loc, bm, values): v.select_set(False) bmesh.update_edit_mesh(obj.data) bm.select_history.clear() - return def extrude_vertices(context, pg, operation, mode, obj, obj_loc, bm, verts, values): + """Extrude Vertices. + + Args: + context: Blender bpy.context instance. + pg, operation, mode, obj, onj_loc, bm, verts, values + + Returns: + Nothing. + """ + if not obj.mode == "EDIT": pg.error = PDT_ERR_EXTEDIT context.window_manager.popup_menu(oops, title="Error", icon="ERROR") @@ -760,10 +804,19 @@ def extrude_vertices(context, pg, operation, mode, obj, obj_loc, bm, verts, valu bmesh.update_edit_mesh(obj.data) bm.select_history.clear() - return def extrude_geometry(context, pg, operation, mode, obj, bm, values): + """Extrude Geometry. + + Args: + context: Blender bpy.context instance. + pg, operation, mode, obj, bm, verts, values + + Returns: + Nothing. + """ + if not obj.mode == "EDIT": pg.error = PDT_ERR_EXTEDIT context.window_manager.popup_menu(oops, title="Error", icon="ERROR") @@ -799,9 +852,19 @@ def extrude_geometry(context, pg, operation, mode, obj, bm, values): update_sel(bm, verts_extr, edges_extr, faces_extr) bmesh.update_edit_mesh(obj.data) bm.select_history.clear() - return + def duplicate_geometry(context, pg, operation, mode, obj, bm, values): + """Duplicate Geometry. + + Args: + context: Blender bpy.context instance. + pg, operation, mode, obj, bm, verts, values + + Returns: + Nothing. + """ + if not obj.mode == "EDIT": pg.error = PDT_ERR_DUPEDIT context.window_manager.popup_menu(oops, title="Error", icon="ERROR") @@ -837,10 +900,19 @@ def duplicate_geometry(context, pg, operation, mode, obj, bm, values): update_sel(bm, verts_dupe, edges_dupe, faces_dupe) bmesh.update_edit_mesh(obj.data) bm.select_history.clear() - return def fillet_geometry(context, pg, mode, obj, bm, verts, values): + """Fillet Geometry. + + Args: + context: Blender bpy.context instance. + pg, operation, mode, obj, bm, verts, values + + Returns: + Nothing. + """ + if not obj.mode == "EDIT": pg.error = PDT_ERR_FILEDIT context.window_manager.popup_menu(oops, title="Error", icon="ERROR") @@ -870,14 +942,14 @@ def fillet_geometry(context, pg, mode, obj, bm, verts, values): v_last = edges[1].verts[0] v_first = edges[1].verts[1] vector_delta, done = intersection(v_active.co, - v_other.co, - v_last.co, - v_first.co, - plane - ) + v_other.co, + v_last.co, + v_first.co, + plane + ) if not done: - errmsg = f"{PDT_ERR_INT_LINES} {plane} {PDT_LAB_PLANE}" - self.report({"ERROR"}, errmsg) + pg.error = f"{PDT_ERR_INT_LINES} {plane} {PDT_LAB_PLANE}" + context.window_manager.popup_menu(oops, title="Error", icon="ERROR") raise PDT_IntersectionError if (v_active.co - vector_delta).length < (v_other.co - vector_delta).length: v_active.co = vector_delta @@ -904,4 +976,3 @@ def fillet_geometry(context, pg, mode, obj, bm, verts, values): profile=_profile, vertex_only=vert_bool ) - return diff --git a/precision_drawing_tools/pdt_design.py b/precision_drawing_tools/pdt_design.py index 20cb6ac3..b6a12633 100644 --- a/precision_drawing_tools/pdt_design.py +++ b/precision_drawing_tools/pdt_design.py @@ -21,42 +21,14 @@ # Author: Alan Odom (Clockmender), Rune Morling (ermo) Copyright (c) 2019 # ----------------------------------------------------------------------- # -import bmesh -import bpy -import numpy as np from bpy.types import Operator -from mathutils import Vector -from mathutils.geometry import intersect_point_line -from math import sin, cos, tan, pi, sqrt -from .pdt_functions import ( - check_selection, - set_axis, - view_coords, - view_coords_i, - intersection, -) from .pdt_msg_strings import ( - PDT_ERR_EDOB_MODE, - PDT_ERR_INT_LINES, - PDT_ERR_INT_NO_ALL, PDT_ERR_NON_VALID, - PDT_ERR_NO_ACT_OBJ, - PDT_ERR_SEL_2_OBJS, - PDT_ERR_SEL_2_VERTIO, - PDT_ERR_SEL_3_OBJS, - PDT_ERR_SEL_3_VERTIO, - PDT_ERR_SEL_4_OBJS, - PDT_ERR_SEL_4_VERTS, - PDT_ERR_TAPER_ANG, - PDT_ERR_TAPER_SEL, - PDT_ERR_VERT_MODE, - PDT_INF_OBJ_MOVED, PDT_LAB_ABS, PDT_LAB_DEL, PDT_LAB_DIR, PDT_LAB_INTERSECT, PDT_LAB_PERCENT, - PDT_LAB_PLANE, ) @@ -587,21 +559,21 @@ class PDT_OT_Fillet(Operator): val_round = context.preferences.addons[__package__].preferences.pdt_input_round if pg.fillet_intersect: pg.command = ( - f"fi{str(round(pg.fillet_radius, val_round))}" - f",{str(round(pg.fillet_segments, val_round))}" - f",{str(round(pg.fillet_profile, val_round))}" + f"fi{str(round(pg.fillet_radius, val_round))}" + f",{str(round(pg.fillet_segments, val_round))}" + f",{str(round(pg.fillet_profile, val_round))}" ) elif pg.fillet_vertices_only: pg.command = ( - f"fv{str(round(pg.fillet_radius, val_round))}" - f",{str(round(pg.fillet_segments, val_round))}" - f",{str(round(pg.fillet_profile, val_round))}" + f"fv{str(round(pg.fillet_radius, val_round))}" + f",{str(round(pg.fillet_segments, val_round))}" + f",{str(round(pg.fillet_profile, val_round))}" ) else: pg.command = ( - f"fe{str(round(pg.fillet_radius, val_round))}" - f",{str(round(pg.fillet_segments, val_round))}" - f",{str(round(pg.fillet_profile, val_round))}" + f"fe{str(round(pg.fillet_radius, val_round))}" + f",{str(round(pg.fillet_segments, val_round))}" + f",{str(round(pg.fillet_profile, val_round))}" ) return {"FINISHED"} diff --git a/precision_drawing_tools/pdt_etof.py b/precision_drawing_tools/pdt_etof.py index 385c12f4..5a7b0985 100644 --- a/precision_drawing_tools/pdt_etof.py +++ b/precision_drawing_tools/pdt_etof.py @@ -29,25 +29,23 @@ import bmesh from mathutils.geometry import intersect_line_plane from .pdt_msg_strings import ( PDT_ERR_NOINT, - PDT_ERR_SEL_1_E_1_F + PDT_ERR_EDOB_MODE, ) from .pdt_functions import oops -def failure_message(self, context): +def failure_message(context): """Warn to the user to select 1 edge and 1 face.""" pg = context.scene.pdt_pg pg.error = f"Select One Face and One Edge" context.window_manager.popup_menu(oops, title="Error", icon="ERROR") - return -def failure_message_on_plane(self, context): +def failure_message_on_plane(context): """Report an informative error message in a popup.""" pg = context.scene.pdt_pg pg.error = f"{PDT_ERR_NOINT}" context.window_manager.popup_menu(oops, title="Error", icon="ERROR") - return def extend_vertex(context): """Computes Edge Extension to Face. @@ -59,31 +57,33 @@ def extend_vertex(context): Nothing.""" obj = bpy.context.edit_object + pg = context.scene.pdt_pg + if all([bool(obj), obj.type == "MESH", obj.mode == "EDIT"]): - me = obj.data - bm = bmesh.from_edit_mesh(me) + object_data = obj.data + bm = bmesh.from_edit_mesh(object_data) verts = bm.verts faces = bm.faces planes = [f for f in faces if f.select] if not len(planes) == 1: - failure_message(self, context) + failure_message(context) return plane = planes[0] plane_vert_indices = plane.verts[:] all_selected_vert_indices = [v for v in verts if v.select] - M = set(plane_vert_indices) - N = set(all_selected_vert_indices) - O = N.difference(M) - O = list(O) + plane_verts = set(plane_vert_indices) + all_verts = set(all_selected_vert_indices) + diff_verts = all_verts.difference(plane_verts) + diff_verts = list(diff_verts) - if not len(O) == 2: - failure_message(self, context) + if not len(diff_verts) == 2: + failure_message(context) return - (v1_ref, v1), (v2_ref, v2) = [(i, i.co) for i in O] + (v1_ref, v1), (v2_ref, v2) = [(i, i.co) for i in diff_verts] plane_co = plane.calc_center_median() plane_no = plane.normal @@ -92,15 +92,15 @@ def extend_vertex(context): if new_co: new_vertex = verts.new(new_co) - A_len = (v1 - new_co).length - B_len = (v2 - new_co).length + a_len = (v1 - new_co).length + b_len = (v2 - new_co).length - vertex_reference = v1_ref if (A_len < B_len) else v2_ref + vertex_reference = v1_ref if (a_len < b_len) else v2_ref bm.edges.new([vertex_reference, new_vertex]) - bmesh.update_edit_mesh(me, True) + bmesh.update_edit_mesh(object_data, True) else: - failure_message_on_plane(self, context) + failure_message_on_plane(context) else: pg.error = f"{PDT_ERR_EDOB_MODE},{obj.mode})" context.window_manager.popup_menu(oops, title="Error", icon="ERROR") @@ -117,10 +117,10 @@ class PDT_OT_EdgeToFace(bpy.types.Operator): @classmethod def poll(cls, context): """Only allow this to work if a mesh is selected in EDIT mode.""" - ob = context.object - if ob is None: + obj = context.object + if obj is None: return False - return all([bool(ob), ob.type == "MESH", ob.mode == "EDIT"]) + return all([bool(obj), obj.type == "MESH", obj.mode == "EDIT"]) def execute(self, context): """Extends Disconnected Edge to Intersect with Face. diff --git a/precision_drawing_tools/pdt_functions.py b/precision_drawing_tools/pdt_functions.py index 65b4069a..c07611f7 100644 --- a/precision_drawing_tools/pdt_functions.py +++ b/precision_drawing_tools/pdt_functions.py @@ -37,12 +37,9 @@ from .pdt_msg_strings import ( PDT_ERR_SEL_2_OBJS, PDT_ERR_NO_ACT_OBJ, PDT_ERR_SEL_1_EDGEM, - PDT_ERR_BAD1VALS, - PDT_ERR_BAD2VALS, - PDT_ERR_BAD3VALS, - PDT_ERR_SEL_2_VERTS, - PDT_ERR_CONNECTED, ) +from . import pdt_exception +PDT_ShaderError = pdt_exception.ShaderError def debug(msg, prefix=""): @@ -96,7 +93,10 @@ def oops(self, context): def set_mode(mode_pl): """Sets Active Axes for View Orientation. - Sets indices of axes for locational vectors + Sets indices of axes for locational vectors: + "XY": a1 = x, a2 = y, a3 = z + "XZ": a1 = x, a2 = z, a3 = y + "YZ": a1 = y, a2 = z, a3 = x Args: mode_pl: Plane Selector variable as input @@ -105,16 +105,12 @@ def set_mode(mode_pl): 3 Integer indices. """ - if mode_pl == "XY": - # a1 = x a2 = y a3 = z - return 0, 1, 2 - if mode_pl == "XZ": - # a1 = x a2 = z a3 = y - return 0, 2, 1 - if mode_pl == "YZ": - # a1 = y a2 = z a3 = x - return 1, 2, 0 - #FIXME: This needs a proper specification and a default + order = { + "XY": (0, 1, 2), + "XZ": (0, 2, 1), + "YZ": (1, 2, 0), + } + return order[mode_pl] def set_axis(mode_pl): @@ -132,19 +128,15 @@ def set_axis(mode_pl): 3 Integer Indicies. """ - if mode_pl == "RX-MY": - return 0, 1, 2 - if mode_pl == "RX-MZ": - return 0, 2, 1 - if mode_pl == "RY-MX": - return 1, 0, 2 - if mode_pl == "RY-MZ": - return 1, 2, 0 - if mode_pl == "RZ-MX": - return 2, 0, 1 - if mode_pl == "RZ-MY": - return 2, 1, 0 - #FIXME: This needs a proper specification and a default + order = { + "RX-MY": (0, 1, 2), + "RX-MZ": (0, 2, 1), + "RY-MX": (1, 0, 2), + "RY-MZ": (1, 2, 0), + "RZ-MX": (2, 0, 1), + "RZ-MY": (2, 1, 0), + } + return order[mode_pl] def check_selection(num, bm, obj): @@ -163,20 +155,19 @@ def check_selection(num, bm, obj): if len(bm.select_history) < num: return None - else: - actE = bm.select_history[-1] - if isinstance(actE, bmesh.types.BMVert): - vector_a = actE.co + active_vertex = bm.select_history[-1] + if isinstance(active_vertex, bmesh.types.BMVert): + vector_a = active_vertex.co if num == 1: return vector_a - elif num == 2: + if num == 2: vector_b = bm.select_history[-2].co return vector_a, vector_b - elif num == 3: + if num == 3: vector_b = bm.select_history[-2].co vector_c = bm.select_history[-3].co return vector_a, vector_b, vector_c - elif num == 4: + if num == 4: vector_b = bm.select_history[-2].co vector_c = bm.select_history[-3].co vector_d = bm.select_history[-4].co @@ -233,13 +224,13 @@ def view_coords(x_loc, y_loc, z_loc): areas = [a for a in bpy.context.screen.areas if a.type == "VIEW_3D"] if len(areas) > 0: - vm = areas[0].spaces.active.region_3d.view_matrix - vm = vm.to_3x3().normalized().inverted() - vl = Vector((x_loc, y_loc, z_loc)) - vw = vm @ vl - return vw - else: - return Vector((0, 0, 0)) + view_matrix = areas[0].spaces.active.region_3d.view_matrix + view_matrix = view_matrix.to_3x3().normalized().inverted() + view_location = Vector((x_loc, y_loc, z_loc)) + new_view_location = view_matrix @ view_location + return new_view_location + + return Vector((0, 0, 0)) def view_coords_i(x_loc, y_loc, z_loc): @@ -258,13 +249,13 @@ def view_coords_i(x_loc, y_loc, z_loc): areas = [a for a in bpy.context.screen.areas if a.type == "VIEW_3D"] if len(areas) > 0: - vm = areas[0].spaces.active.region_3d.view_matrix - vm = vm.to_3x3().normalized() - vl = Vector((x_loc, y_loc, z_loc)) - vw = vm @ vl - return vw - else: - return Vector((0, 0, 0)) + view_matrix = areas[0].spaces.active.region_3d.view_matrix + view_matrix = view_matrix.to_3x3().normalized() + view_location = Vector((x_loc, y_loc, z_loc)) + new_view_location = view_matrix @ view_location + return new_view_location + + return Vector((0, 0, 0)) def view_dir(dis_v, ang_v): @@ -283,15 +274,15 @@ def view_dir(dis_v, ang_v): areas = [a for a in bpy.context.screen.areas if a.type == "VIEW_3D"] if len(areas) > 0: - vm = areas[0].spaces.active.region_3d.view_matrix - vm = vm.to_3x3().normalized().inverted() - vl = Vector((0, 0, 0)) - vl.x = dis_v * cos(ang_v * pi / 180) - vl.y = dis_v * sin(ang_v * pi / 180) - vw = vm @ vl - return vw - else: - return Vector((0, 0, 0)) + view_matrix = areas[0].spaces.active.region_3d.view_matrix + view_matrix = view_matrix.to_3x3().normalized().inverted() + view_location = Vector((0, 0, 0)) + view_location.x = dis_v * cos(ang_v * pi / 180) + view_location.y = dis_v * sin(ang_v * pi / 180) + new_view_location = view_matrix @ view_location + return new_view_location + + return Vector((0, 0, 0)) def euler_to_quaternion(roll, pitch, yaw): @@ -307,16 +298,16 @@ def euler_to_quaternion(roll, pitch, yaw): """ # fmt: off - qx = (np.sin(roll/2) * np.cos(pitch/2) * np.cos(yaw/2) - - np.cos(roll/2) * np.sin(pitch/2) * np.sin(yaw/2)) - qy = (np.cos(roll/2) * np.sin(pitch/2) * np.cos(yaw/2) - + np.sin(roll/2) * np.cos(pitch/2) * np.sin(yaw/2)) - qz = (np.cos(roll/2) * np.cos(pitch/2) * np.sin(yaw/2) - - np.sin(roll/2) * np.sin(pitch/2) * np.cos(yaw/2)) - qw = (np.cos(roll/2) * np.cos(pitch/2) * np.cos(yaw/2) - + np.sin(roll/2) * np.sin(pitch/2) * np.sin(yaw/2)) + quat_x = (np.sin(roll/2) * np.cos(pitch/2) * np.cos(yaw/2) + - np.cos(roll/2) * np.sin(pitch/2) * np.sin(yaw/2)) + quat_y = (np.cos(roll/2) * np.sin(pitch/2) * np.cos(yaw/2) + + np.sin(roll/2) * np.cos(pitch/2) * np.sin(yaw/2)) + quat_z = (np.cos(roll/2) * np.cos(pitch/2) * np.sin(yaw/2) + - np.sin(roll/2) * np.sin(pitch/2) * np.cos(yaw/2)) + quat_w = (np.cos(roll/2) * np.cos(pitch/2) * np.cos(yaw/2) + + np.sin(roll/2) * np.sin(pitch/2) * np.sin(yaw/2)) # fmt: on - return Quaternion((qw, qx, qy, qz)) + return Quaternion((quat_w, quat_x, quat_y, quat_z)) def arc_centre(vector_a, vector_b, vector_c): @@ -331,22 +322,29 @@ def arc_centre(vector_a, vector_b, vector_c): Vector representing Arc Centre and Float representing Arc Radius. """ - A = np.array([vector_a.x, vector_a.y, vector_a.z]) - B = np.array([vector_b.x, vector_b.y, vector_b.z]) - C = np.array([vector_c.x, vector_c.y, vector_c.z]) - a = np.linalg.norm(C - B) - b = np.linalg.norm(C - A) - c = np.linalg.norm(B - A) + coord_a = np.array([vector_a.x, vector_a.y, vector_a.z]) + coord_b = np.array([vector_b.x, vector_b.y, vector_b.z]) + coord_c = np.array([vector_c.x, vector_c.y, vector_c.z]) + line_a = np.linalg.norm(coord_c - coord_b) + line_b = np.linalg.norm(coord_c - coord_a) + line_c = np.linalg.norm(coord_b - coord_a) # fmt: off - s = (a+b+c) / 2 - R = a*b*c/4 / np.sqrt(s * (s-a) * (s-b) * (s-c)) - b1 = a*a * (b*b + c*c - a*a) - b2 = b*b * (a*a + c*c - b*b) - b3 = c*c * (a*a + b*b - c*c) + line_s = (line_a+line_b+line_c) / 2 + radius = ( + line_a*line_b*line_c/4 + / np.sqrt(line_s + * (line_s-line_a) + * (line_s-line_b) + * (line_s-line_c)) + ) + base_1 = line_a*line_a * (line_b*line_b + line_c*line_c - line_a*line_a) + base_2 = line_b*line_b * (line_a*line_a + line_c*line_c - line_b*line_b) + base_3 = line_c*line_c * (line_a*line_a + line_b*line_b - line_c*line_c) # fmt: on - P = np.column_stack((A, B, C)).dot(np.hstack((b1, b2, b3))) - P /= b1 + b2 + b3 - return Vector((P[0], P[1], P[2])), R + intersect_coord = np.column_stack((coord_a, coord_b, coord_c)) + intersect_coord = intersect_coord.dot(np.hstack((base_1, base_2, base_3))) + intersect_coord /= base_1 + base_2 + base_3 + return Vector((intersect_coord[0], intersect_coord[1], intersect_coord[2])), radius def intersection(vertex_a, vertex_b, vertex_c, vertex_d, plane): @@ -371,38 +369,39 @@ def intersection(vertex_a, vertex_b, vertex_c, vertex_d, plane): vertex_offset = vertex_c - vertex_a vertex_c = view_coords_i(vertex_offset.x, vertex_offset.y, vertex_offset.z) vector_ref = Vector((0, 0, 0)) - ap1 = (vertex_c.x, vertex_c.y) - ap2 = (vertex_d.x, vertex_d.y) - bp1 = (vertex_b.x, vertex_b.y) - bp2 = (vector_ref.x, vector_ref.y) + coord_a = (vertex_c.x, vertex_c.y) + coord_b = (vertex_d.x, vertex_d.y) + coord_c = (vertex_b.x, vertex_b.y) + coord_d = (vector_ref.x, vector_ref.y) else: a1, a2, a3 = set_mode(plane) - ap1 = (vertex_c[a1], vertex_c[a2]) - ap2 = (vertex_d[a1], vertex_d[a2]) - bp1 = (vertex_a[a1], vertex_a[a2]) - bp2 = (vertex_b[a1], vertex_b[a2]) - s = np.vstack([ap1, ap2, bp1, bp2]) - h = np.hstack((s, np.ones((4, 1)))) - l1 = np.cross(h[0], h[1]) - l2 = np.cross(h[2], h[3]) - x, y, z = np.cross(l1, l2) - if z == 0: + coord_a = (vertex_c[a1], vertex_c[a2]) + coord_b = (vertex_d[a1], vertex_d[a2]) + coord_c = (vertex_a[a1], vertex_a[a2]) + coord_d = (vertex_b[a1], vertex_b[a2]) + v_stack = np.vstack([coord_a, coord_b, coord_c, coord_d]) + h_stack = np.hstack((v_stack, np.ones((4, 1)))) + line_a = np.cross(h_stack[0], h_stack[1]) + line_b = np.cross(h_stack[2], h_stack[3]) + x_loc, y_loc, z_loc = np.cross(line_a, line_b) + if z_loc == 0: return Vector((0, 0, 0)), False - nx = x / z - nz = y / z + new_x_loc = x_loc / z_loc + new_z_loc = y_loc / z_loc if plane == "LO": - ly = 0 + new_y_loc = 0 else: - ly = vertex_a[a3] + new_y_loc = vertex_a[a3] # Order Vector Delta if plane == "XZ": - vector_delta = Vector((nx, ly, nz)) + vector_delta = Vector((new_x_loc, new_y_loc, new_z_loc)) elif plane == "XY": - vector_delta = Vector((nx, nz, ly)) + vector_delta = Vector((new_x_loc, new_z_loc, new_y_loc)) elif plane == "YZ": - vector_delta = Vector((ly, nx, nz)) - elif plane == "LO": - vector_delta = view_coords(nx, nz, ly) + vertex_a + vector_delta = Vector((new_y_loc, new_x_loc, new_z_loc)) + else: + # Must be Local View Plane + vector_delta = view_coords(new_x_loc, new_z_loc, new_y_loc) + vertex_a return vector_delta, True @@ -442,38 +441,38 @@ def get_percent(obj, flip_p, per_v, data, scene): pg.error = PDT_ERR_SEL_2_V_1_E + str(len(verts)) + " Vertices" bpy.context.window_manager.popup_menu(oops, title="Error", icon="ERROR") return None - p1 = np.array([vector_a.x, vector_a.y, vector_a.z]) - p2 = np.array([vector_b.x, vector_b.y, vector_b.z]) + coord_a = np.array([vector_a.x, vector_a.y, vector_a.z]) + coord_b = np.array([vector_b.x, vector_b.y, vector_b.z]) if obj.mode == "OBJECT": objs = bpy.context.view_layer.objects.selected if len(objs) != 2: pg.error = PDT_ERR_SEL_2_OBJS + str(len(objs)) + ")" bpy.context.window_manager.popup_menu(oops, title="Error", icon="ERROR") return None - p1 = np.array( + coord_a = np.array( [ objs[-1].matrix_world.decompose()[0].x, objs[-1].matrix_world.decompose()[0].y, objs[-1].matrix_world.decompose()[0].z, ] ) - p2 = np.array( + coord_b = np.array( [ objs[-2].matrix_world.decompose()[0].x, objs[-2].matrix_world.decompose()[0].y, objs[-2].matrix_world.decompose()[0].z, ] ) - p4 = np.array([0, 0, 0]) - p3 = p2 - p1 + coord_c = coord_b - coord_a + coord_d = np.array([0, 0, 0]) _per_v = per_v if (flip_p and data != "MV") or data == "MV": _per_v = 100 - per_v - V = (p4+p3) * (_per_v / 100) + p1 - return Vector((V[0], V[1], V[2])) + coord_out = (coord_d+coord_c) * (_per_v / 100) + coord_a + return Vector((coord_out[0], coord_out[1], coord_out[2])) -def obj_check(context, obj, scene, operator): +def obj_check(obj, scene, operator): """Check Object & Selection Validity. Args: @@ -499,32 +498,29 @@ def obj_check(context, obj, scene, operator): pg.error = f"{PDT_ERR_SEL_1_EDGEM} {len(bm.edges)})" bpy.context.window_manager.popup_menu(oops, title="Error", icon="ERROR") return None, False - else: - return bm, True + return bm, True if len(bm.select_history) >= 1: + vector_a = None if _operator not in {"D", "E", "F", "G", "N", "S"}: vector_a = check_selection(1, bm, obj) else: verts = [v for v in bm.verts if v.select] if len(verts) > 0: vector_a = verts[0] - else: - vector_a = None if vector_a is None: pg.error = PDT_ERR_VERT_MODE bpy.context.window_manager.popup_menu(oops, title="Error", icon="ERROR") return None, False return bm, True - else: - return None, True + return None, True -def dis_ang(vals, flip_a, plane, scene): +def dis_ang(values, flip_angle, plane, scene): """Set Working Axes when using Direction command. Args: - vals: Input Arguments (Values) - flip_a: Whether to flip the angle + values: Input Arguments + flip_angle: Whether to flip the angle plane: Working Plane scene: Current Scene @@ -533,9 +529,9 @@ def dis_ang(vals, flip_a, plane, scene): """ pg = scene.pdt_pg - dis_v = float(vals[0]) - ang_v = float(vals[1]) - if flip_a: + dis_v = float(values[0]) + ang_v = float(values[1]) + if flip_angle: if ang_v > 0: ang_v = ang_v - 180 else: @@ -555,10 +551,10 @@ def dis_ang(vals, flip_a, plane, scene): # Shader for displaying the Pivot Point as Graphics. # -shader = gpu.shader.from_builtin("3D_UNIFORM_COLOR") if not bpy.app.background else None +SHADER = gpu.shader.from_builtin("3D_UNIFORM_COLOR") if not bpy.app.background else None -def draw3D(coords, gtype, rgba, context): +def draw_3d(coords, gtype, rgba, context): """Draw Pivot Point Graphics. Draws either Lines Points, or Tris using defined shader @@ -573,19 +569,19 @@ def draw3D(coords, gtype, rgba, context): Nothing. """ - batch = batch_for_shader(shader, gtype, {"pos": coords}) + batch = batch_for_shader(SHADER, gtype, {"pos": coords}) try: if coords is not None: bgl.glEnable(bgl.GL_BLEND) - shader.bind() - shader.uniform_float("color", rgba) - batch.draw(shader) + SHADER.bind() + SHADER.uniform_float("color", rgba) + batch.draw(SHADER) except: - pass + raise PDT_ShaderError -def drawCallback3D(self, context): +def draw_callback_3d(self, context): """Create Coordinate List for Pivot Point Graphic. Creates coordinates for Pivot Point Graphic consisting of 6 Tris @@ -601,73 +597,73 @@ def drawCallback3D(self, context): scene = context.scene pg = scene.pdt_pg - w = context.region.width - x = pg.pivot_loc.x - y = pg.pivot_loc.y - z = pg.pivot_loc.z + region_width = context.region.width + x_loc = pg.pivot_loc.x + y_loc = pg.pivot_loc.y + z_loc = pg.pivot_loc.z # Scale it from view areas = [a for a in context.screen.areas if a.type == "VIEW_3D"] if len(areas) > 0: - sf = abs(areas[0].spaces.active.region_3d.window_matrix.decompose()[2][1]) + scale_factor = abs(areas[0].spaces.active.region_3d.window_matrix.decompose()[2][1]) # Check for orhtographic view and resize #if areas[0].spaces.active.region_3d.is_orthographic_side_view: - # a = w / sf / 60000 * pg.pivot_size + # dim_a = region_width / sf / 60000 * pg.pivot_size #else: - # a = w / sf / 5000 * pg.pivot_size - a = w / sf / 50000 * pg.pivot_size - b = a * 0.65 - c = a * 0.05 + (pg.pivot_width * a * 0.02) - o = c / 3 + # dim_a = region_width / sf / 5000 * pg.pivot_size + dim_a = region_width / scale_factor / 50000 * pg.pivot_size + dim_b = dim_a * 0.65 + dim_c = dim_a * 0.05 + (pg.pivot_width * dim_a * 0.02) + dim_o = dim_c / 3 # fmt: off # X Axis coords = [ - (x, y, z), - (x+b, y-o, z), - (x+b, y+o, z), - (x+a, y, z), - (x+b, y+c, z), - (x+b, y-c, z), + (x_loc, y_loc, z_loc), + (x_loc+dim_b, y_loc-dim_o, z_loc), + (x_loc+dim_b, y_loc+dim_o, z_loc), + (x_loc+dim_a, y_loc, z_loc), + (x_loc+dim_b, y_loc+dim_c, z_loc), + (x_loc+dim_b, y_loc-dim_c, z_loc), ] # fmt: on colour = (1.0, 0.0, 0.0, pg.pivot_alpha) - draw3D(coords, "TRIS", colour, context) - coords = [(x, y, z), (x+a, y, z)] - draw3D(coords, "LINES", colour, context) + draw_3d(coords, "TRIS", colour, context) + coords = [(x_loc, y_loc, z_loc), (x_loc+dim_a, y_loc, z_loc)] + draw_3d(coords, "LINES", colour, context) # fmt: off # Y Axis coords = [ - (x, y, z), - (x-o, y+b, z), - (x+o, y+b, z), - (x, y+a, z), - (x+c, y+b, z), - (x-c, y+b, z), + (x_loc, y_loc, z_loc), + (x_loc-dim_o, y_loc+dim_b, z_loc), + (x_loc+dim_o, y_loc+dim_b, z_loc), + (x_loc, y_loc+dim_a, z_loc), + (x_loc+dim_c, y_loc+dim_b, z_loc), + (x_loc-dim_c, y_loc+dim_b, z_loc), ] # fmt: on colour = (0.0, 1.0, 0.0, pg.pivot_alpha) - draw3D(coords, "TRIS", colour, context) - coords = [(x, y, z), (x, y + a, z)] - draw3D(coords, "LINES", colour, context) + draw_3d(coords, "TRIS", colour, context) + coords = [(x_loc, y_loc, z_loc), (x_loc, y_loc + dim_a, z_loc)] + draw_3d(coords, "LINES", colour, context) # fmt: off # Z Axis coords = [ - (x, y, z), - (x-o, y, z+b), - (x+o, y, z+b), - (x, y, z+a), - (x+c, y, z+b), - (x-c, y, z+b), + (x_loc, y_loc, z_loc), + (x_loc-dim_o, y_loc, z_loc+dim_b), + (x_loc+dim_o, y_loc, z_loc+dim_b), + (x_loc, y_loc, z_loc+dim_a), + (x_loc+dim_c, y_loc, z_loc+dim_b), + (x_loc-dim_c, y_loc, z_loc+dim_b), ] # fmt: on colour = (0.2, 0.5, 1.0, pg.pivot_alpha) - draw3D(coords, "TRIS", colour, context) - coords = [(x, y, z), (x, y, z + a)] - draw3D(coords, "LINES", colour, context) + draw_3d(coords, "TRIS", colour, context) + coords = [(x_loc, y_loc, z_loc), (x_loc, y_loc, z_loc + dim_a)] + draw_3d(coords, "LINES", colour, context) # Centre - coords = [(x, y, z)] + coords = [(x_loc, y_loc, z_loc)] colour = (1.0, 1.0, 0.0, pg.pivot_alpha) - draw3D(coords, "POINTS", colour, context) + draw_3d(coords, "POINTS", colour, context) def scale_set(self, context): diff --git a/precision_drawing_tools/pdt_library.py b/precision_drawing_tools/pdt_library.py index 096cdcf3..0620d3f2 100644 --- a/precision_drawing_tools/pdt_library.py +++ b/precision_drawing_tools/pdt_library.py @@ -31,6 +31,7 @@ from .pdt_msg_strings import PDT_ERR_NO_LIBRARY class PDT_OT_LibShow(Operator): """Show Library File Details.""" + bl_idname = "pdt.lib_show" bl_label = "Show Library Details" bl_options = {"REGISTER", "UNDO"} @@ -51,7 +52,9 @@ class PDT_OT_LibShow(Operator): pg.error = str(Path(file_path)) debug("PDT Parts Library:") debug(f"{pg.error}") - bpy.context.window_manager.popup_menu(oops, title="Information - Parts Library File", icon="INFO") + bpy.context.window_manager.popup_menu( + oops, title="Information - Parts Library File", icon="INFO" + ) return {"FINISHED"} @@ -86,37 +89,51 @@ class PDT_OT_Append(Operator): if path.is_file() and ".blend" in str(path): if pg.lib_mode == "OBJECTS": # Force object Mode - bpy.ops.object.mode_set(mode='OBJECT') + bpy.ops.object.mode_set(mode="OBJECT") bpy.ops.wm.append( - filepath=str(path), directory=str(path) + "/Object", filename=pg.lib_objects + filepath=str(path), + directory=str(path) + "/Object", + filename=pg.lib_objects, ) for obj in context.view_layer.objects: if obj.name not in obj_names: obj.select_set(False) obj.location = Vector( - (scene.cursor.location.x, scene.cursor.location.y, scene.cursor.location.z) + ( + scene.cursor.location.x, + scene.cursor.location.y, + scene.cursor.location.z, + ) ) return {"FINISHED"} - elif pg.lib_mode == "COLLECTIONS": + if pg.lib_mode == "COLLECTIONS": bpy.ops.wm.append( - filepath=str(path), directory=str(path) + "/Collection", filename=pg.lib_collections + filepath=str(path), + directory=str(path) + "/Collection", + filename=pg.lib_collections, ) for obj in context.view_layer.objects: if obj.name not in obj_names: obj.select_set(False) obj.location = Vector( - (scene.cursor.location.x, scene.cursor.location.y, scene.cursor.location.z) + ( + scene.cursor.location.x, + scene.cursor.location.y, + scene.cursor.location.z, + ) ) return {"FINISHED"} - elif pg.lib_mode == "MATERIALS": + if pg.lib_mode == "MATERIALS": bpy.ops.wm.append( - filepath=str(path), directory=str(path) + "/Material", filename=pg.lib_materials + filepath=str(path), + directory=str(path) + "/Material", + filename=pg.lib_materials, ) return {"FINISHED"} - else: - errmsg = PDT_ERR_NO_LIBRARY - self.report({"ERROR"}, errmsg) - return {"FINISHED"} + + errmsg = PDT_ERR_NO_LIBRARY + self.report({"ERROR"}, errmsg) + return {"FINISHED"} class PDT_OT_Link(Operator): @@ -148,26 +165,32 @@ class PDT_OT_Link(Operator): if path.is_file() and ".blend" in str(path): if pg.lib_mode == "OBJECTS": # Force object Mode - bpy.ops.object.mode_set(mode='OBJECT') + bpy.ops.object.mode_set(mode="OBJECT") bpy.ops.wm.link( - filepath=str(path), directory=str(path) + "/Object", filename=pg.lib_objects + filepath=str(path), + directory=str(path) + "/Object", + filename=pg.lib_objects, ) for obj in context.view_layer.objects: obj.select_set(False) return {"FINISHED"} - elif pg.lib_mode == "COLLECTIONS": + if pg.lib_mode == "COLLECTIONS": bpy.ops.wm.link( - filepath=str(path), directory=str(path) + "/Collection", filename=pg.lib_collections + filepath=str(path), + directory=str(path) + "/Collection", + filename=pg.lib_collections, ) for obj in context.view_layer.objects: obj.select_set(False) return {"FINISHED"} - elif pg.lib_mode == "MATERIALS": + if pg.lib_mode == "MATERIALS": bpy.ops.wm.link( - filepath=str(path), directory=str(path) + "/Material", filename=pg.lib_materials + filepath=str(path), + directory=str(path) + "/Material", + filename=pg.lib_materials, ) return {"FINISHED"} - else: - errmsg = PDT_ERR_NO_LIBRARY - self.report({"ERROR"}, errmsg) - return {"FINISHED"} + + errmsg = PDT_ERR_NO_LIBRARY + self.report({"ERROR"}, errmsg) + return {"FINISHED"} diff --git a/precision_drawing_tools/pdt_msg_strings.py b/precision_drawing_tools/pdt_msg_strings.py index 950e8661..a9246fce 100644 --- a/precision_drawing_tools/pdt_msg_strings.py +++ b/precision_drawing_tools/pdt_msg_strings.py @@ -28,147 +28,153 @@ # # Menu Labels # -PDT_LAB_ABS = "Absolute" # "Global" -PDT_LAB_DEL = "Delta" # "Relative" -PDT_LAB_DIR = "Direction" # "Polar" -PDT_LAB_NOR = "Normal" # "Perpendicular" -PDT_LAB_ARCCENTRE = "Arc Centre" -PDT_LAB_PLANE = "Plane" -PDT_LAB_MODE = "Mode" -PDT_LAB_OPERATION = "Operation" -PDT_LAB_PERCENT = "Percent" -PDT_LAB_INTERSECT = "Intersect" # "Convergance" -PDT_LAB_ORDER = "Order" -PDT_LAB_FLIPANGLE = "Flip Angle" -PDT_LAB_FLIPPERCENT = "Flip %" -PDT_LAB_ALLACTIVE = "All/Active" -PDT_LAB_VARIABLES = "Coordinates/Delta Offsets & Other Variables" -PDT_LAB_CVALUE = "Coordinates" -PDT_LAB_DISVALUE = "Distance" -PDT_LAB_ANGLEVALUE = "Angle" -PDT_LAB_PERCENTS = "%" -PDT_LAB_TOOLS = "Tools" -PDT_LAB_JOIN2VERTS = "Join 2 Verts" -PDT_LAB_ORIGINCURSOR = "Origin To Cursor" -PDT_LAB_AD2D = "Set A/D 2D" -PDT_LAB_AD3D = "Set A/D 3D" -PDT_LAB_TAPERAXES = "" # Intentionally left blank -PDT_LAB_TAPER = "Taper" -PDT_LAB_INTERSETALL = "Intersect All" -PDT_LAB_BISECT = "Bisect" -PDT_LAB_EDGETOEFACE = "Edge-To-Face" -PDT_LAB_FILLET = "Fillet" -PDT_LAB_SEGMENTS = "Segments" -PDT_LAB_USEVERTS = "Use Vertices" -PDT_LAB_RADIUS = "Radius" -PDT_LAB_PROFILE = "Profile" -PDT_LAB_PIVOTSIZE = "" # Intentionally left blank -PDT_LAB_PIVOTWIDTH = "" # Intentionally left blank -PDT_LAB_PIVOTALPHA = "" # Intentionally left blank -PDT_LAB_PIVOTLOC = "" # Intentionally left blank -PDT_LAB_PIVOTLOCH = "Location" +PDT_LAB_ABS = "Absolute" # "Global" +PDT_LAB_DEL = "Delta" # "Relative" +PDT_LAB_DIR = "Direction" # "Polar" +PDT_LAB_NOR = "Normal" # "Perpendicular" +PDT_LAB_ARCCENTRE = "Arc Centre" +PDT_LAB_PLANE = "Plane" +PDT_LAB_MODE = "Mode" +PDT_LAB_OPERATION = "Operation" +PDT_LAB_PERCENT = "Percent" +PDT_LAB_INTERSECT = "Intersect" # "Convergance" +PDT_LAB_ORDER = "Order" +PDT_LAB_FLIPANGLE = "Flip Angle" +PDT_LAB_FLIPPERCENT = "Flip %" +PDT_LAB_ALLACTIVE = "All/Active" +PDT_LAB_VARIABLES = "Coordinates/Delta Offsets & Other Variables" +PDT_LAB_CVALUE = "Coordinates" +PDT_LAB_DISVALUE = "Distance" +PDT_LAB_ANGLEVALUE = "Angle" +PDT_LAB_PERCENTS = "%" +PDT_LAB_TOOLS = "Tools" +PDT_LAB_JOIN2VERTS = "Join 2 Verts" +PDT_LAB_ORIGINCURSOR = "Origin To Cursor" +PDT_LAB_AD2D = "Set A/D 2D" +PDT_LAB_AD3D = "Set A/D 3D" +PDT_LAB_TAPERAXES = "" # Intentionally left blank +PDT_LAB_TAPER = "Taper" +PDT_LAB_INTERSETALL = "Intersect All" +PDT_LAB_BISECT = "Bisect" +PDT_LAB_EDGETOEFACE = "Edge-To-Face" +PDT_LAB_FILLET = "Fillet" +PDT_LAB_SEGMENTS = "Segments" +PDT_LAB_USEVERTS = "Use Vertices" +PDT_LAB_RADIUS = "Radius" +PDT_LAB_PROFILE = "Profile" +PDT_LAB_PIVOTSIZE = "" # Intentionally left blank +PDT_LAB_PIVOTWIDTH = "" # Intentionally left blank +PDT_LAB_PIVOTALPHA = "" # Intentionally left blank +PDT_LAB_PIVOTLOC = "" # Intentionally left blank +PDT_LAB_PIVOTLOCH = "Location" # # Error Message # -PDT_ERR_NO_ACT_OBJ = "No Active Object - Please Select an Object" -PDT_OBJ_MODE_ERROR = "Only Mesh Object in Edit or Object Mode Supported" -PDT_ERR_NO_ACT_VERT = "No Active Vertex - Select One Vertex Individually" -PDT_ERR_NO_SEL_GEOM = "No Geometry/Objects Selected" -PDT_ERR_NO_ACT_VERTS = "No Selected Geometry - Please Select some Geometry" -PDT_ERR_NON_VALID = "is Not a Valid Option in Selected Object's Mode for Command:" -PDT_ERR_VERT_MODE = "Work in Vertex Mode for this Function" -PDT_ERR_NOPPLOC = "Custom Property PDT_PP_LOC for this object not found, have you Written it yet?" -PDT_ERR_NO_LIBRARY = "PDT Library Blend File (parts_library.blend) is Missing from Addons/clockworxpdt Folder" +PDT_ERR_NO_ACT_OBJ = "No Active Object - Please Select an Object" +PDT_OBJ_MODE_ERROR = "Only Mesh Object in Edit or Object Mode Supported" +PDT_ERR_NO_ACT_VERT = "No Active Vertex - Select One Vertex Individually" +PDT_ERR_NO_SEL_GEOM = "No Geometry/Objects Selected" +PDT_ERR_NO_ACT_VERTS = "No Selected Geometry - Please Select some Geometry" +PDT_ERR_NON_VALID = "is Not a Valid Option in Selected Object's Mode for Command:" +PDT_ERR_VERT_MODE = "Work in Vertex Mode for this Function" +PDT_ERR_NOPPLOC = ( + "Custom Property PDT_PP_LOC for this object not found, have you Written it yet?" +) +PDT_ERR_NO_LIBRARY = ("PDT Library Blend File (parts_library.blend) is Missing " + + "from Addons/clockworxpdt Folder") -PDT_ERR_SEL_1_VERTI = "Select at least 1 Vertex Individually (Currently selected:" -PDT_ERR_SEL_1_VERT = "Select at least 1 Vertex (Currently selected:" -PDT_ERR_SEL_2_VERTI = "Select at least 2 Vertices Individually (Currently selected:" -PDT_ERR_SEL_2_VERTIO = "Select Exactly 2 Vertices Individually (Currently selected:" -PDT_ERR_SEL_2_VERTS = "Select Exactly 2 Vertices (Currently selected:" -PDT_ERR_SEL_2_EDGES = "Select Only 2 Non-Intersecting Edges (Currently selected:" -PDT_ERR_SEL_3_VERTS = "Select Exactly 3 Vertices (Currently selected:" -PDT_ERR_SEL_3_VERTIO = "Select Exactly 3 Vertices Individually (Currently selected:" -PDT_ERR_SEL_2_V_1_E = "Select 2 Vertices Individually, or 1 Edge (Currently selected:" -PDT_ERR_SEL_4_VERTS = "Select 4 Vertices Individually, or 2 Edges (Currently selected:" -PDT_ERR_SEL_1_E_1_F = "Select 1 Face and 1 Detached Edge" +PDT_ERR_SEL_1_VERTI = "Select at least 1 Vertex Individually (Currently selected:" +PDT_ERR_SEL_1_VERT = "Select at least 1 Vertex (Currently selected:" +PDT_ERR_SEL_2_VERTI = "Select at least 2 Vertices Individually (Currently selected:" +PDT_ERR_SEL_2_VERTIO = "Select Exactly 2 Vertices Individually (Currently selected:" +PDT_ERR_SEL_2_VERTS = "Select Exactly 2 Vertices (Currently selected:" +PDT_ERR_SEL_2_EDGES = "Select Only 2 Non-Intersecting Edges (Currently selected:" +PDT_ERR_SEL_3_VERTS = "Select Exactly 3 Vertices (Currently selected:" +PDT_ERR_SEL_3_VERTIO = "Select Exactly 3 Vertices Individually (Currently selected:" +PDT_ERR_SEL_2_V_1_E = "Select 2 Vertices Individually, or 1 Edge (Currently selected:" +PDT_ERR_SEL_4_VERTS = "Select 4 Vertices Individually, or 2 Edges (Currently selected:" +PDT_ERR_SEL_1_E_1_F = "Select 1 Face and 1 Detached Edge" -PDT_ERR_SEL_1_EDGE = "Select Exactly 1 Edge (Currently selected:" -PDT_ERR_SEL_1_EDGEM = "Select at least 1 Edge (Currently selected:" +PDT_ERR_SEL_1_EDGE = "Select Exactly 1 Edge (Currently selected:" +PDT_ERR_SEL_1_EDGEM = "Select at least 1 Edge (Currently selected:" -PDT_ERR_SEL_1_OBJ = "Select Exactly 1 Object (Currently selected:" -PDT_ERR_SEL_2_OBJS = "Select Exactly 2 Objects (Currently selected:" -PDT_ERR_SEL_3_OBJS = "Select Exactly 3 Objects (Currently selected:" -PDT_ERR_SEL_4_OBJS = "Select Exactly 4 Objects (Currently selected:" +PDT_ERR_SEL_1_OBJ = "Select Exactly 1 Object (Currently selected:" +PDT_ERR_SEL_2_OBJS = "Select Exactly 2 Objects (Currently selected:" +PDT_ERR_SEL_3_OBJS = "Select Exactly 3 Objects (Currently selected:" +PDT_ERR_SEL_4_OBJS = "Select Exactly 4 Objects (Currently selected:" -PDT_ERR_FACE_SEL = "You have a Face Selected, this would have ruined the Topology" +PDT_ERR_FACE_SEL = "You have a Face Selected, this would have ruined the Topology" -PDT_ERR_INT_LINES = "Implied Lines Do Not Intersect in" -PDT_ERR_INT_NO_ALL = "Active Vertex was not Closest to Intersection and All/Act was not Selected" -PDT_ERR_STRIGHT_LINE = "Selected Points all lie in a Straight Line" -PDT_ERR_CONNECTED = "Vertices are already Connected" -PDT_ERR_EDIT_MODE = "Only Works in EDIT Mode (Current mode:" -PDT_ERR_EDOB_MODE = "Only Works in EDIT, or OBJECT Modes (Current mode:" -PDT_ERR_TAPER_ANG = "Angle must be in Range -80 to +80 (Currently set to:" -PDT_ERR_TAPER_SEL = "Select at Least 2 Vertices Individually - Active is Rotation Point (Currently selected:" -PDT_ERR_NO3DVIEW = "View3D not found, cannot run operator" -PDT_ERR_SCALEZERO = "Scale Distance is 0" +PDT_ERR_INT_LINES = "Implied Lines Do Not Intersect in" +PDT_ERR_INT_NO_ALL = ( + "Active Vertex was not Closest to Intersection and All/Act was not Selected" +) +PDT_ERR_STRIGHT_LINE = "Selected Points all lie in a Straight Line" +PDT_ERR_CONNECTED = "Vertices are already Connected" +PDT_ERR_EDIT_MODE = "Only Works in EDIT Mode (Current mode:" +PDT_ERR_EDOB_MODE = "Only Works in EDIT, or OBJECT Modes (Current mode:" +PDT_ERR_TAPER_ANG = "Angle must be in Range -80 to +80 (Currently set to:" +PDT_ERR_TAPER_SEL = ("Select at Least 2 Vertices Individually - Active is Rotation Point " + + "(Currently selected:") +PDT_ERR_NO3DVIEW = "View3D not found, cannot run operator" +PDT_ERR_SCALEZERO = "Scale Distance is 0" -PDT_ERR_CHARS_NUM = "Bad Command Format, not enough Characters" -PDT_ERR_BADFLETTER = "Bad Operator (1st Letter); C D E F G N M P S V or ? only" -PDT_ERR_BADMATHS = "Not a Valid Mathematical Expression!" -PDT_ERR_BADCOORDL = "X Y & Z Not permitted in anything other than Maths Operations" -PDT_ERR_BAD1VALS = "Bad Command - 1 Value needed" -PDT_ERR_BAD2VALS = "Bad Command - 2 Values needed" -PDT_ERR_BAD3VALS = "Bad Command - 3 Coords needed" -PDT_ERR_ADDVEDIT = "Only Add New Vertices in Edit Mode" -PDT_ERR_SPLITEDIT = "Only Split Edges in Edit Mode" -PDT_ERR_EXTEDIT = "Only Extrude Vertices in Edit Mode" -PDT_ERR_DUPEDIT = "Only Duplicate Geometry in Edit Mode" -PDT_ERR_FILEDIT = "Only Fillet Geometry in Edit Mode" -PDT_ERR_NOCOMMAS = "No commas allowed in Maths Command" +PDT_ERR_CHARS_NUM = "Bad Command Format, not enough Characters" +PDT_ERR_BADFLETTER = "Bad Operator (1st Letter); C D E F G N M P S V or ? only" +PDT_ERR_BADMATHS = "Not a Valid Mathematical Expression!" +PDT_ERR_BADCOORDL = "X Y & Z Not permitted in anything other than Maths Operations" +PDT_ERR_BAD1VALS = "Bad Command - 1 Value needed" +PDT_ERR_BAD2VALS = "Bad Command - 2 Values needed" +PDT_ERR_BAD3VALS = "Bad Command - 3 Coords needed" +PDT_ERR_ADDVEDIT = "Only Add New Vertices in Edit Mode" +PDT_ERR_SPLITEDIT = "Only Split Edges in Edit Mode" +PDT_ERR_EXTEDIT = "Only Extrude Vertices in Edit Mode" +PDT_ERR_DUPEDIT = "Only Duplicate Geometry in Edit Mode" +PDT_ERR_FILEDIT = "Only Fillet Geometry in Edit Mode" +PDT_ERR_NOCOMMAS = "No commas allowed in Maths Command" -PDT_ERR_2CPNPE = "Select 2 Co-Planar Non-Parallel Edges" -PDT_ERR_NCEDGES = "Edges must be Co-Planar Non-Parallel Edges, Selected Edges aren't" -PDT_ERR_1EDGE1FACE = "Select 1 face and 1 Detached Edge" -PDT_ERR_NOINT = "No Intersection Found" +PDT_ERR_2CPNPE = "Select 2 Co-Planar Non-Parallel Edges" +PDT_ERR_NCEDGES = "Edges must be Co-Planar Non-Parallel Edges, Selected Edges aren't" +PDT_ERR_1EDGE1FACE = "Select 1 face and 1 Detached Edge" +PDT_ERR_NOINT = "No Intersection Found" # Info messages # -PDT_INF_OBJ_MOVED = "Active Object Moved to Intersection, " +PDT_INF_OBJ_MOVED = "Active Object Moved to Intersection, " # Confirm Messages # -PDT_CON_AREYOURSURE = "Are You Sure About This?" +PDT_CON_AREYOURSURE = "Are You Sure About This?" # Descriptions # -PDT_DES_COORDS = "Cartesian Inputs" -PDT_DES_OFFDIS = "Offset Distance" -PDT_DES_OFFANG = "Offset Angle" -PDT_DES_OFFPER = "Offset Percentage" -PDT_DES_WORPLANE = "Choose Working Plane" -PDT_DES_MOVESEL = "Select Move Mode" -PDT_DES_OPMODE = "Select Operation Mode" -PDT_DES_ROTMOVAX = "Rotational Axis - Movement Axis" -PDT_DES_FLIPANG = "Flip Angle 180 degrees" -PDT_DES_FLIPPER = "Flip Percent to 100 - %" -PDT_DES_TRIM = "Trim/Extend only Active Vertex, or All" -PDT_DES_LIBOBS = "Objects in Library" -PDT_DES_LIBCOLS = "Collections in Library" -PDT_DES_LIBMATS = "Materials in Library" -PDT_DES_LIBMODE = "Library Mode" -PDT_DES_LIBSER = "Enter A Search String (Contained)" -PDT_DES_OBORDER = "Object Order to Lines" -PDT_DES_VALIDLET = "Valid 1st letters; C D E G N P S V, Valid 2nd letters: A D I O P" -PDT_DES_OUTPUT = "Output for Maths Operations" -PDT_DES_PPLOC = "Location of PivotPoint" -PDT_DES_PPSCALEFAC = "Scale Factors" -PDT_DES_PPSIZE = "Pivot Size Factor" -PDT_DES_PPWIDTH = "Pivot Line Width in Pixels" -PDT_DES_PPTRANS = "Pivot Point Transparency" -PDT_DES_PIVOTDIS = "Input Distance to Compare with Sytem Distance to set Scales" -PDT_DES_FILLETRAD = "Fillet Radius" -PDT_DES_FILLETSEG = "Number of Fillet Segments" -PDT_DES_FILLETPROF = "Fillet Profile" -PDT_DES_FILLETVERTS = "Use Vertices, or Edges, Set to False for Extruded Geometry" -PDT_DES_FILLINT = "Intersect & Fillet Two Selected Edges" +PDT_DES_COORDS = "Cartesian Inputs" +PDT_DES_OFFDIS = "Offset Distance" +PDT_DES_OFFANG = "Offset Angle" +PDT_DES_OFFPER = "Offset Percentage" +PDT_DES_WORPLANE = "Choose Working Plane" +PDT_DES_MOVESEL = "Select Move Mode" +PDT_DES_OPMODE = "Select Operation Mode" +PDT_DES_ROTMOVAX = "Rotational Axis - Movement Axis" +PDT_DES_FLIPANG = "Flip Angle 180 degrees" +PDT_DES_FLIPPER = "Flip Percent to 100 - %" +PDT_DES_TRIM = "Trim/Extend only Active Vertex, or All" +PDT_DES_LIBOBS = "Objects in Library" +PDT_DES_LIBCOLS = "Collections in Library" +PDT_DES_LIBMATS = "Materials in Library" +PDT_DES_LIBMODE = "Library Mode" +PDT_DES_LIBSER = "Enter A Search String (Contained)" +PDT_DES_OBORDER = "Object Order to Lines" +PDT_DES_VALIDLET = "Valid 1st letters; C D E G N P S V, Valid 2nd letters: A D I O P" +PDT_DES_OUTPUT = "Output for Maths Operations" +PDT_DES_PPLOC = "Location of PivotPoint" +PDT_DES_PPSCALEFAC = "Scale Factors" +PDT_DES_PPSIZE = "Pivot Size Factor" +PDT_DES_PPWIDTH = "Pivot Line Width in Pixels" +PDT_DES_PPTRANS = "Pivot Point Transparency" +PDT_DES_PIVOTDIS = "Input Distance to Compare with Sytem Distance to set Scales" +PDT_DES_FILLETRAD = "Fillet Radius" +PDT_DES_FILLETSEG = "Number of Fillet Segments" +PDT_DES_FILLETPROF = "Fillet Profile" +PDT_DES_FILLETVERTS = "Use Vertices, or Edges, Set to False for Extruded Geometry" +PDT_DES_FILLINT = "Intersect & Fillet Two Selected Edges" diff --git a/precision_drawing_tools/pdt_pivot_point.py b/precision_drawing_tools/pdt_pivot_point.py index 865064ed..fd09c42d 100644 --- a/precision_drawing_tools/pdt_pivot_point.py +++ b/precision_drawing_tools/pdt_pivot_point.py @@ -26,7 +26,7 @@ import bmesh from bpy.types import Operator, SpaceView3D from mathutils import Vector, Matrix from math import pi -from .pdt_functions import view_coords, drawCallback3D +from .pdt_functions import view_coords, draw_callback_3d from .pdt_msg_strings import ( PDT_CON_AREYOURSURE, PDT_ERR_EDIT_MODE, @@ -60,7 +60,7 @@ class PDT_OT_ModalDrawOperator(bpy.types.Operator): if PDT_OT_ModalDrawOperator._handle is None: PDT_OT_ModalDrawOperator._handle = SpaceView3D.draw_handler_add( - drawCallback3D, (self, context), "WINDOW", "POST_VIEW" + draw_callback_3d, (self, context), "WINDOW", "POST_VIEW" ) context.window_manager.pdt_run_opengl = True @@ -103,9 +103,8 @@ class PDT_OT_ModalDrawOperator(bpy.types.Operator): context.area.tag_redraw() return {"FINISHED"} - else: - self.report({"ERROR"}, PDT_ERR_NO3DVIEW) + self.report({"ERROR"}, PDT_ERR_NO3DVIEW) return {"CANCELLED"} @@ -117,10 +116,11 @@ class PDT_OT_ViewPlaneRotate(Operator): @classmethod def poll(cls, context): - ob = context.object - if ob is None: + """Check Onject Status.""" + obj = context.object + if obj is None: return False - return all([bool(ob), ob.type == "MESH", ob.mode == "EDIT"]) + return all([bool(obj), obj.type == "MESH", obj.mode == "EDIT"]) def execute(self, context): @@ -170,10 +170,11 @@ class PDT_OT_ViewPlaneScale(Operator): @classmethod def poll(cls, context): - ob = context.object - if ob is None: + """Check Onject Status.""" + obj = context.object + if obj is None: return False - return all([bool(ob), ob.type == "MESH", ob.mode == "EDIT"]) + return all([bool(obj), obj.type == "MESH", obj.mode == "EDIT"]) def execute(self, context): @@ -205,17 +206,17 @@ class PDT_OT_ViewPlaneScale(Operator): bm = bmesh.from_edit_mesh(obj.data) verts = verts = [v for v in bm.verts if v.select] for v in verts: - dx = (pg.pivot_loc.x - obj.matrix_world.decompose()[0].x - v.co.x) * ( + delta_x = (pg.pivot_loc.x - obj.matrix_world.decompose()[0].x - v.co.x) * ( 1 - pg.pivot_scale.x ) - dy = (pg.pivot_loc.y - obj.matrix_world.decompose()[0].y - v.co.y) * ( + delta_y = (pg.pivot_loc.y - obj.matrix_world.decompose()[0].y - v.co.y) * ( 1 - pg.pivot_scale.y ) - dz = (pg.pivot_loc.z - obj.matrix_world.decompose()[0].z - v.co.z) * ( + delta_z = (pg.pivot_loc.z - obj.matrix_world.decompose()[0].z - v.co.z) * ( 1 - pg.pivot_scale.z ) - dv = Vector((dx, dy, dz)) - v.co = v.co + dv + delta_v = Vector((delta_x, delta_y, delta_z)) + v.co = v.co + delta_v bmesh.update_edit_mesh(obj.data) return {"FINISHED"} @@ -276,10 +277,11 @@ class PDT_OT_PivotSelected(Operator): @classmethod def poll(cls, context): - ob = context.object - if ob is None: + """Check Onject Status.""" + obj = context.object + if obj is None: return False - return all([bool(ob), ob.type == "MESH", ob.mode == "EDIT"]) + return all([bool(obj), obj.type == "MESH", obj.mode == "EDIT"]) def execute(self, context): @@ -313,9 +315,9 @@ class PDT_OT_PivotSelected(Operator): pg.pivot_loc = scene.cursor.location scene.cursor.location = old_cursor_loc return {"FINISHED"} - else: - self.report({"ERROR"}, PDT_ERR_NO_SEL_GEOM) - return {"FINISHED"} + + self.report({"ERROR"}, PDT_ERR_NO_SEL_GEOM) + return {"FINISHED"} class PDT_OT_PivotOrigin(Operator): @@ -326,10 +328,11 @@ class PDT_OT_PivotOrigin(Operator): @classmethod def poll(cls, context): - ob = context.object - if ob is None: + """Check Onject Status.""" + obj = context.object + if obj is None: return False - return all([bool(ob), ob.type == "MESH"]) + return all([bool(obj), obj.type == "MESH"]) def execute(self, context): """Moves Pivot Point to Object Origin. @@ -362,10 +365,11 @@ class PDT_OT_PivotWrite(Operator): @classmethod def poll(cls, context): - ob = context.object - if ob is None: + """Check Onject Status.""" + obj = context.object + if obj is None: return False - return all([bool(ob), ob.type == "MESH"]) + return all([bool(obj), obj.type == "MESH"]) def execute(self, context): """Writes Pivot Point Location to Object's Custom Properties. @@ -408,10 +412,11 @@ class PDT_OT_PivotRead(Operator): @classmethod def poll(cls, context): - ob = context.object - if ob is None: + """Check Onject Status.""" + obj = context.object + if obj is None: return False - return all([bool(ob), ob.type == "MESH"]) + return all([bool(obj), obj.type == "MESH"]) def execute(self, context): """Reads Pivot Point Location from Object's Custom Properties. @@ -438,6 +443,6 @@ class PDT_OT_PivotRead(Operator): if "PDT_PP_LOC" in obj: pg.pivot_loc = obj["PDT_PP_LOC"] return {"FINISHED"} - else: - self.report({"ERROR"}, PDT_ERR_NOPPLOC) - return {"FINISHED"} + + self.report({"ERROR"}, PDT_ERR_NOPPLOC) + return {"FINISHED"} diff --git a/precision_drawing_tools/pdt_view.py b/precision_drawing_tools/pdt_view.py index f1e73245..087ce2f5 100644 --- a/precision_drawing_tools/pdt_view.py +++ b/precision_drawing_tools/pdt_view.py @@ -32,6 +32,8 @@ from .pdt_functions import debug, euler_to_quaternion class PDT_OT_ViewRot(Operator): + """Rotate View by Absolute Coordinates.""" + bl_idname = "pdt.viewrot" bl_label = "Rotate View" bl_options = {"REGISTER", "UNDO"} @@ -58,13 +60,15 @@ class PDT_OT_ViewRot(Operator): roll_value = euler_to_quaternion( pg.rotation_coords.x * pi / 180, pg.rotation_coords.y * pi / 180, - pg.rotation_coords.z * pi / 180 + pg.rotation_coords.z * pi / 180, ) context.region_data.view_rotation = roll_value return {"FINISHED"} -class PDT_OT_vRotL(Operator): +class PDT_OT_ViewRotL(Operator): + """Rotate View Left.""" + bl_idname = "pdt.viewleft" bl_label = "Rotate Left" bl_options = {"REGISTER", "UNDO"} @@ -90,7 +94,9 @@ class PDT_OT_vRotL(Operator): return {"FINISHED"} -class PDT_OT_vRotR(Operator): +class PDT_OT_ViewRotR(Operator): + """Rotate View Right.""" + bl_idname = "pdt.viewright" bl_label = "Rotate Right" bl_options = {"REGISTER", "UNDO"} @@ -117,7 +123,9 @@ class PDT_OT_vRotR(Operator): return {"FINISHED"} -class PDT_OT_vRotU(Operator): +class PDT_OT_ViewRotU(Operator): + """Rotate View Up.""" + bl_idname = "pdt.viewup" bl_label = "Rotate Up" bl_options = {"REGISTER", "UNDO"} @@ -144,7 +152,9 @@ class PDT_OT_vRotU(Operator): return {"FINISHED"} -class PDT_OT_vRotD(Operator): +class PDT_OT_ViewRotD(Operator): + """Rotate View Down.""" + bl_idname = "pdt.viewdown" bl_label = "Rotate Down" bl_options = {"REGISTER", "UNDO"} @@ -171,7 +181,9 @@ class PDT_OT_vRotD(Operator): return {"FINISHED"} -class PDT_OT_vRoll(Operator): +class PDT_OT_ViewRoll(Operator): + """Roll View.""" + bl_idname = "pdt.viewroll" bl_label = "Roll View" bl_options = {"REGISTER", "UNDO"} @@ -198,7 +210,9 @@ class PDT_OT_vRoll(Operator): return {"FINISHED"} -class PDT_OT_viso(Operator): +class PDT_OT_ViewIso(Operator): + """Set View Isometric.""" + bl_idname = "pdt.viewiso" bl_label = "Isometric View" bl_options = {"REGISTER", "UNDO"} @@ -216,17 +230,17 @@ class PDT_OT_viso(Operator): Status Set. """ # Try working this out in your head! - context.region_data.view_rotation = Quaternion( - (0.8205, 0.4247, -0.1759, -0.3399) - ) - context.region_data.view_perspective = 'ORTHO' + context.region_data.view_rotation = Quaternion((0.8205, 0.4247, -0.1759, -0.3399)) + context.region_data.view_perspective = "ORTHO" return {"FINISHED"} class PDT_OT_Reset3DView(Operator): + """Reset Views to Factory Default.""" + bl_idname = "pdt.reset_3d_view" bl_label = "Reset 3D View" - bl_options = {'REGISTER', 'UNDO'} + bl_options = {"REGISTER", "UNDO"} bl_description = "Reset 3D View to Blender Defaults." def execute(self, context): @@ -241,13 +255,15 @@ class PDT_OT_Reset3DView(Operator): # The default view_distance to the origin when starting up Blender default_view_distance = 17.986562728881836 - default_view_distance = bpy.data.screens['Layout'].areas[-1].spaces[0].region_3d.view_distance + default_view_distance = ( + bpy.data.screens["Layout"].areas[-1].spaces[0].region_3d.view_distance + ) # The default view_matrix when starting up Blender default_view_matrix = ( (0.41, -0.4017, 0.8188, 0.0), (0.912, 0.1936, -0.3617, 0.0), (-0.0133, 0.8950, 0.4458, 0.0), - (0.0, 0.0, -17.9866, 1.0) + (0.0, 0.0, -17.9866, 1.0), ) view = context.region_data @@ -270,4 +286,4 @@ class PDT_OT_Reset3DView(Operator): view.update() debug(f"view_matrix AFTER reset:\n{view.view_matrix}") - return {'FINISHED'} + return {"FINISHED"} diff --git a/precision_drawing_tools/pdt_xall.py b/precision_drawing_tools/pdt_xall.py index 1c283cb6..dd690284 100644 --- a/precision_drawing_tools/pdt_xall.py +++ b/precision_drawing_tools/pdt_xall.py @@ -29,14 +29,18 @@ from mathutils.geometry import intersect_line_line as LineIntersect import itertools from collections import defaultdict from . import pdt_cad_module as cm +from .pdt_functions import oops +from .pdt_msg_strings import ( + PDT_ERR_EDOB_MODE +) def order_points(edge, point_list): """Order these edges from distance to v1, then sandwich the sorted list with v1, v2.""" v1, v2 = edge - def dist(co): - return (v1 - co).length + def dist(coord): + return (v1 - coord).length point_list = sorted(point_list, key=dist) return [v1] + point_list + [v2] @@ -89,8 +93,8 @@ def get_intersection_dictionary(bm, edge_indices): permutations = get_valid_permutations(bm, edge_indices) - k = defaultdict(list) - d = defaultdict(list) + list_k = defaultdict(list) + list_d = defaultdict(list) for edges in permutations: raw_vert_indices = cm.vertex_indices_from_edges_tuple(bm, edges) @@ -103,35 +107,35 @@ def get_intersection_dictionary(bm, edge_indices): continue # reaches this point only when an intersection happens on both edges. - [k[edge].append(points[0]) for edge in edges] + [list_k[edge].append(points[0]) for edge in edges] # k will contain a dict of edge indices and points found on those edges. - for edge_idx, unordered_points in k.items(): + for edge_idx, unordered_points in list_k.items(): tv1, tv2 = bm.edges[edge_idx].verts v1 = bm.verts[tv1.index].co v2 = bm.verts[tv2.index].co ordered_points = order_points((v1, v2), unordered_points) - d[edge_idx].extend(ordered_points) + list_d[edge_idx].extend(ordered_points) - return d + return list_d def update_mesh(bm, int_dict): """Make new geometry (delete old first).""" - oe = bm.edges - ov = bm.verts + orig_e = bm.edges + orig_v = bm.verts new_verts = [] collect = new_verts.extend for _, point_list in int_dict.items(): num_edges_to_add = len(point_list) - 1 for i in range(num_edges_to_add): - a = ov.new(point_list[i]) - b = ov.new(point_list[i + 1]) - oe.new((a, b)) + coord_a = orig_v.new(point_list[i]) + coord_b = orig_v.new(point_list[i + 1]) + orig_e.new((coord_a, coord_b)) bm.normal_update() - collect([a, b]) + collect([coord_a, coord_b]) bmesh.ops.delete(bm, geom=[edge for edge in bm.edges if edge.select], context="EDGES") bmesh.ops.remove_doubles(bm, verts=bm.verts, dist=0.0001) @@ -178,6 +182,7 @@ def intersect_all(context): bmesh.update_edit_mesh(obj.data) else: + pg.error = f"{PDT_ERR_EDOB_MODE},{obj.mode})" context.window_manager.popup_menu(oops, title="Error", icon="ERROR") return @@ -196,10 +201,19 @@ class PDT_OT_IntersectAllEdges(bpy.types.Operator): @classmethod def poll(cls, context): - ob = context.active_object - if ob is None: + """Check to see object is in correct condidtion. + + Args: + Class, + context: Blender bpy.context instance. + + Returns: + Boolean + """ + obj = context.active_object + if obj is None: return False - return ob is not None and ob.type == "MESH" and ob.mode == "EDIT" + return obj is not None and obj.type == "MESH" and obj.mode == "EDIT" def execute(self, context): """Computes All intersections with Crossing Geometry. |