2
$\begingroup$

I'm looking for a way to automate the selection of adjacent faces through a script, which I could then assign to a hotkey in Blender.

I come from Maya, which doesn't have this ability either, but I was able to make a Mel script that does this type of selection for me with the following steps.

1- Store the current selection of faces in a variable.

2- Expand the selection once ("ctrl +" is the blender equivalent).

3- Subtract the faces I stored at the beginning from my current selection.

4- The polygon border remains!

Is there a way to achieve the same thing through a blender script, or maybe there's an existing blender command I'm unaware of? Even if there is some methodology for doing this in blender, the one-key-press automation is my ultimate goal.

enter image description here

$\endgroup$
3
$\begingroup$

Bmesh and sets.

enter image description here

Use sets because there will only be one instance of an item.

One set is our selected faces.

For all the vertices in each selected face, look at the link faces loop (all edges connected to that vert) and add any face that isn't already selected to another set.

import bpy
import bmesh
context = bpy.context
ob = context.edit_object
me = ob.data
bm = bmesh.from_edit_mesh(me)

sel_faces = set(f for f in bm.faces if f.select)

grow_faces =  set(fs for f in sel_faces for v in f.verts for fs in v.link_faces if not fs.select)

for f in sel_faces:
    f.select = False
for f in grow_faces:
    f.select = True

bmesh.update_edit_mesh(me)

Note: For keypress operation convert this into an operator, because I'm feeling generous here is above pasted into Text editor > Templates > Python > Simple Operator

import bpy
import bmesh

class SimpleOperator(bpy.types.Operator):
    """Tooltip"""
    bl_idname = "object.simple_operator"
    bl_label = "Simple Object Operator"

    @classmethod
    def poll(cls, context):
        return context.edit_object is not None

    def execute(self, context):
        ob = context.edit_object
        me = ob.data
        bm = bmesh.from_edit_mesh(me)

        sel_faces = set(f for f in bm.faces if f.select)

        grow_faces =  set(fs for f in sel_faces for v in f.verts for fs in v.link_faces if not fs.select)

        for f in sel_faces:
            f.select = False
        for f in grow_faces:
            f.select = True

        bmesh.update_edit_mesh(me)
        return {'FINISHED'}


def register():
    bpy.utils.register_class(SimpleOperator)


def unregister():
    bpy.utils.unregister_class(SimpleOperator)


if __name__ == "__main__":
    register()

    # test call
    bpy.ops.object.simple_operator()
$\endgroup$
1
  • $\begingroup$ Thanks generous person. I never would of figured out the Blender way on my own, and your generosity provides insight that will make future coding much easier. $\endgroup$ – Armored Wolf Mar 4 '19 at 17:49
0
$\begingroup$

@batFINGER.

This code also works fine as far as I can tell, but I'm wondering if simplifying in this manner is frowned upon for some reason inherent to Blender's behavior.

import bpy
import bmesh
context = bpy.context
ob = context.edit_object
me = ob.data
bm = bmesh.from_edit_mesh(me)

grow_faces = set(v for v in bm.verts if v.select for v in v.link_faces if not v.select)

bpy.ops.mesh.select_all(action='DESELECT')

for v in grow_faces:
    v.select = True

bmesh.update_edit_mesh(me)
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.