mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-11 18:16:40 +00:00
Fix bug where switching to an object with modifiers applied would double the effect of modifiers.
This commit is contained in:
@@ -251,7 +251,7 @@ class UpdateRepresentation(bpy.types.Operator):
|
||||
def auto_detect_ifc_representation_class(self, element, representation, data):
|
||||
material = ifcopenshell.util.element.get_material(element)
|
||||
|
||||
if material.is_a("IfcMaterialProfileSetUsage"):
|
||||
if material and material.is_a("IfcMaterialProfileSetUsage"):
|
||||
data["ifc_representation_class"] = "IfcExtrudedAreaSolid/IfcMaterialProfileSetUsage"
|
||||
data["profile_set_usage"] = material
|
||||
return
|
||||
|
||||
@@ -60,9 +60,6 @@ def load_post(*args):
|
||||
IfcStore.add_element_listener(slab.element_listener)
|
||||
IfcStore.add_element_listener(profile.element_listener)
|
||||
|
||||
ifcopenshell.api.add_pre_listener(
|
||||
"geometry.add_representation", "BlenderBIM.DumbWall.EnsureSolid", wall.ensure_solid
|
||||
)
|
||||
ifcopenshell.api.add_post_listener(
|
||||
"geometry.add_representation", "BlenderBIM.DumbWall.GenerateAxis", wall.generate_axis
|
||||
)
|
||||
@@ -76,9 +73,6 @@ def load_post(*args):
|
||||
"type.assign_type", "BlenderBIM.DumbWall.RegenerateFromType", wall.DumbWallPlaner().regenerate_from_type
|
||||
)
|
||||
|
||||
ifcopenshell.api.add_pre_listener(
|
||||
"geometry.add_representation", "BlenderBIM.DumbSlab.EnsureSolid", slab.ensure_solid
|
||||
)
|
||||
ifcopenshell.api.add_post_listener(
|
||||
"geometry.add_representation", "BlenderBIM.DumbSlab.GenerateFootprint", slab.generate_footprint
|
||||
)
|
||||
@@ -92,9 +86,6 @@ def load_post(*args):
|
||||
"type.assign_type", "BlenderBIM.DumbSlab.RegenerateFromType", slab.DumbSlabPlaner().regenerate_from_type
|
||||
)
|
||||
|
||||
ifcopenshell.api.add_pre_listener(
|
||||
"geometry.add_representation", "BlenderBIM.DumbProfile.EnsureSolid", profile.ensure_solid
|
||||
)
|
||||
ifcopenshell.api.add_pre_listener(
|
||||
"material.edit_profile",
|
||||
"BlenderBIM.DumbProfile.SyncObjectFromProfile",
|
||||
|
||||
@@ -92,17 +92,6 @@ def mode_callback(obj, data):
|
||||
obj.matrix_world.translation = new_origin
|
||||
|
||||
|
||||
def ensure_solid(usecase_path, ifc_file, settings):
|
||||
product = ifc_file.by_id(settings["blender_object"].BIMObjectProperties.ifc_definition_id)
|
||||
parametric = ifcopenshell.util.element.get_psets(product).get("EPset_Parametric")
|
||||
if not parametric or parametric["Engine"] != "BlenderBIM.DumbProfile":
|
||||
return
|
||||
material = ifcopenshell.util.element.get_material(product)
|
||||
if material and material.is_a("IfcMaterialProfileSetUsage"):
|
||||
settings["profile_set_usage"] = material
|
||||
settings["ifc_representation_class"] = "IfcExtrudedAreaSolid/IfcMaterialProfileSetUsage"
|
||||
|
||||
|
||||
class DumbProfileGenerator:
|
||||
def __init__(self, relating_type):
|
||||
self.relating_type = relating_type
|
||||
|
||||
@@ -100,14 +100,6 @@ def ensure_solidify_modifier(obj):
|
||||
return modifier
|
||||
|
||||
|
||||
def ensure_solid(usecase_path, ifc_file, settings):
|
||||
product = ifc_file.by_id(settings["blender_object"].BIMObjectProperties.ifc_definition_id)
|
||||
parametric = ifcopenshell.util.element.get_psets(product).get("EPset_Parametric")
|
||||
if not parametric or parametric["Engine"] != "BlenderBIM.DumbLayer3":
|
||||
return
|
||||
settings["ifc_representation_class"] = "IfcExtrudedAreaSolid/IfcArbitraryProfileDefWithVoids"
|
||||
|
||||
|
||||
def generate_footprint(usecase_path, ifc_file, settings):
|
||||
footprint_context = ifcopenshell.util.representation.get_context(ifc_file, "Plan", "FootPrint", "SKETCH_VIEW")
|
||||
if not footprint_context:
|
||||
|
||||
@@ -816,14 +816,6 @@ class DumbWallGenerator:
|
||||
return obj
|
||||
|
||||
|
||||
def ensure_solid(usecase_path, ifc_file, settings):
|
||||
product = ifc_file.by_id(settings["blender_object"].BIMObjectProperties.ifc_definition_id)
|
||||
parametric = ifcopenshell.util.element.get_psets(product).get("EPset_Parametric")
|
||||
if not parametric or parametric["Engine"] != "BlenderBIM.DumbLayer2":
|
||||
return
|
||||
settings["ifc_representation_class"] = "IfcExtrudedAreaSolid/IfcArbitraryClosedProfileDef"
|
||||
|
||||
|
||||
def generate_axis(usecase_path, ifc_file, settings):
|
||||
axis_context = ifcopenshell.util.representation.get_context(ifc_file, "Model", "Axis", "GRAPH_VIEW")
|
||||
if not axis_context:
|
||||
|
||||
@@ -85,8 +85,7 @@ def switch_representation(
|
||||
geometry.link(representation, data)
|
||||
|
||||
geometry.change_object_data(obj, data, is_global=is_global)
|
||||
geometry.clear_modifiers(obj)
|
||||
|
||||
if enable_dynamic_voids and geometry.is_body_representation(representation):
|
||||
geometry.create_dynamic_voids(obj)
|
||||
else:
|
||||
geometry.clear_dynamic_voids(obj)
|
||||
|
||||
@@ -58,7 +58,7 @@ class Context:
|
||||
@interface
|
||||
class Geometry:
|
||||
def change_object_data(cls, obj, data, is_global=False): pass
|
||||
def clear_dynamic_voids(cls, obj): pass
|
||||
def clear_modifiers(cls, obj): pass
|
||||
def create_dynamic_voids(cls, obj): pass
|
||||
def does_object_have_mesh_with_faces(cls, obj): pass
|
||||
def duplicate_object_data(cls, obj): pass
|
||||
|
||||
@@ -35,10 +35,9 @@ class Geometry(blenderbim.core.tool.Geometry):
|
||||
obj.data = data
|
||||
|
||||
@classmethod
|
||||
def clear_dynamic_voids(cls, obj):
|
||||
def clear_modifiers(cls, obj):
|
||||
for modifier in obj.modifiers:
|
||||
if modifier.type == "BOOLEAN" and "IfcOpeningElement" in modifier.name:
|
||||
obj.modifiers.remove(modifier)
|
||||
obj.modifiers.remove(modifier)
|
||||
|
||||
@classmethod
|
||||
def create_dynamic_voids(cls, obj):
|
||||
|
||||
@@ -33,6 +33,26 @@ Scenario: Switch representation
|
||||
And I press "bim.switch_representation(obj='IfcWall/Cube', ifc_definition_id={representation})"
|
||||
Then nothing happens
|
||||
|
||||
Scenario: Switch representation - existing Blender modifiers must be purged
|
||||
Given an empty IFC project
|
||||
And I add a cube
|
||||
And the object "Cube" is selected
|
||||
And I add an array modifier
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWall"
|
||||
And I press "bim.assign_class"
|
||||
When the variable "representation" is "{ifc}.by_type('IfcShapeRepresentation')[0].id()"
|
||||
And I press "bim.switch_representation(obj='IfcWall/Cube', ifc_definition_id={representation})"
|
||||
Then the object "IfcWall/Cube" has no modifiers
|
||||
|
||||
Scenario: Update representation
|
||||
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 press "bim.update_representation(obj='IfcWall/Cube')"
|
||||
Then the object "IfcWall/Cube" has a "Tessellation" representation of "Model/Body/MODEL_VIEW"
|
||||
|
||||
Scenario: Copy representation
|
||||
Given an empty IFC project
|
||||
And I add a cube
|
||||
|
||||
@@ -94,6 +94,11 @@ def i_add_a_material():
|
||||
bpy.context.active_object.active_material = bpy.data.materials.new("Material")
|
||||
|
||||
|
||||
@given("I add an array modifier")
|
||||
def i_add_a_cube():
|
||||
bpy.ops.object.modifier_add(type="ARRAY")
|
||||
|
||||
|
||||
@when(parsers.parse('I add a cube of size "{size}" at "{location}"'))
|
||||
def i_add_a_cube_of_size_size_at_location(size, location):
|
||||
bpy.ops.mesh.primitive_cube_add(size=float(size), location=[float(co) for co in location.split(",")])
|
||||
@@ -424,3 +429,8 @@ def the_file_name_should_contain_value(name, value):
|
||||
name = replace_variables(name)
|
||||
with open(name, "r") as f:
|
||||
assert value in f.read()
|
||||
|
||||
|
||||
@then(parsers.parse('the object "{name}" has no modifiers'))
|
||||
def the_object_name_has_no_modifiers(name):
|
||||
assert len(the_object_name_exists(name).modifiers) == 0
|
||||
|
||||
@@ -189,6 +189,7 @@ class TestSwitchRepresentation:
|
||||
geometry.rename_object("new_data", "name").should_be_called()
|
||||
geometry.link("representation", "new_data").should_be_called()
|
||||
geometry.change_object_data("obj", "new_data", is_global=True).should_be_called()
|
||||
geometry.clear_modifiers("obj").should_be_called()
|
||||
geometry.is_body_representation("representation").should_be_called().will_return(True)
|
||||
geometry.create_dynamic_voids("obj").should_be_called()
|
||||
subject.switch_representation(
|
||||
@@ -204,6 +205,7 @@ class TestSwitchRepresentation:
|
||||
geometry.resolve_mapped_representation("mapped_rep").should_be_called().will_return("representation")
|
||||
geometry.get_representation_data("representation").should_be_called().will_return("data")
|
||||
geometry.change_object_data("obj", "data", is_global=True).should_be_called()
|
||||
geometry.clear_modifiers("obj").should_be_called()
|
||||
geometry.is_body_representation("representation").should_be_called().will_return(True)
|
||||
geometry.create_dynamic_voids("obj").should_be_called()
|
||||
subject.switch_representation(
|
||||
@@ -219,7 +221,7 @@ class TestSwitchRepresentation:
|
||||
geometry.resolve_mapped_representation("mapped_rep").should_be_called().will_return("representation")
|
||||
geometry.get_representation_data("representation").should_be_called().will_return("data")
|
||||
geometry.change_object_data("obj", "data", is_global=False).should_be_called()
|
||||
geometry.clear_dynamic_voids("obj").should_be_called()
|
||||
geometry.clear_modifiers("obj").should_be_called()
|
||||
subject.switch_representation(
|
||||
geometry,
|
||||
obj="obj",
|
||||
|
||||
@@ -53,11 +53,11 @@ class TestChangeObjectData(test.bim.bootstrap.NewFile):
|
||||
assert obj2.data == data2
|
||||
|
||||
|
||||
class TestClearDynamicVoids(test.bim.bootstrap.NewFile):
|
||||
class TestClearModifiers(test.bim.bootstrap.NewFile):
|
||||
def test_run(self):
|
||||
obj = bpy.data.objects.new("Object", bpy.data.meshes.new("Mesh"))
|
||||
obj.modifiers.new("IfcOpeningElement", "BOOLEAN")
|
||||
subject.clear_dynamic_voids(obj)
|
||||
subject.clear_modifiers(obj)
|
||||
assert len(obj.modifiers) == 0
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user