[Bf-extensions-cvs] [5a4afc8f] master: xoffsets: full update to version alpha_007b

NBurn noreply at git.blender.org
Wed May 31 04:16:45 CEST 2017


Commit: 5a4afc8f8b19ba773dcb97a4b00c845985ac1af5
Author: NBurn
Date:   Tue May 30 22:14:35 2017 -0400
Branches: master
https://developer.blender.org/rBAC5a4afc8f8b19ba773dcb97a4b00c845985ac1af5

xoffsets: full update to version alpha_007b

Faster and more organized selection set handling
More concise and efficient point finding
Uses Vector methods instead of custom Python code
More logical variable, function, and method names
Removed unused code and redundant/unneeded operations and arguments
Split long lines of code

===================================================================

M	mesh_xoffsets.py

===================================================================

diff --git a/mesh_xoffsets.py b/mesh_xoffsets.py
index 9059c041..2cba5db7 100644
--- a/mesh_xoffsets.py
+++ b/mesh_xoffsets.py
@@ -19,7 +19,7 @@ END GPL LICENSE BLOCK
 
 #============================================================================
 
-mesh_xoffsets.py (alpha version 005)
+mesh_xoffsets.py (alpha version 007b)
 
 Install instructions (if downloaded separately from Blender):
 1) Save the mesh_xoffsets.py file to your computer.
@@ -47,7 +47,7 @@ todo:
 bl_info = {
     "name": "Exact Offsets",
     "author": "nBurn",
-    "version": (0, 0, 5),
+    "version": (0, 0, 7),
     "blender": (2, 7, 7),
     "location": "View3D",
     "description": "Tool for precisely setting distance, scale, and rotation of mesh geometry",
@@ -64,8 +64,6 @@ from math import fmod, sqrt, degrees, radians
 from mathutils import Vector, geometry, Quaternion, Euler
 from mathutils.geometry import intersect_line_line_2d
 from bpy_extras.view3d_utils import location_3d_to_region_2d
-#import code
-#code.interact(local=locals())
 #__import__('code').interact(local=dict(globals(), **locals()))
 
 print("Exact Offsets loaded")
@@ -105,9 +103,71 @@ class Colr:
     grey  = 1.0, 1.0, 1.0, 0.4
 
 
+# Class to stores selection info for scene and/or edited mesh
+# Generates a list of mesh objects in the scene and lists of selected mesh
+# and non-mesh objects and selected vertices (if in Edit Mode). These lists
+# are used to speed up mesh object iteration and for restoring the selected
+# objects after transforms.
+class SceneSelectionInfo:
+    def __init__(self):
+        self.selNMObjs = []  # selected non-mesh objects
+        self.MshObjs = []
+        self.selMshObjs = []
+        self.selMshVts = []
+        self.activeObj = None
+        self.obj = bpy.context.scene.objects  # short hand, for internal use
+
+    # Checks if there was changes to the selected objects or verts. It is
+    # assumed no objects added or removed while the addon is running. This
+    # should not be run while the snap point is active / existing.
+    def update(self, EdType):
+        tmp = []
+        if EdType == "OBJECT":
+            if self.obj.active.type == 'MESH':
+                self.activeObj = self.obj.active
+            else:
+                self.obj.active = self.obj[ self.MshObjs[0] ]
+                self.activeObj = self.obj.active
+            for i in self.MshObjs:
+                if self.obj[i].select:
+                    tmp.append(i)
+            self.selMshObjs = tmp.copy()
+            #print("self.selMshObjs", self.selMshObjs)  # debug
+
+        elif EdType == "EDIT_MESH":
+            bm = bmesh.from_edit_mesh(bpy.context.edit_object.data)
+            if hasattr(bm.verts, "ensure_lookup_table"):
+                bm.verts.ensure_lookup_table()
+            for ind in range(len(bm.verts)):
+                if bm.verts[ind].select == True:
+                    tmp.append(ind)
+            self.selMshVts = tmp.copy()
+
+    def restoreSelected(self, EdType):
+        if EdType == "OBJECT":
+            self.obj.active = self.activeObj
+            for ind in self.selMshObjs:
+                self.obj[ind].select = True
+        elif EdType == "EDIT_MESH":
+            bm = bmesh.from_edit_mesh(bpy.context.edit_object.data)
+            if hasattr(bm.verts, "ensure_lookup_table"):
+                bm.verts.ensure_lookup_table()
+            for ind in self.selMshVts:
+                bm.verts[ind].select = True
+
+    # for generating MshObjs and selNMObjs info when addon first run
+    def startRun(self, EdType):
+        for i in range(len(self.obj)):
+            if self.obj[i].type == 'MESH':
+                self.MshObjs.append(i)
+            elif self.obj[i].select:
+                self.selNMObjs.append(i)
+        self.update(EdType)
+
+
 # vertex storage class, stores reference point info
 class VertObj:
-    def __init__(self, objInd=-1, vertInd=-1, co3D=(), co2D=(), dist2D=-1, refInd=-1):
+    def __init__(self, objInd=-1, vertInd=-1, co3D=(), co2D=(), dist2D=4000, refInd=-1):
         self.objInd = objInd
         self.vertInd = vertInd
         self.co3D = co3D
@@ -200,78 +260,44 @@ class RotationData:
 
 # === Linear Equations ===
 
-#def getMidpoint2D(x1, y1, x2, y2):
-#    return ( (x1+x2)/2 , (y1+y2)/2 )
-
-
-def getMidpoint3D(ptA, ptB):
-    x1, y1, z1 = ptA[0], ptA[1], ptA[2]
-    x2, y2, z2 = ptB[0], ptB[1], ptB[2]
-    return Vector([ (x1+x2)/2 , (y1+y2)/2 , (z1+z2)/2 ])
-
+def getMidpoint(ptA, ptB):
+    return ptA.lerp(ptB, 0.5)
 
-def get_dist_2D(ptA, ptB):
-    x1, y1 = ptA[0], ptA[1]
-    x2, y2 = ptB[0], ptB[1]
-    return sqrt( abs( ((x2-x1)**2) + ((y2-y1)**2) ) )
 
-
-def get_dist_3D(ptA, ptB):
-    x1, y1, z1 = ptA[0], ptA[1], ptA[2]
-    x2, y2, z2 = ptB[0], ptB[1], ptB[2]
-    res = sqrt( abs( ((x2-x1)**2) + ((y2-y1)**2) + ((z2-z1)**2) ) )
-    return res
+def get_dist(ptA, ptB):
+    return (ptA - ptB).length
 
 
 # For making sure rise over run doesn't get flipped.
 def slope_check(pt1, pt2):
-    cmp = ( pt1[0] >= pt2[0], pt1[1] >= pt2[1], pt1[2] >= pt2[2] )
-    return cmp
-
-
-def get_slope_3D(self, ptA, ptB):
-    dist3D = get_dist_3D(ptA, ptB)
-    x1, y1, z1 = ptA[0], ptA[1], ptA[2]
-    x2, y2, z2 = ptB[0], ptB[1], ptB[2]
-    if dist3D == 0:
-        self.report({'ERROR'}, 'Distance between points cannot be zero.')
-        return
-    xSlope = (x1 - x2) / dist3D
-    ySlope = (y1 - y2) / dist3D
-    zSlope = (z1 - z2) / dist3D
-    return (xSlope, ySlope, zSlope)
-
-
-def get_new_pt_3D(xyz, slope3D, dis3D):
-    #newX = (x1 +- (dis3D * slopeX) )
-    x1, y1, z1 = xyz[0], xyz[1], xyz[2]
-    slopeX, slopeY, slopeZ = slope3D[0], slope3D[1], slope3D[2]
-    newX = x1 + (dis3D * slopeX)
-    newY = y1 + (dis3D * slopeY)
-    newZ = z1 + (dis3D * slopeZ)
-    return Vector([newX, newY, newZ])
+    cmp_ls = []
+    for i in range(len(pt1)):
+        cmp_ls.append(floatsAlmEq(pt1[i], pt2[i]) or pt1[i] > pt2[i])
+    return cmp_ls
 
 
 # Finds 3D location that shares same slope of line connecting Anchor and
 # Free or that is on axis line going through Anchor.
-def get_new_3D_coor(self, lock, ptA, ptF, newDis):
-    ptN_1, ptN_2 = (), ()
+def get_new_3D_co(self, lock, rpLs, oldDis, newDis):
+    ptA, ptF = rpLs[0].co3D, rpLs[1].co3D
     if lock == '':
         if newDis == 0:
             return ptA
         origSlope = slope_check(ptA, ptF)
-        slope3D = get_slope_3D(self, ptF, ptA)
-        ptN_1 = get_new_pt_3D(ptA, slope3D, newDis)
-        ptN_2 = get_new_pt_3D(ptA, slope3D, -newDis)
+        scale = newDis / oldDis
+        ptN_1 = ptA.lerp(ptF,  scale)
+        ptN_2 = ptA.lerp(ptF, -scale)
         ptN_1_slp = slope_check(ptA, ptN_1)
         ptN_2_slp = slope_check(ptA, ptN_2)
         if origSlope == ptN_1_slp:
+            #print("ptN_1 !")  # debug
             if newDis > 0:
                 return ptN_1
             else:
                 # for negative distances
                 return ptN_2
         elif origSlope == ptN_2_slp:
+            #print("ptN_2 !")  # debug
             if newDis > 0:
                 return ptN_2
             else:
@@ -301,7 +327,7 @@ def get_new_3D_coor(self, lock, ptA, ptF, newDis):
 # try a different power of ten for the "tol" value (eg 0.01 or 0.00001)
 # todo: replace this with Python 3.5's math.isclose() ?
 # do recent versions of Blender support math.isclose()?
-def AreFloatsEq(flt_A, flt_B):
+def floatsAlmEq(flt_A, flt_B):
     tol = 0.0001
     return flt_A > (flt_B - tol) and flt_A < (flt_B + tol)
 
@@ -317,14 +343,16 @@ def getLineAngle3D(Aco, Bco, Cco):
 # Checks if the 3 coordinates arguments (pt1, pt2, pt3) will create
 # an angle with a measurement matching the value in the argument
 # expAngMeas (expected angle measurement).
-def angleMatch3D(pt1, pt2, pt3, expAng):
+def angleMatch3D(pt1, pt2, pt3, expAngMeas):
     angMeas = getLineAngle3D(pt1, pt2, pt3)
-    #print("pt1", pt1)  # debug
-    #print("pt2", pt2)  # debug
-    #print("pt3", pt3)  # debug
-    #print("expAng ", expAng)  # debug
-    #print("angMeas ", angMeas)  # debug
-    return AreFloatsEq(angMeas, expAng)
+    '''
+    print("pt1", pt1)  # debug
+    print("pt2", pt2)  # debug
+    print("pt3", pt3)  # debug
+    print("expAng ", expAngMeas)  # debug
+    print("angMeas ", angMeas)  # debug
+    '''
+    return floatsAlmEq(angMeas, expAngMeas)
 
 
 # Calculates rotation around axis or face normal at Pivot's location.
@@ -349,85 +377,80 @@ def getRotatedPoint(PivC, angleDiffRad, rotDat, movCo):
     return movAligned + PivC
 
 
-# Takes axis (str), list of 3D coordinates, and amount of 3D coordinates (int)
-# returns modified list of 3D coordinates or empty tuple if problem
-# returns supplied list of 3D coordinates if no axis lock
-# todo : send transfMode instead of refCount ?
+# Takes a refPts (ReferencePoints class) argument and modifies its member
+# variable lpLs (lock pt list). The lpLs variable is assigned a modified list
+# of 3D coordinates (if an axis lock was provided), the contents of the
+# refPts' rpLs var (if no axis lock was provided), or an empty list (if there
+# wasn't enough refPts or there was a problem creating the modified list).
 # todo : move inside ReferencePoints class ?
-def setLockPts(axis, rPts, refCount):
-    if refCount < 2:
-        return []
-    if axis == '':
-        return rPts
+def setLockPts(refPts):
+    if refPts.cnt < 2:
+        refPts.lpLs = []
+    elif refPts.axLock == '':
+        refPts.lpLs = refPts.rpLs
     else:
-        NewPtLs = [ VertObj(), VertObj() ]
-        rPts2 = [rPts[i].co3D for i in range(refCount)]  # shorthand
-
+        refPts.lpLs = []
+        new0, new1 = VertObj(), VertObj()
+        ptls = [refPts.rpLs[i].co3D for i in range(refPts.cnt)]  # shorthand
         # finds 3D midpoint between 2 supplied coordinates
         # axis determines which coordinates are assigned midpoint values
         # if X, Anchor is [AncX, MidY, MidZ] and Free is [FreeX, MidY, MidZ]
-        if refCount == 2:  # translate
-            mid3D = getMidpoint3D( rPts2[0], rPts2[1] )
-            if axis == 'X':
-                NewPtLs[0].co3D = Vector([ rPts2[0][0], mid3D[1], mid3D[2] ])
-                NewPtLs[1].co3D = Vector([ rPts2[1][0], m

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-extensions-cvs mailing list