mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 17:31:45 +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.AddProfile,
|
||||
operator.AssignMaterial,
|
||||
operator.AssignMaterialToSelected,
|
||||
operator.AssignParameterizedProfile,
|
||||
operator.ContractMaterialCategory,
|
||||
operator.DisableEditingAssignedMaterial,
|
||||
|
||||
@@ -117,6 +117,7 @@ class AssignParameterizedProfile(bpy.types.Operator, tool.Ifc.Operator):
|
||||
class AddMaterial(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.add_material"
|
||||
bl_label = "Add Material"
|
||||
bl_description = "Create a new IfcMaterial"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
name: bpy.props.StringProperty(default="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))
|
||||
|
||||
|
||||
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):
|
||||
bl_idname = "bim.assign_material"
|
||||
bl_label = "Assign Material"
|
||||
@@ -192,6 +219,18 @@ class AssignMaterial(bpy.types.Operator, tool.Ifc.Operator):
|
||||
obj: 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):
|
||||
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)
|
||||
|
||||
@@ -143,7 +143,7 @@ class BIMMaterialProperties(PropertyGroup):
|
||||
|
||||
class BIMObjectMaterialProperties(PropertyGroup):
|
||||
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)
|
||||
material_set_usage_attributes: CollectionProperty(name="Material Set Usage 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 = row.operator("bim.select_by_material", text="", icon="RESTRICT_SELECT_OFF")
|
||||
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.material = material.ifc_definition_id
|
||||
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:
|
||||
op = row.operator("bim.select_by_material", text="", icon="RESTRICT_SELECT_OFF")
|
||||
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
|
||||
|
||||
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(
|
||||
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:
|
||||
material_type = material_type or material_tool.get_active_object_material()
|
||||
material = material_tool.get_active_material()
|
||||
"""Assign material to the provided objects.
|
||||
|
||||
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:
|
||||
element = ifc.get_entity(obj)
|
||||
if not element:
|
||||
continue
|
||||
|
||||
ifc.run("material.assign_material", products=[element], type=material_type, material=material)
|
||||
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)
|
||||
|
||||
|
||||
|
||||
@@ -493,7 +493,7 @@ class Material:
|
||||
def enable_editing_materials(cls): pass
|
||||
def get_active_material(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_material(cls, element, should_inherit): pass
|
||||
def get_material_attributes(cls): pass
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
from __future__ import annotations
|
||||
import bpy
|
||||
import ifcopenshell
|
||||
import ifcopenshell.api.material
|
||||
import blenderbim.core.tool
|
||||
import blenderbim.core.material
|
||||
import blenderbim.tool as tool
|
||||
@@ -165,19 +166,27 @@ class Material(blenderbim.core.tool.Material):
|
||||
props.active_material_id = 0
|
||||
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
|
||||
def get_type(cls, element: ifcopenshell.entity_instance) -> Union[ifcopenshell.entity_instance, None]:
|
||||
return ifcopenshell.util.element.get_type(element)
|
||||
|
||||
@classmethod
|
||||
def get_active_object_material(cls) -> Union[str, None]:
|
||||
def get_object_ui_material_type(cls) -> str:
|
||||
active_obj = bpy.context.active_object
|
||||
if not active_obj:
|
||||
return
|
||||
return active_obj.BIMObjectMaterialProperties.material_type
|
||||
|
||||
@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))
|
||||
|
||||
@classmethod
|
||||
|
||||
Reference in New Issue
Block a user