Skip to content
Snippets Groups Projects
curve_assign_shapekey.py 39 KiB
Newer Older
  • Learn to ignore specific revisions
  •         
            def comparer(left, right):
                for fn in matchPartCmpFns:
                    a = fn(left)
                    b = fn(right)
                    
                    if(floatCmpWithMargin(a, b)):
                        continue
                    else:
                        return (a > b) - ( a < b) #No cmp in python3
    
                return 0
                
            parts = sorted(parts, key = cmp_to_key(comparer))
            
        alignCmpFn = None
        if(alignBy == 'vertCo'):            
            def evalCmp(criteria, pt1, pt2):
                if(len(criteria) == 0):
                    return True
                    
                minmax = criteria[0][0]
                axisIdx = criteria[0][1]
                val1 = pt1[axisIdx]
                val2 = pt2[axisIdx]
                
                if(floatCmpWithMargin(val1, val2)):
                    criteria = criteria[:]
                    criteria.pop(0)
                    return evalCmp(criteria, pt1, pt2)
                
                return val1 < val2 if minmax == 'min' else val1 > val2
    
            alignCri = [[a[:3], ord(a[3:]) - ord('X')] for a in alignValues]
            alignCmpFn = lambda pt1, pt2, curve: (evalCmp(alignCri, \
                curve.matrix_world @ pt1, curve.matrix_world @ pt2))
    
        startPt = None
        startIdx = None
        
        for i in range(0, len(parts)):        
            #Only truly closed parts
            if(alignCmpFn != None and parts[i].isClosed):
                for j in range(0, parts[i].getSegCnt()):
                    seg = parts[i].getSeg(j)
                    if(j == 0 or alignCmpFn(seg.start, startPt, path.curve)):
                        startPt = seg.start
                        startIdx = j
                        
                path.parts[i]= Part(path, parts[i].getSegsCopy(startIdx, None) + \
                    parts[i].getSegsCopy(None, startIdx), parts[i].isClosed)
            else:
                path.parts[i] = parts[i]
                
    #TODO: Other shape key attributes like interpolation...?
    def getExistingShapeKeyPaths(path):
        obj = path.curve
        paths = []
        
        if(obj.data.shape_keys != None):
            keyblocks = obj.data.shape_keys.key_blocks[1:]#Skip basis
            for key in keyblocks:
                datacopy = obj.data.copy()
                i = 0
                for spline in datacopy.splines:
                    for pt in spline.bezier_points:
                        pt.co = key.data[i].co
                        pt.handle_left = key.data[i].handle_left
                        pt.handle_right = key.data[i].handle_right
                        i += 1 
                paths.append(Path(obj, datacopy, key.name))
        return paths
        
    def addShapeKey(curve, paths, space):
        for path in paths:
            key = curve.shape_key_add(name = path.name)
            pts = [pt for pset in path.getBezierPtsBySpline() for pt in pset]
            for i, pt in enumerate(pts):
                if(space == 'worldspace'):
                    pt = [curve.matrix_world.inverted() @ (path.curve.matrix_world @ p) for p in pt]
                key.data[i].co = pt[0]
                key.data[i].handle_left = pt[1]
                key.data[i].handle_right = pt[2]
    
    #TODO: Remove try    
    def safeRemoveCurveObj(obj):
        try:
            collections = obj.users_collection
    
            for c in collections:
                c.objects.unlink(obj)
                
            if(obj.name in bpy.context.scene.collection.objects):
                bpy.context.scene.collection.objects.unlink(obj)
                
            if(obj.data.users == 1):
                if(obj.type == 'CURVE'):
                    bpy.data.curves.remove(obj.data) #This also removes object?        
                elif(obj.type == 'MESH'):
                    bpy.data.meshes.remove(obj.data)
            
            bpy.data.objects.remove(obj)
        except:
            pass