mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-10-02 21:12:07 +00:00
Fix #2599. Unassigning materials now also removes the Blender material.
This commit is contained in:
@@ -142,26 +142,20 @@ class AssignMaterial(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
material_type: bpy.props.StringProperty()
|
material_type: bpy.props.StringProperty()
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
self.file = IfcStore.get_file()
|
objects = [bpy.data.objects.get(self.obj)] if self.obj else context.selected_objects
|
||||||
|
|
||||||
if self.obj:
|
|
||||||
objects = [bpy.data.objects.get(self.obj)]
|
|
||||||
else:
|
|
||||||
objects = context.selected_objects
|
|
||||||
active_obj = context.active_object
|
active_obj = context.active_object
|
||||||
active_object_material_type = self.material_type or active_obj.BIMObjectMaterialProperties.material_type
|
active_object_material_type = self.material_type or active_obj.BIMObjectMaterialProperties.material_type
|
||||||
active_object_material = active_obj.BIMObjectMaterialProperties.material
|
material = tool.Ifc.get().by_id(int(active_obj.BIMObjectMaterialProperties.material))
|
||||||
for obj in objects:
|
for obj in objects:
|
||||||
element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)
|
element = tool.Ifc.get_entity(obj)
|
||||||
ifcopenshell.api.run(
|
if element:
|
||||||
"material.assign_material",
|
ifcopenshell.api.run(
|
||||||
self.file,
|
"material.assign_material",
|
||||||
**{
|
tool.Ifc.get(),
|
||||||
"product": element,
|
product=element,
|
||||||
"type": active_object_material_type,
|
type=active_object_material_type,
|
||||||
"material": self.file.by_id(int(active_object_material)),
|
material=material,
|
||||||
},
|
)
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class UnassignMaterial(bpy.types.Operator, tool.Ifc.Operator):
|
class UnassignMaterial(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
@@ -171,18 +165,11 @@ class UnassignMaterial(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
obj: bpy.props.StringProperty()
|
obj: bpy.props.StringProperty()
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
self.file = IfcStore.get_file()
|
objects = [bpy.data.objects.get(self.obj)] if self.obj else context.selected_objects
|
||||||
|
|
||||||
if self.obj:
|
|
||||||
objects = [bpy.data.objects.get(self.obj)]
|
|
||||||
else:
|
|
||||||
objects = context.selected_objects
|
|
||||||
for obj in objects:
|
for obj in objects:
|
||||||
ifcopenshell.api.run(
|
element = tool.Ifc.get_entity(obj)
|
||||||
"material.unassign_material",
|
if element:
|
||||||
self.file,
|
ifcopenshell.api.run("material.unassign_material", tool.Ifc.get(), product=element)
|
||||||
**{"product": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)},
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class AddConstituent(bpy.types.Operator, tool.Ifc.Operator):
|
class AddConstituent(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
|
|||||||
@@ -50,6 +50,10 @@ def load_post(*args):
|
|||||||
usecase, "BlenderBIM.Product.EnsureMaterialAssigned", product.ensure_material_assigned
|
usecase, "BlenderBIM.Product.EnsureMaterialAssigned", product.ensure_material_assigned
|
||||||
)
|
)
|
||||||
|
|
||||||
|
ifcopenshell.api.add_post_listener(
|
||||||
|
"material.unassign_material", "BlenderBIM.Product.EnsureMaterialUnassigned", product.ensure_material_unassigned
|
||||||
|
)
|
||||||
|
|
||||||
ifcopenshell.api.add_post_listener(
|
ifcopenshell.api.add_post_listener(
|
||||||
"material.edit_profile_usage",
|
"material.edit_profile_usage",
|
||||||
"BlenderBIM.Product.RegenerateProfileUsage",
|
"BlenderBIM.Product.RegenerateProfileUsage",
|
||||||
|
|||||||
@@ -527,3 +527,29 @@ def ensure_material_assigned(usecase_path, ifc_file, settings):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
obj.data.materials.append(IfcStore.get_element(material[0].id()))
|
obj.data.materials.append(IfcStore.get_element(material[0].id()))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def ensure_material_unassigned(usecase_path, ifc_file, settings):
|
||||||
|
elements = [settings["product"]]
|
||||||
|
if elements[0].is_a("IfcElementType"):
|
||||||
|
elements.extend(ifcopenshell.util.element.get_types(elements[0]))
|
||||||
|
for element in elements:
|
||||||
|
obj = tool.Ifc.get_object(element)
|
||||||
|
if not obj or not obj.data:
|
||||||
|
continue
|
||||||
|
element_material = ifcopenshell.util.element.get_material(element)
|
||||||
|
if element_material:
|
||||||
|
continue
|
||||||
|
to_remove = []
|
||||||
|
for i, slot in enumerate(obj.material_slots):
|
||||||
|
if not slot.material:
|
||||||
|
continue
|
||||||
|
material = tool.Ifc.get_entity(slot.material)
|
||||||
|
if material:
|
||||||
|
to_remove.append(i)
|
||||||
|
total_removed = 0
|
||||||
|
for i in to_remove:
|
||||||
|
obj.active_material_index = i - total_removed
|
||||||
|
bpy.ops.object.material_slot_remove({'object': obj})
|
||||||
|
total_removed += 1
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ Scenario: Unassign material - single material
|
|||||||
And I set "active_object.BIMObjectMaterialProperties.material_type" to "IfcMaterial"
|
And I set "active_object.BIMObjectMaterialProperties.material_type" to "IfcMaterial"
|
||||||
And I press "bim.assign_material"
|
And I press "bim.assign_material"
|
||||||
When I press "bim.unassign_material"
|
When I press "bim.unassign_material"
|
||||||
Then nothing happens
|
Then the object "IfcWall/Cube" does not have the material "Default"
|
||||||
|
|
||||||
Scenario: Enable editing assigned material - single material
|
Scenario: Enable editing assigned material - single material
|
||||||
Given an empty IFC project
|
Given an empty IFC project
|
||||||
@@ -132,10 +132,6 @@ Scenario: Edit assigned material - single material
|
|||||||
|
|
||||||
Scenario: Assign material - material layer set
|
Scenario: Assign material - material layer set
|
||||||
Given an empty IFC project
|
Given an empty IFC project
|
||||||
And I add a cube
|
|
||||||
And the object "Cube" is selected
|
|
||||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWall"
|
|
||||||
And I press "bim.assign_class"
|
|
||||||
And I add an empty
|
And I add an empty
|
||||||
And the object "Empty" is selected
|
And the object "Empty" is selected
|
||||||
And I set "scene.BIMRootProperties.ifc_product" to "IfcElementType"
|
And I set "scene.BIMRootProperties.ifc_product" to "IfcElementType"
|
||||||
@@ -144,14 +140,10 @@ Scenario: Assign material - material layer set
|
|||||||
And I press "bim.add_material(obj='')"
|
And I press "bim.add_material(obj='')"
|
||||||
When I set "active_object.BIMObjectMaterialProperties.material_type" to "IfcMaterialLayerSet"
|
When I set "active_object.BIMObjectMaterialProperties.material_type" to "IfcMaterialLayerSet"
|
||||||
And I press "bim.assign_material"
|
And I press "bim.assign_material"
|
||||||
Then nothing happens
|
Then the object "IfcWallType/Empty" does not have the material "Default"
|
||||||
|
|
||||||
Scenario: Unassign material - material layer set
|
Scenario: Unassign material - material layer set
|
||||||
Given an empty IFC project
|
Given an empty IFC project
|
||||||
And I add a cube
|
|
||||||
And the object "Cube" is selected
|
|
||||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWall"
|
|
||||||
And I press "bim.assign_class"
|
|
||||||
And I add an empty
|
And I add an empty
|
||||||
And the object "Empty" is selected
|
And the object "Empty" is selected
|
||||||
And I set "scene.BIMRootProperties.ifc_product" to "IfcElementType"
|
And I set "scene.BIMRootProperties.ifc_product" to "IfcElementType"
|
||||||
@@ -219,10 +211,6 @@ Scenario: Edit assigned material - material layer set
|
|||||||
|
|
||||||
Scenario: Assign material - material profile set
|
Scenario: Assign material - material profile set
|
||||||
Given an empty IFC project
|
Given an empty IFC project
|
||||||
And I add a cube
|
|
||||||
And the object "Cube" is selected
|
|
||||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWall"
|
|
||||||
And I press "bim.assign_class"
|
|
||||||
And I add an empty
|
And I add an empty
|
||||||
And the object "Empty" is selected
|
And the object "Empty" is selected
|
||||||
And I set "scene.BIMRootProperties.ifc_product" to "IfcElementType"
|
And I set "scene.BIMRootProperties.ifc_product" to "IfcElementType"
|
||||||
@@ -231,14 +219,10 @@ Scenario: Assign material - material profile set
|
|||||||
And I press "bim.add_material(obj='')"
|
And I press "bim.add_material(obj='')"
|
||||||
When I set "active_object.BIMObjectMaterialProperties.material_type" to "IfcMaterialProfileSet"
|
When I set "active_object.BIMObjectMaterialProperties.material_type" to "IfcMaterialProfileSet"
|
||||||
And I press "bim.assign_material"
|
And I press "bim.assign_material"
|
||||||
Then nothing happens
|
Then the object "IfcWallType/Empty" does not have the material "Default"
|
||||||
|
|
||||||
Scenario: Unassign material - material profile set
|
Scenario: Unassign material - material profile set
|
||||||
Given an empty IFC project
|
Given an empty IFC project
|
||||||
And I add a cube
|
|
||||||
And the object "Cube" is selected
|
|
||||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWall"
|
|
||||||
And I press "bim.assign_class"
|
|
||||||
And I add an empty
|
And I add an empty
|
||||||
And the object "Empty" is selected
|
And the object "Empty" is selected
|
||||||
And I set "scene.BIMRootProperties.ifc_product" to "IfcElementType"
|
And I set "scene.BIMRootProperties.ifc_product" to "IfcElementType"
|
||||||
|
|||||||
@@ -498,6 +498,11 @@ def the_object_name_has_the_material_material(name, material):
|
|||||||
assert material in [ms.material.name for ms in the_object_name_exists(name).material_slots]
|
assert material in [ms.material.name for ms in the_object_name_exists(name).material_slots]
|
||||||
|
|
||||||
|
|
||||||
|
@then(parsers.parse('the object "{name}" does not have the material "{material}"'))
|
||||||
|
def the_object_name_does_not_have_the_material_material(name, material):
|
||||||
|
assert material not in [ms.material.name for ms in the_object_name_exists(name).material_slots]
|
||||||
|
|
||||||
|
|
||||||
@then(parsers.parse('the object "{name}" is in the collection "{collection}"'))
|
@then(parsers.parse('the object "{name}" is in the collection "{collection}"'))
|
||||||
def the_object_name_is_in_the_collection_collection(name, collection):
|
def the_object_name_is_in_the_collection_collection(name, collection):
|
||||||
assert collection in [c.name for c in the_object_name_exists(name).users_collection]
|
assert collection in [c.name for c in the_object_name_exists(name).users_collection]
|
||||||
|
|||||||
Reference in New Issue
Block a user