Resolve mapped/boolean items in unassign_representation_item_style #6931

Use ifcopenshell.util.representation.resolve_base_items on the active
representation to reach the geometry items that actually carry styles,
unwrapping IfcMappedItem (Revit families) and IfcBooleanResult (openings)
instead of the previous shallow, all-representations walk.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Ryan Schultz
2026-07-15 15:05:55 -05:00
parent f5609e2095
commit 5285df13ec
@@ -3446,45 +3446,35 @@ class UnassignRepresentationItemStyle(bpy.types.Operator, tool.Ifc.Operator):
self.report({"ERROR"}, "Couldn't find any styles associated with the active representation item.") self.report({"ERROR"}, "Couldn't find any styles associated with the active representation item.")
return {"CANCELLED"} return {"CANCELLED"}
# Helper function to get all representation items (including mapped) # Resolve an object's active representation down to its base geometry items,
def get_all_representation_items(obj): # unwrapping mapped items (Revit families) and boolean results (openings/cuts)
items = set() # so we reach the items that actually carry styles.
element = tool.Ifc.get_entity(obj) def get_base_representation_items(obj):
if not element or not element.Representation: representation = tool.Geometry.get_active_representation(obj)
return items if not representation or not representation.is_a("IfcRepresentation"):
return
yield from ifcopenshell.util.representation.resolve_base_items(representation)
for rep in element.Representation.Representations: # Unassign the style from the active representation item.
for item in rep.Items: tool.Style.assign_style_to_representation_item(active_representation_item, None)
if item.is_a("IfcMappedItem"): tool.Geometry.reload_representation(active_obj)
mapped = item.MappingSource.MappedRepresentation
items.update(mapped.Items)
else:
items.add(item)
return items
# Unassign styles from the active representation item # Iterate over other selected objects and unassign matching styles.
for style in active_styles:
tool.Style.assign_style_to_representation_item(active_representation_item, None)
tool.Geometry.reload_representation(active_obj)
break
# Iterate over other selected objects and unassign matching styles
for obj in context.selected_objects: for obj in context.selected_objects:
if obj == active_obj: if obj == active_obj:
continue continue
for item in get_all_representation_items(obj): for item in get_base_representation_items(obj):
item_styles = set() item_styles = set()
if hasattr(item, "StyledByItem"): if hasattr(item, "StyledByItem"):
for styled_by_item in item.StyledByItem: for styled_by_item in item.StyledByItem:
if hasattr(styled_by_item, "Styles"): if hasattr(styled_by_item, "Styles"):
item_styles.update(styled_by_item.Styles) item_styles.update(styled_by_item.Styles)
for style in item_styles: if item_styles & active_styles:
if style in active_styles: tool.Style.assign_style_to_representation_item(item, None)
tool.Style.assign_style_to_representation_item(item, None) tool.Geometry.reload_representation(obj)
tool.Geometry.reload_representation(obj) break # Only remove one matching style per object
break # Only remove one matching style per object
bpy.ops.bim.disable_editing_representation_items() bpy.ops.bim.disable_editing_representation_items()
bpy.ops.bim.enable_editing_representation_items() bpy.ops.bim.enable_editing_representation_items()