mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-11 18:16:40 +00:00
Fix regression where changing assigned types didn't update the materials.
This commit is contained in:
@@ -169,7 +169,9 @@ class UnassignMaterial(bpy.types.Operator, tool.Ifc.Operator):
|
||||
for obj in objects:
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
if element:
|
||||
ifcopenshell.api.run("material.unassign_material", tool.Ifc.get(), product=element)
|
||||
material = ifcopenshell.util.element.get_material(element, should_inherit=False)
|
||||
if "Usage" not in material.is_a():
|
||||
ifcopenshell.api.run("material.unassign_material", tool.Ifc.get(), product=element)
|
||||
|
||||
|
||||
class AddConstituent(bpy.types.Operator, tool.Ifc.Operator):
|
||||
|
||||
@@ -418,7 +418,9 @@ class DumbProfileJoiner:
|
||||
self.body = copy.deepcopy(body)
|
||||
material = ifcopenshell.util.element.get_material(element, should_skip_usage=False)
|
||||
usage = None
|
||||
if not material or (not material.is_a("IfcMaterialProfileSet") and not material.is_a("IfcMaterialProfileSetUsage")):
|
||||
if not material:
|
||||
return
|
||||
if "ProfileSet" not in material.is_a():
|
||||
return
|
||||
if material.is_a("IfcMaterialProfileSetUsage"):
|
||||
usage = material
|
||||
|
||||
@@ -141,6 +141,7 @@ Scenario: Assign material - material layer set
|
||||
When I set "active_object.BIMObjectMaterialProperties.material_type" to "IfcMaterialLayerSet"
|
||||
And I press "bim.assign_material"
|
||||
Then the object "IfcWallType/Empty" does not have the material "Default"
|
||||
And the object "IfcWallType/Empty" has a "0.1" thick layered material containing the material "Default"
|
||||
|
||||
Scenario: Unassign material - material layer set
|
||||
Given an empty IFC project
|
||||
@@ -155,6 +156,27 @@ Scenario: Unassign material - material layer set
|
||||
When I press "bim.unassign_material"
|
||||
Then nothing happens
|
||||
|
||||
Scenario: Unassign material - material layer set usages will not be removed
|
||||
Given an empty IFC project
|
||||
And I add a cube
|
||||
And the object "Cube" is selected
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWall"
|
||||
And I press "bim.assign_class"
|
||||
And I add an empty
|
||||
And the object "Empty" is selected
|
||||
And I set "scene.BIMRootProperties.ifc_product" to "IfcElementType"
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWallType"
|
||||
And I press "bim.assign_class"
|
||||
And I press "bim.add_material(obj='')"
|
||||
And I set "active_object.BIMObjectMaterialProperties.material_type" to "IfcMaterialLayerSet"
|
||||
And I press "bim.assign_material"
|
||||
And the object "IfcWall/Cube" is selected
|
||||
When the variable "type" is "{ifc}.by_type('IfcWallType')[0].id()"
|
||||
And I press "bim.assign_type(relating_type={type}, related_object='IfcWall/Cube')"
|
||||
Then the object "IfcWall/Cube" has a "0.1" thick layered material containing the material "Default"
|
||||
When I press "bim.unassign_material"
|
||||
Then the object "IfcWall/Cube" has a "0.1" thick layered material containing the material "Default"
|
||||
|
||||
Scenario: Enable editing assigned material - material layer set
|
||||
Given an empty IFC project
|
||||
And I add a cube
|
||||
|
||||
@@ -1,6 +1,25 @@
|
||||
@type
|
||||
Feature: Type
|
||||
|
||||
Scenario: Enable editing type
|
||||
Given an empty IFC project
|
||||
And I add a cube
|
||||
And the object "Cube" is selected
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWall"
|
||||
And I press "bim.assign_class"
|
||||
When I press "bim.enable_editing_type"
|
||||
Then nothing happens
|
||||
|
||||
Scenario: Disable editing type
|
||||
Given an empty IFC project
|
||||
And I add a cube
|
||||
And the object "Cube" is selected
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWall"
|
||||
And I press "bim.assign_class"
|
||||
And I press "bim.enable_editing_type"
|
||||
When I press "bim.disable_editing_type"
|
||||
Then nothing happens
|
||||
|
||||
Scenario: Assign type - assign to an empty type
|
||||
Given an empty IFC project
|
||||
And I add a cube
|
||||
@@ -31,7 +50,7 @@ Scenario: Assign type - assign to a type with representation maps
|
||||
And I press "bim.assign_type(relating_type={type}, related_object='IfcWall/Cube')"
|
||||
Then the object "IfcWall/Cube" has a "MappedRepresentation" representation of "Model/Body/MODEL_VIEW"
|
||||
|
||||
Scenario: Assign type - assign to a type with a material layer set
|
||||
Scenario: Assign type - assign to a type with a material layer set, which automatically recreates the shape
|
||||
Given an empty IFC project
|
||||
And I add a cube
|
||||
And the object "Cube" is selected
|
||||
@@ -45,17 +64,50 @@ Scenario: Assign type - assign to a type with a material layer set
|
||||
And I press "bim.add_material(obj='')"
|
||||
And I set "active_object.BIMObjectMaterialProperties.material_type" to "IfcMaterialLayerSet"
|
||||
And I press "bim.assign_material"
|
||||
And I press "bim.enable_editing_assigned_material"
|
||||
And the variable "layer_set" is "{ifc}.by_type("IfcMaterialLayerSet")[0].id()"
|
||||
And I press "bim.add_layer(layer_set={layer_set})"
|
||||
And the variable "layer" is "{ifc}.by_type("IfcMaterialLayer")[0].id()"
|
||||
And I press "bim.enable_editing_material_set_item(material_set_item={layer})"
|
||||
And I set "active_object.BIMObjectMaterialProperties.material_set_item_attributes[0].float_value" to "0.1"
|
||||
And I press "bim.edit_material_set_item(material_set_item={layer})"
|
||||
And I press "bim.edit_assigned_material(material_set={layer_set})"
|
||||
When the variable "type" is "{ifc}.by_type('IfcWallType')[0].id()"
|
||||
And I press "bim.assign_type(relating_type={type}, related_object='IfcWall/Cube')"
|
||||
Then the object "IfcWall/Cube" has a "SweptSolid" representation of "Model/Body/MODEL_VIEW"
|
||||
And the object "IfcWall/Cube" has the material "Default"
|
||||
And the object "IfcWall/Cube" has a "0.1" thick layered material containing the material "Default"
|
||||
And the object "IfcWall/Cube" dimensions are "2,.1,3"
|
||||
|
||||
Scenario: Assign type - assign to a dfferent type with a material layer set
|
||||
Given an empty IFC project
|
||||
And I add a cube
|
||||
And the object "Cube" is selected
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWall"
|
||||
And I press "bim.assign_class"
|
||||
And I add an empty
|
||||
And the object "Empty" is selected
|
||||
And I set "scene.BIMRootProperties.ifc_product" to "IfcElementType"
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWallType"
|
||||
And I press "bim.assign_class"
|
||||
And the variable "type" is "{ifc}.by_type('IfcWallType')[-1].id()"
|
||||
And I press "bim.add_material(obj='')"
|
||||
And I set "active_object.BIMObjectMaterialProperties.material_type" to "IfcMaterialLayerSet"
|
||||
And I press "bim.assign_material"
|
||||
And I add an empty
|
||||
And the object "Empty" is selected
|
||||
And I set "scene.BIMRootProperties.ifc_product" to "IfcElementType"
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWallType"
|
||||
And I press "bim.assign_class"
|
||||
And I set "active_object.BIMObjectMaterialProperties.material_type" to "IfcMaterialLayerSet"
|
||||
And I press "bim.assign_material"
|
||||
And the variable "type2" is "[w for w in {ifc}.by_type('IfcWallType') if w.id() != {type}][0].id()"
|
||||
And the variable "layer_set" is "ifcopenshell.util.element.get_material({ifc}.by_id({type2})).id()"
|
||||
And the variable "layer" is "{ifc}.by_id({layer_set}).MaterialLayers[0].id()"
|
||||
And I press "bim.enable_editing_material_set_item(material_set_item={layer})"
|
||||
And I set "active_object.BIMObjectMaterialProperties.material_set_item_attributes[0].float_value" to "0.2"
|
||||
And I press "bim.edit_material_set_item(material_set_item={layer})"
|
||||
And I press "bim.edit_assigned_material(material_set={layer_set})"
|
||||
When I press "bim.assign_type(relating_type={type}, related_object='IfcWall/Cube')"
|
||||
Then the object "IfcWall/Cube" has a "SweptSolid" representation of "Model/Body/MODEL_VIEW"
|
||||
And the object "IfcWall/Cube" has the material "Default"
|
||||
And the object "IfcWall/Cube" has a "0.1" thick layered material containing the material "Default"
|
||||
And the object "IfcWall/Cube" dimensions are "2,.1,3"
|
||||
When I press "bim.assign_type(relating_type={type2}, related_object='IfcWall/Cube')"
|
||||
Then the object "IfcWall/Cube" has a "0.2" thick layered material containing the material "Default"
|
||||
And the object "IfcWall/Cube" dimensions are "2,.2,3"
|
||||
|
||||
Scenario: Assign type - assign to a type with a material profile set
|
||||
Given an empty IFC project
|
||||
|
||||
@@ -48,6 +48,10 @@ def replace_variables(value):
|
||||
return value
|
||||
|
||||
|
||||
def is_x(number, x):
|
||||
return abs(number - x) < 1e-6
|
||||
|
||||
|
||||
@given("an untestable scenario")
|
||||
def an_untestable_scenario():
|
||||
pass
|
||||
@@ -498,6 +502,27 @@ def the_object_name_has_the_material_material(name, material):
|
||||
assert material in [ms.material.name for ms in the_object_name_exists(name).material_slots]
|
||||
|
||||
|
||||
@then(
|
||||
parsers.parse('the object "{name}" has a "{thickness}" thick layered material containing the material "{material}"')
|
||||
)
|
||||
def the_object_name_has_the_thickness_thick_layered_material_containing_the_material_material(
|
||||
name, thickness, material
|
||||
):
|
||||
material_name = material
|
||||
element = tool.Ifc.get_entity(the_object_name_exists(name))
|
||||
material = ifcopenshell.util.element.get_material(element)
|
||||
assert material and "LayerSet" in material.is_a()
|
||||
if material.is_a("IfcMaterialLayerSetUsage"):
|
||||
material = material.ForLayerSet
|
||||
total_thickness = 0
|
||||
material_names = []
|
||||
for layer in material.MaterialLayers or []:
|
||||
total_thickness += layer.LayerThickness
|
||||
material_names.append(layer.Material.Name)
|
||||
assert is_x(total_thickness, float(thickness))
|
||||
assert material_name in material_names
|
||||
|
||||
|
||||
@then(parsers.parse('the object "{name}" does not have the material "{material}"'))
|
||||
def the_object_name_does_not_have_the_material_material(name, material):
|
||||
assert material not in [ms.material.name for ms in the_object_name_exists(name).material_slots]
|
||||
@@ -548,7 +573,10 @@ def the_object_name_has_no_scale(name):
|
||||
|
||||
@then(parsers.parse('the object "{name}" dimensions are "{dimensions}"'))
|
||||
def the_object_name_dimensions_are_dimensions(name, dimensions):
|
||||
assert list(the_object_name_exists(name).dimensions) == [float(co) for co in dimensions.split(",")]
|
||||
actual_dimensions = list(the_object_name_exists(name).dimensions)
|
||||
expected_dimensions = [float(co) for co in dimensions.split(",")]
|
||||
for i, number in enumerate(actual_dimensions):
|
||||
assert is_x(number, expected_dimensions[i])
|
||||
|
||||
|
||||
@then(parsers.parse('the object "{name}" bottom left corner is at "{location}"'))
|
||||
|
||||
@@ -75,11 +75,8 @@ class Usecase:
|
||||
for rel in self.settings["product"].HasAssociations:
|
||||
if rel.is_a("IfcRelAssociatesMaterial"):
|
||||
if rel.RelatingMaterial.is_a() in ["IfcMaterialLayerSetUsage", "IfcMaterialProfileSetUsage"]:
|
||||
# Usages cannot be unassigned, as all occurrences of a type
|
||||
# which has a parametric material must use the parametric
|
||||
# material. Instead, unassign the parametric material from
|
||||
# the type.
|
||||
continue
|
||||
# Warning: this may leave the model in a non-compliant state.
|
||||
self.file.remove(rel.RelatingMaterial)
|
||||
if len(rel.RelatedObjects) == 1:
|
||||
self.file.remove(rel)
|
||||
continue
|
||||
|
||||
Reference in New Issue
Block a user