2021-01-17 12:46:35 +11:00
|
|
|
from bpy.types import Panel
|
2021-03-25 10:48:31 +11:00
|
|
|
from ifcopenshell.api.material.data import Data
|
2021-04-08 21:03:37 +10:00
|
|
|
from ifcopenshell.api.profile.data import Data as ProfileData
|
2021-01-17 12:46:35 +11:00
|
|
|
from blenderbim.bim.ifc import IfcStore
|
|
|
|
|
|
|
|
|
|
|
2021-01-26 11:45:58 +11:00
|
|
|
class BIM_PT_material(Panel):
|
|
|
|
|
bl_label = "IFC Material"
|
|
|
|
|
bl_idname = "BIM_PT_material"
|
|
|
|
|
bl_space_type = "PROPERTIES"
|
|
|
|
|
bl_region_type = "WINDOW"
|
|
|
|
|
bl_context = "material"
|
|
|
|
|
|
2021-03-08 12:11:29 +11:00
|
|
|
@classmethod
|
|
|
|
|
def poll(cls, context):
|
2021-03-08 16:19:26 +11:00
|
|
|
return IfcStore.get_file() and context.active_object and context.active_object.active_material
|
2021-03-08 12:11:29 +11:00
|
|
|
|
2021-01-26 11:45:58 +11:00
|
|
|
def draw(self, context):
|
|
|
|
|
row = self.layout.row()
|
|
|
|
|
if bool(context.active_object.active_material.BIMObjectProperties.ifc_definition_id):
|
|
|
|
|
row.operator("bim.remove_material", icon="X", text="Remove IFC Material")
|
|
|
|
|
else:
|
|
|
|
|
row.operator("bim.add_material", icon="ADD", text="Create IFC Material")
|
|
|
|
|
|
|
|
|
|
|
2021-01-17 12:46:35 +11:00
|
|
|
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):
|
2021-01-26 21:28:54 +11:00
|
|
|
props = context.active_object.BIMObjectProperties
|
|
|
|
|
if not props.ifc_definition_id:
|
|
|
|
|
return False
|
|
|
|
|
if not hasattr(IfcStore.get_file().by_id(props.ifc_definition_id), "HasAssociations"):
|
|
|
|
|
return False
|
|
|
|
|
return True
|
2021-01-17 12:46:35 +11:00
|
|
|
|
|
|
|
|
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:
|
2021-03-25 10:48:31 +11:00
|
|
|
Data.load(IfcStore.get_file())
|
2021-01-17 12:46:35 +11:00
|
|
|
if self.oprops.ifc_definition_id not in Data.products:
|
2021-03-25 10:48:31 +11:00
|
|
|
Data.load(IfcStore.get_file(), self.oprops.ifc_definition_id)
|
2021-04-08 21:03:37 +10:00
|
|
|
if not ProfileData.is_loaded:
|
|
|
|
|
ProfileData.load(self.file)
|
2021-01-17 12:46:35 +11:00
|
|
|
self.product_data = Data.products[self.oprops.ifc_definition_id]
|
|
|
|
|
|
2021-01-26 20:01:16 +11:00
|
|
|
if not Data.materials:
|
|
|
|
|
row = self.layout.row()
|
|
|
|
|
row.label(text="No Materials Available")
|
|
|
|
|
return
|
|
|
|
|
|
2021-01-17 12:46:35 +11:00
|
|
|
if self.product_data:
|
|
|
|
|
if self.product_data["type"] == "IfcMaterialConstituentSet":
|
2021-03-05 18:27:19 +11:00
|
|
|
self.material_set_id = self.product_data["id"]
|
|
|
|
|
self.material_set_data = Data.constituent_sets[self.material_set_id]
|
2021-03-08 08:40:56 +11:00
|
|
|
self.set_items = self.material_set_data["MaterialConstituents"] or []
|
2021-01-17 12:46:35 +11:00
|
|
|
self.set_data = Data.constituents
|
|
|
|
|
self.set_item_name = "constituent"
|
|
|
|
|
elif self.product_data["type"] == "IfcMaterialLayerSet":
|
2021-03-05 18:27:19 +11:00
|
|
|
self.material_set_id = self.product_data["id"]
|
|
|
|
|
self.material_set_data = Data.layer_sets[self.material_set_id]
|
2021-03-08 08:40:56 +11:00
|
|
|
self.set_items = self.material_set_data["MaterialLayers"] or []
|
2021-03-05 18:27:19 +11:00
|
|
|
self.set_data = Data.layers
|
|
|
|
|
self.set_item_name = "layer"
|
|
|
|
|
elif self.product_data["type"] == "IfcMaterialLayerSetUsage":
|
|
|
|
|
self.material_set_usage = Data.layer_set_usages[self.product_data["id"]]
|
|
|
|
|
self.material_set_id = self.material_set_usage["ForLayerSet"]
|
|
|
|
|
self.material_set_data = Data.layer_sets[self.material_set_id]
|
2021-03-08 08:40:56 +11:00
|
|
|
self.set_items = self.material_set_data["MaterialLayers"] or []
|
2021-01-17 12:46:35 +11:00
|
|
|
self.set_data = Data.layers
|
|
|
|
|
self.set_item_name = "layer"
|
|
|
|
|
elif self.product_data["type"] == "IfcMaterialProfileSet":
|
2021-03-05 18:27:19 +11:00
|
|
|
self.material_set_id = self.product_data["id"]
|
|
|
|
|
self.material_set_data = Data.profile_sets[self.material_set_id]
|
2021-03-08 08:40:56 +11:00
|
|
|
self.set_items = self.material_set_data["MaterialProfiles"] or []
|
2021-04-15 18:38:28 +10:00
|
|
|
self.set_data = Data.profiles
|
|
|
|
|
self.set_item_name = "profile"
|
|
|
|
|
elif self.product_data["type"] == "IfcMaterialProfileSetUsage":
|
|
|
|
|
self.material_set_usage = Data.profile_set_usages[self.product_data["id"]]
|
|
|
|
|
self.material_set_id = self.material_set_usage["ForProfileSet"]
|
|
|
|
|
self.material_set_data = Data.profile_sets[self.material_set_id]
|
|
|
|
|
self.set_items = self.material_set_data["MaterialProfiles"] or []
|
2021-01-17 12:46:35 +11:00
|
|
|
self.set_data = Data.profiles
|
|
|
|
|
self.set_item_name = "profile"
|
|
|
|
|
elif self.product_data["type"] == "IfcMaterialList":
|
2021-03-05 18:27:19 +11:00
|
|
|
self.material_set_id = self.product_data["id"]
|
|
|
|
|
self.material_set_data = Data.lists[self.material_set_id]
|
2021-03-08 08:40:56 +11:00
|
|
|
self.set_items = self.material_set_data["Materials"] or []
|
2021-01-17 12:46:35 +11:00
|
|
|
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:
|
2021-03-05 18:27:19 +11:00
|
|
|
op = row.operator("bim.edit_assigned_material", icon="CHECKMARK", text="")
|
|
|
|
|
op.material_set = self.material_set_id
|
2021-05-19 17:59:13 +10:00
|
|
|
row.operator("bim.disable_editing_assigned_material", icon="CANCEL", text="")
|
2021-01-17 12:46:35 +11:00
|
|
|
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="")
|
2021-03-05 18:27:19 +11:00
|
|
|
setattr(op, f"{self.set_item_name}_set", self.material_set_id)
|
2021-01-17 12:46:35 +11:00
|
|
|
|
|
|
|
|
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:
|
2021-03-08 14:20:43 +11:00
|
|
|
self.draw_read_only_set_item_ui(
|
|
|
|
|
set_item_id, index, is_first=index == 0, is_last=index == total_items - 1
|
|
|
|
|
)
|
2021-01-17 12:46:35 +11:00
|
|
|
|
|
|
|
|
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
|
2021-05-19 17:59:13 +10:00
|
|
|
row.operator("bim.disable_editing_material_set_item", icon="CANCEL", text="")
|
2021-01-17 12:46:35 +11:00
|
|
|
|
|
|
|
|
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="")
|
|
|
|
|
|
2021-04-08 21:03:37 +10:00
|
|
|
if self.set_item_name == "profile":
|
|
|
|
|
self.draw_assign_profile_ui(box, item)
|
|
|
|
|
self.draw_editable_profile_ui(box, item)
|
|
|
|
|
|
|
|
|
|
def draw_assign_profile_ui(self, layout, item):
|
|
|
|
|
row = layout.row(align=True)
|
|
|
|
|
row.prop(self.props, "profile_classes", text="")
|
|
|
|
|
if self.props.profile_classes == "IfcParameterizedProfileDef":
|
|
|
|
|
row.prop(self.props, "parameterized_profile_classes", text="")
|
|
|
|
|
op = row.operator("bim.assign_parameterized_profile", icon="GREASEPENCIL" if item["Profile"] else "ADD", text="")
|
|
|
|
|
op.ifc_class = self.props.parameterized_profile_classes
|
|
|
|
|
op.material_profile = item["id"]
|
|
|
|
|
else:
|
|
|
|
|
# TODO: support non parametric profiles by showing a list of named profiles to select from, or an
|
|
|
|
|
# eyedropper to pick profile geometry from the scene
|
2021-05-19 17:59:13 +10:00
|
|
|
row.operator("bim.disable_editing_material_set_item", icon="CANCEL", text="")
|
2021-04-08 21:03:37 +10:00
|
|
|
|
|
|
|
|
def draw_editable_profile_ui(self, layout, item):
|
|
|
|
|
for attribute in self.props.material_set_item_profile_attributes:
|
|
|
|
|
row = layout.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)
|
|
|
|
|
elif attribute.data_type == "enum":
|
|
|
|
|
row.prop(attribute, "enum_value", text=attribute.name)
|
|
|
|
|
if attribute.is_optional:
|
|
|
|
|
row.prop(attribute, "is_null", icon="RADIOBUT_OFF" if attribute.is_null else "RADIOBUT_ON", text="")
|
|
|
|
|
|
2021-03-08 14:20:43 +11:00
|
|
|
def draw_read_only_set_item_ui(self, set_item_id, index, is_first=False, is_last=False):
|
2021-01-17 12:46:35 +11:00
|
|
|
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)
|
2021-03-08 08:40:56 +11:00
|
|
|
row.label(text=item.get("Name", "Unnamed") or "Unnamed", icon="ALIGN_CENTER")
|
2021-01-17 12:46:35 +11:00
|
|
|
row.label(text=Data.materials[item["Material"]]["Name"], icon="MATERIAL")
|
|
|
|
|
|
|
|
|
|
if not is_first:
|
2021-03-08 16:19:26 +11:00
|
|
|
op = row.operator(f"bim.reorder_material_set_item", icon="TRIA_UP", text="")
|
2021-03-08 14:20:43 +11:00
|
|
|
op.old_index = index
|
|
|
|
|
op.new_index = index - 1
|
2021-03-08 16:19:26 +11:00
|
|
|
setattr(op, "material_set", self.material_set_id)
|
2021-01-17 12:46:35 +11:00
|
|
|
if not is_last:
|
2021-03-08 16:19:26 +11:00
|
|
|
op = row.operator(f"bim.reorder_material_set_item", icon="TRIA_DOWN", text="")
|
2021-03-08 14:20:43 +11:00
|
|
|
op.old_index = index
|
|
|
|
|
op.new_index = index + 1
|
2021-03-08 16:19:26 +11:00
|
|
|
setattr(op, "material_set", self.material_set_id)
|
2021-01-17 12:46:35 +11:00
|
|
|
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":
|
2021-03-05 18:27:19 +11:00
|
|
|
setattr(op, "list_item_set", self.material_set_id)
|
2021-01-17 12:46:35 +11:00
|
|
|
setattr(op, self.set_item_name, item["id"])
|
|
|
|
|
|
|
|
|
|
def draw_read_only_set_ui(self):
|
2021-03-05 18:27:19 +11:00
|
|
|
if (
|
|
|
|
|
self.product_data["type"] == "IfcMaterialLayerSetUsage"
|
|
|
|
|
or self.product_data["type"] == "IfcMaterialLayerSet"
|
|
|
|
|
):
|
|
|
|
|
name_attr = "LayerSetName"
|
|
|
|
|
else:
|
|
|
|
|
name_attr = "Name"
|
2021-01-17 12:46:35 +11:00
|
|
|
row = self.layout.row(align=True)
|
|
|
|
|
row.label(text=name_attr)
|
2021-03-08 08:40:56 +11:00
|
|
|
row.label(text=self.material_set_data.get(name_attr, "Unnamed") or "Unnamed")
|
2021-01-17 12:46:35 +11:00
|
|
|
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)
|
2021-03-08 08:40:56 +11:00
|
|
|
row.label(text=item.get("Name", "Unnamed") or "Unnamed", icon="ALIGN_CENTER")
|
2021-01-17 12:46:35 +11:00
|
|
|
row.label(text=Data.materials[item["Material"]]["Name"], icon="MATERIAL")
|