def by_direction(direction, divergence, extend=False): mesh = bpy.context.active_object.data direction = mathutils.Vector(direction) hasSelected = mesh_extras.contains_selected_item(mesh.faces) # Make sure there's an actual directions if direction.length: # Loop through all the given faces for f in mesh.faces: isSelected = f.select s = selectCheck(isSelected, hasSelected, extend) d = deselectCheck(isSelected, hasSelected, extend) angle = direction.angle(f.normal) if s and angle <= divergence: f.select = True elif d and angle > divergence: f.select = False return
def selectFaces(selFaces, extend=False): mesh = bpy.context.active_object.data hasSelected = mesh_extras.contains_selected_item(mesh.faces) for f in mesh.faces: # We extend and have a selection, so we just need to select extra stuff # Selecting what is already selected does no harm if extend and hasSelected: if f in selFaces: f.select = True # If we already have a selection and we don't extend.. we just deselect what is selected elif hasSelected: if not f in selFaces: f.select = False # If we have no selection yet.. we only select what's in the list else: if f in selFaces: f.select = True return
def by_direction(direction, divergence, extend=False): me = bpy.context.active_object.data direction = mathutils.Vector(direction) hasSelected = mesh_extras.contains_selected_item(me.polygons) # Make sure there's an actual directions if direction.length: # Loop through all the given polygons for p in me.polygons: isSelected = p.select s = selectCheck(isSelected, hasSelected, extend) d = deselectCheck(isSelected, hasSelected, extend) if p.normal.length: angle = direction.angle(p.normal) else: angle = 0.0 if s and angle <= divergence: p.select = True elif d and angle > divergence: p.select = False return
def selectFaces(selFaces, extend=False): mesh = bpy.context.active_object.data hasSelected = mesh_extras.contains_selected_item(mesh.faces) for f in mesh.faces: # We extend and have a selection, so we just need to select extra stuff # Selecting what is already selected does no harm if extend and hasSelected: if f in selFaces: f.select = True # If we already have a selection and we don't extend.. we just deselect what is selected elif hasSelected: if not f in selFaces: f.select = False # If we have no selection yet.. we only select what's in the list else: if f in selFaces: f.select = True
def selectpolygons(selpolygons, extend=False): mesh = bpy.context.active_object.data hasSelected = mesh_extras.contains_selected_item(mesh.polygons) for p in mesh.polygons: # We extend and have a selection, so we just need to select extra stuff # Selecting what is already selected does no harm if extend and hasSelected: if p in selpolygons: p.select = True # If we already have a selection and we don't extend.. we just deselect what is selected elif hasSelected: if not p in selpolygons: p.select = False # If we have no selection yet.. we only select what's in the list else: if p in selpolygons: p.select = True vertexCheck() return
def doubleCheckSelection(self, selection): # Make sure there's never more than 12 faces we grow out of if selection['area'] == 'faces': select_faces.limit(selection['limit'], self.dnaString) # If we still have something selected, then we need to check for Islands (only one coninuous island should be selected) if selection['type'] == 'direction' and selection['area'] == 'area' and mesh_extras.contains_selected_item(self.me.faces): self.checkForIslands(selection['vector'])
def patches(size, extend=False): me = bpy.context.active_object.data patches = [] hasSelected = mesh_extras.contains_selected_item(me.polygons) return
def liberal(key='', extend=False): from macouno import liberty lib = liberty.liberty('bool', key) mesh = bpy.context.active_object.data hasSelected = mesh_extras.contains_selected_item(mesh.faces) # Loop through all the given faces for f in mesh.faces: s = selectCheck(f.select, hasSelected, extend) d = deselectCheck(f.select, hasSelected, extend) # Check if the faces match any of the directions if s and lib.Choose('bool'): f.select = True if d and not lib.Choose('bool'): f.select = False
def makeAffectedGroups(self, string, baseGroups, subCount): print('subcnt', subCount) selection = string['selection'] newGroups = [] formmatrix = mathutils.Matrix() growmatrices = [] # Deselect all faces to start clean! select_faces.none() # Select everything in the base groups for g in baseGroups: select_faces.in_group(g,True) #print('in_group',len(mesh_extras.get_selected_faces())) # If nothing is selected there's nothing to do if mesh_extras.contains_selected_item(self.me.faces): if selection['type'] == 'twig': # Lets find the middle... selFaces = mesh_extras.get_selected_faces() midPoint = mathutils.Vector(); for f1 in selFaces: midPoint += f1.center midPoint /= len(selFaces) midDist = 0.0 nearest = 0 for fc, f1 in enumerate(selFaces): dist = midPoint - f1.center dist = dist.length if not fc or dist < midDist: nearest = f1 midDist = dist select_faces.none() nearest.select = True print('found at distance',len(mesh_extras.get_selected_faces(self.me.faces))) # If we have selected faces... we can add em to a new group newGroups, formmatrix, growmatrices = self.addToNewGroups(string, newGroups, growmatrices) # Select the faces at the tip in a certain direction elif selection['type'] == 'joint' or selection['type'] == 'tip' : select_faces.innermost() if mesh_extras.contains_selected_item(self.me.faces): if selection['type'] == 'joint': select_faces.connected(True) selCnt = len(mesh_extras.get_selected_faces()) nuCnt = selCnt div = selection['divergence'] # If the nr of faces selected isn't diminished... we select less! while selCnt and selCnt == nuCnt and div > 0.1: select_faces.by_direction(selection['vector'],div) div = div * 0.75 selFaces = mesh_extras.get_selected_faces() nuCnt = len(selFaces) # Check for opposing normals.. .cause they should not be there! for f1 in selFaces: if f1.select: f1No = f1.normal for f2 in selFaces: if f2.select and not f1 is f2: f2No = f2.normal ang = f2No.angle(f1No) if ang > math.radians(120): f1.select = False break selFaces = mesh_extras.get_selected_faces() nuCnt = len(selFaces) if nuCnt == selCnt: select_faces.none() # If we have selected faces... we can add em to a new group newGroups, formmatrix, growmatrices = self.addToNewGroups(string, newGroups, growmatrices) # Select by pi (fake random) elif selection['type'] == 'liberal': select_faces.liberal(self.dnaString) # If we have selected faces... we can add em to a new group newGroups, formmatrix, growmatrices = self.addToNewGroups(string, newGroups, growmatrices) # Select all loops in the group elif selection['type'] == 'loops': select_faces.connected() self.deselectUnGrouped() step = 0 # As long as something is selected, we can continue while mesh_extras.contains_selected_item(self.ob.data.faces): select_faces.connected() self.deselectGrouped(baseGroups) # Skip selection just in case if not step % selection['frequency']: # If we have selected faces... we can add em to a new group newGroups, formmatrix, grw = self.addToNewGroups(string, newGroups, growmatrices) growmatrices.extend(grw) step += 1 print(step) # Select by direction elif selection['type'] == 'direction': select_faces.by_direction(selection['vector'],selection['divergence']) newGroups, formmatrix, growmatrices = self.addToNewGroups(string, newGroups, growmatrices) # All! else: newGroups, formmatrix, growmatrices = self.addToNewGroups(string, newGroups, growmatrices) return newGroups, formmatrix, growmatrices
def executeDNA(self, string, baseGroups, baseWeight, subCount): '''' if string['number'] >= 1: #if string['number'] in [0,1,3]: return elif string['number'] == 5 or string['number'] == 6: return ''' # Redraw hack #bpy.ops.wm.redraw_timer(type='DRAW_WIN_SWAP', iterations=1) newGroups, formmatrix, growmatrices = self.makeAffectedGroups(string, baseGroups, subCount) groupLen = len(newGroups) pad = str(' ').rjust(string['level'], ' ') idText = 'limb '+misc.nr4(string['number'])+' '+string['name'].ljust(10, ' ') print(pad,idText) # only if we made a group with something in it do we continue if not groupLen: print(' - No group!') else: # Loop through all the groups for i, group in enumerate(newGroups): # The step number to print out stepText = misc.nr4(i+1)+' of '+misc.nr4(groupLen) # We need a check matrix only if we're not on the trunk or body if string['name'] == 'trunk' or string['name'] == 'body' or True: try: del(self.ob['formmatrix']) except: pass # If not... then just try to get rid of it else: self.ob['formmatrix'] = formmatrix # Body gets a set matrix (so it grows nice and straight) if string['name'] == 'trunk': growmatrix = mathutils.Matrix(((1.0,0.0,0.0),(0.0,-1.0,0.0),(0.0,0.0,1.0))).transposed() # In all other cases the matrix can be dealt with by the grow addon else: growmatrix = growmatrices[i] self.ob['growmatrix'] = growmatrix # Select a group select_faces.none() select_faces.in_group(group) # No need to continue if we have no selected faces if not mesh_extras.contains_selected_item(self.me.faces): print(pad,'skip ',stepText,'no selection',string['action']['name']) else: a = string['action'] if a['type'] == 'grow': # Check for mirroring right = mathutils.Vector((1.0,0.0,0.0)) check = mathutils.Vector(growmatrix[2]) # If we're aiming left we "invert" the rotation if right.dot(check) < 0.0: rot = mathutils.Vector((-a['rotation'][0],a['rotation'][1],-a['rotation'][2])) else: rot = a['rotation'] # Add relative intensity here (half the original + half the weight) weight = baseWeight * self.getWeight(groupLen, a['scalin']) trans = a['translation'] if a['type'] == 'grow' and trans == 0.0: print(pad,'skip ',stepText,'too short',trans,'from',a['translation']) else: print(pad,'step ',stepText,a['name']) bpy.ops.object.mode_set(mode='EDIT') if a['type'] == 'bump': bpy.ops.mesh.bump( type=a['bumptype'], scale=a['bumpscale'], steps=True, ) else: bpy.ops.mesh.grow( translation=trans, rotation=rot, rotation_falloff=a['rotation_falloff'], scale=a['scale'], scale_falloff=a['scale_falloff'], retain=True, steps=True, debug=False, ) bpy.ops.object.mode_set(mode='OBJECT') select_faces.none() select_faces.in_group(group) self.applyGrowthColor(a) if a['type'] == 'grow': self.applyGrowthCrease(a) # Remove new stuff from all but the current group self.cleanGroup(group) # Keep track of how much steps we've taken self.dnaStep += 1 # If there's a sub if len(string['strings']): for sc, s in enumerate(string['strings']): #print('going sub', string['name'], s['name']) self.executeDNA(s, [group], weight, sc)
def executeDNA(self, string, baseGroups, baseWeight): pad = str(' ').rjust(string['level'], ' ') # Stop if the limit is reached! (mostly for debugging) if self.steplimit and string['number'] >= self.steplimit: print(pad,' # Reached steplimit',self.steplimit,'>> RETURNING') return ''' if string['number'] == 5 or string['number'] == 6: return ''' #print(pad,'1 makegroups') newGroups, formmatrix, growmatrices = self.makeAffectedGroups(string, baseGroups) groupLen = len(newGroups) # Temporary halt! #return #if string['number'] == (self.steplimit-1): # print(pad,' # Reached steplimit',self.steplimit,'>> RETURNING') # return idText = 'limb '+misc.nr4(string['number'])+' '+string['name'].ljust(10, ' ') #print(pad,idText) # only if we made a group with something in it do we continue if not groupLen: print(pad,' ### No group!') else: # Loop through all the groups for i, group in enumerate(newGroups): # The step number to print out stepText = misc.nr4(i+1)+' of '+misc.nr4(groupLen) # We need a check matrix only if we're not on the head or body if string['name'] == 'head' or string['name'] == 'body' or True: try: del(self.ob['formmatrix']) except: pass # If not... then just try to get rid of it else: self.ob['formmatrix'] = formmatrix # Body gets a set matrix (so it grows nice and straight) if string['name'] == 'head': growmatrix = mathutils.Matrix(((1.0,0.0,0.0),(0.0,0.0,1.0),(0.0,-1.0,0.0))).transposed() # Head gets a set matrix (so it grows nice and straight) elif string['name'] == 'body': growmatrix = mathutils.Matrix(((-1.0,0.0,0.0),(0.0,0.0,1.0),(0.0,1.0,0.0))).transposed() # In all other cases the matrix can be dealt with by the grow addon else: growmatrix = growmatrices[i] self.ob['growmatrix'] = growmatrix # Select a group #print(pad,'2 select groups') select_bmesh_faces.go(mode='GROUPED', group=group.index) #print('sel-',len(mesh_extras.get_selected_polygons()),group.name) mesh_extras.smooth_selection() # No need to continue if we have no selected polygons if not mesh_extras.contains_selected_item(self.me.polygons): print(pad,'skip ',stepText,'no selection',string['action']['name']) else: action = string['action'] if action['type'] == 'grow': # Check for mirroring right = mathutils.Vector((1.0,0.0,0.0)) check = mathutils.Vector(growmatrix[2]) # If we're aiming left we "invert" the rotation if right.dot(check) < 0.0: rot = mathutils.Vector((-action['rotation'][0],action['rotation'][1],-action['rotation'][2])) else: rot = action['rotation'] # Add relative intensity here (half the original + half the weight) weight = baseWeight * self.getWeight(groupLen, action['scalin']) print(pad,'step ',stepText,action['name'], string['number']) # Cast the selection to the correct shape please bmesh_extras.cast_loop(corners=action['loop_corners'], falloff_scale=action['loop_scale'], falloff_shape=action['loop_shape'],corner_group='corner') bpy.ops.object.mode_set(mode='EDIT') if action['type'] == 'bump': bpy.ops.mesh.bump( type=action['bumptype'], scale=action['bumpscale'], steps=True, ) else: bpy.ops.mesh.grow( translation=action['translation'], rotation=rot, rotation_falloff=action['rotation_falloff'], scale=action['scale'], scale_falloff=action['scale_falloff'], retain=True, steps=True, debug=False, ) bpy.ops.object.mode_set(mode='OBJECT') select_bmesh_faces.go(mode='GROUPED', group=group.index) bmesh_extras.color_limb(col=action['vertexcolor'], jon=action['jointcolor'], hard=action['colorstyle']) # RESELECT GROUPED... select_bmesh_faces.go(mode='GROUPED', group=group.index) bmesh_extras.crease_edges(sharpness=action['crease'], group='corner') select_bmesh_faces.go(mode='GROUPED', group=group.index) # Remove new stuff from all but the current group self.cleanGroup(group) select_bmesh_faces.go(mode='GROUPED', group=group.index) # Keep track of how much steps we've taken self.dnaStep += 1 # Redraw hack to see what is happening #bpy.ops.wm.redraw_timer(type='DRAW_WIN_SWAP', iterations=1) # If there's a sub string and we're allowed deeper... lets do that if len(string['strings']): for s in string['strings']: if s['number'] < self.steplimit or not self.steplimit: #print('going sub', string['name'], s['name']) self.executeDNA(s, [group], weight)
def makeAffectedGroups(self, string, baseGroups): selection = string['selection'] newGroups = [] formmatrix = mathutils.Matrix() growmatrices = [] # Select everything in the base groups for i, g in enumerate(baseGroups): # Deselect on the first go if not i: e = False else: e = True #print('base',g.name) select_bmesh_faces.go(mode='GROUPED', extend=e, group=g.index) #print('in_group',len(mesh_extras.get_selected_polygons())) # If nothing is selected there's nothing to do if mesh_extras.contains_selected_item(self.me.polygons): # Select the polygons at the tip in a certain direction if selection['type'] == 'joint': select_bmesh_faces.go(mode='INNER') #print('1, selected',len(mesh_extras.get_selected_polygons()),mesh_extras.contains_selected_item(self.me.polygons)) if mesh_extras.contains_selected_item(self.me.polygons): #return newGroups, formmatrix, growmatrices # Select connected twice to make sure we have enough now that selection is doubled select_bmesh_faces.go(mode='CONNECTED', extend=True) select_bmesh_faces.go(mode='CONNECTED', extend=True) #print('2, selected',len(mesh_extras.get_selected_polygons())) selCnt = len(mesh_extras.get_selected_polygons()) nuCnt = selCnt div = selection['divergence'] # If the nr of polygons selected isn't diminished... we select less! while selCnt and selCnt == nuCnt and div > 0.1: select_bmesh_faces.go(mode='DIRECTIONAL', direction=selection['vector'], limit=div) nuCnt = len(mesh_extras.get_selected_polygons()) #print('join selection at',math.degrees(div), nuCnt) div = div * 0.5 if nuCnt == selCnt: select_bmesh_faces.go(mode='NONE') # If we have selected polygons... we can add em to a new group newGroups, formmatrix, growmatrices = self.addToNewGroups(string, newGroups, growmatrices) # Select by direction elif selection['type'] == 'direction': select_bmesh_faces.go(mode='DIRECTIONAL', direction=selection['vector'],limit=selection['divergence']) #print('done selecting', len(mesh_extras.get_selected_polygons()),'polys in',selection['vector'],math.degrees(selection['divergence'])) newGroups, formmatrix, growmatrices = self.addToNewGroups(string, newGroups, growmatrices) # All! else: newGroups, formmatrix, growmatrices = self.addToNewGroups(string, newGroups, growmatrices) return newGroups, formmatrix, growmatrices
def executeDNA(self, string, baseGroups, baseWeight): ''' if string['number'] >= 1: #if string['number'] in [0,1,3]: return elif string['number'] == 5 or string['number'] == 6: return ''' # Redraw hack to see what is happening # bpy.ops.wm.redraw_timer(type='DRAW_WIN_SWAP', iterations=1) newGroups, formmatrix, growmatrices = self.makeAffectedGroups(string, baseGroups) groupLen = len(newGroups)\ pad = str(' ').rjust(string['level'], ' ') idText = 'limb '+misc.nr4(string['number'])+' '+string['name'].ljust(10, ' ') print(pad,idText) # only if we made a group with something in it do we continue if not groupLen: print(' - No group!') else: # Loop through all the groups for i, group in enumerate(newGroups): # The step number to print out stepText = misc.nr4(i+1)+' of '+misc.nr4(groupLen) # We need a check matrix only if we're not on the head or body if string['name'] == 'head' or string['name'] == 'body' or True: try: del(self.ob['formmatrix']) except: pass # If not... then just try to get rid of it else: self.ob['formmatrix'] = formmatrix # Body gets a set matrix (so it grows nice and straight) if string['name'] == 'head': growmatrix = mathutils.Matrix(((1.0,0.0,0.0),(0.0,0.0,1.0),(0.0,-1.0,0.0))).transposed() # Head gets a set matrix (so it grows nice and straight) elif string['name'] == 'body': growmatrix = mathutils.Matrix(((-1.0,0.0,0.0),(0.0,0.0,1.0),(0.0,1.0,0.0))).transposed() # In all other cases the matrix can be dealt with by the grow addon else: growmatrix = growmatrices[i] self.ob['growmatrix'] = growmatrix # Select a group select_faces.none() select_faces.in_group(group) # No need to continue if we have no selected faces if not mesh_extras.contains_selected_item(self.me.faces): print(pad,'skip ',stepText,'no selection',string['action']['name']) else: a = string['action'] if a['type'] == 'grow': # Check for mirroring right = mathutils.Vector((1.0,0.0,0.0)) check = mathutils.Vector(growmatrix[2]) # If we're aiming left we "invert" the rotation if right.dot(check) < 0.0: rot = mathutils.Vector((-a['rotation'][0],a['rotation'][1],-a['rotation'][2])) else: rot = a['rotation'] # Add relative intensity here (half the original + half the weight) weight = baseWeight * self.getWeight(groupLen, a['scalin']) trans = a['translation'] #trans = self.applyIntensity(a['translation'], weight, 'float') #rot = self.applyIntensity(rot, weight, 'inc') if a['type'] == 'grow' and trans == 0.0: print(pad,'skip ',stepText,'too short',trans,'from',a['translation']) else: print(pad,'step ',stepText,a['name']) #print(self.applyIntensity(a['push'], weight, 'float')) bpy.ops.object.mode_set(mode='EDIT') if a['type'] == 'bump': bpy.ops.mesh.bump( type=a['bumptype'], scale=a['bumpscale'], steps=True, ) else: bpy.ops.mesh.grow( translation=trans, rotation=rot, rotation_falloff=a['rotation_falloff'], scale=a['scale'], scale_falloff=a['scale_falloff'], retain=True, steps=True, debug=False, ) bpy.ops.object.mode_set(mode='OBJECT') select_faces.none() select_faces.in_group(group) self.applyGrowthColor(a) if a['type'] == 'grow': self.applyGrowthCrease(a) # Remove new stuff from all but the current group self.cleanGroup(group) # Keep track of how much steps we've taken self.dnaStep += 1 # If there's a sub if len(string['strings']): for s in string['strings']: #print('going sub', string['name'], s['name']) self.executeDNA(s, [group], weight)
def __init__(self, context, invert): me = context.active_object.data bpy.ops.object.mode_set(mode='OBJECT') oList = [f.index for f in mesh_extras.get_selected_faces()] oLen = len(oList) # If no faces are selected, we just return if not oLen: bpy.ops.object.mode_set(mode='EDIT') return # If all faces are selected, select nothing and return if oLen == len(me.faces): bpy.ops.object.mode_set(mode='EDIT') bpy.ops.mesh.select_all(action='DESELECT') return fList = False # If we invert, we just want to select less once, and then we're done if invert: bpy.ops.object.mode_set(mode='EDIT') bpy.ops.mesh.select_less() bpy.ops.object.mode_set(mode='OBJECT') fList = [f.index for f in mesh_extras.get_selected_faces()] # Only if there's now less selected do we change anything if len(fList) < oLen: for f in me.faces: fIn = f.index if fIn in oList and not fIn in fList: f.select = True else: f.select = False bpy.ops.object.mode_set(mode='EDIT') return # So now we can start and see what's up while mesh_extras.contains_selected_item(me.faces): if fList is False: fList = oList else: fList = [f.index for f in mesh_extras.get_selected_faces()] bpy.ops.object.mode_set(mode='EDIT') bpy.ops.mesh.select_less() bpy.ops.object.mode_set(mode='OBJECT') if len(fList) < oLen: for f in me.faces: if f.index in fList: f.select = True else: f.select = False bpy.ops.object.mode_set(mode='EDIT')
def makeAffectedGroups(self, string, baseGroups): selection = string['selection'] newGroups = [] formmatrix = mathutils.Matrix() growmatrices = [] # Deselect all faces to start clean! select_faces.none() # Select everything in the base groups for g in baseGroups: select_faces.in_group(g,True) #print('in_group',len(mesh_extras.get_selected_faces())) # If nothing is selected there's nothing to do if mesh_extras.contains_selected_item(self.me.faces): # Select the faces at the tip in a certain direction if selection['type'] == 'joint' or selection['type'] == 'tip': select_faces.innermost() if mesh_extras.contains_selected_item(self.me.faces): if selection['type'] == 'joint': select_faces.connected(True) selCnt = len(mesh_extras.get_selected_faces()) nuCnt = selCnt div = selection['divergence'] # If the nr of faces selected isn't diminished... we select less! while selCnt and selCnt == nuCnt and div > 0.1: select_faces.by_direction(selection['vector'],div) div = div * 0.75 selFaces = mesh_extras.get_selected_faces() nuCnt = len(selFaces) # Check for opposing normals.. .cause they should not be there! for f1 in selFaces: if f1.select: f1No = f1.normal for f2 in selFaces: if f2.select and not f1 is f2: f2No = f2.normal ang = f2No.angle(f1No) if ang > math.radians(120): f1.select = False break selFaces = mesh_extras.get_selected_faces() nuCnt = len(selFaces) if nuCnt == selCnt: select_faces.none() # If we have selected faces... we can add em to a new group newGroups, formmatrix, growmatrices = self.addToNewGroups(string, newGroups, growmatrices) # Select by pi (fake random) elif selection['type'] == 'liberal': select_faces.liberal(self.dnaString) # If we have selected faces... we can add em to a new group newGroups, formmatrix, growmatrices = self.addToNewGroups(string, newGroups, growmatrices) # Select all loops in the group elif selection['type'] == 'loops': select_faces.connected() self.deselectUnGrouped() step = 0 # As long as something is selected, we can continue while mesh_extras.contains_selected_item(self.ob.data.faces): select_faces.connected() self.deselectGrouped(baseGroups) # Skip selection just in case if not step % selection['frequency']: # If we have selected faces... we can add em to a new group newGroups, formmatrix, grw = self.addToNewGroups(string, newGroups, growmatrices) growmatrices.extend(grw) step += 1 print(step) # Select by direction elif selection['type'] == 'direction': select_faces.by_direction(selection['vector'],selection['divergence']) newGroups, formmatrix, growmatrices = self.addToNewGroups(string, newGroups, growmatrices) # All! else: newGroups, formmatrix, growmatrices = self.addToNewGroups(string, newGroups, growmatrices) return newGroups, formmatrix, growmatrices