mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 01:41:57 +00:00
Fix #3169. Don't allow the user to create invalid material sets without items.
This commit is contained in:
@@ -96,6 +96,7 @@ class ObjectMaterialData:
|
|||||||
cls.data["total_thickness"] = cls.total_thickness()
|
cls.data["total_thickness"] = cls.total_thickness()
|
||||||
cls.data["materials"] = cls.materials()
|
cls.data["materials"] = cls.materials()
|
||||||
cls.data["type_material"] = cls.type_material()
|
cls.data["type_material"] = cls.type_material()
|
||||||
|
cls.data["material_type"] = cls.material_type()
|
||||||
cls.is_loaded = True
|
cls.is_loaded = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -244,3 +245,17 @@ class ObjectMaterialData:
|
|||||||
else:
|
else:
|
||||||
name_attr = "Name"
|
name_attr = "Name"
|
||||||
return getattr(material, name_attr, "Unnamed") or "Unnamed"
|
return getattr(material, name_attr, "Unnamed") or "Unnamed"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def material_type(cls):
|
||||||
|
material_types = [
|
||||||
|
"IfcMaterial",
|
||||||
|
"IfcMaterialConstituentSet",
|
||||||
|
"IfcMaterialLayerSet",
|
||||||
|
"IfcMaterialProfileSet",
|
||||||
|
"IfcMaterialList",
|
||||||
|
]
|
||||||
|
version = tool.Ifc.get_schema()
|
||||||
|
if version == "IFC2X3":
|
||||||
|
material_types = ["IfcMaterial", "IfcMaterialLayerSet", "IfcMaterialList"]
|
||||||
|
return [(m, m, ifcopenshell.util.doc.get_entity_doc(version, m).get("description", "")) for m in material_types]
|
||||||
|
|||||||
@@ -189,23 +189,25 @@ class AssignMaterial(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
material=material,
|
material=material,
|
||||||
)
|
)
|
||||||
assigned_material = ifcopenshell.util.element.get_material(element)
|
assigned_material = ifcopenshell.util.element.get_material(element)
|
||||||
if assigned_material.is_a() in ("IfcMaterialLayerSet", "IfcMaterialLayerSetUsage"):
|
if assigned_material.is_a("IfcMaterialConstituentSet"):
|
||||||
if assigned_material.is_a("IfcMaterialLayerSet"):
|
if not assigned_material.MaterialConstituents:
|
||||||
layer_set = assigned_material
|
ifcopenshell.api.run(
|
||||||
else:
|
"material.add_constituent",
|
||||||
layer_set = assigned_material.ForLayerSet
|
tool.Ifc.get(),
|
||||||
|
constituent_set=assigned_material,
|
||||||
if not layer_set.MaterialLayers:
|
material=material,
|
||||||
|
)
|
||||||
|
elif assigned_material.is_a() == "IfcMaterialLayerSet":
|
||||||
|
if not assigned_material.MaterialLayers:
|
||||||
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
|
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
|
||||||
layer = ifcopenshell.api.run(
|
layer = ifcopenshell.api.run(
|
||||||
"material.add_layer",
|
"material.add_layer",
|
||||||
tool.Ifc.get(),
|
tool.Ifc.get(),
|
||||||
layer_set=layer_set,
|
layer_set=assigned_material,
|
||||||
material=material,
|
material=material,
|
||||||
)
|
)
|
||||||
thickness = 0.1 # Arbitrary metric thickness for now
|
thickness = 0.1 # Arbitrary metric thickness for now
|
||||||
layer.LayerThickness = thickness / unit_scale
|
layer.LayerThickness = thickness / unit_scale
|
||||||
|
|
||||||
elif assigned_material.is_a("IfcMaterialProfileSet"):
|
elif assigned_material.is_a("IfcMaterialProfileSet"):
|
||||||
if not assigned_material.MaterialProfiles:
|
if not assigned_material.MaterialProfiles:
|
||||||
named_profiles = [p for p in tool.Ifc.get().by_type("IfcProfileDef") if p.ProfileName]
|
named_profiles = [p for p in tool.Ifc.get().by_type("IfcProfileDef") if p.ProfileName]
|
||||||
@@ -279,12 +281,12 @@ class RemoveConstituent(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
constituent: bpy.props.IntProperty()
|
constituent: bpy.props.IntProperty()
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
for inverse in tool.Ifc.get().get_inverse(tool.Ifc.get().by_id(self.constituent)):
|
constituent = tool.Ifc.get().by_id(self.constituent)
|
||||||
if inverse.is_a("IfcMaterialConstituentSet") and len(inverse.MaterialConstituents) == 1:
|
for material_set in layer.ToMaterialConstituentSet:
|
||||||
return
|
if len(material_set.MaterialConstituents) == 1:
|
||||||
ifcopenshell.api.run(
|
self.report({"ERROR"}, "At least one constituent must exist")
|
||||||
"material.remove_constituent", tool.Ifc.get(), constituent=tool.Ifc.get().by_id(self.constituent)
|
return {"ERROR"}
|
||||||
)
|
ifcopenshell.api.run("material.remove_constituent", tool.Ifc.get(), constituent=constituent)
|
||||||
|
|
||||||
|
|
||||||
class AddProfile(bpy.types.Operator, tool.Ifc.Operator):
|
class AddProfile(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
@@ -314,10 +316,12 @@ class RemoveProfile(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
profile: bpy.props.IntProperty()
|
profile: bpy.props.IntProperty()
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
for inverse in tool.Ifc.get().get_inverse(tool.Ifc.get().by_id(self.profile)):
|
profile = tool.Ifc.get().by_id(self.profile)
|
||||||
if inverse.is_a("IfcMaterialProfileSet") and len(inverse.MaterialProfiles) == 1:
|
for material_set in profile.ToMaterialProfileSet:
|
||||||
return
|
if len(material_set.MaterialProfiles) == 1:
|
||||||
ifcopenshell.api.run("material.remove_profile", tool.Ifc.get(), profile=tool.Ifc.get().by_id(self.profile))
|
self.report({"ERROR"}, "At least one profile must exist")
|
||||||
|
return {"ERROR"}
|
||||||
|
ifcopenshell.api.run("material.remove_profile", tool.Ifc.get(), profile=profile)
|
||||||
|
|
||||||
|
|
||||||
class AddLayer(bpy.types.Operator, tool.Ifc.Operator):
|
class AddLayer(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
@@ -340,7 +344,7 @@ class AddLayer(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
)
|
)
|
||||||
|
|
||||||
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
|
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
|
||||||
thickness = 0.1 # Arbitrary metric thickness for now
|
thickness = 0.1 # Arbitrary metric thickness for now
|
||||||
layer.LayerThickness = thickness / unit_scale
|
layer.LayerThickness = thickness / unit_scale
|
||||||
|
|
||||||
|
|
||||||
@@ -376,13 +380,12 @@ class RemoveLayer(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
layer: bpy.props.IntProperty()
|
layer: bpy.props.IntProperty()
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
for inverse in tool.Ifc.get().get_inverse(tool.Ifc.get().by_id(self.layer)):
|
layer = tool.Ifc.get().by_id(self.layer)
|
||||||
if inverse.is_a("IfcMaterialLayerSet") and len(inverse.MaterialLayers) == 1:
|
for material_set in layer.ToMaterialLayerSet:
|
||||||
self.report(
|
if len(material_set.MaterialLayers) == 1:
|
||||||
{"ERROR"}, "Cannot remove material layer - IfcMaterialLayerSet should alawys have atleast 1 layer"
|
self.report({"ERROR"}, "At least one layer must exist")
|
||||||
)
|
|
||||||
return {"ERROR"}
|
return {"ERROR"}
|
||||||
ifcopenshell.api.run("material.remove_layer", tool.Ifc.get(), layer=tool.Ifc.get().by_id(self.layer))
|
ifcopenshell.api.run("material.remove_layer", tool.Ifc.get(), layer=layer)
|
||||||
|
|
||||||
|
|
||||||
class AddListItem(bpy.types.Operator, tool.Ifc.Operator):
|
class AddListItem(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
|
|||||||
@@ -85,24 +85,10 @@ def get_materials(self, context):
|
|||||||
return ObjectMaterialData.data["materials"]
|
return ObjectMaterialData.data["materials"]
|
||||||
|
|
||||||
|
|
||||||
def get_object_material_types(self, context):
|
def get_object_material_type(self, context):
|
||||||
global materialtypes_enum
|
if not ObjectMaterialData.is_loaded:
|
||||||
if len(materialtypes_enum) == 0 and IfcStore.get_file():
|
ObjectMaterialData.load()
|
||||||
material_types = [
|
return ObjectMaterialData.data["material_type"]
|
||||||
"IfcMaterial",
|
|
||||||
"IfcMaterialConstituentSet",
|
|
||||||
"IfcMaterialLayerSet",
|
|
||||||
"IfcMaterialLayerSetUsage",
|
|
||||||
"IfcMaterialProfileSet",
|
|
||||||
"IfcMaterialProfileSetUsage",
|
|
||||||
"IfcMaterialList",
|
|
||||||
]
|
|
||||||
version = tool.Ifc.get_schema()
|
|
||||||
if version == "IFC2X3":
|
|
||||||
material_types = ["IfcMaterial", "IfcMaterialLayerSet", "IfcMaterialLayerSetUsage", "IfcMaterialList"]
|
|
||||||
materialtypes_enum.clear()
|
|
||||||
materialtypes_enum = [(m, m, get_entity_doc(version, m).get("description", "")) for m in material_types]
|
|
||||||
return materialtypes_enum
|
|
||||||
|
|
||||||
|
|
||||||
def get_material_types(self, context):
|
def get_material_types(self, context):
|
||||||
@@ -137,7 +123,7 @@ class BIMMaterialProperties(PropertyGroup):
|
|||||||
|
|
||||||
|
|
||||||
class BIMObjectMaterialProperties(PropertyGroup):
|
class BIMObjectMaterialProperties(PropertyGroup):
|
||||||
material_type: EnumProperty(items=get_object_material_types, name="Material Type")
|
material_type: EnumProperty(items=get_object_material_type, name="Material Type")
|
||||||
material: EnumProperty(items=get_materials, name="Material")
|
material: EnumProperty(items=get_materials, name="Material")
|
||||||
is_editing: BoolProperty(name="Is Editing", default=False)
|
is_editing: BoolProperty(name="Is Editing", default=False)
|
||||||
material_set_usage_attributes: CollectionProperty(name="Material Set Usage Attributes", type=Attribute)
|
material_set_usage_attributes: CollectionProperty(name="Material Set Usage Attributes", type=Attribute)
|
||||||
|
|||||||
@@ -155,13 +155,7 @@ class BIM_PT_object_material(Panel):
|
|||||||
|
|
||||||
row = self.layout.row(align=True)
|
row = self.layout.row(align=True)
|
||||||
prop_with_search(row, self.props, "material_type", text="")
|
prop_with_search(row, self.props, "material_type", text="")
|
||||||
if self.props.material_type in (
|
prop_with_search(row, self.props, "material", text="")
|
||||||
"IfcMaterial",
|
|
||||||
"IfcMaterialList",
|
|
||||||
"IfcMaterialLayerSet",
|
|
||||||
"IfcMaterialLayerSetUsage",
|
|
||||||
):
|
|
||||||
prop_with_search(row, self.props, "material", text="")
|
|
||||||
row.operator("bim.assign_material", icon="ADD", text="")
|
row.operator("bim.assign_material", icon="ADD", text="")
|
||||||
|
|
||||||
def draw_material_ui(self):
|
def draw_material_ui(self):
|
||||||
|
|||||||
Reference in New Issue
Block a user