mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-21 14:23:53 +00:00
support assigning existing non-ifcmaterials materials
Example - https://imgur.com/a/KN8mQPL Also added some description to material operators (https://imgur.com/a/eIVNEdU). Need to somehow emphasize that this UI is only for IfcMaterials and cannot be used to assign existing layer sets, profile sets, etc...
This commit is contained in:
@@ -28,6 +28,7 @@ classes = (
|
|||||||
operator.AddMaterialSet,
|
operator.AddMaterialSet,
|
||||||
operator.AddProfile,
|
operator.AddProfile,
|
||||||
operator.AssignMaterial,
|
operator.AssignMaterial,
|
||||||
|
operator.AssignMaterialToSelected,
|
||||||
operator.AssignParameterizedProfile,
|
operator.AssignParameterizedProfile,
|
||||||
operator.ContractMaterialCategory,
|
operator.ContractMaterialCategory,
|
||||||
operator.DisableEditingAssignedMaterial,
|
operator.DisableEditingAssignedMaterial,
|
||||||
|
|||||||
@@ -117,6 +117,7 @@ class AssignParameterizedProfile(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
class AddMaterial(bpy.types.Operator, tool.Ifc.Operator):
|
class AddMaterial(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
bl_idname = "bim.add_material"
|
bl_idname = "bim.add_material"
|
||||||
bl_label = "Add Material"
|
bl_label = "Add Material"
|
||||||
|
bl_description = "Create a new IfcMaterial"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
name: bpy.props.StringProperty(default="Default")
|
name: bpy.props.StringProperty(default="Default")
|
||||||
category: bpy.props.StringProperty(default="")
|
category: bpy.props.StringProperty(default="")
|
||||||
@@ -185,6 +186,32 @@ class RemoveMaterialSet(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
core.remove_material_set(tool.Ifc, tool.Material, material=tool.Ifc.get().by_id(self.material))
|
core.remove_material_set(tool.Ifc, tool.Material, material=tool.Ifc.get().by_id(self.material))
|
||||||
|
|
||||||
|
|
||||||
|
class AssignMaterialToSelected(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
|
bl_idname = "bim.assign_material_to_selected"
|
||||||
|
bl_label = "Assign Material To Selected"
|
||||||
|
bl_description = "Assign currently selected material in Materials UI to the selected objects"
|
||||||
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
material: bpy.props.IntProperty(name="Material IFC ID")
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def poll(cls, context):
|
||||||
|
if not context.selected_objects:
|
||||||
|
cls.poll_message_set("No objects selected")
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def _execute(self, context):
|
||||||
|
material = tool.Ifc.get().by_id(self.material)
|
||||||
|
objects = tool.Blender.get_selected_objects()
|
||||||
|
core.assign_material(
|
||||||
|
tool.Ifc,
|
||||||
|
tool.Material,
|
||||||
|
material_type=tool.Material.get_active_material_type(),
|
||||||
|
objects=objects,
|
||||||
|
material=material,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class AssignMaterial(bpy.types.Operator, tool.Ifc.Operator):
|
class AssignMaterial(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
bl_idname = "bim.assign_material"
|
bl_idname = "bim.assign_material"
|
||||||
bl_label = "Assign Material"
|
bl_label = "Assign Material"
|
||||||
@@ -192,6 +219,18 @@ class AssignMaterial(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
obj: bpy.props.StringProperty()
|
obj: bpy.props.StringProperty()
|
||||||
material_type: bpy.props.StringProperty()
|
material_type: bpy.props.StringProperty()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def description(cls, context, properties):
|
||||||
|
if not (material_type := properties.material_type):
|
||||||
|
if not (obj := context.active_object):
|
||||||
|
return ""
|
||||||
|
material_type = obj.BIMObjectMaterialProperties.material_type
|
||||||
|
|
||||||
|
description = "Assign current IfcMaterial to the selected objects"
|
||||||
|
if material_type != "IfcMaterial":
|
||||||
|
description += f" as part of a new {material_type}"
|
||||||
|
return description
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
objects = [bpy.data.objects.get(self.obj)] if self.obj else tool.Blender.get_selected_objects()
|
objects = [bpy.data.objects.get(self.obj)] if self.obj else tool.Blender.get_selected_objects()
|
||||||
core.assign_material(tool.Ifc, tool.Material, material_type=self.material_type, objects=objects)
|
core.assign_material(tool.Ifc, tool.Material, material_type=self.material_type, objects=objects)
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ class BIMMaterialProperties(PropertyGroup):
|
|||||||
|
|
||||||
class BIMObjectMaterialProperties(PropertyGroup):
|
class BIMObjectMaterialProperties(PropertyGroup):
|
||||||
material_type: EnumProperty(items=get_object_material_type, 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", description="Currently selected IfcMaterial")
|
||||||
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)
|
||||||
material_set_attributes: CollectionProperty(name="Material Set Attributes", type=Attribute)
|
material_set_attributes: CollectionProperty(name="Material Set Attributes", type=Attribute)
|
||||||
|
|||||||
@@ -67,6 +67,8 @@ class BIM_PT_materials(Panel):
|
|||||||
op.material = material.ifc_definition_id
|
op.material = material.ifc_definition_id
|
||||||
op = row.operator("bim.select_by_material", text="", icon="RESTRICT_SELECT_OFF")
|
op = row.operator("bim.select_by_material", text="", icon="RESTRICT_SELECT_OFF")
|
||||||
op.material = material.ifc_definition_id
|
op.material = material.ifc_definition_id
|
||||||
|
op = row.operator("bim.assign_material_to_selected", text="", icon="BRUSH_DATA")
|
||||||
|
op.material = material.ifc_definition_id
|
||||||
op = row.operator("bim.enable_editing_material", text="", icon="GREASEPENCIL")
|
op = row.operator("bim.enable_editing_material", text="", icon="GREASEPENCIL")
|
||||||
op.material = material.ifc_definition_id
|
op.material = material.ifc_definition_id
|
||||||
op = row.operator("bim.enable_editing_material_style", text="", icon="SHADING_RENDERED")
|
op = row.operator("bim.enable_editing_material_style", text="", icon="SHADING_RENDERED")
|
||||||
@@ -81,6 +83,8 @@ class BIM_PT_materials(Panel):
|
|||||||
if material.ifc_definition_id:
|
if material.ifc_definition_id:
|
||||||
op = row.operator("bim.select_by_material", text="", icon="RESTRICT_SELECT_OFF")
|
op = row.operator("bim.select_by_material", text="", icon="RESTRICT_SELECT_OFF")
|
||||||
op.material = material.ifc_definition_id
|
op.material = material.ifc_definition_id
|
||||||
|
op = row.operator("bim.assign_material_to_selected", text="", icon="BRUSH_DATA")
|
||||||
|
op.material = material.ifc_definition_id
|
||||||
row.operator("bim.remove_material_set", text="", icon="X").material = material.ifc_definition_id
|
row.operator("bim.remove_material_set", text="", icon="X").material = material.ifc_definition_id
|
||||||
|
|
||||||
self.layout.template_list("BIM_UL_materials", "", self.props, "materials", self.props, "active_material_index")
|
self.layout.template_list("BIM_UL_materials", "", self.props, "materials", self.props, "active_material_index")
|
||||||
|
|||||||
@@ -99,17 +99,33 @@ def disable_editing_material(material_tool: tool.Material) -> None:
|
|||||||
|
|
||||||
|
|
||||||
def assign_material(
|
def assign_material(
|
||||||
ifc: tool.Ifc, material_tool: tool.Material, material_type: Union[str, None], objects: list[bpy.types.Object]
|
ifc: tool.Ifc,
|
||||||
|
material_tool: tool.Material,
|
||||||
|
material_type: Union[str, None],
|
||||||
|
objects: list[bpy.types.Object],
|
||||||
|
material: Optional[ifcopenshell.entity_instance] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
material_type = material_type or material_tool.get_active_object_material()
|
"""Assign material to the provided objects.
|
||||||
material = material_tool.get_active_material()
|
|
||||||
|
If `material_type` or `material` are not provided, the active ones from
|
||||||
|
Object Materials UI is used.
|
||||||
|
"""
|
||||||
|
material_type = material_type or material_tool.get_object_ui_material_type()
|
||||||
|
material = material or material_tool.get_object_ui_active_material()
|
||||||
for obj in objects:
|
for obj in objects:
|
||||||
element = ifc.get_entity(obj)
|
element = ifc.get_entity(obj)
|
||||||
if not element:
|
if not element:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
ifc.run("material.assign_material", products=[element], type=material_type, material=material)
|
ifc.run("material.assign_material", products=[element], type=material_type, material=material)
|
||||||
assigned_material = material_tool.get_material(element)
|
assigned_material = material_tool.get_material(element)
|
||||||
if material_tool.is_a_material_set(assigned_material):
|
assert assigned_material # Type checker.
|
||||||
|
|
||||||
|
if material_tool.is_a_material_set(material):
|
||||||
|
# Ensure set is a valid IFC.
|
||||||
|
default_material = material_tool.get_default_material()
|
||||||
|
material_tool.add_material_to_set(material_set=material, material=default_material)
|
||||||
|
elif material_tool.is_a_material_set(assigned_material):
|
||||||
material_tool.add_material_to_set(material_set=assigned_material, material=material)
|
material_tool.add_material_to_set(material_set=assigned_material, material=material)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -493,7 +493,7 @@ class Material:
|
|||||||
def enable_editing_materials(cls): pass
|
def enable_editing_materials(cls): pass
|
||||||
def get_active_material(cls): pass
|
def get_active_material(cls): pass
|
||||||
def get_active_material_type(cls): pass
|
def get_active_material_type(cls): pass
|
||||||
def get_active_object_material(cls, obj): pass
|
def get_active_object_material_type(cls, obj): pass
|
||||||
def get_elements_by_material(cls, material): pass
|
def get_elements_by_material(cls, material): pass
|
||||||
def get_material(cls, element, should_inherit): pass
|
def get_material(cls, element, should_inherit): pass
|
||||||
def get_material_attributes(cls): pass
|
def get_material_attributes(cls): pass
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
import bpy
|
import bpy
|
||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
|
import ifcopenshell.api.material
|
||||||
import blenderbim.core.tool
|
import blenderbim.core.tool
|
||||||
import blenderbim.core.material
|
import blenderbim.core.material
|
||||||
import blenderbim.tool as tool
|
import blenderbim.tool as tool
|
||||||
@@ -165,19 +166,27 @@ class Material(blenderbim.core.tool.Material):
|
|||||||
props.active_material_id = 0
|
props.active_material_id = 0
|
||||||
props.editing_material_type = ""
|
props.editing_material_type = ""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_default_material(cls) -> ifcopenshell.entity_instance:
|
||||||
|
"""Return first found IfcMaterial in IFC file or create a new default material."""
|
||||||
|
ifc_file = tool.Ifc.get()
|
||||||
|
material = next(iter(ifc_file.by_type("IfcMaterial")), None)
|
||||||
|
if material:
|
||||||
|
return material
|
||||||
|
material = ifcopenshell.api.material.add_material(ifc_file, name="Default")
|
||||||
|
return material
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_type(cls, element: ifcopenshell.entity_instance) -> Union[ifcopenshell.entity_instance, None]:
|
def get_type(cls, element: ifcopenshell.entity_instance) -> Union[ifcopenshell.entity_instance, None]:
|
||||||
return ifcopenshell.util.element.get_type(element)
|
return ifcopenshell.util.element.get_type(element)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_active_object_material(cls) -> Union[str, None]:
|
def get_object_ui_material_type(cls) -> str:
|
||||||
active_obj = bpy.context.active_object
|
active_obj = bpy.context.active_object
|
||||||
if not active_obj:
|
|
||||||
return
|
|
||||||
return active_obj.BIMObjectMaterialProperties.material_type
|
return active_obj.BIMObjectMaterialProperties.material_type
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_active_material(cls) -> ifcopenshell.entity_instance:
|
def get_object_ui_active_material(cls) -> ifcopenshell.entity_instance:
|
||||||
return tool.Ifc.get().by_id(int(bpy.context.active_object.BIMObjectMaterialProperties.material))
|
return tool.Ifc.get().by_id(int(bpy.context.active_object.BIMObjectMaterialProperties.material))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|||||||
Reference in New Issue
Block a user