From c1c50f886819ec54879f4ef8deaf1593dd581c75 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Wed, 10 Nov 2021 12:46:07 +1100 Subject: [PATCH] Minor fix. --- src/blenderbim/blenderbim/bim/export_ifc.py | 2 +- .../bim/module/geometry/operator.py | 4 ++-- .../blenderbim/bim/module/model/data.py | 11 ++++----- .../blenderbim/bim/module/model/workspace.py | 24 +++++++++---------- src/blenderbim/blenderbim/core/geometry.py | 5 ++-- src/blenderbim/blenderbim/core/tool.py | 1 + src/blenderbim/blenderbim/tool/geometry.py | 11 +++++++++ src/blenderbim/test/core/test_geometry.py | 15 ++++++------ src/blenderbim/test/tool/test_geometry.py | 8 +++++++ .../api/geometry/add_representation.py | 9 ------- 10 files changed, 50 insertions(+), 40 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/export_ifc.py b/src/blenderbim/blenderbim/bim/export_ifc.py index 5724be53b7..094b77dcaa 100644 --- a/src/blenderbim/blenderbim/bim/export_ifc.py +++ b/src/blenderbim/blenderbim/bim/export_ifc.py @@ -155,7 +155,7 @@ class IfcExporter: float(props.blender_x_axis_ordinate), ) if not np.allclose(ifc_matrix, blender_matrix, atol=0.0001): - blenderbim.core.geometry.edit_object_placement(tool.Ifc, tool.Surveyor, obj=obj) + blenderbim.core.geometry.edit_object_placement(tool.Ifc, tool.Geometry, tool.Surveyor, obj=obj) return element def sync_grid_axis_object_placement(self, obj, element): diff --git a/src/blenderbim/blenderbim/bim/module/geometry/operator.py b/src/blenderbim/blenderbim/bim/module/geometry/operator.py index 7dbe97b83b..ee84ede153 100644 --- a/src/blenderbim/blenderbim/bim/module/geometry/operator.py +++ b/src/blenderbim/blenderbim/bim/module/geometry/operator.py @@ -54,7 +54,7 @@ class EditObjectPlacement(bpy.types.Operator, Operator): def _execute(self, context): objs = [bpy.data.objects.get(self.obj)] if self.obj else context.selected_objects for obj in objs: - core.edit_object_placement(tool.Ifc, tool.Surveyor, obj=obj) + core.edit_object_placement(tool.Ifc, tool.Geometry, tool.Surveyor, obj=obj) class AddRepresentation(bpy.types.Operator, Operator): @@ -153,7 +153,7 @@ class UpdateRepresentation(bpy.types.Operator): ifcopenshell.api.run("grid.create_axis_curve", self.file, **{"axis_curve": obj, "grid_axis": product}) return - core.edit_object_placement(tool.Ifc, tool.Surveyor, obj=obj) + core.edit_object_placement(tool.Ifc, tool.Geometry, tool.Surveyor, obj=obj) old_representation = self.file.by_id(obj.data.BIMMeshProperties.ifc_definition_id) context_of_items = old_representation.ContextOfItems diff --git a/src/blenderbim/blenderbim/bim/module/model/data.py b/src/blenderbim/blenderbim/bim/module/model/data.py index b358c6323d..3bd199dd5a 100644 --- a/src/blenderbim/blenderbim/bim/module/model/data.py +++ b/src/blenderbim/blenderbim/bim/module/model/data.py @@ -22,7 +22,6 @@ import blenderbim.tool as tool def refresh(): AuthoringData.is_loaded = False - WorkspaceData.is_loaded = False class AuthoringData: @@ -31,21 +30,23 @@ class AuthoringData: @classmethod def load(cls): + cls.is_loaded = True cls.data = { "ifc_classes": cls.ifc_classes(), "relating_types": cls.relating_types(), } - cls.is_loaded = True @classmethod def ifc_classes(cls): results = [] - classes = set([e.is_a() for e in tool.Ifc.get().by_type("IfcElementType")]) + classes = {e.is_a() for e in tool.Ifc.get().by_type("IfcElementType")} results.extend([(c, c, "") for c in sorted(classes)]) return results @classmethod def relating_types(cls): + if not cls.ifc_classes(): + return [] results = [] ifc_class = bpy.context.scene.BIMModelProperties.ifc_class if ifc_class: @@ -53,7 +54,3 @@ class AuthoringData: results.extend(sorted(elements, key=lambda s: s[1])) return results return [] - - -class WorkspaceData(AuthoringData): - pass diff --git a/src/blenderbim/blenderbim/bim/module/model/workspace.py b/src/blenderbim/blenderbim/bim/module/model/workspace.py index a2ae6e52ad..0e7a7c7fa2 100644 --- a/src/blenderbim/blenderbim/bim/module/model/workspace.py +++ b/src/blenderbim/blenderbim/bim/module/model/workspace.py @@ -21,7 +21,7 @@ import bpy import blenderbim.bim.module.type.prop as type_prop from bpy.types import WorkSpaceTool from blenderbim.bim.ifc import IfcStore -from blenderbim.bim.module.model.data import WorkspaceData +from blenderbim.bim.module.model.data import AuthoringData class BimTool(WorkSpaceTool): @@ -52,19 +52,19 @@ class BimTool(WorkSpaceTool): ) def draw_settings(context, layout, tool): - if not WorkspaceData.is_loaded: - WorkspaceData.load() + if not AuthoringData.is_loaded: + AuthoringData.load() row = layout.row(align=True) if not IfcStore.get_file(): row.label(text="No IFC Project", icon="ERROR") return props = context.scene.BIMModelProperties - if WorkspaceData.data["ifc_classes"]: + if AuthoringData.data["ifc_classes"]: row.prop(props, "ifc_class", text="") else: row.label(text="No IFC Class") - if WorkspaceData.data["relating_types"]: + if AuthoringData.data["relating_types"]: row.prop(props, "relating_type", text="") else: row.label(text="No Relating Type") @@ -75,7 +75,7 @@ class BimTool(WorkSpaceTool): row.label(text="", icon="EVENT_SHIFT") row.label(text="Add Type Instance", icon="EVENT_A") - if not ifc_classes_is_empty: + if AuthoringData.data["ifc_classes"]: if props.ifc_class == "IfcWallType": row = layout.row() row.label(text="Join") @@ -147,9 +147,9 @@ class Hotkey(bpy.types.Operator): def _execute(self, context): self.props = context.scene.BIMModelProperties - self.ifc_classes_is_empty = True + self.has_ifc_class = True try: - self.ifc_classes_is_empty = bool(self.props.ifc_class) + self.has_ifc_class = bool(self.props.ifc_class) except: pass getattr(self, f"hotkey_{self.hotkey}")() @@ -159,13 +159,13 @@ class Hotkey(bpy.types.Operator): bpy.ops.bim.add_type_instance() def hotkey_S_C(self): - if not self.ifc_classes_is_empty and self.props.ifc_class == "IfcWallType": + if self.has_ifc_class and self.props.ifc_class == "IfcWallType": bpy.ops.bim.align_wall(align_type="CENTERLINE") else: bpy.ops.bim.align_product(align_type="CENTERLINE") def hotkey_S_E(self): - if self.ifc_classes_is_empty: + if not self.has_ifc_class: return if self.props.ifc_class == "IfcWallType": bpy.ops.bim.join_wall(join_type="T") @@ -173,13 +173,13 @@ class Hotkey(bpy.types.Operator): bpy.ops.bim.extend_profile() def hotkey_S_V(self): - if not self.ifc_classes_is_empty and self.props.ifc_class == "IfcWallType": + if self.has_ifc_class and self.props.ifc_class == "IfcWallType": bpy.ops.bim.align_wall(align_type="INTERIOR") else: bpy.ops.bim.align_product(align_type="POSITIVE") def hotkey_S_X(self): - if not self.ifc_classes_is_empty and self.props.ifc_class == "IfcWallType": + if self.has_ifc_class and self.props.ifc_class == "IfcWallType": if bpy.ops.bim.align_wall.poll(): bpy.ops.bim.align_wall(align_type="EXTERIOR") else: diff --git a/src/blenderbim/blenderbim/core/geometry.py b/src/blenderbim/blenderbim/core/geometry.py index 9e123651f5..dbc70cea58 100644 --- a/src/blenderbim/blenderbim/core/geometry.py +++ b/src/blenderbim/blenderbim/core/geometry.py @@ -19,9 +19,10 @@ import blenderbim.core.style -def edit_object_placement(ifc, surveyor, obj=None): +def edit_object_placement(ifc, geometry, surveyor, obj=None): element = ifc.get_entity(obj) if element: + geometry.clear_scale(obj) ifc.run("geometry.edit_object_placement", product=element, matrix=surveyor.get_absolute_matrix(obj)) @@ -32,7 +33,7 @@ def add_representation( if not element: return - edit_object_placement(ifc, surveyor, obj=obj) + edit_object_placement(ifc, geometry, surveyor, obj=obj) data = geometry.get_object_data(obj) if not data: diff --git a/src/blenderbim/blenderbim/core/tool.py b/src/blenderbim/blenderbim/core/tool.py index b2d20cedf2..b50fb96788 100644 --- a/src/blenderbim/blenderbim/core/tool.py +++ b/src/blenderbim/blenderbim/core/tool.py @@ -74,6 +74,7 @@ class Context: class Geometry: def change_object_data(cls, obj, data, is_global=False): pass def clear_modifiers(cls, obj): pass + def clear_scale(cls, obj): pass def create_dynamic_voids(cls, obj): pass def delete_data(cls, data): pass def does_object_have_mesh_with_faces(cls, obj): pass diff --git a/src/blenderbim/blenderbim/tool/geometry.py b/src/blenderbim/blenderbim/tool/geometry.py index 170d2158fe..7544cbfc0c 100644 --- a/src/blenderbim/blenderbim/tool/geometry.py +++ b/src/blenderbim/blenderbim/tool/geometry.py @@ -39,6 +39,17 @@ class Geometry(blenderbim.core.tool.Geometry): for modifier in obj.modifiers: obj.modifiers.remove(modifier) + @classmethod + def clear_scale(cls, obj): + if obj.scale != Vector((1.0, 1.0, 1.0)): + if obj.data.users == 1: + context_override = {} + context_override["object"] = context_override["active_object"] = obj + context_override["selected_objects"] = context_override["selected_editable_objects"] = [obj] + bpy.ops.object.transform_apply(context_override, location=False, rotation=False, scale=True) + else: + obj.scale = Vector((1.0, 1.0, 1.0)) + @classmethod def create_dynamic_voids(cls, obj): element = tool.Ifc.get_entity(obj) diff --git a/src/blenderbim/test/core/test_geometry.py b/src/blenderbim/test/core/test_geometry.py index 128b2c3b08..a80991906e 100644 --- a/src/blenderbim/test/core/test_geometry.py +++ b/src/blenderbim/test/core/test_geometry.py @@ -22,19 +22,20 @@ from test.core.bootstrap import ifc, surveyor, geometry, style class TestEditObjectPlacement: - def predict(self, ifc, surveyor): + def predict(self, ifc, geometry, surveyor): ifc.get_entity("obj").should_be_called().will_return("element") + geometry.clear_scale("obj").should_be_called() surveyor.get_absolute_matrix("obj").should_be_called().will_return("matrix") ifc.run("geometry.edit_object_placement", product="element", matrix="matrix").should_be_called() - def test_run(self, ifc, surveyor): - self.predict(ifc, surveyor) - subject.edit_object_placement(ifc, surveyor, obj="obj") + def test_run(self, ifc, geometry, surveyor): + self.predict(ifc, geometry, surveyor) + subject.edit_object_placement(ifc, geometry, surveyor, obj="obj") class TestAddRepresentation: def test_run(self, ifc, geometry, style, surveyor): - TestEditObjectPlacement.predict(self, ifc, surveyor) + TestEditObjectPlacement.predict(self, ifc, geometry, surveyor) # Add representation geometry.get_object_data("obj").should_be_called().will_return("data") @@ -96,7 +97,7 @@ class TestAddRepresentation: ) def test_not_handling_styles_if_representation_has_no_faces(self, ifc, geometry, style, surveyor): - TestEditObjectPlacement.predict(self, ifc, surveyor) + TestEditObjectPlacement.predict(self, ifc, geometry, surveyor) # Add representation geometry.get_object_data("obj").should_be_called().will_return("data") @@ -145,7 +146,7 @@ class TestAddRepresentation: ) def test_only_updating_the_placement_if_there_is_no_object_data(self, ifc, geometry, style, surveyor): - TestEditObjectPlacement.predict(self, ifc, surveyor) + TestEditObjectPlacement.predict(self, ifc, geometry, surveyor) # Add representation geometry.get_object_data("obj").should_be_called().will_return(None) diff --git a/src/blenderbim/test/tool/test_geometry.py b/src/blenderbim/test/tool/test_geometry.py index 4e948a31d0..d1caf5b85a 100644 --- a/src/blenderbim/test/tool/test_geometry.py +++ b/src/blenderbim/test/tool/test_geometry.py @@ -61,6 +61,14 @@ class TestClearModifiers(NewFile): assert len(obj.modifiers) == 0 +class TestClearScale(NewFile): + def test_run(self): + obj = bpy.data.objects.new("Object", bpy.data.meshes.new("Mesh")) + obj.scale[0] = 2 + subject.clear_scale(obj) + assert list(obj.scale) == [1, 1, 1] + + class TestCreateDynamicVoids(NewFile): def test_run(self): ifc = ifcopenshell.file() diff --git a/src/ifcopenshell-python/ifcopenshell/api/geometry/add_representation.py b/src/ifcopenshell-python/ifcopenshell/api/geometry/add_representation.py index ae2ed7cd82..906a06e610 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/geometry/add_representation.py +++ b/src/ifcopenshell-python/ifcopenshell/api/geometry/add_representation.py @@ -66,15 +66,6 @@ class Usecase: return any([abs((tM @ v.co).z) > threshold for v in face.verts]) def evaluate_geometry(self): - if self.settings["blender_object"].scale != Vector((1., 1., 1.)): - if self.settings["blender_object"].data.users == 1: - context_override = {} - context_override["object"] = context_override["active_object"] = self.settings["blender_object"] - context_override["selected_objects"] = context_override["selected_editable_objects"] = [self.settings["blender_object"]] - bpy.ops.object.transform_apply(context_override, location=False, rotation=False, scale=True) - else: - self.settings["blender_object"].scale = Vector((1., 1., 1.)) - for modifier in self.settings["blender_object"].modifiers: if modifier.type == "BOOLEAN": modifier.show_viewport = False