91 lines
2.6 KiB
Python
91 lines
2.6 KiB
Python
bl_info = {
|
|
"name": "Select Contiguous Material",
|
|
"author": "ChatGPT + Ryan Schultz",
|
|
"version": (1, 1, 0),
|
|
"blender": (3, 0, 0),
|
|
"location": "Edit Mode > Face Select",
|
|
"description": "Select connected face regions sharing the same material as any selected face",
|
|
"category": "Mesh",
|
|
}
|
|
|
|
import bpy
|
|
import bmesh
|
|
|
|
|
|
class MESH_OT_select_contiguous_material(bpy.types.Operator):
|
|
"""Expand selection to all connected faces that share the same material as the selected faces"""
|
|
bl_idname = "mesh.select_contiguous_material"
|
|
bl_label = "Select Contiguous Material (Multi)"
|
|
bl_options = {'REGISTER', 'UNDO'}
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
obj = context.edit_object
|
|
return obj and obj.type == 'MESH' and context.mode == 'EDIT_MESH'
|
|
|
|
def execute(self, context):
|
|
obj = context.edit_object
|
|
me = obj.data
|
|
|
|
bm = bmesh.from_edit_mesh(me)
|
|
bm.faces.ensure_lookup_table()
|
|
|
|
# collect all initially selected faces (seeds)
|
|
seed_faces = [f for f in bm.faces if f.select]
|
|
|
|
if not seed_faces:
|
|
self.report({'WARNING'}, "Select at least one face")
|
|
return {'CANCELLED'}
|
|
|
|
# remember material per seed
|
|
seed_materials = {f: f.material_index for f in seed_faces}
|
|
|
|
# clear selection (we will rebuild it)
|
|
for f in bm.faces:
|
|
f.select = False
|
|
|
|
visited = set()
|
|
stack = list(seed_faces)
|
|
|
|
while stack:
|
|
face = stack.pop()
|
|
|
|
if face in visited:
|
|
continue
|
|
visited.add(face)
|
|
|
|
# determine which material this flood belongs to
|
|
# (it inherits the material of the original seed that reached it)
|
|
for seed, mat in seed_materials.items():
|
|
if face.material_index == mat:
|
|
face.select = True
|
|
|
|
for edge in face.edges:
|
|
for linked_face in edge.link_faces:
|
|
if linked_face not in visited:
|
|
stack.append(linked_face)
|
|
break
|
|
|
|
bmesh.update_edit_mesh(me)
|
|
return {'FINISHED'}
|
|
|
|
|
|
def menu_func(self, context):
|
|
self.layout.operator(
|
|
MESH_OT_select_contiguous_material.bl_idname,
|
|
text="Contiguous Material (Multi)"
|
|
)
|
|
|
|
|
|
def register():
|
|
bpy.utils.register_class(MESH_OT_select_contiguous_material)
|
|
bpy.types.VIEW3D_MT_select_edit_mesh.append(menu_func)
|
|
|
|
|
|
def unregister():
|
|
bpy.types.VIEW3D_MT_select_edit_mesh.remove(menu_func)
|
|
bpy.utils.unregister_class(MESH_OT_select_contiguous_material)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
register()
|