mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 01:41:57 +00:00
WIP port object material assignment with 3 new features. See message. See #1222.
* Full support for editing IfcMaterialList added * The reusability of material set relationships are now roundtripped * UI is sensitive to IFC schema version and adapts intelligently
This commit is contained in:
@@ -20,6 +20,7 @@ if bpy is not None:
|
||||
"bimtester": None,
|
||||
"debug": None,
|
||||
"geometry": None,
|
||||
"material": None,
|
||||
"model": None,
|
||||
"owner": None,
|
||||
"project": None,
|
||||
@@ -191,10 +192,6 @@ if bpy is not None:
|
||||
operator.AddSectionsAnnotations,
|
||||
prop.StrProperty,
|
||||
prop.Attribute,
|
||||
prop.MaterialLayer,
|
||||
prop.MaterialConstituent,
|
||||
prop.MaterialProfile,
|
||||
prop.MaterialSet,
|
||||
prop.Variable,
|
||||
prop.Role,
|
||||
prop.Address,
|
||||
@@ -250,9 +247,7 @@ if bpy is not None:
|
||||
ui.BIM_PT_diff,
|
||||
ui.BIM_PT_patch,
|
||||
ui.BIM_PT_mvd,
|
||||
ui.BIM_PT_material,
|
||||
ui.BIM_PT_presentation_layer_data,
|
||||
ui.BIM_PT_object_material,
|
||||
ui.BIM_PT_classification_references,
|
||||
ui.BIM_PT_documents,
|
||||
ui.BIM_PT_constraint_relations,
|
||||
@@ -302,7 +297,7 @@ if bpy is not None:
|
||||
bpy.types.Scene.MapConversion = bpy.props.PointerProperty(type=prop.MapConversion)
|
||||
bpy.types.Scene.TargetCRS = bpy.props.PointerProperty(type=prop.TargetCRS)
|
||||
bpy.types.Object.BIMObjectProperties = bpy.props.PointerProperty(type=prop.BIMObjectProperties)
|
||||
bpy.types.Collection.BIMObjectProperties = bpy.props.PointerProperty(type=prop.BIMObjectProperties)
|
||||
bpy.types.Collection.BIMObjectProperties = bpy.props.PointerProperty(type=prop.BIMObjectProperties) # Check if we need this
|
||||
bpy.types.Material.BIMMaterialProperties = bpy.props.PointerProperty(type=prop.BIMMaterialProperties)
|
||||
bpy.types.Mesh.BIMMeshProperties = bpy.props.PointerProperty(type=prop.BIMMeshProperties)
|
||||
bpy.types.Camera.BIMCameraProperties = bpy.props.PointerProperty(type=prop.BIMCameraProperties)
|
||||
@@ -326,7 +321,7 @@ if bpy is not None:
|
||||
del bpy.types.Scene.MapConversion
|
||||
del bpy.types.Scene.TargetCRS
|
||||
del bpy.types.Object.BIMObjectProperties
|
||||
del bpy.types.Collection.BIMObjectProperties
|
||||
del bpy.types.Collection.BIMObjectProperties # Check if we need this
|
||||
del bpy.types.Material.BIMMaterialProperties
|
||||
del bpy.types.Mesh.BIMMeshProperties
|
||||
del bpy.types.Camera.BIMCameraProperties
|
||||
|
||||
@@ -180,86 +180,31 @@ class MaterialCreator:
|
||||
def create_single(self, material):
|
||||
if material.Name not in self.materials:
|
||||
self.create_new_single(material)
|
||||
self.obj.BIMObjectProperties.material_type = "IfcMaterial"
|
||||
self.obj.BIMObjectProperties.material = self.materials[material.Name]
|
||||
|
||||
def create_layer_set(self, layer_set):
|
||||
props = self.obj.BIMObjectProperties
|
||||
props.material_type = "IfcMaterialLayerSet"
|
||||
props.material_set.name = layer_set.LayerSetName or ""
|
||||
if hasattr(layer_set, "Description"): # IFC2X3 support
|
||||
props.material_set.description = layer_set.Description or ""
|
||||
for layer in layer_set.MaterialLayers:
|
||||
new = props.material_set.material_layers.add()
|
||||
if layer.Material:
|
||||
if layer.Material.Name not in self.materials:
|
||||
self.create_new_single(layer.Material)
|
||||
new.material = self.materials[layer.Material.Name]
|
||||
new.layer_thickness = layer.LayerThickness
|
||||
new.is_ventilated = "TRUE" if layer.IsVentilated else "FALSE"
|
||||
if not hasattr(layer, "Name"):
|
||||
continue # IFC2X3 support
|
||||
new.name = layer.Name or ""
|
||||
new.description = layer.Description or ""
|
||||
try:
|
||||
new.category = layer.Category if layer.Category else "None"
|
||||
except:
|
||||
new.custom_category = layer.Category or ""
|
||||
new.priority = layer.Priority or 0
|
||||
|
||||
def create_constituent_set(self, constituent_set):
|
||||
props = self.obj.BIMObjectProperties
|
||||
props.material_type = "IfcMaterialConstituentSet"
|
||||
props.material_set.name = constituent_set.Name or ""
|
||||
props.material_set.description = constituent_set.Description or ""
|
||||
for constituent in constituent_set.MaterialConstituents:
|
||||
new = props.material_set.material_constituents.add()
|
||||
new.name = constituent.Name or ""
|
||||
new.description = constituent.Description or ""
|
||||
if constituent.Material.Name not in self.materials:
|
||||
self.create_new_single(constituent.Material)
|
||||
new.material = self.materials[constituent.Material.Name]
|
||||
new.fraction = constituent.Fraction or 0.0
|
||||
new.category = constituent.Category or ""
|
||||
|
||||
def create_profile_set(self, profile_set):
|
||||
props = self.obj.BIMObjectProperties
|
||||
props.material_type = "IfcMaterialProfileSet"
|
||||
props.material_set.name = profile_set.Name or ""
|
||||
props.material_set.description = profile_set.Description or ""
|
||||
for profile in profile_set.MaterialProfiles:
|
||||
new = props.material_set.material_profiles.add()
|
||||
new.name = profile.Name or ""
|
||||
new.description = profile.Description or ""
|
||||
if profile.Material.Name not in self.materials:
|
||||
self.create_new_single(profile.Material)
|
||||
new.material = self.materials[profile.Material.Name]
|
||||
try:
|
||||
new.profile = profile.Profile.is_a()
|
||||
for i, attribute in enumerate(profile.Profile):
|
||||
newa = new.profile_attributes.add()
|
||||
newa.name = profile.Profile.attribute_name(i)
|
||||
newa.string_value = str(attribute)
|
||||
except:
|
||||
pass # TODO: currently, only parametric profile sets are supported
|
||||
new.priority = profile.Priority or 0
|
||||
new.category = profile.Category or ""
|
||||
|
||||
def create_material_list(self, material_list):
|
||||
props = self.obj.BIMObjectProperties
|
||||
props.material_type = "IfcMaterialConstituentSet" # Constituent sets are the recommended upgrade path
|
||||
for material in material_list.Materials:
|
||||
new = props.material_set.material_constituents.add()
|
||||
if material.Name not in self.materials:
|
||||
self.create_new_single(material)
|
||||
new.material = self.materials[material.Name]
|
||||
|
||||
def create_new_single(self, material):
|
||||
self.materials[material.Name] = obj = bpy.data.materials.new(material.Name)
|
||||
obj.BIMMaterialProperties.ifc_definition_id = int(material.id())
|
||||
self.ifc_importer.add_element_attributes(material, obj.BIMMaterialProperties)
|
||||
for pset in getattr(material, "HasProperties", ()):
|
||||
self.ifc_importer.add_pset(pset, obj.BIMMaterialProperties)
|
||||
if not material.HasRepresentation or not material.HasRepresentation[0].Representations:
|
||||
return
|
||||
for representation in material.HasRepresentation[0].Representations:
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import bpy
|
||||
from . import ui, prop, operator
|
||||
|
||||
classes = (
|
||||
operator.AssignMaterial,
|
||||
operator.UnassignMaterial,
|
||||
operator.AddConstituent,
|
||||
operator.RemoveConstituent,
|
||||
operator.AddLayer,
|
||||
operator.RemoveLayer,
|
||||
operator.AddListItem,
|
||||
operator.RemoveListItem,
|
||||
operator.EnableEditingAssignedMaterial,
|
||||
operator.DisableEditingAssignedMaterial,
|
||||
operator.EditAssignedMaterial,
|
||||
operator.EnableEditingMaterialSetItem,
|
||||
operator.DisableEditingMaterialSetItem,
|
||||
operator.EditMaterialSetItem,
|
||||
prop.BIMObjectMaterialProperties,
|
||||
ui.BIM_PT_object_material,
|
||||
)
|
||||
|
||||
|
||||
def register():
|
||||
bpy.types.Object.BIMObjectMaterialProperties = bpy.props.PointerProperty(type=prop.BIMObjectMaterialProperties)
|
||||
|
||||
|
||||
def unregister():
|
||||
del bpy.types.Object.BIMObjectMaterialProperties
|
||||
@@ -0,0 +1,16 @@
|
||||
import ifcopenshell
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, settings=None):
|
||||
self.file = file
|
||||
self.settings = {"constituent_set": None, "material": None}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
constituents = list(self.settings["constituent_set"].MaterialConstituents)
|
||||
constituent = self.file.create_entity("IfcMaterialConstituent", **{"Material": self.settings["material"]})
|
||||
constituents.append(constituent)
|
||||
self.settings["constituent_set"].MaterialConstituents = constituents
|
||||
return constituent
|
||||
@@ -0,0 +1,19 @@
|
||||
import ifcopenshell
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, settings=None):
|
||||
self.file = file
|
||||
self.settings = {"layer_set": None, "material": None}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
layers = list(self.settings["layer_set"].MaterialLayers)
|
||||
layer = self.file.create_entity("IfcMaterialLayer", **{
|
||||
"Material": self.settings["material"],
|
||||
"LayerThickness": 0.
|
||||
})
|
||||
layers.append(layer)
|
||||
self.settings["layer_set"].MaterialLayers = layers
|
||||
return layer
|
||||
@@ -0,0 +1,14 @@
|
||||
import ifcopenshell
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, settings=None):
|
||||
self.file = file
|
||||
self.settings = {"material_list": None, "material": None}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
materials = list(self.settings["material_list"].Materials)
|
||||
materials.append(self.settings["material"])
|
||||
self.settings["material_list"].Materials = materials
|
||||
@@ -0,0 +1,58 @@
|
||||
import ifcopenshell
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, settings=None):
|
||||
self.file = file
|
||||
self.settings = {"product": None, "type": "IfcMaterial", "material": None}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
if self.settings["type"] == "IfcMaterial":
|
||||
self.assign_ifc_material()
|
||||
elif self.settings["type"] == "IfcMaterialConstituentSet":
|
||||
material_set = self.file.create_entity(self.settings["type"])
|
||||
material_set.MaterialConstituents = [self.settings["material"]]
|
||||
self.create_material_association(material_set)
|
||||
elif self.settings["type"] == "IfcMaterialLayerSet":
|
||||
material_set = self.file.create_entity(self.settings["type"])
|
||||
material_set.MaterialLayers = [self.settings["material"]]
|
||||
self.create_material_association(material_set)
|
||||
elif self.settings["type"] == "IfcMaterialProfileSet":
|
||||
material_set = self.file.create_entity(self.settings["type"])
|
||||
material_set.MaterialProfiles = [self.settings["material"]]
|
||||
self.create_material_association(material_set)
|
||||
elif self.settings["type"] == "IfcMaterialList":
|
||||
material_set = self.file.create_entity(self.settings["type"])
|
||||
material_set.Materials = [self.settings["material"]]
|
||||
self.create_material_association(material_set)
|
||||
|
||||
def assign_ifc_material(self):
|
||||
rel = self.get_rel_associates_material(self.settings["material"])
|
||||
if not rel:
|
||||
return self.create_material_association(self.settings["material"])
|
||||
related_objects = list(rel.RelatedObjects)
|
||||
related_objects.append(self.settings["product"])
|
||||
rel.RelatedObjects = related_objects
|
||||
|
||||
def create_material_association(self, relating_material):
|
||||
return self.file.create_entity(
|
||||
"IfcRelAssociatesMaterial",
|
||||
**{
|
||||
"GlobalId": ifcopenshell.guid.new(),
|
||||
"RelatedObjects": [self.settings["product"]],
|
||||
"RelatingMaterial": relating_material,
|
||||
}
|
||||
)
|
||||
|
||||
def get_rel_associates_material(self, material):
|
||||
if self.file.schema == "IFC2X3":
|
||||
rel = [
|
||||
r
|
||||
for r in self.file.by_type("IfcRelAssociatesMaterial")
|
||||
if r.RelatingMaterial == self.settings["material"]
|
||||
]
|
||||
return rel[0] if rel else None
|
||||
if self.settings["material"].AssociatedTo:
|
||||
return self.settings["material"].AssociatedTo[0]
|
||||
@@ -0,0 +1,88 @@
|
||||
import ifcopenshell
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
|
||||
|
||||
class Data:
|
||||
is_loaded = False
|
||||
materials = {}
|
||||
constituent_sets = {}
|
||||
constituents = {}
|
||||
layer_sets = {}
|
||||
layers = {}
|
||||
profile_sets = {}
|
||||
profiles = {}
|
||||
lists = {}
|
||||
products = {}
|
||||
_file = None
|
||||
|
||||
@classmethod
|
||||
def load(cls, product_id=None):
|
||||
cls._file = IfcStore.get_file()
|
||||
if not cls._file:
|
||||
return
|
||||
if product_id:
|
||||
return cls.load_product_material(product_id)
|
||||
cls.load_materials()
|
||||
cls.load_constituents()
|
||||
cls.load_layers()
|
||||
cls.load_profiles()
|
||||
cls.load_lists()
|
||||
cls.is_loaded = True
|
||||
|
||||
@classmethod
|
||||
def load_materials(cls):
|
||||
cls.load_element("IfcMaterial", cls.materials)
|
||||
|
||||
@classmethod
|
||||
def load_constituents(cls):
|
||||
cls.load_element("IfcMaterialConstituent", cls.constituents)
|
||||
cls.load_element("IfcMaterialConstituentSet", cls.constituent_sets)
|
||||
|
||||
@classmethod
|
||||
def load_layers(cls):
|
||||
cls.load_element("IfcMaterialLayer", cls.layers)
|
||||
cls.load_element("IfcMaterialLayerSet", cls.layer_sets)
|
||||
|
||||
@classmethod
|
||||
def load_profiles(cls):
|
||||
cls.load_element("IfcMaterialProfile", cls.profiles)
|
||||
cls.load_element("IfcMaterialProfileSet", cls.profile_sets)
|
||||
|
||||
@classmethod
|
||||
def load_lists(cls):
|
||||
cls.load_element("IfcMaterialList", cls.lists)
|
||||
|
||||
@classmethod
|
||||
def load_product_material(cls, product_id):
|
||||
cls.products[product_id] = {}
|
||||
for association in cls._file.by_id(product_id).HasAssociations:
|
||||
if association.is_a("IfcRelAssociatesMaterial"):
|
||||
cls.load_association(association, product_id)
|
||||
|
||||
@classmethod
|
||||
def load_element(cls, ifc_class, to_dict):
|
||||
try:
|
||||
elements = cls._file.by_type(ifc_class)
|
||||
except:
|
||||
return
|
||||
for element in elements:
|
||||
to_dict[element.id()] = cls.get_simple_info(element)
|
||||
|
||||
@classmethod
|
||||
def get_simple_info(cls, element):
|
||||
info = element.get_info()
|
||||
for key, value in info.items():
|
||||
if isinstance(value, ifcopenshell.entity_instance):
|
||||
info[key] = value.id()
|
||||
elif isinstance(value, tuple) and value and isinstance(value[0], ifcopenshell.entity_instance):
|
||||
info[key] = [v.id() for v in value]
|
||||
return info
|
||||
|
||||
@classmethod
|
||||
def load_association(cls, association, product_id):
|
||||
material_select = association.RelatingMaterial
|
||||
if material_select.is_a("IfcMaterialLayerSetUsage"): # TODO: implement usages
|
||||
material_select = material_select.ForLayerSet
|
||||
elif material_select.is_a("IfcMaterialProfileSetUsage"): # TODO: implement usages
|
||||
material_select = material_select.ForProfileSet
|
||||
cls.products[product_id] = {"type": material_select.is_a(), "id": material_select.id()}
|
||||
@@ -0,0 +1,13 @@
|
||||
class Usecase():
|
||||
def __init__(self, file, settings=None):
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"element": None,
|
||||
"attributes": {}
|
||||
}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
for name, value in self.settings["attributes"].items():
|
||||
setattr(self.settings["element"], name, value)
|
||||
@@ -0,0 +1,15 @@
|
||||
class Usecase():
|
||||
def __init__(self, file, settings=None):
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"constituent": None,
|
||||
"attributes": {},
|
||||
"material": None
|
||||
}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
for name, value in self.settings["attributes"].items():
|
||||
setattr(self.settings["constituent"], name, value)
|
||||
self.settings["constituent"].Material = self.settings["material"]
|
||||
@@ -0,0 +1,15 @@
|
||||
class Usecase():
|
||||
def __init__(self, file, settings=None):
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"layer": None,
|
||||
"attributes": {},
|
||||
"material": None
|
||||
}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
for name, value in self.settings["attributes"].items():
|
||||
setattr(self.settings["layer"], name, value)
|
||||
self.settings["layer"].Material = self.settings["material"]
|
||||
@@ -0,0 +1,15 @@
|
||||
class Usecase():
|
||||
def __init__(self, file, settings=None):
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"profile": None,
|
||||
"attributes": {},
|
||||
"material": None
|
||||
}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
for name, value in self.settings["attributes"].items():
|
||||
setattr(self.settings["profile"], name, value)
|
||||
self.settings["profile"].Material = self.settings["material"]
|
||||
@@ -0,0 +1,377 @@
|
||||
import bpy
|
||||
import blenderbim.bim.module.material.assign_material as assign_material
|
||||
import blenderbim.bim.module.material.unassign_material as unassign_material
|
||||
import blenderbim.bim.module.material.add_constituent as add_constituent
|
||||
import blenderbim.bim.module.material.remove_constituent as remove_constituent
|
||||
import blenderbim.bim.module.material.add_layer as add_layer
|
||||
import blenderbim.bim.module.material.edit_layer as edit_layer
|
||||
import blenderbim.bim.module.material.remove_layer as remove_layer
|
||||
import blenderbim.bim.module.material.add_list_item as add_list_item
|
||||
import blenderbim.bim.module.material.remove_list_item as remove_list_item
|
||||
import blenderbim.bim.module.material.edit_assigned_material as edit_assigned_material
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
from blenderbim.bim.module.material.data import Data
|
||||
|
||||
|
||||
class AssignMaterial(bpy.types.Operator):
|
||||
bl_idname = "bim.assign_material"
|
||||
bl_label = "Assign Material"
|
||||
obj: bpy.props.StringProperty()
|
||||
material_type: bpy.props.StringProperty()
|
||||
|
||||
def execute(self, context):
|
||||
obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object
|
||||
material_type = self.material_type or obj.BIMObjectMaterialProperties.material_type
|
||||
self.file = IfcStore.get_file()
|
||||
assign_material.Usecase(
|
||||
self.file,
|
||||
{
|
||||
"product": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id),
|
||||
"type": material_type,
|
||||
"material": self.file.by_id(int(obj.BIMObjectMaterialProperties.material)),
|
||||
},
|
||||
).execute()
|
||||
Data.load(obj.BIMObjectProperties.ifc_definition_id)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class UnassignMaterial(bpy.types.Operator):
|
||||
bl_idname = "bim.unassign_material"
|
||||
bl_label = "Unassign Material"
|
||||
obj: bpy.props.StringProperty()
|
||||
|
||||
def execute(self, context):
|
||||
obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object
|
||||
self.file = IfcStore.get_file()
|
||||
unassign_material.Usecase(
|
||||
self.file, {"product": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)}
|
||||
).execute()
|
||||
Data.load(obj.BIMObjectProperties.ifc_definition_id)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class AddConstituent(bpy.types.Operator):
|
||||
bl_idname = "bim.add_constituent"
|
||||
bl_label = "Add Constituent"
|
||||
obj: bpy.props.StringProperty()
|
||||
constituent_set: bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object
|
||||
self.file = IfcStore.get_file()
|
||||
add_constituent.Usecase(
|
||||
self.file,
|
||||
{
|
||||
"constituent_set": self.file.by_id(self.constituent_set),
|
||||
"material": self.file.by_id(int(obj.BIMObjectMaterialProperties.material)),
|
||||
},
|
||||
).execute()
|
||||
Data.load_constituents()
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class RemoveConstituent(bpy.types.Operator):
|
||||
bl_idname = "bim.remove_constituent"
|
||||
bl_label = "Remove Constituent"
|
||||
obj: bpy.props.StringProperty()
|
||||
constituent: bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object
|
||||
self.file = IfcStore.get_file()
|
||||
remove_constituent.Usecase(self.file, {"constituent": self.file.by_id(self.constituent)}).execute()
|
||||
Data.load_constituents()
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class AddLayer(bpy.types.Operator):
|
||||
bl_idname = "bim.add_layer"
|
||||
bl_label = "Add Layer"
|
||||
obj: bpy.props.StringProperty()
|
||||
layer_set: bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object
|
||||
self.file = IfcStore.get_file()
|
||||
add_layer.Usecase(
|
||||
self.file,
|
||||
{
|
||||
"layer_set": self.file.by_id(self.layer_set),
|
||||
"material": self.file.by_id(int(obj.BIMObjectMaterialProperties.material)),
|
||||
},
|
||||
).execute()
|
||||
Data.load_layers()
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class RemoveLayer(bpy.types.Operator):
|
||||
bl_idname = "bim.remove_layer"
|
||||
bl_label = "Remove Layer"
|
||||
obj: bpy.props.StringProperty()
|
||||
layer: bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object
|
||||
self.file = IfcStore.get_file()
|
||||
remove_layer.Usecase(self.file, {"layer": self.file.by_id(self.layer)}).execute()
|
||||
Data.load_layers()
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class AddListItem(bpy.types.Operator):
|
||||
bl_idname = "bim.add_list_item"
|
||||
bl_label = "Add List Item"
|
||||
obj: bpy.props.StringProperty()
|
||||
list_item_set: bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object
|
||||
self.file = IfcStore.get_file()
|
||||
add_list_item.Usecase(
|
||||
self.file,
|
||||
{
|
||||
"material_list": self.file.by_id(self.list_item_set),
|
||||
"material": self.file.by_id(int(obj.BIMObjectMaterialProperties.material)),
|
||||
},
|
||||
).execute()
|
||||
Data.load_lists()
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class RemoveListItem(bpy.types.Operator):
|
||||
bl_idname = "bim.remove_list_item"
|
||||
bl_label = "Remove List Item"
|
||||
obj: bpy.props.StringProperty()
|
||||
list_item_set: bpy.props.IntProperty()
|
||||
list_item: bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object
|
||||
self.file = IfcStore.get_file()
|
||||
remove_list_item.Usecase(
|
||||
self.file,
|
||||
{
|
||||
"material_list": self.file.by_id(self.list_item_set),
|
||||
"material": self.file.by_id(self.list_item),
|
||||
},
|
||||
).execute()
|
||||
Data.load_lists()
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class EnableEditingAssignedMaterial(bpy.types.Operator):
|
||||
bl_idname = "bim.enable_editing_assigned_material"
|
||||
bl_label = "Enable Editing Assigned Material"
|
||||
obj: bpy.props.StringProperty()
|
||||
|
||||
def execute(self, context):
|
||||
obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object
|
||||
props = obj.BIMObjectMaterialProperties
|
||||
props.is_editing = True
|
||||
product_data = Data.products[obj.BIMObjectProperties.ifc_definition_id]
|
||||
|
||||
if product_data["type"] == "IfcMaterial":
|
||||
props.material = str(product_data["id"])
|
||||
return {"FINISHED"}
|
||||
|
||||
if product_data["type"] == "IfcMaterialConstituentSet":
|
||||
material_set_data = Data.constituent_sets[product_data["id"]]
|
||||
elif product_data["type"] == "IfcMaterialLayerSet":
|
||||
material_set_data = Data.layer_sets[product_data["id"]]
|
||||
elif product_data["type"] == "IfcMaterialProfileSet":
|
||||
material_set_data = Data.profile_sets[product_data["id"]]
|
||||
elif product_data["type"] == "IfcMaterialList":
|
||||
material_set_data = Data.lists[product_data["id"]]
|
||||
else:
|
||||
material_set_data = {}
|
||||
|
||||
while len(props.material_set_attributes) > 0:
|
||||
props.material_set_attributes.remove(0)
|
||||
|
||||
for attribute in IfcStore.get_schema().declaration_by_name(product_data["type"]).all_attributes():
|
||||
if "<string>" not in str(attribute.type_of_attribute):
|
||||
continue
|
||||
if attribute.name() in material_set_data:
|
||||
new = props.material_set_attributes.add()
|
||||
new.name = attribute.name()
|
||||
new.is_null = material_set_data[attribute.name()] is None
|
||||
new.string_value = "" if new.is_null else material_set_data[attribute.name()]
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class DisableEditingAssignedMaterial(bpy.types.Operator):
|
||||
bl_idname = "bim.disable_editing_assigned_material"
|
||||
bl_label = "Disable Editing Assigned Material"
|
||||
obj: bpy.props.StringProperty()
|
||||
|
||||
def execute(self, context):
|
||||
obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object
|
||||
props = obj.BIMObjectMaterialProperties
|
||||
props.is_editing = False
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class EditAssignedMaterial(bpy.types.Operator):
|
||||
bl_idname = "bim.edit_assigned_material"
|
||||
bl_label = "Edit Assigned Material"
|
||||
obj: bpy.props.StringProperty()
|
||||
material_set: bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
self.file = IfcStore.get_file()
|
||||
obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object
|
||||
props = obj.BIMObjectMaterialProperties
|
||||
product_data = Data.products[obj.BIMObjectProperties.ifc_definition_id]
|
||||
material_set_id = self.material_set or product_data["id"]
|
||||
material_set = self.file.by_id(material_set_id)
|
||||
|
||||
if product_data["type"] == "IfcMaterial":
|
||||
bpy.ops.bim.unassign_material(obj=obj.name)
|
||||
bpy.ops.bim.assign_material(obj=obj.name, material_type="IfcMaterial")
|
||||
Data.load(obj.BIMObjectProperties.ifc_definition_id)
|
||||
bpy.ops.bim.disable_editing_assigned_material(obj=obj.name)
|
||||
return {"FINISHED"}
|
||||
|
||||
attributes = {}
|
||||
for attribute in props.material_set_attributes:
|
||||
attributes[attribute.name] = None if attribute.is_null else attribute.string_value
|
||||
edit_assigned_material.Usecase(
|
||||
self.file,
|
||||
{
|
||||
"element": material_set,
|
||||
"attributes": attributes,
|
||||
},
|
||||
).execute()
|
||||
Data.load(obj.BIMObjectProperties.ifc_definition_id)
|
||||
if material_set.is_a("IfcMaterialConstituentSet"):
|
||||
Data.load_constituents()
|
||||
elif material_set.is_a("IfcMaterialLayerSet"):
|
||||
Data.load_layers()
|
||||
elif material_set.is_a("IfcMaterialProfileSet"):
|
||||
Data.load_profiles()
|
||||
bpy.ops.bim.disable_editing_assigned_material(obj=obj.name)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class EnableEditingMaterialSetItem(bpy.types.Operator):
|
||||
bl_idname = "bim.enable_editing_material_set_item"
|
||||
bl_label = "Enable Editing Material Set Item"
|
||||
obj: bpy.props.StringProperty()
|
||||
material_set_item: bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
self.file = IfcStore.get_file()
|
||||
obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object
|
||||
props = obj.BIMObjectMaterialProperties
|
||||
props.active_material_set_item_id = self.material_set_item
|
||||
product_data = Data.products[obj.BIMObjectProperties.ifc_definition_id]
|
||||
material_set_item = self.file.by_id(self.material_set_item)
|
||||
|
||||
if product_data["type"] == "IfcMaterialConstituentSet":
|
||||
material_set_item_data = Data.constituents[self.material_set_item]
|
||||
elif product_data["type"] == "IfcMaterialLayerSet":
|
||||
material_set_item_data = Data.layers[self.material_set_item]
|
||||
elif product_data["type"] == "IfcMaterialProfileSet":
|
||||
material_set_item_data = Data.profiles[self.material_set_item]
|
||||
else:
|
||||
material_set_item_data = {}
|
||||
|
||||
props.material_set_item_material = str(material_set_item_data["Material"])
|
||||
|
||||
while len(props.material_set_item_attributes) > 0:
|
||||
props.material_set_item_attributes.remove(0)
|
||||
|
||||
for attribute in IfcStore.get_schema().declaration_by_name(material_set_item.is_a()).all_attributes():
|
||||
data_type = str(attribute.type_of_attribute)
|
||||
if "<entity" in data_type:
|
||||
continue
|
||||
if attribute.name() in material_set_item_data:
|
||||
new = props.material_set_item_attributes.add()
|
||||
new.name = attribute.name()
|
||||
new.is_null = material_set_item_data[attribute.name()] is None
|
||||
if "<string>" in data_type:
|
||||
new.string_value = "" if new.is_null else material_set_item_data[attribute.name()]
|
||||
new.data_type = "string"
|
||||
elif "<real>" in data_type:
|
||||
new.float_value = 0.0 if new.is_null else material_set_item_data[attribute.name()]
|
||||
new.data_type = "float"
|
||||
elif "<integer>" in data_type:
|
||||
new.int_value = 0 if new.is_null else material_set_item_data[attribute.name()]
|
||||
new.data_type = "integer"
|
||||
elif "<boolean>" in data_type or "<logical>" in data_type:
|
||||
new.bool_value = False if new.is_null else material_set_item_data[attribute.name()]
|
||||
new.data_type = "boolean"
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class DisableEditingMaterialSetItem(bpy.types.Operator):
|
||||
bl_idname = "bim.disable_editing_material_set_item"
|
||||
bl_label = "Disable Editing Material Set Item"
|
||||
obj: bpy.props.StringProperty()
|
||||
|
||||
def execute(self, context):
|
||||
obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object
|
||||
props = obj.BIMObjectMaterialProperties
|
||||
props.active_material_set_item_id = 0
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class EditMaterialSetItem(bpy.types.Operator):
|
||||
bl_idname = "bim.edit_material_set_item"
|
||||
bl_label = "Edit Material Set Item"
|
||||
obj: bpy.props.StringProperty()
|
||||
material_set_item: bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object
|
||||
self.file = IfcStore.get_file()
|
||||
props = obj.BIMObjectMaterialProperties
|
||||
product_data = Data.products[obj.BIMObjectProperties.ifc_definition_id]
|
||||
|
||||
attributes = {}
|
||||
for attribute in props.material_set_item_attributes:
|
||||
if attribute.data_type == "string":
|
||||
value = attribute.string_value
|
||||
elif attribute.data_type == "float":
|
||||
value = attribute.float_value
|
||||
elif attribute.data_type == "integer":
|
||||
value = attribute.int_value
|
||||
elif attribute.data_type == "boolean":
|
||||
value = attribute.bool_value
|
||||
attributes[attribute.name] = None if attribute.is_null else value
|
||||
|
||||
if product_data["type"] == "IfcMaterialConstituentSet":
|
||||
edit_constituent.Usecase(
|
||||
self.file,
|
||||
{
|
||||
"constituent": self.file.by_id(self.material_set_item),
|
||||
"attributes": attributes,
|
||||
"material": self.file.by_id(int(obj.BIMObjectMaterialProperties.material_set_item_material)),
|
||||
},
|
||||
).execute()
|
||||
Data.load_constituents()
|
||||
elif product_data["type"] == "IfcMaterialLayerSet":
|
||||
edit_layer.Usecase(
|
||||
self.file,
|
||||
{
|
||||
"layer": self.file.by_id(self.material_set_item),
|
||||
"attributes": attributes,
|
||||
"material": self.file.by_id(int(obj.BIMObjectMaterialProperties.material_set_item_material)),
|
||||
},
|
||||
).execute()
|
||||
Data.load_layers()
|
||||
elif product_data["type"] == "IfcMaterialProfileSet":
|
||||
edit_profile.Usecase(
|
||||
self.file,
|
||||
{
|
||||
"profile": self.file.by_id(self.material_set_item),
|
||||
"attributes": attributes,
|
||||
"material": self.file.by_id(int(obj.BIMObjectMaterialProperties.material_set_item_material)),
|
||||
},
|
||||
).execute()
|
||||
Data.load_profiles()
|
||||
else:
|
||||
pass
|
||||
|
||||
bpy.ops.bim.disable_editing_material_set_item(obj=obj.name)
|
||||
return {"FINISHED"}
|
||||
@@ -0,0 +1,54 @@
|
||||
import bpy
|
||||
import blenderbim.bim.schema # refactor
|
||||
from blenderbim.bim.module.material.data import Data
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
from blenderbim.bim.prop import StrProperty, Attribute
|
||||
from bpy.types import PropertyGroup
|
||||
from bpy.props import (
|
||||
PointerProperty,
|
||||
StringProperty,
|
||||
EnumProperty,
|
||||
BoolProperty,
|
||||
IntProperty,
|
||||
FloatProperty,
|
||||
FloatVectorProperty,
|
||||
CollectionProperty,
|
||||
)
|
||||
|
||||
materials_enum = []
|
||||
materialtypes_enum = []
|
||||
|
||||
|
||||
def getMaterials(self, context):
|
||||
global materials_enum
|
||||
if len(materials_enum) == 0 and IfcStore.get_file():
|
||||
materials_enum.clear()
|
||||
materials_enum = [(str(m_id), m["Name"], "") for m_id, m in Data.materials.items()]
|
||||
return materials_enum
|
||||
|
||||
|
||||
def getMaterialTypes(self, context):
|
||||
global materialtypes_enum
|
||||
if len(materialtypes_enum) == 0 and IfcStore.get_file():
|
||||
material_types = [
|
||||
"IfcMaterial",
|
||||
"IfcMaterialConstituentSet",
|
||||
"IfcMaterialLayerSet",
|
||||
"IfcMaterialProfileSet",
|
||||
"IfcMaterialList",
|
||||
]
|
||||
if IfcStore.get_file().schema == "IFC2X3":
|
||||
material_types = ["IfcMaterial", "IfcMaterialLayerSet", "IfcMaterialList"]
|
||||
materialtypes_enum.clear()
|
||||
materialtypes_enum = [(m, m, "") for m in material_types]
|
||||
return materialtypes_enum
|
||||
|
||||
|
||||
class BIMObjectMaterialProperties(PropertyGroup):
|
||||
material_type: EnumProperty(items=getMaterialTypes, name="Material Type")
|
||||
material: EnumProperty(items=getMaterials, name="Material")
|
||||
is_editing: BoolProperty(name="Is Editing", default=False)
|
||||
material_set_attributes: CollectionProperty(name="Material Set Attributes", type=Attribute)
|
||||
active_material_set_item_id: IntProperty(name="Active Material Set ID")
|
||||
material_set_item_attributes: CollectionProperty(name="Material Set Item Attributes", type=Attribute)
|
||||
material_set_item_material: EnumProperty(items=getMaterials, name="Material")
|
||||
@@ -0,0 +1,12 @@
|
||||
import ifcopenshell
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, settings=None):
|
||||
self.file = file
|
||||
self.settings = {"constituent": None}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
self.file.remove(self.settings["constituent"])
|
||||
@@ -0,0 +1,12 @@
|
||||
import ifcopenshell
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, settings=None):
|
||||
self.file = file
|
||||
self.settings = {"layer": None}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
self.file.remove(self.settings["layer"])
|
||||
@@ -0,0 +1,13 @@
|
||||
import ifcopenshell
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, settings=None):
|
||||
self.file = file
|
||||
self.settings = {"material_list": None, "material": None}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
materials = [m for m in self.settings["material_list"].Materials if m != self.settings["material"]]
|
||||
self.settings["material_list"].Materials = materials
|
||||
@@ -0,0 +1,175 @@
|
||||
from bpy.types import Panel
|
||||
from blenderbim.bim.module.material.data import Data
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
|
||||
|
||||
class BIM_PT_object_material(Panel):
|
||||
bl_label = "IFC Object Material"
|
||||
bl_idname = "BIM_PT_object_material"
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "object"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return bool(context.active_object.BIMObjectProperties.ifc_definition_id)
|
||||
|
||||
def draw(self, context):
|
||||
self.file = IfcStore.get_file()
|
||||
self.oprops = context.active_object.BIMObjectProperties
|
||||
self.props = context.active_object.BIMObjectMaterialProperties
|
||||
if not Data.is_loaded:
|
||||
Data.load()
|
||||
if self.oprops.ifc_definition_id not in Data.products:
|
||||
Data.load(self.oprops.ifc_definition_id)
|
||||
self.product_data = Data.products[self.oprops.ifc_definition_id]
|
||||
|
||||
if self.product_data:
|
||||
if self.product_data["type"] == "IfcMaterialConstituentSet":
|
||||
self.material_set_data = Data.constituent_sets[self.product_data["id"]]
|
||||
self.set_items = self.material_set_data["MaterialConstituents"]
|
||||
self.set_data = Data.constituents
|
||||
self.set_item_name = "constituent"
|
||||
elif self.product_data["type"] == "IfcMaterialLayerSet":
|
||||
self.material_set_data = Data.layer_sets[self.product_data["id"]]
|
||||
self.set_items = self.material_set_data["MaterialLayers"]
|
||||
self.set_data = Data.layers
|
||||
self.set_item_name = "layer"
|
||||
elif self.product_data["type"] == "IfcMaterialProfileSet":
|
||||
self.material_set_data = Data.profile_sets[self.product_data["id"]]
|
||||
self.set_items = self.material_set_data["MaterialProfiles"]
|
||||
self.set_data = Data.profiles
|
||||
self.set_item_name = "profile"
|
||||
elif self.product_data["type"] == "IfcMaterialList":
|
||||
self.material_set_data = Data.lists[self.product_data["id"]]
|
||||
self.set_items = self.material_set_data["Materials"]
|
||||
self.set_item_name = "list_item"
|
||||
return self.draw_material_ui()
|
||||
|
||||
row = self.layout.row(align=True)
|
||||
row.prop(self.props, "material_type", text="")
|
||||
if self.props.material_type == "IfcMaterial" or self.props.material_type == "IfcMaterialList":
|
||||
row.prop(self.props, "material", text="")
|
||||
row.operator("bim.assign_material", icon="ADD", text="")
|
||||
|
||||
def draw_material_ui(self):
|
||||
row = self.layout.row(align=True)
|
||||
row.label(text=self.product_data["type"])
|
||||
|
||||
if self.props.is_editing:
|
||||
row.operator("bim.edit_assigned_material", icon="CHECKMARK", text="")
|
||||
row.operator("bim.disable_editing_assigned_material", icon="X", text="")
|
||||
else:
|
||||
row.operator("bim.enable_editing_assigned_material", icon="GREASEPENCIL", text="")
|
||||
row.operator("bim.unassign_material", icon="X", text="")
|
||||
|
||||
if self.product_data["type"] == "IfcMaterial":
|
||||
self.draw_single_ui()
|
||||
else:
|
||||
self.draw_set_ui()
|
||||
|
||||
def draw_single_ui(self):
|
||||
if self.props.is_editing:
|
||||
return self.draw_editable_single_ui()
|
||||
return self.draw_read_only_single_ui()
|
||||
|
||||
def draw_editable_single_ui(self):
|
||||
row = self.layout.row(align=True)
|
||||
row.prop(self.props, "material", text="")
|
||||
|
||||
def draw_read_only_single_ui(self):
|
||||
material = Data.materials[self.product_data["id"]]
|
||||
row = self.layout.row(align=True)
|
||||
row.label(text="Name")
|
||||
row.label(text=material["Name"])
|
||||
|
||||
def draw_set_ui(self):
|
||||
if self.props.is_editing:
|
||||
return self.draw_editable_set_ui()
|
||||
self.draw_read_only_set_ui()
|
||||
|
||||
def draw_editable_set_ui(self):
|
||||
for attribute in self.props.material_set_attributes:
|
||||
row = self.layout.row(align=True)
|
||||
row.prop(attribute, "string_value", text=attribute.name)
|
||||
row.prop(attribute, "is_null", icon="RADIOBUT_OFF" if attribute.is_null else "RADIOBUT_ON", text="")
|
||||
row = self.layout.row(align=True)
|
||||
row.prop(self.props, "material", text="")
|
||||
|
||||
op = row.operator(f"bim.add_{self.set_item_name}", icon="ADD", text="")
|
||||
setattr(op, f"{self.set_item_name}_set", self.product_data["id"])
|
||||
|
||||
total_items = len(self.set_items)
|
||||
for index, set_item_id in enumerate(self.set_items):
|
||||
if self.props.active_material_set_item_id == set_item_id:
|
||||
self.draw_editable_set_item_ui(set_item_id)
|
||||
else:
|
||||
self.draw_read_only_set_item_ui(set_item_id, is_first=index == 0, is_last=index == total_items - 1)
|
||||
|
||||
def draw_editable_set_item_ui(self, set_item_id):
|
||||
item = self.set_data[set_item_id]
|
||||
material = Data.materials[item["Material"]]
|
||||
|
||||
box = self.layout.box()
|
||||
row = box.row(align=True)
|
||||
row.prop(self.props, "material_set_item_material", icon="MATERIAL")
|
||||
op = row.operator("bim.edit_material_set_item", icon="CHECKMARK", text="")
|
||||
op.material_set_item = set_item_id
|
||||
row.operator("bim.disable_editing_material_set_item", icon="X", text="")
|
||||
|
||||
for attribute in self.props.material_set_item_attributes:
|
||||
row = box.row(align=True)
|
||||
if attribute.data_type == "string":
|
||||
row.prop(attribute, "string_value", text=attribute.name)
|
||||
elif attribute.data_type == "integer":
|
||||
row.prop(attribute, "int_value", text=attribute.name)
|
||||
elif attribute.data_type == "float":
|
||||
row.prop(attribute, "float_value", text=attribute.name)
|
||||
elif attribute.data_type == "boolean":
|
||||
row.prop(attribute, "bool_value", text=attribute.name)
|
||||
row.prop(attribute, "is_null", icon="RADIOBUT_OFF" if attribute.is_null else "RADIOBUT_ON", text="")
|
||||
|
||||
def draw_read_only_set_item_ui(self, set_item_id, is_first=False, is_last=False):
|
||||
if self.product_data["type"] == "IfcMaterialList":
|
||||
item = Data.materials[set_item_id]
|
||||
row = self.layout.row(align=True)
|
||||
row.label(text="IfcMaterial", icon="ALIGN_CENTER")
|
||||
row.label(text=item["Name"], icon="MATERIAL")
|
||||
else:
|
||||
item = self.set_data[set_item_id]
|
||||
row = self.layout.row(align=True)
|
||||
row.label(text=item.get("Name", "Unnamed"), icon="ALIGN_CENTER")
|
||||
row.label(text=Data.materials[item["Material"]]["Name"], icon="MATERIAL")
|
||||
|
||||
if not is_first:
|
||||
row.operator("bim.edit_attributes", icon="TRIA_UP", text="")
|
||||
if not is_last:
|
||||
row.operator("bim.edit_attributes", icon="TRIA_DOWN", text="")
|
||||
if not self.props.active_material_set_item_id and self.product_data["type"] != "IfcMaterialList":
|
||||
op = row.operator("bim.enable_editing_material_set_item", icon="GREASEPENCIL", text="")
|
||||
op.material_set_item = set_item_id
|
||||
op = row.operator(f"bim.remove_{self.set_item_name}", icon="X", text="")
|
||||
if self.product_data["type"] == "IfcMaterialList":
|
||||
setattr(op, "list_item_set", self.product_data["id"])
|
||||
setattr(op, self.set_item_name, item["id"])
|
||||
|
||||
def draw_read_only_set_ui(self):
|
||||
name_attr = "LayerSetName" if self.product_data["type"] == "IfcMaterialLayerSet" else "Name"
|
||||
row = self.layout.row(align=True)
|
||||
row.label(text=name_attr)
|
||||
row.label(text=self.material_set_data.get(name_attr, "Unnamed"))
|
||||
if hasattr(self.material_set_data, "Description") and self.material_set_data["Description"]:
|
||||
row = self.layout.row(align=True)
|
||||
row.label(text="Description")
|
||||
row.label(text=str(self.material_set_data["Description"]))
|
||||
|
||||
for item_id in self.set_items:
|
||||
if self.product_data["type"] == "IfcMaterialList":
|
||||
row = self.layout.row(align=True)
|
||||
row.label(text="IfcMaterial", icon="ALIGN_CENTER")
|
||||
row.label(text=Data.materials[item_id]["Name"], icon="MATERIAL")
|
||||
else:
|
||||
item = self.set_data[item_id]
|
||||
row = self.layout.row(align=True)
|
||||
row.label(text=item.get("Name", "Unnamed"), icon="ALIGN_CENTER")
|
||||
row.label(text=Data.materials[item["Material"]]["Name"], icon="MATERIAL")
|
||||
@@ -0,0 +1,14 @@
|
||||
import ifcopenshell
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, settings=None):
|
||||
self.file = file
|
||||
self.settings = {"product": None}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
for association in self.settings["product"].HasAssociations:
|
||||
if association.is_a("IfcRelAssociatesMaterial"):
|
||||
self.file.remove(association)
|
||||
@@ -40,7 +40,6 @@ propertysettemplates_enum = []
|
||||
classification_enum = []
|
||||
attributes_enum = []
|
||||
materialattributes_enum = []
|
||||
materialtypes_enum = []
|
||||
contexts_enum = []
|
||||
subcontexts_enum = []
|
||||
target_views_enum = []
|
||||
@@ -285,13 +284,6 @@ def getAttributeEnumValues(self, context):
|
||||
return [(e, e, "") for e in json.loads(self.enum_items)]
|
||||
|
||||
|
||||
def getProfileDef(self, context):
|
||||
global profiledef_enum
|
||||
if len(profiledef_enum) < 1:
|
||||
profiledef_enum.extend([(e, e, "") for e in getattr(schema.ifc, "IfcParameterizedProfileDef")])
|
||||
return profiledef_enum
|
||||
|
||||
|
||||
def getPersons(self, context):
|
||||
from blenderbim.bim.module.owner.data import Data
|
||||
if not Data.is_loaded:
|
||||
@@ -424,27 +416,6 @@ def getApplicableMaterialAttributes(self, context):
|
||||
return materialattributes_enum
|
||||
|
||||
|
||||
def refreshProfileAttributes(self, context):
|
||||
if not context.active_object:
|
||||
return
|
||||
props = context.active_object.BIMObjectProperties
|
||||
profile = props.material_set.material_profiles[props.material_set.active_material_profile_index]
|
||||
while len(profile.profile_attributes) > 0:
|
||||
profile.profile_attributes.remove(0)
|
||||
for attribute in schema.ifc.IfcParameterizedProfileDef[profile.profile]["attributes"]:
|
||||
profile_attribute = profile.profile_attributes.add()
|
||||
profile_attribute.name = attribute["name"]
|
||||
|
||||
|
||||
def getMaterialTypes(self, context):
|
||||
global materialtypes_enum
|
||||
materialtypes_enum.clear()
|
||||
materialtypes_enum = [
|
||||
(m, m, "") for m in ["None", "IfcMaterial", "IfcMaterialConstituentSet", "IfcMaterialLayerSet", "IfcMaterialProfileSet"]
|
||||
]
|
||||
return materialtypes_enum
|
||||
|
||||
|
||||
def getContexts(self, context):
|
||||
from blenderbim.bim.module.context.data import Data
|
||||
if not Data.is_loaded:
|
||||
@@ -511,64 +482,6 @@ class Attribute(PropertyGroup):
|
||||
enum_value: EnumProperty(items=getAttributeEnumValues, name="Value")
|
||||
|
||||
|
||||
class MaterialLayer(PropertyGroup):
|
||||
name: StringProperty(name="Name")
|
||||
material: PointerProperty(name="Material", type=bpy.types.Material)
|
||||
layer_thickness: FloatProperty(name="Layer Thickness")
|
||||
is_ventilated: EnumProperty(
|
||||
items=[
|
||||
("TRUE", "True", "Is an air gap and provides air exchange from the layer to outside air"),
|
||||
("FALSE", "False", "Is a solid material layer"),
|
||||
("UNKNOWN", "Unknown", "Is an air gap but does not provide air exchange or not known"),
|
||||
],
|
||||
name="Is Ventilated",
|
||||
default="FALSE",
|
||||
)
|
||||
description: StringProperty(name="Description")
|
||||
category: EnumProperty(
|
||||
items=[
|
||||
("None", "None", ""),
|
||||
("LoadBearing", "Load Bearing", ""),
|
||||
("Insulation", "Insulation", ""),
|
||||
("Finish", "Finish", ""),
|
||||
("Custom", "Custom", ""),
|
||||
],
|
||||
name="Category",
|
||||
default="None",
|
||||
)
|
||||
custom_category: StringProperty(name="Custom Category")
|
||||
priority: IntProperty(name="Priority")
|
||||
|
||||
|
||||
class MaterialConstituent(PropertyGroup):
|
||||
name: StringProperty(name="Name")
|
||||
description: StringProperty(name="Description")
|
||||
material: PointerProperty(name="Material", type=bpy.types.Material)
|
||||
fraction: FloatProperty(name="Fraction")
|
||||
category: StringProperty(name="Category")
|
||||
|
||||
|
||||
class MaterialProfile(PropertyGroup):
|
||||
name: StringProperty(name="Name")
|
||||
description: StringProperty(name="Description")
|
||||
material: PointerProperty(name="Material", type=bpy.types.Material)
|
||||
profile: EnumProperty(items=getProfileDef, name="Parameterized Profile Def", update=refreshProfileAttributes)
|
||||
profile_attributes: CollectionProperty(name="Profile Attributes", type=Attribute)
|
||||
priority: IntProperty(name="Priority")
|
||||
category: StringProperty(name="Category")
|
||||
|
||||
|
||||
class MaterialSet(PropertyGroup):
|
||||
name: StringProperty(name="Name")
|
||||
description: StringProperty(name="Description")
|
||||
active_material_layer_index: IntProperty(name="Active Material Layer Index")
|
||||
material_layers: CollectionProperty(name="Material Layers", type=MaterialLayer)
|
||||
active_material_constituent_index: IntProperty(name="Active Material Constituent Index")
|
||||
material_constituents: CollectionProperty(name="Material Constituents", type=MaterialConstituent)
|
||||
active_material_profile_index: IntProperty(name="Active Material Profile Index")
|
||||
material_profiles: CollectionProperty(name="Material Profiles", type=MaterialProfile)
|
||||
|
||||
|
||||
class Drawing(PropertyGroup):
|
||||
name: StringProperty(name="Name", update=updateDrawingName)
|
||||
camera: PointerProperty(name="Camera", type=bpy.types.Object)
|
||||
@@ -1227,7 +1140,7 @@ class BIMProperties(PropertyGroup):
|
||||
import_should_allow_non_element_aggregates: BoolProperty(name="Import Non-Element Aggregates", default=False)
|
||||
import_should_offset_model: BoolProperty(name="Import and Offset Model", default=False)
|
||||
import_model_offset_coordinates: StringProperty(name="Model Offset Coordinates", default="0,0,0")
|
||||
|
||||
|
||||
person: PointerProperty(type=Person)
|
||||
active_person_id: IntProperty(name="Active Person Id")
|
||||
organisation: PointerProperty(type=Organisation)
|
||||
@@ -1426,9 +1339,6 @@ class BIMObjectProperties(PropertyGroup):
|
||||
constraints: CollectionProperty(name="Constraints", type=Constraint)
|
||||
active_constraint_index: IntProperty(name="Active Constraint Index")
|
||||
classifications: CollectionProperty(name="Classifications", type=ClassificationReference)
|
||||
material_type: EnumProperty(items=getMaterialTypes, name="Material Type")
|
||||
material: PointerProperty(name="Material", type=bpy.types.Material)
|
||||
material_set: PointerProperty(name="Material Set", type=MaterialSet)
|
||||
has_boundary_condition: BoolProperty(name="Has Boundary Condition")
|
||||
boundary_condition: PointerProperty(name="Boundary Condition", type=BoundaryCondition)
|
||||
structural_member_connection: PointerProperty(name="Structural Member Connection", type=bpy.types.Object)
|
||||
|
||||
@@ -5,144 +5,6 @@ from bpy.types import Panel
|
||||
from bpy.props import StringProperty
|
||||
|
||||
|
||||
class BIM_PT_object_material(Panel):
|
||||
bl_label = "IFC Object Material"
|
||||
bl_idname = "BIM_PT_object_material"
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "object"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return context.active_object is not None and hasattr(context.active_object, "BIMObjectProperties")
|
||||
|
||||
def draw(self, context):
|
||||
if context.active_object is None:
|
||||
return
|
||||
layout = self.layout
|
||||
props = context.active_object.BIMObjectProperties
|
||||
row = layout.row()
|
||||
row.prop(props, "material_type")
|
||||
|
||||
if props.material_type == "None" and props.relating_type:
|
||||
props = props.relating_type.BIMObjectProperties
|
||||
if props.material_type == "None":
|
||||
pass
|
||||
elif props.material_type == "IfcMaterial" and props.material:
|
||||
layout.label(text="Inherited Material:")
|
||||
elif props.material_set:
|
||||
layout.label(text="Inherited Material Set:")
|
||||
|
||||
if props.material_type == "None":
|
||||
pass
|
||||
elif props.material_type == "IfcMaterial":
|
||||
row = layout.row()
|
||||
row.prop(props, "material")
|
||||
else:
|
||||
set_props = props.material_set
|
||||
row = layout.row()
|
||||
row.prop(set_props, "name", text="Name")
|
||||
row = layout.row()
|
||||
row.prop(set_props, "description", text="Description")
|
||||
row = layout.row()
|
||||
|
||||
if props.material_type == "IfcMaterialLayerSet":
|
||||
row.template_list(
|
||||
"MATERIAL_UL_matslots", "", set_props, "material_layers", set_props, "active_material_layer_index"
|
||||
)
|
||||
col = row.column(align=True)
|
||||
col.operator("bim.add_material_layer", icon="ADD", text="")
|
||||
col.operator(
|
||||
"bim.remove_material_layer", icon="REMOVE", text=""
|
||||
).index = set_props.active_material_layer_index
|
||||
col.operator("bim.move_material_layer", icon="TRIA_UP", text="").direction = "UP"
|
||||
col.operator("bim.move_material_layer", icon="TRIA_DOWN", text="").direction = "DOWN"
|
||||
|
||||
if set_props.active_material_layer_index < len(set_props.material_layers):
|
||||
material = set_props.material_layers[set_props.active_material_layer_index]
|
||||
row = layout.row()
|
||||
row.prop(material, "material")
|
||||
row = layout.row()
|
||||
row.prop(material, "name")
|
||||
row = layout.row()
|
||||
row.prop(material, "description")
|
||||
row = layout.row()
|
||||
row.prop(material, "category")
|
||||
if material.category == "Custom":
|
||||
row = layout.row()
|
||||
row.prop(material, "custom_category")
|
||||
row = layout.row()
|
||||
row.prop(material, "layer_thickness")
|
||||
row = layout.row()
|
||||
row.prop(material, "is_ventilated")
|
||||
row = layout.row()
|
||||
row.prop(material, "priority")
|
||||
elif props.material_type == "IfcMaterialConstituentSet":
|
||||
row.template_list(
|
||||
"MATERIAL_UL_matslots",
|
||||
"",
|
||||
set_props,
|
||||
"material_constituents",
|
||||
set_props,
|
||||
"active_material_constituent_index",
|
||||
)
|
||||
col = row.column(align=True)
|
||||
col.operator("bim.add_material_constituent", icon="ADD", text="")
|
||||
col.operator(
|
||||
"bim.remove_material_constituent", icon="REMOVE", text=""
|
||||
).index = set_props.active_material_constituent_index
|
||||
col.operator("bim.move_material_constituent", icon="TRIA_UP", text="").direction = "UP"
|
||||
col.operator("bim.move_material_constituent", icon="TRIA_DOWN", text="").direction = "DOWN"
|
||||
|
||||
if set_props.active_material_constituent_index < len(set_props.material_constituents):
|
||||
material = set_props.material_constituents[set_props.active_material_constituent_index]
|
||||
row = layout.row()
|
||||
row.prop(material, "material")
|
||||
row = layout.row()
|
||||
row.prop(material, "name")
|
||||
row = layout.row()
|
||||
row.prop(material, "description")
|
||||
row = layout.row()
|
||||
row.prop(material, "fraction")
|
||||
row = layout.row()
|
||||
row.prop(material, "category")
|
||||
elif props.material_type == "IfcMaterialProfileSet":
|
||||
row.template_list(
|
||||
"MATERIAL_UL_matslots",
|
||||
"",
|
||||
set_props,
|
||||
"material_profiles",
|
||||
set_props,
|
||||
"active_material_profile_index",
|
||||
)
|
||||
col = row.column(align=True)
|
||||
col.operator("bim.add_material_profile", icon="ADD", text="")
|
||||
col.operator(
|
||||
"bim.remove_material_profile", icon="REMOVE", text=""
|
||||
).index = set_props.active_material_profile_index
|
||||
col.operator("bim.move_material_profile", icon="TRIA_UP", text="").direction = "UP"
|
||||
col.operator("bim.move_material_profile", icon="TRIA_DOWN", text="").direction = "DOWN"
|
||||
|
||||
if set_props.active_material_profile_index < len(set_props.material_profiles):
|
||||
material = set_props.material_profiles[set_props.active_material_profile_index]
|
||||
row = layout.row()
|
||||
row.prop(material, "material")
|
||||
row = layout.row()
|
||||
row.prop(material, "name")
|
||||
row = layout.row()
|
||||
row.prop(material, "description")
|
||||
row = layout.row()
|
||||
row.prop(material, "priority")
|
||||
row = layout.row()
|
||||
row.prop(material, "category")
|
||||
row = layout.row()
|
||||
row.prop(material, "profile")
|
||||
for index, attribute in enumerate(material.profile_attributes):
|
||||
row = layout.row(align=True)
|
||||
row.prop(attribute, "name", text="")
|
||||
row.prop(attribute, "string_value", text="")
|
||||
|
||||
|
||||
class BIM_PT_object_structural(Panel):
|
||||
bl_label = "IFC Structural Relationships"
|
||||
bl_idname = "BIM_PT_object_structural"
|
||||
|
||||
Reference in New Issue
Block a user