remove bbim material unassignment listener #4843

Listeners are implicit and get in the way sometimes, we should work on our core methods and make explicit calls.
This commit is contained in:
Andrej730
2024-07-05 17:36:07 +05:00
parent 7a89d8f5ed
commit 8a9ca9ac60
6 changed files with 40 additions and 36 deletions
@@ -406,7 +406,9 @@ class UpdateRepresentation(bpy.types.Operator, Operator):
element_type = ifcopenshell.util.element.get_type(product)
if element_type: # Some invalid IFCs use material sets without a type.
ifcopenshell.api.run("material.unassign_material", tool.Ifc.get(), products=[element_type])
tool.Material.ensure_material_unassigned([element_type])
ifcopenshell.api.run("material.unassign_material", tool.Ifc.get(), products=[product])
tool.Material.ensure_material_unassigned([product])
else:
# These objects are parametrically based on an axis and should not be modified as a mesh
return
@@ -50,10 +50,6 @@ def load_post(*args):
usecase, "BlenderBIM.Product.EnsureMaterialAssigned", product.ensure_material_assigned
)
ifcopenshell.api.add_post_listener(
"material.unassign_material", "BlenderBIM.Product.EnsureMaterialUnassigned", product.ensure_material_unassigned
)
ifcopenshell.api.add_post_listener(
"material.edit_profile_usage",
"BlenderBIM.Product.RegenerateProfileUsage",
@@ -542,23 +542,3 @@ def ensure_material_assigned(usecase_path: str, ifc_file: ifcopenshell.file, set
elements.extend(tool.Model.get_occurrences_without_material_override(element))
tool.Model.apply_ifc_material_changes(elements, assigned_material=settings["material"])
def ensure_material_unassigned(usecase_path: str, ifc_file: ifcopenshell.file, settings: dict[str, Any]) -> None:
return # TODO ensure this now works with the new approach of styles
elements = settings["products"]
# unassign_material could be called when product is about to get removed
# and representation might be already removed.
elements = [
e
for e in elements
if (obj := tool.Ifc.get_object(e))
and obj.data
and tool.Ifc.get_entity_by_id(obj.data.BIMMeshProperties.ifc_definition_id)
]
for element in elements[:]:
if element.is_a("IfcElementType"):
elements.extend(tool.Model.get_occurrences_without_material_override(element))
tool.Model.apply_ifc_material_changes(elements)
+18 -12
View File
@@ -116,21 +116,27 @@ def assign_material(
def unassign_material(ifc: tool.Ifc, material_tool: tool.Material, objects: list[bpy.types.Object]) -> None:
for obj in objects:
element = ifc.get_entity(obj)
if element:
material = material_tool.get_material(element, should_inherit=False)
inherited_material = material_tool.get_material(element, should_inherit=True)
if material:
if "Usage" in material.is_a():
element_type = material_tool.get_type(element)
ifc.run("material.unassign_material", products=[element_type])
else:
ifc.run("material.unassign_material", products=[element])
elif inherited_material:
if not element:
continue
material = material_tool.get_material(element, should_inherit=False)
inherited_material = material_tool.get_material(element, should_inherit=True)
if material:
if "Usage" in material.is_a():
element_type = material_tool.get_type(element)
assert element_type # Type checker.
ifc.run("material.unassign_material", products=[element_type])
material_tool.ensure_material_unassigned(elements=[element_type])
else:
# Has no material and has no inherited material, nothing to unassign.
pass
ifc.run("material.unassign_material", products=[element])
material_tool.ensure_material_unassigned(elements=[element])
elif inherited_material:
element_type = material_tool.get_type(element)
assert element_type # Type checker.
ifc.run("material.unassign_material", products=[element_type])
material_tool.ensure_material_unassigned(elements=[element_type])
else:
# Has no material and has no inherited material, nothing to unassign.
pass
def patch_non_parametric_mep_segment(
@@ -284,3 +284,18 @@ class Material(blenderbim.core.tool.Material):
for style in item.Styles:
if style.is_a("IfcSurfaceStyle"):
return style
@classmethod
def ensure_material_unassigned(cls, elements: list[ifcopenshell.entity_instance]) -> None:
"""Ensure blender materials are updated after a material unassignment.
E.g. during a material unassignment some material style may not apply anymore
or some other may be applied now since it's no longer overridden,
therefore we need to make sure blender materials reflect correct styles.
Designed to be called after material.unassign_material API call."""
elements = elements.copy() # Avoid argument mutation.
for element in elements[:]:
if element.is_a("IfcElementType"):
elements.extend(tool.Model.get_occurrences_without_material_override(element))
tool.Model.apply_ifc_material_changes(elements)
+5
View File
@@ -546,6 +546,7 @@ class TestApplyIfcMaterialChanges(NewFile):
assert self.get_used_styles(obj) == expected
ifcopenshell.api.material.unassign_material(ifc_file, products=[element_type])
tool.Material.ensure_material_unassigned([element_type])
assert self.get_used_styles(tool.Ifc.get_object(element_type)) == set()
for element in ifc_file.by_type("IfcActuator"):
obj = tool.Ifc.get_object(element)
@@ -573,6 +574,7 @@ class TestApplyIfcMaterialChanges(NewFile):
assert self.get_used_styles(obj) == {green_style}
ifcopenshell.api.material.unassign_material(ifc_file, products=[element_type])
tool.Material.ensure_material_unassigned([element_type])
assert self.get_used_styles(tool.Ifc.get_object(element_type)) == {green_style}
for element in ifc_file.by_type("IfcActuator"):
obj = tool.Ifc.get_object(element)
@@ -613,6 +615,7 @@ class TestApplyIfcMaterialChanges(NewFile):
ifcopenshell.api.material.assign_material(ifc_file, products=[element], material=red_material)
assert self.get_used_styles(obj) == {green_style, red_style}
ifcopenshell.api.material.unassign_material(ifc_file, products=[element])
tool.Material.ensure_material_unassigned([element])
mesh = self.get_mesh(obj)
assert len(mesh.materials) == 2
assert set(mesh.materials) == {bpy.data.materials["Green"], None}
@@ -630,6 +633,7 @@ class TestApplyIfcMaterialChanges(NewFile):
assert set(get_material_indices(mesh)) == {mesh.materials.find("Red")}
ifcopenshell.api.material.unassign_material(ifc_file, products=[element])
tool.Material.ensure_material_unassigned([element])
mesh = self.get_mesh(obj)
assert len(mesh.materials) == 2
assert set(mesh.materials) == {bpy.data.materials["Red"], None}
@@ -651,4 +655,5 @@ class TestApplyIfcMaterialChanges(NewFile):
assert self.get_mesh(obj).materials[:] == []
ifcopenshell.api.material.unassign_material(ifc_file, products=[element])
tool.Material.ensure_material_unassigned([element])
assert self.get_mesh(obj).materials[:] == [bpy.data.materials["Red"]]