diff --git a/src/bonsai/bonsai/bim/module/root/operator.py b/src/bonsai/bonsai/bim/module/root/operator.py index 159f157d44..01f9480732 100644 --- a/src/bonsai/bonsai/bim/module/root/operator.py +++ b/src/bonsai/bonsai/bim/module/root/operator.py @@ -380,6 +380,14 @@ class AssignClass(bpy.types.Operator, tool.Ifc.Operator): # TODO: reload representation might lead to the object being replaced by object of the other type. # We probably should track it somehow and keep the original selection. + # Objects may have just been relinked into new collections (e.g. types + # into the "IfcTypeProduct" collection) above. Make sure the view + # layer's object bases are up to date before validating the selection + # below, otherwise a just-relinked (but perfectly valid) active object + # can be seen as "not in the current view layer" and be dropped, + # leaving `context.active_object` as None for the rest of the caller. + context.view_layer.update() + # Validate selection and reapply it. current_selection = tool.Blender.validate_object_selection(*current_selection) tool.Blender.set_objects_selection(*current_selection) diff --git a/src/bonsai/bonsai/core/material.py b/src/bonsai/bonsai/core/material.py index 0a08f5e0bf..f641909a65 100644 --- a/src/bonsai/bonsai/core/material.py +++ b/src/bonsai/bonsai/core/material.py @@ -130,10 +130,23 @@ def assign_material( if can_be_usage and not material_tool.is_type_product(element): element_material_type = material_type + "Usage" + # A "...Usage" type always wraps an existing material *set* + # (IfcMaterialLayerSet/IfcMaterialProfileSet), never a plain + # IfcMaterial. `material` here is whatever single IfcMaterial is + # selected in the Object Materials UI, so it can't be passed + # through as-is or ifcopenshell.api.material.assign_material will + # assert (e.g. "IfcMaterial cannot be assiged as a + # IfcMaterialLayerSetUsage."). Passing None lets the API derive + # (or create) the proper set from the element's type; the + # selected material is added into that set below instead. + material_for_assignment = None else: element_material_type = material_type + material_for_assignment = material - ifc.run("material.assign_material", products=[element], type=element_material_type, material=material) + ifc.run( + "material.assign_material", products=[element], type=element_material_type, material=material_for_assignment + ) assigned_material = material_tool.get_material(element) assert assigned_material # Type checker.