From e50259f8fa1677a858b20bbf311cb437477ea146 Mon Sep 17 00:00:00 2001 From: Vukas Pajic <83825269+vulevukusej@users.noreply.github.com> Date: Wed, 29 Jun 2022 18:07:32 +0200 Subject: [PATCH 01/24] fix error I accidentally introduced. --- src/blenderbim/blenderbim/bim/module/pset/ui.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/blenderbim/blenderbim/bim/module/pset/ui.py b/src/blenderbim/blenderbim/bim/module/pset/ui.py index 25adeb2156..250ea2febc 100644 --- a/src/blenderbim/blenderbim/bim/module/pset/ui.py +++ b/src/blenderbim/blenderbim/bim/module/pset/ui.py @@ -95,7 +95,7 @@ def draw_psetqto_ui(context, pset_id, pset, props, layout, obj_type): def draw_psetqto_editable_ui(box, props, prop): row = box.row(align=True) - draw_attribute(box, prop, row, copy_operator="bim.copy_property_to_selection") + draw_attribute(prop, row, copy_operator="bim.copy_property_to_selection") if ( "length" in prop.name.lower() or "width" in prop.name.lower() From 4ad4bdef3bb141f0efa5b37b1ef2effa808e40a3 Mon Sep 17 00:00:00 2001 From: Gorgious56 Date: Wed, 29 Jun 2022 19:49:17 +0200 Subject: [PATCH 02/24] Initial Commit --- .../blenderbim/bim/module/root/__init__.py | 1 + .../blenderbim/bim/module/root/operator.py | 23 ++++++++++++++++++- .../blenderbim/bim/module/root/prop.py | 18 +++++++++++++++ .../blenderbim/bim/module/root/ui.py | 3 ++- 4 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/root/__init__.py b/src/blenderbim/blenderbim/bim/module/root/__init__.py index 00a36e0817..d98cbd8d48 100644 --- a/src/blenderbim/blenderbim/bim/module/root/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/root/__init__.py @@ -26,6 +26,7 @@ classes = ( operator.EnableReassignClass, operator.ReassignClass, operator.UnlinkObject, + operator.BIM_OT_root_property_textfield, prop.BIMRootProperties, ui.BIM_PT_class, ) diff --git a/src/blenderbim/blenderbim/bim/module/root/operator.py b/src/blenderbim/blenderbim/bim/module/root/operator.py index e64b2e5920..6971353be0 100644 --- a/src/blenderbim/blenderbim/bim/module/root/operator.py +++ b/src/blenderbim/blenderbim/bim/module/root/operator.py @@ -31,7 +31,7 @@ import blenderbim.core.root as core import blenderbim.tool as tool from ifcopenshell.api.void.data import Data as VoidData from blenderbim.bim.ifc import IfcStore -from blenderbim.bim.module.root.prop import get_contexts +from blenderbim.bim.module.root.prop import get_contexts, get_ifc_classes_filtered class Operator: @@ -189,3 +189,24 @@ class CopyClass(bpy.types.Operator, Operator): for obj in objects: core.copy_class(tool.Ifc, tool.Collector, tool.Geometry, tool.Root, obj=obj) blenderbim.bim.handler.purge_module_data() + + +class BIM_OT_root_property_textfield(bpy.types.Operator): + bl_idname = "bim.root_ifc_class_filter" + bl_label = "Filter Property" + bl_options = {"REGISTER", "UNDO"} + + def invoke(self, context, event): + return context.window_manager.invoke_props_dialog(self) + + def execute(self, context): + context.scene.BIMRootProperties.ifc_class = context.scene.BIMRootProperties.ifc_class_filter_enum + return {"FINISHED"} + + def draw(self, context): + props = context.scene.BIMRootProperties + self.layout.prop(props, "ifc_class_filter_textfield") + if len(get_ifc_classes_filtered(props, context)) > 10: + self.layout.prop(props, "ifc_class_filter_enum") + else: + self.layout.props_enum(props, "ifc_class_filter_enum") diff --git a/src/blenderbim/blenderbim/bim/module/root/prop.py b/src/blenderbim/blenderbim/bim/module/root/prop.py index 8b598a2338..eeceb1b3f6 100644 --- a/src/blenderbim/blenderbim/bim/module/root/prop.py +++ b/src/blenderbim/blenderbim/bim/module/root/prop.py @@ -34,11 +34,14 @@ from bpy.props import ( ) types_enum = [] +classes_enum = [] def purge(): global types_enum types_enum = [] + global classes_enum + classes_enum = [] def getIfcPredefinedTypes(self, context): @@ -69,6 +72,10 @@ def refreshPredefinedTypes(self, context): context.scene.BIMRootProperties.ifc_predefined_type = enum[0][0] +def update_class_enum(self, context): + self.ifc_class = self.ifc_class_filter_enum + + def get_ifc_products(self, context): if not IfcClassData.is_loaded: IfcClassData.load() @@ -81,6 +88,15 @@ def get_ifc_classes(self, context): return IfcClassData.data["ifc_classes"] +def get_ifc_classes_filtered(self, context): + ifc_classes = get_ifc_classes(self, context) + global classes_enum + classes_enum = [ + c for c in ifc_classes + if self.ifc_class_filter_textfield.lower() in c[0].lower()] or ifc_classes + return classes_enum + + def get_contexts(self, context): if not IfcClassData.is_loaded: IfcClassData.load() @@ -91,5 +107,7 @@ class BIMRootProperties(PropertyGroup): contexts: EnumProperty(items=get_contexts, name="Contexts") ifc_product: EnumProperty(items=get_ifc_products, name="Products", update=refresh_classes) ifc_class: EnumProperty(items=get_ifc_classes, name="Class", update=refreshPredefinedTypes) + ifc_class_filter_textfield: StringProperty(name="Filter", options={"TEXTEDIT_UPDATE"}) + ifc_class_filter_enum: EnumProperty(items=get_ifc_classes_filtered, name="Class", update=update_class_enum) ifc_predefined_type: EnumProperty(items=getIfcPredefinedTypes, name="Predefined Type", default=None) ifc_userdefined_type: StringProperty(name="Userdefined Type") diff --git a/src/blenderbim/blenderbim/bim/module/root/ui.py b/src/blenderbim/blenderbim/bim/module/root/ui.py index 369f0b50e8..a7c61e7814 100644 --- a/src/blenderbim/blenderbim/bim/module/root/ui.py +++ b/src/blenderbim/blenderbim/bim/module/root/ui.py @@ -79,8 +79,9 @@ class BIM_PT_class(Panel): if not is_reassigning_class: row = self.layout.row() row.prop(props, "ifc_product") - row = self.layout.row() + row = self.layout.row(align=True) row.prop(props, "ifc_class") + row.operator("bim.root_ifc_class_filter", text="", icon="VIEWZOOM") if ifc_predefined_types: row = self.layout.row() row.prop(props, "ifc_predefined_type") From c73fedaaaf832e6d044fa23344ffc8b342a1a7a9 Mon Sep 17 00:00:00 2001 From: Vukas Pajic <83825269+vulevukusej@users.noreply.github.com> Date: Fri, 1 Jul 2022 13:41:20 +0200 Subject: [PATCH 03/24] fix error that stopped user from adding properties --- .../ifcopenshell/api/pset/edit_pset.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/ifcopenshell-python/ifcopenshell/api/pset/edit_pset.py b/src/ifcopenshell-python/ifcopenshell/api/pset/edit_pset.py index d6b234071d..28c307756c 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/pset/edit_pset.py +++ b/src/ifcopenshell-python/ifcopenshell/api/pset/edit_pset.py @@ -102,9 +102,11 @@ class Usecase: if value is None: continue if isinstance(value, ifcopenshell.entity_instance): - nominal_value = value if value.is_a(True) == "IFC4.IfcPropertyEnumeratedValue": properties.append(value) + continue + else: + nominal_value = value #TODO-The following "elif" is temporary code, will need to refactor at some point - vulevukusej elif isinstance(value, list): for pset_template in self.settings["pset_template"].HasPropertyTemplates: @@ -122,17 +124,18 @@ class Usecase: EnumerationReference=prop_enum ) properties.append(prop_enum_value) + continue else: primary_measure_type = self.get_primary_measure_type(name, new_value=value) value = self.cast_value_to_primary_measure_type(value, primary_measure_type) nominal_value = self.file.create_entity(primary_measure_type, value) - properties.append( - self.file.create_entity( - "IfcPropertySingleValue", - **{"Name": name, "NominalValue": nominal_value}, - ) + properties.append( + self.file.create_entity( + "IfcPropertySingleValue", + **{"Name": name, "NominalValue": nominal_value}, ) + ) return properties def extend_pset_with_new_properties(self, new_properties): From 37f91461d20d43d98d04b97268c2d2bb64dacbb4 Mon Sep 17 00:00:00 2001 From: Gorgious56 Date: Sun, 3 Jul 2022 22:37:41 +0200 Subject: [PATCH 04/24] Add prop search to fields with a lot of enumerated values (#2253) * Add prop_search layout function * Display props operator * display search for pset * Display search for root * Update operator and UI layout function * Add search buttons to brick, geometry, patch, project, pset, pset_template, root and unit modules enums --- .../blenderbim/bim/module/brick/prop.py | 6 +++ .../blenderbim/bim/module/brick/ui.py | 6 ++- .../blenderbim/bim/module/geometry/ui.py | 3 +- .../blenderbim/bim/module/patch/prop.py | 4 ++ .../blenderbim/bim/module/patch/ui.py | 3 +- .../blenderbim/bim/module/project/prop.py | 25 +++++++++++ .../blenderbim/bim/module/project/ui.py | 16 +++---- .../blenderbim/bim/module/pset/prop.py | 45 ++++++++++++------- .../blenderbim/bim/module/pset/ui.py | 13 +++--- .../bim/module/pset_template/prop.py | 9 ++++ .../blenderbim/bim/module/pset_template/ui.py | 7 +-- .../blenderbim/bim/module/root/__init__.py | 2 +- .../blenderbim/bim/module/root/operator.py | 26 ++++++----- .../blenderbim/bim/module/root/prop.py | 19 ++++---- .../blenderbim/bim/module/root/ui.py | 21 ++++----- .../blenderbim/bim/module/unit/prop.py | 6 +++ .../blenderbim/bim/module/unit/ui.py | 9 ++-- src/blenderbim/blenderbim/bim/ui.py | 9 ++++ 18 files changed, 151 insertions(+), 78 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/brick/prop.py b/src/blenderbim/blenderbim/bim/module/brick/prop.py index 6e0ba7c814..0d4eec7a6d 100644 --- a/src/blenderbim/blenderbim/bim/module/brick/prop.py +++ b/src/blenderbim/blenderbim/bim/module/brick/prop.py @@ -69,3 +69,9 @@ class BIMBrickProperties(PropertyGroup): libraries: EnumProperty(name="Libraries", items=get_libraries) namespace: EnumProperty(name="Namespace", items=get_namespaces) brick_equipment_class: EnumProperty(name="Brick Equipment Class", items=get_brick_equipment_classes) + + getter_enum = { + "libraries": get_libraries, + "namespace": get_namespaces, + "brick_equipment_class": get_brick_equipment_classes, + } diff --git a/src/blenderbim/blenderbim/bim/module/brick/ui.py b/src/blenderbim/blenderbim/bim/module/brick/ui.py index da3647ab6d..f0b1cedce7 100644 --- a/src/blenderbim/blenderbim/bim/module/brick/ui.py +++ b/src/blenderbim/blenderbim/bim/module/brick/ui.py @@ -18,6 +18,7 @@ import blenderbim.tool as tool from bpy.types import Panel, UIList +from blenderbim.bim.ui import prop_with_search from blenderbim.bim.module.brick.data import BrickschemaData, BrickschemaReferencesData @@ -48,7 +49,8 @@ class BIM_PT_brickschema(Panel): row.operator("bim.close_brick_project", text="", icon="CANCEL") row = self.layout.row(align=True) - row.prop(self.props, "namespace", text="") + prop_with_search(row, self.props, "namespace", text="") + prop_with_search(row, self.props, "brick_equipment_class", text="") row.prop(self.props, "brick_equipment_class", text="") row.operator("bim.add_brick", text="", icon="ADD") @@ -101,7 +103,7 @@ class BIM_PT_ifc_brickschema_references(Panel): return row = self.layout.row(align=True) - row.prop(self.props, "libraries") + prop_with_search(row, self.props, "libraries") row.operator("bim.convert_brick_project", text="", icon="ADD") row = self.layout.row(align=True) diff --git a/src/blenderbim/blenderbim/bim/module/geometry/ui.py b/src/blenderbim/blenderbim/bim/module/geometry/ui.py index 78c8e21414..4ce050ffb9 100644 --- a/src/blenderbim/blenderbim/bim/module/geometry/ui.py +++ b/src/blenderbim/blenderbim/bim/module/geometry/ui.py @@ -19,6 +19,7 @@ import bpy from bpy.types import Panel from blenderbim.bim.ifc import IfcStore +from blenderbim.bim.ui import prop_with_search from blenderbim.bim.module.geometry.data import RepresentationsData, DerivedPlacementsData @@ -50,7 +51,7 @@ class BIM_PT_representations(Panel): layout.label(text="No representations found") row = layout.row(align=True) - row.prop(context.scene.BIMRootProperties, "contexts", text="") + prop_with_search(row, context.scene.BIMRootProperties, "contexts", text="") row.operator("bim.add_representation", icon="ADD", text="") for representation in RepresentationsData.data["representations"]: diff --git a/src/blenderbim/blenderbim/bim/module/patch/prop.py b/src/blenderbim/blenderbim/bim/module/patch/prop.py index 27c0e44ab5..0fb0a5f341 100644 --- a/src/blenderbim/blenderbim/bim/module/patch/prop.py +++ b/src/blenderbim/blenderbim/bim/module/patch/prop.py @@ -66,3 +66,7 @@ class BIMPatchProperties(PropertyGroup): ifc_patch_output: StringProperty(default="", name="IFC Patch Output IFC") ifc_patch_args: StringProperty(default="", name="Arguments") ifc_patch_args_attr: CollectionProperty(type=Attribute, name="Arguments") + + getter_enum = { + "ifc_patch_recipes": get_ifcpatch_recipes, + } diff --git a/src/blenderbim/blenderbim/bim/module/patch/ui.py b/src/blenderbim/blenderbim/bim/module/patch/ui.py index 618a5077ca..9d58971d7d 100644 --- a/src/blenderbim/blenderbim/bim/module/patch/ui.py +++ b/src/blenderbim/blenderbim/bim/module/patch/ui.py @@ -16,6 +16,7 @@ # You should have received a copy of the GNU General Public License # along with BlenderBIM Add-on. If not, see . +from blenderbim.bim.ui import prop_with_search import bpy from blenderbim.bim.helper import draw_attributes @@ -37,7 +38,7 @@ class BIM_PT_patch(bpy.types.Panel): scene = context.scene props = scene.BIMPatchProperties row = layout.row() - row.prop(props, "ifc_patch_recipes") + prop_with_search(row, props, "ifc_patch_recipes") row = layout.row(align=True) row.prop(props, "ifc_patch_input") diff --git a/src/blenderbim/blenderbim/bim/module/project/prop.py b/src/blenderbim/blenderbim/bim/module/project/prop.py index 3fe5e5077f..4d38d465fe 100644 --- a/src/blenderbim/blenderbim/bim/module/project/prop.py +++ b/src/blenderbim/blenderbim/bim/module/project/prop.py @@ -167,3 +167,28 @@ class BIMProjectProperties(PropertyGroup): def get_library_element_index(self, lib_element): return next((i for i in range(len(self.library_elements)) if self.library_elements[i] == lib_element)) + + getter_enum = { + "collection_mode": lambda self, context: [ + ("DECOMPOSITION", "Decomposition", "Collections represent aggregates and spatial containers"), + ("SPATIAL_DECOMPOSITION", "Spatial Decomposition", "Collections represent spatial containers"), + ("IFC_CLASS", "IFC Class", "Collections represent IFC class"), + ("NONE", "None", "No collections are created"), + ], + "filter_mode": lambda self, context: [ + ("NONE", "None", "No filtering is performed"), + ("DECOMPOSITION", "Decomposition", "Filter objects by decomposition"), + ("IFC_CLASS", "IFC Class", "Filter objects by class"), + ("IFC_TYPE", "IFC Type", "Filter objects by type"), + ("WHITELIST", "Whitelist", "Filter objects using a custom whitelist query"), + ("BLACKLIST", "Blacklist", "Filter objects using a custom blacklist query"), + ], + "merge_mode": lambda self, context: [ + ("NONE", "None", "No objects are merged"), + ("IFC_CLASS", "IFC Class", "One object per IFC class"), + ("IFC_TYPE", "IFC Type", "One object per IFC construction type"), + ("MATERIAL", "Material", "One object per material"), + ], + "export_schema": get_export_schema, + "template_file": get_template_file, + } diff --git a/src/blenderbim/blenderbim/bim/module/project/ui.py b/src/blenderbim/blenderbim/bim/module/project/ui.py index c8be2f2933..8a0a21f109 100644 --- a/src/blenderbim/blenderbim/bim/module/project/ui.py +++ b/src/blenderbim/blenderbim/bim/module/project/ui.py @@ -17,6 +17,7 @@ # along with BlenderBIM Add-on. If not, see . import os +from blenderbim.bim.ui import prop_with_search from bpy.types import Panel, UIList from blenderbim.bim.ifc import IfcStore from blenderbim.bim.module.project.data import ProjectData @@ -48,10 +49,8 @@ class BIM_PT_project(Panel): def draw_load_ui(self, context): pprops = context.scene.BIMProjectProperties - row = self.layout.row() - row.prop(pprops, "collection_mode") - row = self.layout.row() - row.prop(pprops, "filter_mode") + prop_with_search(self.layout, pprops, "collection_mode") + prop_with_search(self.layout, pprops, "filter_mode") if pprops.filter_mode in ["DECOMPOSITION", "IFC_CLASS", "IFC_TYPE"]: row = self.layout.row(align=True) row.label(text=f"Total: {pprops.total_elements}") @@ -84,8 +83,7 @@ class BIM_PT_project(Panel): row = self.layout.row() row.prop(pprops, "is_coordinating") if pprops.is_coordinating: - row = self.layout.row() - row.prop(pprops, "merge_mode") + prop_with_search(self.layout, pprops, "merge_mode") row = self.layout.row() row.prop(pprops, "deflection_tolerance") row = self.layout.row() @@ -170,8 +168,7 @@ class BIM_PT_project(Panel): def draw_create_project_ui(self, context): props = context.scene.BIMProperties pprops = context.scene.BIMProjectProperties - row = self.layout.row() - row.prop(pprops, "export_schema") + prop_with_search(self.layout, pprops, "export_schema") row = self.layout.row() row.prop(context.scene.unit_settings, "system") row = self.layout.row() @@ -180,8 +177,7 @@ class BIM_PT_project(Panel): row.prop(props, "area_unit", text="Area Unit") row = self.layout.row() row.prop(props, "volume_unit", text="Volume Unit") - row = self.layout.row() - row.prop(pprops, "template_file", text="Template") + prop_with_search(self.layout, pprops, "template_file", text="Template") row = self.layout.row(align=True) row.operator("bim.create_project") diff --git a/src/blenderbim/blenderbim/bim/module/pset/prop.py b/src/blenderbim/blenderbim/bim/module/pset/prop.py index 14fedf0f33..9510329013 100644 --- a/src/blenderbim/blenderbim/bim/module/pset/prop.py +++ b/src/blenderbim/blenderbim/bim/module/pset/prop.py @@ -18,7 +18,7 @@ import bpy import blenderbim.bim.schema -from blenderbim.bim.prop import Attribute +from blenderbim.bim.prop import Attribute, StrProperty import ifcopenshell from ifcopenshell.api.pset.data import Data from blenderbim.bim.module.pset.data import AddEditCustomPropertiesData @@ -47,7 +47,7 @@ def purge(): qtonames = {} -def getPsetNames(self, context): +def get_pset_names(self, context): global psetnames obj = context.active_object if not obj.BIMObjectProperties.ifc_definition_id: @@ -122,7 +122,7 @@ def getWorkSchedulePsetNames(self, context): return psetnames[ifc_class] -def getQtoNames(self, context): +def get_qto_names(self, context): global qtonames if "/" in context.active_object.name: ifc_class = context.active_object.name.split("/")[0] @@ -145,22 +145,27 @@ class EnumerationValues(PropertyGroup): int_value: IntProperty(name="Value") float_value: FloatProperty(name="Value") is_selected: BoolProperty(default=False) - - + + class IfcSimpleProperty(Attribute): - #bounded_values: + # bounded_values: enumerated_values: CollectionProperty(type=EnumerationValues) - #list_values: - #reference_values: - #table_values: - - + # list_values: + # reference_values: + # table_values: + + class PsetProperties(PropertyGroup): active_pset_id: IntProperty(name="Active Pset ID") active_pset_name: StringProperty(name="Pset Name") properties: CollectionProperty(name="Properties", type=IfcSimpleProperty) - pset_name: EnumProperty(items=getPsetNames, name="Pset Name") - qto_name: EnumProperty(items=getQtoNames, name="Qto Name") + pset_name: EnumProperty(items=get_pset_names, name="Pset Name") + qto_name: EnumProperty(items=get_qto_names, name="Qto Name") + + getter_enum = { + "qto_name": get_qto_names, + "pset_name": get_pset_names, + } class MaterialPsetProperties(PropertyGroup): @@ -215,13 +220,21 @@ class AddEditProperties(PropertyGroup): primary_measure_type: EnumProperty(items=get_primary_measure_type, name="Primary Measure Type") template_type: EnumProperty( items=[ - ("IfcPropertySingleValue","IfcPropertySingleValue","IfcPropertySingleValue"), - ("IfcPropertyEnumeratedValue","IfcPropertyEnumeratedValue","IfcPropertyEnumeratedValue") + ("IfcPropertySingleValue", "IfcPropertySingleValue", "IfcPropertySingleValue"), + ("IfcPropertyEnumeratedValue", "IfcPropertyEnumeratedValue", "IfcPropertyEnumeratedValue"), ], - name="Template Type" + name="Template Type", ) enum_values: CollectionProperty(name="Enum Values", type=EnumerationValues) + getter_enum = { + "primary_measure_type": get_primary_measure_type, + "template_type": lambda self, context: [ + ("IfcPropertySingleValue", "IfcPropertySingleValue", "IfcPropertySingleValue"), + ("IfcPropertyEnumeratedValue", "IfcPropertyEnumeratedValue", "IfcPropertyEnumeratedValue"), + ], + } + def get_value_name(self): ifc_data_type = IfcStore.get_schema().declaration_by_name(self.primary_measure_type) data_type = ifcopenshell.util.attribute.get_primitive_type(ifc_data_type) diff --git a/src/blenderbim/blenderbim/bim/module/pset/ui.py b/src/blenderbim/blenderbim/bim/module/pset/ui.py index 250ea2febc..ebc421420c 100644 --- a/src/blenderbim/blenderbim/bim/module/pset/ui.py +++ b/src/blenderbim/blenderbim/bim/module/pset/ui.py @@ -18,6 +18,7 @@ from bpy.types import Panel from blenderbim.bim.ifc import IfcStore +from blenderbim.bim.ui import prop_with_search from blenderbim.bim.helper import draw_attribute from blenderbim.bim.module.pset.data import ( ObjectPsetsData, @@ -138,7 +139,7 @@ class BIM_PT_object_psets(Panel): props = context.active_object.PsetProperties row = self.layout.row(align=True) - row.prop(props, "pset_name", text="") + prop_with_search(row, props, "pset_name", text="") op = row.operator("bim.add_pset", icon="ADD", text="") op.obj = context.active_object.name op.obj_type = "Object" @@ -177,7 +178,7 @@ class BIM_PT_object_qtos(Panel): props = context.active_object.PsetProperties row = self.layout.row(align=True) - row.prop(props, "qto_name", text="") + prop_with_search(row, props, "qto_name", text="") op = row.operator("bim.add_qto", icon="ADD", text="") op.obj = context.active_object.name op.obj_type = "Object" @@ -450,12 +451,12 @@ class BIM_PT_add_edit_custom_properties(Panel): row.prop(prop, "property_name", text="") if prop.template_type == "IfcPropertySingleValue": row.prop(prop, prop.get_value_name(), text="") - row.prop(prop, "primary_measure_type", text="") - row.prop(prop, "template_type", text="") + prop_with_search(row, prop, "primary_measure_type", text="") + prop_with_search(row, prop, "template_type", text="") op = row.operator("bim.remove_property_to_edit", icon="X", text="") op.index = index op.option = "AddEditProperties" - + if prop.template_type == "IfcPropertyEnumeratedValue": op = row.operator("bim.add_property_to_edit", icon="ADD", text="Add Enum") op.option = "AddEditProperties" @@ -494,7 +495,7 @@ class BIM_PT_delete_psets(Panel): row = layout.row() op = row.operator("bim.add_property_to_edit", icon="ADD") op.option = "DeletePsets" - + if props: for index, prop in enumerate(props): row = layout.row(align=True) diff --git a/src/blenderbim/blenderbim/bim/module/pset_template/prop.py b/src/blenderbim/blenderbim/bim/module/pset_template/prop.py index 0d6a46a94e..1cb59a22ed 100644 --- a/src/blenderbim/blenderbim/bim/module/pset_template/prop.py +++ b/src/blenderbim/blenderbim/bim/module/pset_template/prop.py @@ -152,6 +152,10 @@ class PropTemplate(PropertyGroup): description: StringProperty(name="Description") primary_measure_type: EnumProperty(items=get_primary_measure_type, name="Primary Measure Type") + getter_enum = { + "primary_measure_type": get_primary_measure_type, + } + class BIMPsetTemplateProperties(PropertyGroup): pset_template_files: EnumProperty( @@ -162,3 +166,8 @@ class BIMPsetTemplateProperties(PropertyGroup): active_prop_template_id: IntProperty(name="Active Prop Template Id") active_pset_template: PointerProperty(type=PsetTemplate) active_prop_template: PointerProperty(type=PropTemplate) + + getter_enum = { + "pset_template_files": getPsetTemplateFiles, + "pset_templates": getPsetTemplates, + } diff --git a/src/blenderbim/blenderbim/bim/module/pset_template/ui.py b/src/blenderbim/blenderbim/bim/module/pset_template/ui.py index 91f90f82d8..058f4e9b59 100644 --- a/src/blenderbim/blenderbim/bim/module/pset_template/ui.py +++ b/src/blenderbim/blenderbim/bim/module/pset_template/ui.py @@ -19,6 +19,7 @@ import bpy from bpy.types import Panel from blenderbim.bim.ifc import IfcStore +from blenderbim.bim.ui import prop_with_search from blenderbim.bim.module.pset_template.prop import ( getPsetTemplates, ) @@ -39,13 +40,13 @@ class BIM_PT_pset_template(Panel): props = context.scene.BIMPsetTemplateProperties row = layout.row(align=True) - row.prop(props, "pset_template_files", text="") + prop_with_search(row, props, "pset_template_files", text="") row.operator("bim.save_pset_template_file", text="", icon="EXPORT") row = layout.row(align=True) if bool(getPsetTemplates(props, context)): - row.prop(props, "pset_templates", text="", icon="COPY_ID") + prop_with_search(row, props, "pset_templates", text="", icon="COPY_ID") else: row.label(text="No Pset Templates", icon="COPY_ID") @@ -93,7 +94,7 @@ class BIM_PT_pset_template(Panel): if props.active_prop_template_id and props.active_prop_template_id == prop_template_id: row.prop(props.active_prop_template, "name", text="") row.prop(props.active_prop_template, "description", text="") - row.prop(props.active_prop_template, "primary_measure_type", text="") + prop_with_search(row, props.active_prop_template, "primary_measure_type", text="") else: row.label(text=prop_template["Name"]) row.label(text=prop_template["Description"]) diff --git a/src/blenderbim/blenderbim/bim/module/root/__init__.py b/src/blenderbim/blenderbim/bim/module/root/__init__.py index d98cbd8d48..523f3b77cd 100644 --- a/src/blenderbim/blenderbim/bim/module/root/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/root/__init__.py @@ -26,7 +26,7 @@ classes = ( operator.EnableReassignClass, operator.ReassignClass, operator.UnlinkObject, - operator.BIM_OT_root_property_textfield, + operator.BIM_OT_enum_property_search, prop.BIMRootProperties, ui.BIM_PT_class, ) diff --git a/src/blenderbim/blenderbim/bim/module/root/operator.py b/src/blenderbim/blenderbim/bim/module/root/operator.py index 6971353be0..ee57c74f0f 100644 --- a/src/blenderbim/blenderbim/bim/module/root/operator.py +++ b/src/blenderbim/blenderbim/bim/module/root/operator.py @@ -31,7 +31,8 @@ import blenderbim.core.root as core import blenderbim.tool as tool from ifcopenshell.api.void.data import Data as VoidData from blenderbim.bim.ifc import IfcStore -from blenderbim.bim.module.root.prop import get_contexts, get_ifc_classes_filtered +from blenderbim.bim.module.root.prop import get_contexts +from blenderbim.bim.prop import StrProperty class Operator: @@ -191,22 +192,25 @@ class CopyClass(bpy.types.Operator, Operator): blenderbim.bim.handler.purge_module_data() -class BIM_OT_root_property_textfield(bpy.types.Operator): - bl_idname = "bim.root_ifc_class_filter" - bl_label = "Filter Property" +class BIM_OT_enum_property_search(bpy.types.Operator): + bl_idname = "bim.enum_property_search" + bl_label = "Search For Property" bl_options = {"REGISTER", "UNDO"} + prop_name: bpy.props.StringProperty() + collection: bpy.props.CollectionProperty(type=StrProperty) def invoke(self, context, event): + self.data = context.data + getter = self.data.getter_enum.get(self.prop_name, None) + if getter is None: + return {"FINISHED"} + self.collection.clear() + for item in getter(self.data, context): + self.collection.add().name = item[0] return context.window_manager.invoke_props_dialog(self) def execute(self, context): - context.scene.BIMRootProperties.ifc_class = context.scene.BIMRootProperties.ifc_class_filter_enum return {"FINISHED"} def draw(self, context): - props = context.scene.BIMRootProperties - self.layout.prop(props, "ifc_class_filter_textfield") - if len(get_ifc_classes_filtered(props, context)) > 10: - self.layout.prop(props, "ifc_class_filter_enum") - else: - self.layout.props_enum(props, "ifc_class_filter_enum") + self.layout.prop_search(self.data, self.prop_name, self, "collection") diff --git a/src/blenderbim/blenderbim/bim/module/root/prop.py b/src/blenderbim/blenderbim/bim/module/root/prop.py index eeceb1b3f6..8e3fbeca94 100644 --- a/src/blenderbim/blenderbim/bim/module/root/prop.py +++ b/src/blenderbim/blenderbim/bim/module/root/prop.py @@ -21,6 +21,7 @@ import ifcopenshell import ifcopenshell.util.schema from blenderbim.bim.module.root.data import IfcClassData from blenderbim.bim.ifc import IfcStore +from blenderbim.bim.prop import StrProperty from bpy.types import PropertyGroup from bpy.props import ( PointerProperty, @@ -88,15 +89,6 @@ def get_ifc_classes(self, context): return IfcClassData.data["ifc_classes"] -def get_ifc_classes_filtered(self, context): - ifc_classes = get_ifc_classes(self, context) - global classes_enum - classes_enum = [ - c for c in ifc_classes - if self.ifc_class_filter_textfield.lower() in c[0].lower()] or ifc_classes - return classes_enum - - def get_contexts(self, context): if not IfcClassData.is_loaded: IfcClassData.load() @@ -107,7 +99,12 @@ class BIMRootProperties(PropertyGroup): contexts: EnumProperty(items=get_contexts, name="Contexts") ifc_product: EnumProperty(items=get_ifc_products, name="Products", update=refresh_classes) ifc_class: EnumProperty(items=get_ifc_classes, name="Class", update=refreshPredefinedTypes) - ifc_class_filter_textfield: StringProperty(name="Filter", options={"TEXTEDIT_UPDATE"}) - ifc_class_filter_enum: EnumProperty(items=get_ifc_classes_filtered, name="Class", update=update_class_enum) ifc_predefined_type: EnumProperty(items=getIfcPredefinedTypes, name="Predefined Type", default=None) ifc_userdefined_type: StringProperty(name="Userdefined Type") + + getter_enum = { + "contexts": get_contexts, + "ifc_product": get_ifc_products, + "ifc_class": get_ifc_classes, + "ifc_predefined_type": getIfcPredefinedTypes, + } diff --git a/src/blenderbim/blenderbim/bim/module/root/ui.py b/src/blenderbim/blenderbim/bim/module/root/ui.py index a7c61e7814..b6a5f99268 100644 --- a/src/blenderbim/blenderbim/bim/module/root/ui.py +++ b/src/blenderbim/blenderbim/bim/module/root/ui.py @@ -20,6 +20,7 @@ import bpy import blenderbim.bim.module.root.prop as root_prop from bpy.types import Panel from blenderbim.bim.ifc import IfcStore +from blenderbim.bim.ui import prop_with_search from blenderbim.bim.module.root.data import IfcClassData @@ -76,18 +77,14 @@ class BIM_PT_class(Panel): def draw_class_dropdowns(self, context, ifc_predefined_types, is_reassigning_class=False): props = context.scene.BIMRootProperties + layout = self.layout if not is_reassigning_class: - row = self.layout.row() - row.prop(props, "ifc_product") - row = self.layout.row(align=True) - row.prop(props, "ifc_class") - row.operator("bim.root_ifc_class_filter", text="", icon="VIEWZOOM") + prop_with_search(layout, props, "ifc_product") + prop_with_search(layout, props, "ifc_class") if ifc_predefined_types: - row = self.layout.row() - row.prop(props, "ifc_predefined_type") - if ifc_predefined_types == "USERDEFINED": - row = self.layout.row() - row.prop(props, "ifc_userdefined_type") + prop_with_search(layout, props, "ifc_predefined_type") + if props.ifc_predefined_type == "USERDEFINED": + row = layout.row() + row.prop(props, "ifc_userdefined_type") if not is_reassigning_class: - row = self.layout.row() - row.prop(context.scene.BIMRootProperties, "contexts") + prop_with_search(layout, props, "contexts") diff --git a/src/blenderbim/blenderbim/bim/module/unit/prop.py b/src/blenderbim/blenderbim/bim/module/unit/prop.py index 22ef9c7a0e..f631ac1b69 100644 --- a/src/blenderbim/blenderbim/bim/module/unit/prop.py +++ b/src/blenderbim/blenderbim/bim/module/unit/prop.py @@ -68,3 +68,9 @@ class BIMUnitProperties(PropertyGroup): conversion_unit_types: EnumProperty(items=get_conversion_unit_types, name="Conversion Unit Types") named_unit_types: EnumProperty(items=get_named_unit_types, name="Named Unit Types") unit_attributes: CollectionProperty(name="Unit Attributes", type=Attribute) + + getter_enum = { + "unit_classes": get_unit_classes, + "conversion_unit_types": get_conversion_unit_types, + "named_unit_types": get_named_unit_types, + } diff --git a/src/blenderbim/blenderbim/bim/module/unit/ui.py b/src/blenderbim/blenderbim/bim/module/unit/ui.py index a6d13447f5..183ed5cbe7 100644 --- a/src/blenderbim/blenderbim/bim/module/unit/ui.py +++ b/src/blenderbim/blenderbim/bim/module/unit/ui.py @@ -19,6 +19,7 @@ import blenderbim.bim.helper from bpy.types import Panel, UIList from blenderbim.bim.ifc import IfcStore +from blenderbim.bim.ui import prop_with_search from blenderbim.bim.module.unit.data import UnitsData @@ -53,22 +54,22 @@ class BIM_PT_units(Panel): return row = self.layout.row(align=True) - row.prop(self.props, "unit_classes", text="") + prop_with_search(row, self.props, "unit_classes", text="") if self.props.unit_classes == "IfcMonetaryUnit": row.operator("bim.add_monetary_unit", text="", icon="ADD") elif self.props.unit_classes in ("IfcConversionBasedUnit", "IfcConversionBasedUnitWithOffset"): - row.prop(self.props, "conversion_unit_types", text="") + prop_with_search(row, self.props, "conversion_unit_types", text="") op = row.operator("bim.add_conversion_based_unit", text="", icon="ADD") op.name = self.props.conversion_unit_types elif self.props.unit_classes == "IfcDerivedUnit": pass # TODO elif self.props.unit_classes == "IfcSIUnit": - row.prop(self.props, "named_unit_types", text="") + prop_with_search(row, self.props, "named_unit_types", text="") op = row.operator("bim.add_si_unit", text="", icon="ADD") op.unit_type = self.props.named_unit_types elif self.props.unit_classes == "IfcContextDependentUnit": - row.prop(self.props, "named_unit_types", text="") + prop_with_search(row, self.props, "named_unit_types", text="") op = row.operator("bim.add_context_dependent_unit", text="", icon="ADD") op.name = "THINGAMAJIG" op.unit_type = self.props.named_unit_types diff --git a/src/blenderbim/blenderbim/bim/ui.py b/src/blenderbim/blenderbim/bim/ui.py index 2457cd99bf..e04e05d5be 100644 --- a/src/blenderbim/blenderbim/bim/ui.py +++ b/src/blenderbim/blenderbim/bim/ui.py @@ -170,6 +170,15 @@ class BIM_ADDON_preferences(bpy.types.AddonPreferences): row.operator("bim.configure_visibility") +def prop_with_search(layout, data, prop_name, **kwargs): # Kwargs are layout.prop arguments (text, icon, etc.) + row = layout.row(align=True) + # Magick courtesy of https://blender.stackexchange.com/a/203443/86891 + row.context_pointer_set(name="data", data=data) + row.prop(data, prop_name, **kwargs) + op = row.operator("bim.enum_property_search", text="", icon="VIEWZOOM") + op.prop_name = prop_name + + def ifc_units(self, context): scene = context.scene props = scene.BIMProperties From 018be92063b370687fde127b93780f89d92d84d2 Mon Sep 17 00:00:00 2001 From: Vukas Pajic <83825269+vulevukusej@users.noreply.github.com> Date: Mon, 4 Jul 2022 13:48:51 +0200 Subject: [PATCH 05/24] support enums in new pset_templates --- src/blenderbim/blenderbim/bim/helper.py | 2 +- .../blenderbim/bim/module/pset/operator.py | 2 +- .../bim/module/pset_template/__init__.py | 5 + .../bim/module/pset_template/operator.py | 105 +++++++++++++++++- .../bim/module/pset_template/prop.py | 32 +++++- .../blenderbim/bim/module/pset_template/ui.py | 33 +++++- .../api/pset_template/add_prop_template.py | 1 + .../ifcopenshell/api/pset_template/data.py | 2 + 8 files changed, 173 insertions(+), 9 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/helper.py b/src/blenderbim/blenderbim/bim/helper.py index 6703bda0dc..8dc2442216 100644 --- a/src/blenderbim/blenderbim/bim/helper.py +++ b/src/blenderbim/blenderbim/bim/helper.py @@ -40,7 +40,7 @@ def draw_attribute(attribute, layout, copy_operator=None): return if len(attribute.enumerated_values) != 0: layout.label(text=attribute.name) - grid = layout.column_flow(columns=4) + grid = layout.column_flow(columns=3) for e in attribute.enumerated_values: grid.prop( e, diff --git a/src/blenderbim/blenderbim/bim/module/pset/operator.py b/src/blenderbim/blenderbim/bim/module/pset/operator.py index 1829ebee78..72d03570ad 100644 --- a/src/blenderbim/blenderbim/bim/module/pset/operator.py +++ b/src/blenderbim/blenderbim/bim/module/pset/operator.py @@ -412,7 +412,7 @@ class BIM_OT_add_property_to_edit(bpy.types.Operator): bl_idname = "bim.add_property_to_edit" bl_options = {"REGISTER", "UNDO"} option: bpy.props.StringProperty() - index: bpy.props.IntProperty() + index: bpy.props.IntProperty(default=-1) def execute(self, context): if self.index == -1: diff --git a/src/blenderbim/blenderbim/bim/module/pset_template/__init__.py b/src/blenderbim/blenderbim/bim/module/pset_template/__init__.py index e4e5591da4..1f822620da 100644 --- a/src/blenderbim/blenderbim/bim/module/pset_template/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/pset_template/__init__.py @@ -20,6 +20,8 @@ import bpy from . import ui, prop, operator classes = ( + operator.RefreshPsetTemplates, + operator.AddPsetFile, operator.SavePsetTemplateFile, operator.AddPsetTemplate, operator.EditPsetTemplate, @@ -30,8 +32,11 @@ classes = ( operator.EnableEditingPsetTemplate, operator.DisableEditingPsetTemplate, operator.EnableEditingPropTemplate, + operator.DeletePropEnum, + operator.AddPropEnum, operator.DisableEditingPropTemplate, prop.PsetTemplate, + prop.EnumerationValues, prop.PropTemplate, prop.BIMPsetTemplateProperties, ui.BIM_PT_pset_template, diff --git a/src/blenderbim/blenderbim/bim/module/pset_template/operator.py b/src/blenderbim/blenderbim/bim/module/pset_template/operator.py index 8699f6d327..9013a6901f 100644 --- a/src/blenderbim/blenderbim/bim/module/pset_template/operator.py +++ b/src/blenderbim/blenderbim/bim/module/pset_template/operator.py @@ -16,16 +16,66 @@ # You should have received a copy of the GNU General Public License # along with BlenderBIM Add-on. If not, see . +import os import bpy import ifcopenshell import ifcopenshell.api import blenderbim.bim.schema import blenderbim.bim.handler -from blenderbim.bim.module.pset_template.prop import updatePsetTemplateFiles, updatePsetTemplates, getPsetTemplates +from blenderbim.bim.module.pset_template.prop import purge as purge_templates, updatePsetTemplates, getPsetTemplates +from blenderbim.bim.module.pset.prop import purge as purge_psets from ifcopenshell.api.pset_template.data import Data from blenderbim.bim.ifc import IfcStore +#This is just a temporary operator until +#@Moult performs some of his refactor-magic ;) - vulevukusej +class RefreshPsetTemplates(bpy.types.Operator): + bl_idname = "bim.refresh_psettemplates" + bl_label = "Refresh the data for PsetTemplates" + bl_options = {"REGISTER", "UNDO"} + + def execute(self, context): + purge_templates() + purge_psets() + return {"FINISHED"} + + +class AddPsetFile(bpy.types.Operator): + bl_idname = "bim.add_pset_file" + bl_label = "Add Pset File" + bl_options = {"REGISTER", "UNDO"} + + def invoke(self, context, event): + return context.window_manager.invoke_props_dialog(self, width=250) + + def draw(self, context): + self.props = context.scene.BIMPsetTemplateProperties + self.layout.prop(self.props, "new_template_filename", text="Filename:") + + def execute(self, context): + template = ifcopenshell.file() + filepath = os.path.join( + context.scene.BIMProperties.data_dir, + "pset", + self.props.new_template_filename + ".ifc", + ) + + template.create_entity( + "IFCPROPERTYSETTEMPLATE", + **{ + "GlobalId": ifcopenshell.guid.new(), + "Name": "Name", + "Description": "Description", + "TemplateType": "PSET_TYPEDRIVENONLY", + "ApplicableEntity": "IfcTypeObject" + } + ) + template.write(filepath) + self.props.new_template_filename = "" + return {"FINISHED"} + + class AddPsetTemplate(bpy.types.Operator): bl_idname = "bim.add_pset_template" bl_label = "Add Pset Template" @@ -41,7 +91,6 @@ class AddPsetTemplate(bpy.types.Operator): return result def _execute(self, context): - props = context.scene.BIMPsetTemplateProperties ifcopenshell.api.run("pset_template.add_pset_template", IfcStore.pset_template_file) Data.load(IfcStore.pset_template_file) updatePsetTemplates(self, context) @@ -139,6 +188,38 @@ class EnableEditingPropTemplate(bpy.types.Operator): props.active_prop_template.name = template["Name"] or "" props.active_prop_template.description = template["Description"] or "" props.active_prop_template.primary_measure_type = template["PrimaryMeasureType"] + props.active_prop_template.template_type = template["TemplateType"] + props.active_prop_template.enum_values.clear() + + if template["Enumerators"]: + props.active_prop_template.enum_values.clear() + data_type = props.active_prop_template.get_value_name() + for e in template["Enumerators"].EnumerationValues: + new = props.active_prop_template.enum_values.add() + setattr(new, data_type, e.wrappedValue) + + return {"FINISHED"} + +class DeletePropEnum(bpy.types.Operator): + bl_idname = "bim.delete_prop_enum" + bl_label = "delete property enumeration" + bl_options = {"REGISTER", "UNDO"} + index: bpy.props.IntProperty() + + def execute(self, context): + active_prop = context.scene.BIMPsetTemplateProperties.active_prop_template + active_prop.enum_values.remove(self.index) + return {"FINISHED"} + +class AddPropEnum(bpy.types.Operator): + bl_idname = "bim.add_prop_enum" + bl_label = "add property enumeration" + bl_options = {"REGISTER", "UNDO"} + index: bpy.props.IntProperty() + + def execute(self, context): + active_prop = context.scene.BIMPsetTemplateProperties.active_prop_template + active_prop.enum_values.add() return {"FINISHED"} @@ -285,6 +366,10 @@ class EditPropTemplate(bpy.types.Operator): def _execute(self, context): props = context.scene.BIMPsetTemplateProperties + if props.active_prop_template.template_type == "P_ENUMERATEDVALUE": + enumerator = self.generate_prop_enum(props) + else: + enumerator = None ifcopenshell.api.run( "pset_template.edit_prop_template", IfcStore.pset_template_file, @@ -294,12 +379,28 @@ class EditPropTemplate(bpy.types.Operator): "Name": props.active_prop_template.name, "Description": props.active_prop_template.description, "PrimaryMeasureType": props.active_prop_template.primary_measure_type, + "TemplateType": props.active_prop_template.template_type, + "Enumerators": enumerator }, } ) Data.load(IfcStore.pset_template_file) bpy.ops.bim.disable_editing_prop_template() return {"FINISHED"} + + #TODO -This will need to go into the + # api code at some point - vulevukusej + def generate_prop_enum(self, props): + self.file = IfcStore.pset_template_file + data_type = props.active_prop_template.get_value_name() + prop = props.active_prop_template + prop_enum = self.file.create_entity( + "IFCPROPERTYENUMERATION", + Name=prop.name, + EnumerationValues=tuple(self.file.create_entity( + prop.primary_measure_type, ev[data_type]) for ev in prop.enum_values) + ) + return prop_enum def rollback(self, data): IfcStore.pset_template_file.undo() diff --git a/src/blenderbim/blenderbim/bim/module/pset_template/prop.py b/src/blenderbim/blenderbim/bim/module/pset_template/prop.py index 1cb59a22ed..4554c229c4 100644 --- a/src/blenderbim/blenderbim/bim/module/pset_template/prop.py +++ b/src/blenderbim/blenderbim/bim/module/pset_template/prop.py @@ -146,16 +146,43 @@ class PsetTemplate(PropertyGroup): applicable_entity: StringProperty(name="Applicable Entity") +class EnumerationValues(PropertyGroup): + string_value: StringProperty(name="Value") + bool_value: BoolProperty(name="Value") + int_value: IntProperty(name="Value") + float_value: FloatProperty(name="Value") + + class PropTemplate(PropertyGroup): global_id: StringProperty(name="Global ID") name: StringProperty(name="Name") description: StringProperty(name="Description") primary_measure_type: EnumProperty(items=get_primary_measure_type, name="Primary Measure Type") - + template_type: EnumProperty( + items=[ + ("P_SINGLEVALUE","P_SINGLEVALUE",""), + ("P_ENUMERATEDVALUE","P_ENUMERATEDVALUE","") + ], + name="Template Type" + ) + enum_values: CollectionProperty(type=EnumerationValues) getter_enum = { "primary_measure_type": get_primary_measure_type, } + + def get_value_name(self): + ifc_data_type = IfcStore.get_schema().declaration_by_name(self.primary_measure_type) + data_type = ifcopenshell.util.attribute.get_primitive_type(ifc_data_type) + if data_type == "string": + return "string_value" + elif data_type == "boolean": + return "bool_value" + elif data_type == "integer": + return "int_value" + elif data_type == "float": + return "float_value" + class BIMPsetTemplateProperties(PropertyGroup): pset_template_files: EnumProperty( @@ -166,7 +193,8 @@ class BIMPsetTemplateProperties(PropertyGroup): active_prop_template_id: IntProperty(name="Active Prop Template Id") active_pset_template: PointerProperty(type=PsetTemplate) active_prop_template: PointerProperty(type=PropTemplate) - + new_template_filename: StringProperty("New TemplateFileName") + getter_enum = { "pset_template_files": getPsetTemplateFiles, "pset_templates": getPsetTemplates, diff --git a/src/blenderbim/blenderbim/bim/module/pset_template/ui.py b/src/blenderbim/blenderbim/bim/module/pset_template/ui.py index 058f4e9b59..858f856711 100644 --- a/src/blenderbim/blenderbim/bim/module/pset_template/ui.py +++ b/src/blenderbim/blenderbim/bim/module/pset_template/ui.py @@ -38,11 +38,13 @@ class BIM_PT_pset_template(Panel): def draw(self, context): layout = self.layout props = context.scene.BIMPsetTemplateProperties - + row = layout.row(align=True) prop_with_search(row, props, "pset_template_files", text="") row.operator("bim.save_pset_template_file", text="", icon="EXPORT") - + row.operator("bim.add_pset_file",icon="ADD",text="") + row.operator("bim.refresh_psettemplates", icon="FILE_REFRESH", text="") + row = layout.row(align=True) if bool(getPsetTemplates(props, context)): @@ -74,7 +76,7 @@ class BIM_PT_pset_template(Panel): row.prop(props.active_pset_template, "template_type") row = layout.row() row.prop(props.active_pset_template, "applicable_entity") - else: + else: pset_template = Data.pset_templates[int(props.pset_templates)] for name, value in pset_template.items(): if name == "id" or name == "type" or name == "HasPropertyTemplates": @@ -86,6 +88,9 @@ class BIM_PT_pset_template(Panel): row = layout.row(align=True) row.label(text="Property Templates", icon="COPY_ID") row.operator("bim.add_prop_template", icon="ADD", text="") + + row = layout.row() + row.label(text="Name | Description | PrimaryMeasureType | TemplateType") for prop_template_id in pset_template["HasPropertyTemplates"]: prop_template = Data.prop_templates[prop_template_id] @@ -95,10 +100,32 @@ class BIM_PT_pset_template(Panel): row.prop(props.active_prop_template, "name", text="") row.prop(props.active_prop_template, "description", text="") prop_with_search(row, props.active_prop_template, "primary_measure_type", text="") + row.prop(props.active_prop_template, "template_type", text="") + + if props.active_prop_template.template_type == "P_ENUMERATEDVALUE": + row = layout.row(align=True) + split = row.split(factor=0.2) + c=split.column() + c.label(text="Enumerations:",) + + c=split.column() + box = c.box() + grid = box.column_flow(columns=4) + value_name = props.active_prop_template.get_value_name() + r = grid.row() + r.operator("bim.add_prop_enum", text="Add Enum") + for k,v in enumerate(props.active_prop_template.enum_values): + r = grid.row(align=True) + r.prop(v, value_name, text="") + op = r.operator("bim.delete_prop_enum", icon="X", text="") + op.index = k + + else: row.label(text=prop_template["Name"]) row.label(text=prop_template["Description"]) row.label(text=prop_template["PrimaryMeasureType"]) + row.label(text=prop_template["TemplateType"]) if props.active_prop_template_id and props.active_prop_template_id == prop_template_id: op = row.operator("bim.edit_prop_template", icon="CHECKMARK", text="") diff --git a/src/ifcopenshell-python/ifcopenshell/api/pset_template/add_prop_template.py b/src/ifcopenshell-python/ifcopenshell/api/pset_template/add_prop_template.py index 3c3d9cc334..10061e2ec3 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/pset_template/add_prop_template.py +++ b/src/ifcopenshell-python/ifcopenshell/api/pset_template/add_prop_template.py @@ -35,6 +35,7 @@ class Usecase: "PrimaryMeasureType": "IfcLabel", "TemplateType": "P_SINGLEVALUE", "AccessState": "READWRITE", + "Enumerators": None } ) has_property_templates = list(self.settings["pset_template"].HasPropertyTemplates or []) diff --git a/src/ifcopenshell-python/ifcopenshell/api/pset_template/data.py b/src/ifcopenshell-python/ifcopenshell/api/pset_template/data.py index 2a1adda379..71b255cc41 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/pset_template/data.py +++ b/src/ifcopenshell-python/ifcopenshell/api/pset_template/data.py @@ -49,5 +49,7 @@ class Data: "Name": data["Name"], "Description": data["Description"], "PrimaryMeasureType": data["PrimaryMeasureType"], + "TemplateType": data["TemplateType"], + "Enumerators": data["Enumerators"] } cls.is_loaded = True From c7272065e6f7ac4e9e20fc2e779684d3cb8c59bc Mon Sep 17 00:00:00 2001 From: Gorgious56 Date: Mon, 4 Jul 2022 23:09:03 +0200 Subject: [PATCH 06/24] Improve prop search v2 (#2262) * Minor fixes * Fix #2257 : enums with a different id and name now correctly show the name in the search field * Add prop search to template_type --- src/blenderbim/blenderbim/bim/__init__.py | 1 + .../bim/module/pset_template/prop.py | 102 +++++++++--------- .../blenderbim/bim/module/pset_template/ui.py | 3 +- .../blenderbim/bim/module/root/__init__.py | 1 - .../blenderbim/bim/module/root/operator.py | 33 +----- .../blenderbim/bim/module/root/prop.py | 1 - src/blenderbim/blenderbim/bim/operator.py | 39 +++++++ 7 files changed, 98 insertions(+), 82 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/__init__.py b/src/blenderbim/blenderbim/bim/__init__.py index c29a3f9298..3ad281d07d 100644 --- a/src/blenderbim/blenderbim/bim/__init__.py +++ b/src/blenderbim/blenderbim/bim/__init__.py @@ -93,6 +93,7 @@ classes = [ operator.SelectSchemaDir, operator.SelectURIAttribute, prop.StrProperty, + operator.BIM_OT_enum_property_search, # /!\ Register AFTER prop.StrProperty prop.ObjProperty, prop.Attribute, prop.ModuleVisibility, diff --git a/src/blenderbim/blenderbim/bim/module/pset_template/prop.py b/src/blenderbim/blenderbim/bim/module/pset_template/prop.py index 4554c229c4..eb648969d0 100644 --- a/src/blenderbim/blenderbim/bim/module/pset_template/prop.py +++ b/src/blenderbim/blenderbim/bim/module/pset_template/prop.py @@ -94,65 +94,70 @@ def get_primary_measure_type(self, context): return PsetTemplatesData.data["primary_measure_type"] +def get_template_type(self, context): + return [ + ( + "PSET_TYPEDRIVENONLY", + "Pset - IfcTypeObject", + "The property sets defined by this IfcPropertySetTemplate can only be assigned to subtypes of IfcTypeObject.", + ), + ( + "PSET_TYPEDRIVENOVERRIDE", + "Pset - IfcTypeObject - Override", + "The property sets defined by this IfcPropertySetTemplate can only be assigned to subtypes of IfcTypeObject.", + ), + ( + "PSET_OCCURRENCEDRIVEN", + "Pset - IfcObject", + "The property sets defined by this IfcPropertySetTemplate can only be assigned to subtypes of IfcObject.", + ), + ( + "PSET_PERFORMANCEDRIVEN", + "Pset - IfcPerformanceHistory", + "The property sets defined by this IfcPropertySetTemplate can only be assigned to IfcPerformanceHistory.", + ), + ( + "QTO_TYPEDRIVENONLY", + "Qto - IfcTypeObject", + "The element quantity defined by this IfcPropertySetTemplate can only be assigned to subtypes of IfcTypeObject.", + ), + ( + "QTO_TYPEDRIVENOVERRIDE", + "Qto - IfcTypeObject - Override", + "The element quantity defined by this IfcPropertySetTemplate can be assigned to subtypes of IfcTypeObject and can be overridden by an element quantity with same name at subtypes of IfcObject.", + ), + ( + "QTO_OCCURRENCEDRIVEN", + "Qto - IfcObject", + "The element quantity defined by this IfcPropertySetTemplate can only be assigned to subtypes of IfcObject.", + ), + ( + "NOTDEFINED", + "Not defined", + "No restriction provided, the property sets defined by this IfcPropertySetTemplate can be assigned to any entity, if not otherwise restricted by the ApplicableEntity attribute.", + ), + ] + + class PsetTemplate(PropertyGroup): global_id: StringProperty(name="Global ID") name: StringProperty(name="Name") description: StringProperty(name="Description") - template_type: EnumProperty( - items=[ - ( - "PSET_TYPEDRIVENONLY", - "Pset - IfcTypeObject", - "The property sets defined by this IfcPropertySetTemplate can only be assigned to subtypes of IfcTypeObject.", - ), - ( - "PSET_TYPEDRIVENOVERRIDE", - "Pset - IfcTypeObject - Override", - "The property sets defined by this IfcPropertySetTemplate can only be assigned to subtypes of IfcTypeObject.", - ), - ( - "PSET_OCCURRENCEDRIVEN", - "Pset - IfcObject", - "The property sets defined by this IfcPropertySetTemplate can only be assigned to subtypes of IfcObject.", - ), - ( - "PSET_PERFORMANCEDRIVEN", - "Pset - IfcPerformanceHistory", - "The property sets defined by this IfcPropertySetTemplate can only be assigned to IfcPerformanceHistory.", - ), - ( - "QTO_TYPEDRIVENONLY", - "Qto - IfcTypeObject", - "The element quantity defined by this IfcPropertySetTemplate can only be assigned to subtypes of IfcTypeObject.", - ), - ( - "QTO_TYPEDRIVENOVERRIDE", - "Qto - IfcTypeObject - Override", - "The element quantity defined by this IfcPropertySetTemplate can be assigned to subtypes of IfcTypeObject and can be overridden by an element quantity with same name at subtypes of IfcObject.", - ), - ( - "QTO_OCCURRENCEDRIVEN", - "Qto - IfcObject", - "The element quantity defined by this IfcPropertySetTemplate can only be assigned to subtypes of IfcObject.", - ), - ( - "NOTDEFINED", - "Not defined", - "No restriction provided, the property sets defined by this IfcPropertySetTemplate can be assigned to any entity, if not otherwise restricted by the ApplicableEntity attribute.", - ), - ], - name="Template Type", - ) + template_type: EnumProperty(items=get_template_type, name="Template Type") applicable_entity: StringProperty(name="Applicable Entity") + getter_enum = { + "template_type": lambda self, context: get_template_type(self, context), + } + class EnumerationValues(PropertyGroup): string_value: StringProperty(name="Value") bool_value: BoolProperty(name="Value") int_value: IntProperty(name="Value") float_value: FloatProperty(name="Value") - - + + class PropTemplate(PropertyGroup): global_id: StringProperty(name="Global ID") name: StringProperty(name="Name") @@ -170,7 +175,6 @@ class PropTemplate(PropertyGroup): "primary_measure_type": get_primary_measure_type, } - def get_value_name(self): ifc_data_type = IfcStore.get_schema().declaration_by_name(self.primary_measure_type) data_type = ifcopenshell.util.attribute.get_primitive_type(ifc_data_type) @@ -194,7 +198,7 @@ class BIMPsetTemplateProperties(PropertyGroup): active_pset_template: PointerProperty(type=PsetTemplate) active_prop_template: PointerProperty(type=PropTemplate) new_template_filename: StringProperty("New TemplateFileName") - + getter_enum = { "pset_template_files": getPsetTemplateFiles, "pset_templates": getPsetTemplates, diff --git a/src/blenderbim/blenderbim/bim/module/pset_template/ui.py b/src/blenderbim/blenderbim/bim/module/pset_template/ui.py index 858f856711..1c914f83d3 100644 --- a/src/blenderbim/blenderbim/bim/module/pset_template/ui.py +++ b/src/blenderbim/blenderbim/bim/module/pset_template/ui.py @@ -72,8 +72,7 @@ class BIM_PT_pset_template(Panel): row.prop(props.active_pset_template, "name") row = layout.row() row.prop(props.active_pset_template, "description") - row = layout.row() - row.prop(props.active_pset_template, "template_type") + prop_with_search(layout, props.active_pset_template, "template_type") row = layout.row() row.prop(props.active_pset_template, "applicable_entity") else: diff --git a/src/blenderbim/blenderbim/bim/module/root/__init__.py b/src/blenderbim/blenderbim/bim/module/root/__init__.py index 523f3b77cd..00a36e0817 100644 --- a/src/blenderbim/blenderbim/bim/module/root/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/root/__init__.py @@ -26,7 +26,6 @@ classes = ( operator.EnableReassignClass, operator.ReassignClass, operator.UnlinkObject, - operator.BIM_OT_enum_property_search, prop.BIMRootProperties, ui.BIM_PT_class, ) diff --git a/src/blenderbim/blenderbim/bim/module/root/operator.py b/src/blenderbim/blenderbim/bim/module/root/operator.py index ee57c74f0f..b2c39b7b44 100644 --- a/src/blenderbim/blenderbim/bim/module/root/operator.py +++ b/src/blenderbim/blenderbim/bim/module/root/operator.py @@ -31,8 +31,6 @@ import blenderbim.core.root as core import blenderbim.tool as tool from ifcopenshell.api.void.data import Data as VoidData from blenderbim.bim.ifc import IfcStore -from blenderbim.bim.module.root.prop import get_contexts -from blenderbim.bim.prop import StrProperty class Operator: @@ -128,12 +126,13 @@ class AssignClass(bpy.types.Operator, Operator): ifc_representation_class: bpy.props.StringProperty() def _execute(self, context): + props = context.scene.BIMRootProperties objects = [bpy.data.objects.get(self.obj)] if self.obj else context.selected_objects - ifc_class = self.ifc_class or context.scene.BIMRootProperties.ifc_class + ifc_class = self.ifc_class or props.ifc_class predefined_type = self.userdefined_type if self.predefined_type == "USERDEFINED" else self.predefined_type ifc_context = self.context_id - if not ifc_context and get_contexts(self, context): - ifc_context = int(context.scene.BIMRootProperties.contexts or "0") or None + if not ifc_context and props.getter_enum["contexts"](props, context): + ifc_context = int(props.contexts or "0") or None if ifc_context: ifc_context = tool.Ifc.get().by_id(ifc_context) active_object = context.active_object @@ -190,27 +189,3 @@ class CopyClass(bpy.types.Operator, Operator): for obj in objects: core.copy_class(tool.Ifc, tool.Collector, tool.Geometry, tool.Root, obj=obj) blenderbim.bim.handler.purge_module_data() - - -class BIM_OT_enum_property_search(bpy.types.Operator): - bl_idname = "bim.enum_property_search" - bl_label = "Search For Property" - bl_options = {"REGISTER", "UNDO"} - prop_name: bpy.props.StringProperty() - collection: bpy.props.CollectionProperty(type=StrProperty) - - def invoke(self, context, event): - self.data = context.data - getter = self.data.getter_enum.get(self.prop_name, None) - if getter is None: - return {"FINISHED"} - self.collection.clear() - for item in getter(self.data, context): - self.collection.add().name = item[0] - return context.window_manager.invoke_props_dialog(self) - - def execute(self, context): - return {"FINISHED"} - - def draw(self, context): - self.layout.prop_search(self.data, self.prop_name, self, "collection") diff --git a/src/blenderbim/blenderbim/bim/module/root/prop.py b/src/blenderbim/blenderbim/bim/module/root/prop.py index 8e3fbeca94..2b009a551b 100644 --- a/src/blenderbim/blenderbim/bim/module/root/prop.py +++ b/src/blenderbim/blenderbim/bim/module/root/prop.py @@ -21,7 +21,6 @@ import ifcopenshell import ifcopenshell.util.schema from blenderbim.bim.module.root.data import IfcClassData from blenderbim.bim.ifc import IfcStore -from blenderbim.bim.prop import StrProperty from bpy.types import PropertyGroup from bpy.props import ( PointerProperty, diff --git a/src/blenderbim/blenderbim/bim/operator.py b/src/blenderbim/blenderbim/bim/operator.py index 7b171961e0..17ec6ed626 100644 --- a/src/blenderbim/blenderbim/bim/operator.py +++ b/src/blenderbim/blenderbim/bim/operator.py @@ -25,6 +25,7 @@ import blenderbim.bim.handler import blenderbim.tool as tool from . import schema from blenderbim.bim.ifc import IfcStore +from blenderbim.bim.prop import StrProperty from blenderbim.bim.ui import IFCFileSelector from mathutils import Vector, Matrix, Euler from math import radians @@ -523,3 +524,41 @@ class ConfigureVisibility(bpy.types.Operator): def execute(self, context): return {"FINISHED"} + + +def update_enum_property_search_prop(self, context): + for i, prop in enumerate(self.collection_name): + if prop.name == self.dummy_name: + setattr(context.data, self.prop_name, self.collection_identifier[i].name) + + +class BIM_OT_enum_property_search(bpy.types.Operator): + bl_idname = "bim.enum_property_search" + bl_label = "Search For Property" + bl_options = {"REGISTER", "UNDO"} + dummy_name: bpy.props.StringProperty(name="Property", update=update_enum_property_search_prop) + collection_name: bpy.props.CollectionProperty(type=StrProperty) + collection_identifier: bpy.props.CollectionProperty(type=StrProperty) + prop_name: bpy.props.StringProperty() + + def invoke(self, context, event): + self.data = context.data + getter = self.data.getter_enum.get(self.prop_name, None) + if getter is None: + return {"FINISHED"} + self.collection_name.clear() + self.collection_identifier.clear() + for item in getter(self.data, context): + self.collection_identifier.add().name = item[0] + if item[0] == getattr(self.data, self.prop_name): + self.dummy_name = item[1] # We found the current enum value + self.collection_name.add().name = item[1] + return context.window_manager.invoke_props_dialog(self) + + def execute(self, context): + return {"FINISHED"} + + def draw(self, context): + # Mandatory to access context.data in update : + self.layout.context_pointer_set(name="data", data=self.data) + self.layout.prop_search(self, "dummy_name", self, "collection_name") From 9e87f0f0272b7fa0e72b939045f6e3a875153985 Mon Sep 17 00:00:00 2001 From: Vukas Pajic <83825269+vulevukusej@users.noreply.github.com> Date: Tue, 5 Jul 2022 07:34:23 +0200 Subject: [PATCH 07/24] fix for issue #2261 --- .../ifcopenshell/api/pset/edit_pset.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/ifcopenshell-python/ifcopenshell/api/pset/edit_pset.py b/src/ifcopenshell-python/ifcopenshell/api/pset/edit_pset.py index 28c307756c..71e6ada005 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/pset/edit_pset.py +++ b/src/ifcopenshell-python/ifcopenshell/api/pset/edit_pset.py @@ -106,7 +106,11 @@ class Usecase: properties.append(value) continue else: - nominal_value = value + properties.append( + self.file.create_entity( + "IfcPropertySingleValue", + **{"Name": name, "NominalValue": value}, + ) #TODO-The following "elif" is temporary code, will need to refactor at some point - vulevukusej elif isinstance(value, list): for pset_template in self.settings["pset_template"].HasPropertyTemplates: @@ -130,12 +134,12 @@ class Usecase: value = self.cast_value_to_primary_measure_type(value, primary_measure_type) nominal_value = self.file.create_entity(primary_measure_type, value) - properties.append( - self.file.create_entity( - "IfcPropertySingleValue", - **{"Name": name, "NominalValue": nominal_value}, + properties.append( + self.file.create_entity( + "IfcPropertySingleValue", + **{"Name": name, "NominalValue": nominal_value}, + ) ) - ) return properties def extend_pset_with_new_properties(self, new_properties): From 6b9e670bf34ebb49c08ff9f0e152e3ab926a2c13 Mon Sep 17 00:00:00 2001 From: Vukas Pajic <83825269+vulevukusej@users.noreply.github.com> Date: Tue, 5 Jul 2022 07:41:51 +0200 Subject: [PATCH 08/24] missing comma --- src/ifcopenshell-python/ifcopenshell/api/pset/edit_pset.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/ifcopenshell-python/ifcopenshell/api/pset/edit_pset.py b/src/ifcopenshell-python/ifcopenshell/api/pset/edit_pset.py index 71e6ada005..5388727517 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/pset/edit_pset.py +++ b/src/ifcopenshell-python/ifcopenshell/api/pset/edit_pset.py @@ -107,9 +107,10 @@ class Usecase: continue else: properties.append( - self.file.create_entity( - "IfcPropertySingleValue", - **{"Name": name, "NominalValue": value}, + self.file.create_entity( + "IfcPropertySingleValue", + **{"Name": name, "NominalValue": value}, + ) ) #TODO-The following "elif" is temporary code, will need to refactor at some point - vulevukusej elif isinstance(value, list): From 2ab4e44248b7061d71689cbe6d64e0ce0510fc3a Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Tue, 5 Jul 2022 09:45:55 +0200 Subject: [PATCH 09/24] #2256 try explicit cast for clang --- src/serializers/SvgSerializer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/serializers/SvgSerializer.cpp b/src/serializers/SvgSerializer.cpp index 96738e9942..9fdfc22586 100644 --- a/src/serializers/SvgSerializer.cpp +++ b/src/serializers/SvgSerializer.cpp @@ -808,7 +808,7 @@ void SvgSerializer::write(const geometry_data& data) { const std::string& ty_entity_name = ty->declaration().name(); // Damn you, IFC if (ty_entity_name == "IfcDoorStyle" || ty_entity_name == "IfcDoorType") { - operation_type = *((IfcUtil::IfcBaseEntity*)ty)->get("OperationType"); + operation_type = (std::string)*((IfcUtil::IfcBaseEntity*)ty)->get("OperationType"); } } } From 952719f19b3b2a3f1733d5db5d7a82a1f10448d9 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Tue, 5 Jul 2022 10:27:44 +0200 Subject: [PATCH 10/24] #2260 correct init order --- src/ifcwrap/IfcGeomWrapper.i | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/ifcwrap/IfcGeomWrapper.i b/src/ifcwrap/IfcGeomWrapper.i index ebc76c9350..4f7f08ca9d 100644 --- a/src/ifcwrap/IfcGeomWrapper.i +++ b/src/ifcwrap/IfcGeomWrapper.i @@ -483,6 +483,15 @@ struct ShapeRTTI : public boost::static_visitor } } + if (!ifc_representation) { + if (reps->size()) { + // Return a random representation + ifc_representation = *reps->begin(); + } else { + throw IfcParse::IfcException("No suitable IfcRepresentation found"); + } + } + // Read precision for found representation's context auto context = ifc_representation->ContextOfItems(); if (context->template as()) { @@ -499,15 +508,6 @@ struct ShapeRTTI : public boost::static_visitor kernel.setValue(IfcGeom::Kernel::GV_PRECISION, p); } - if (!ifc_representation) { - if (reps->size()) { - // Return a random representation - ifc_representation = *reps->begin(); - } else { - throw IfcParse::IfcException("No suitable IfcRepresentation found"); - } - } - IfcGeom::BRepElement* brep = kernel.convert(settings, ifc_representation, product); if (!brep) { throw IfcParse::IfcException("Failed to process shape"); From 87f110bae50f2bbbbda4867d1a5493c5fcc5597b Mon Sep 17 00:00:00 2001 From: Gorgious56 Date: Tue, 5 Jul 2022 15:24:10 +0200 Subject: [PATCH 11/24] Add search operator to material enum field --- src/blenderbim/blenderbim/bim/module/material/prop.py | 4 ++++ src/blenderbim/blenderbim/bim/module/material/ui.py | 8 ++++---- .../blenderbim/bim/module/pset_template/prop.py | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/material/prop.py b/src/blenderbim/blenderbim/bim/module/material/prop.py index 8f400ab07f..88b85fa0ee 100644 --- a/src/blenderbim/blenderbim/bim/module/material/prop.py +++ b/src/blenderbim/blenderbim/bim/module/material/prop.py @@ -137,3 +137,7 @@ class BIMObjectMaterialProperties(PropertyGroup): parameterized_profile_classes: EnumProperty( items=getParameterizedProfileClasses, name="Parameterized Profile Classes" ) + + getter_enum = { + "material": get_materials + } diff --git a/src/blenderbim/blenderbim/bim/module/material/ui.py b/src/blenderbim/blenderbim/bim/module/material/ui.py index d0048f5633..f657ab0a40 100644 --- a/src/blenderbim/blenderbim/bim/module/material/ui.py +++ b/src/blenderbim/blenderbim/bim/module/material/ui.py @@ -22,6 +22,7 @@ from ifcopenshell.api.material.data import Data from ifcopenshell.api.profile.data import Data as ProfileData from blenderbim.bim.ifc import IfcStore from blenderbim.bim.helper import draw_attributes +from blenderbim.bim.ui import prop_with_search from blenderbim.bim.module.material.data import MaterialsData, ObjectMaterialData @@ -190,7 +191,7 @@ class BIM_PT_object_material(Panel): row = self.layout.row(align=True) row.prop(self.props, "material_type", text="") if self.props.material_type == "IfcMaterial" or self.props.material_type == "IfcMaterialList": - row.prop(self.props, "material", text="") + prop_with_search(row, self.props, "material", text="") row.operator("bim.assign_material", icon="ADD", text="") def draw_material_ui(self): @@ -220,8 +221,7 @@ class BIM_PT_object_material(Panel): return self.draw_read_only_single_ui() def draw_editable_single_ui(self): - row = self.layout.row(align=True) - row.prop(self.props, "material", text="") + prop_with_search(self.layout, self.props, "material", text="") def draw_read_only_single_ui(self): material = Data.materials[self.product_data["id"]] @@ -242,7 +242,7 @@ class BIM_PT_object_material(Panel): row.prop(attribute, "string_value", text=attribute.name) row.prop(attribute, "is_null", icon="RADIOBUT_OFF" if attribute.is_null else "RADIOBUT_ON", text="") row = self.layout.row(align=True) - row.prop(self.props, "material", text="") + prop_with_search(row, self.props, "material", text="") op = row.operator(f"bim.add_{self.set_item_name}", icon="ADD", text="") setattr(op, f"{self.set_item_name}_set", self.material_set_id) diff --git a/src/blenderbim/blenderbim/bim/module/pset_template/prop.py b/src/blenderbim/blenderbim/bim/module/pset_template/prop.py index eb648969d0..94acb6c234 100644 --- a/src/blenderbim/blenderbim/bim/module/pset_template/prop.py +++ b/src/blenderbim/blenderbim/bim/module/pset_template/prop.py @@ -147,7 +147,7 @@ class PsetTemplate(PropertyGroup): applicable_entity: StringProperty(name="Applicable Entity") getter_enum = { - "template_type": lambda self, context: get_template_type(self, context), + "template_type": get_template_type, } From 084823164e3014b93eabb14185be8fdafb67f5ce Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Wed, 6 Jul 2022 18:25:29 +1000 Subject: [PATCH 12/24] Fix #2264 refactor property data structures to be separate from attributes --- src/blenderbim/blenderbim/bim/helper.py | 20 +- .../blenderbim/bim/module/pset/__init__.py | 4 +- .../blenderbim/bim/module/pset/operator.py | 190 ++++++++++-------- .../blenderbim/bim/module/pset/prop.py | 24 +-- .../blenderbim/bim/module/pset/ui.py | 42 +++- 5 files changed, 158 insertions(+), 122 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/helper.py b/src/blenderbim/blenderbim/bim/helper.py index 8dc2442216..f0dab98427 100644 --- a/src/blenderbim/blenderbim/bim/helper.py +++ b/src/blenderbim/blenderbim/bim/helper.py @@ -38,21 +38,11 @@ def draw_attribute(attribute, layout, copy_operator=None): if not value_name: layout.label(text=attribute.name) return - if len(attribute.enumerated_values) != 0: - layout.label(text=attribute.name) - grid = layout.column_flow(columns=3) - for e in attribute.enumerated_values: - grid.prop( - e, - "is_selected", - text=str(e[value_name]) - ) - else: - layout.prop( - attribute, - value_name, - text=attribute.name, - ) + layout.prop( + attribute, + value_name, + text=attribute.name, + ) if attribute.is_optional: layout.prop(attribute, "is_null", icon="RADIOBUT_OFF" if attribute.is_null else "RADIOBUT_ON", text="") if copy_operator: diff --git a/src/blenderbim/blenderbim/bim/module/pset/__init__.py b/src/blenderbim/blenderbim/bim/module/pset/__init__.py index c2d845661d..5e04e16662 100644 --- a/src/blenderbim/blenderbim/bim/module/pset/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/pset/__init__.py @@ -35,8 +35,8 @@ classes = ( operator.BIM_OT_rename_parameters, operator.BIM_OT_add_edit_custom_property, operator.BIM_OT_bulk_remove_psets, - prop.EnumerationValues, - prop.IfcSimpleProperty, + prop.IfcPropertyEnumeratedValue, + prop.IfcProperty, prop.PsetProperties, prop.MaterialPsetProperties, prop.TaskPsetProperties, diff --git a/src/blenderbim/blenderbim/bim/module/pset/operator.py b/src/blenderbim/blenderbim/bim/module/pset/operator.py index 72d03570ad..1758806560 100644 --- a/src/blenderbim/blenderbim/bim/module/pset/operator.py +++ b/src/blenderbim/blenderbim/bim/module/pset/operator.py @@ -122,85 +122,91 @@ class EnablePsetEditing(bpy.types.Operator): for prop_template in pset_template.HasPropertyTemplates: if not prop_template.is_a("IfcSimplePropertyTemplate"): continue # Other types not yet supported - if prop_template.TemplateType == "P_SINGLEVALUE": - try: - data_type = ifcopenshell.util.attribute.get_primitive_type( - IfcStore.get_schema().declaration_by_name(prop_template.PrimaryMeasureType or "IfcLabel") - ) - except: - # TODO: Occurs if the data type is something that exists in - # IFC4 and not in IFC2X3. To fully fix this we need to - # generate the IFC2X3 pset template definitions. - continue - elif prop_template.TemplateType in ["Q_LENGTH", "Q_AREA", "Q_VOLUME", "Q_WEIGHT", "Q_TIME"]: - data_type = "float" - elif prop_template.TemplateType == "Q_COUNT": - data_type = "integer" + self.load_single_value(prop_template, data) elif prop_template.TemplateType == "P_ENUMERATEDVALUE": - enum_items = [v.wrappedValue for v in prop_template.Enumerators.EnumerationValues] - #selected_enum_items = [e.EnumerationValues.wrappedValue for e in Data.properties[e]] - data_type = "" - else: - continue # Other types not yet supported + self.load_enumerated_value(prop_template, data) - new = self.props.properties.add() - new.name = prop_template.Name - new.is_null = data.get(prop_template.Name, None) is None - new.is_optional = True - new.is_uri = prop_template.PrimaryMeasureType == "IfcURIReference" - new.data_type = data_type - - if data_type == "string": - new.string_value = "" if new.is_null else data[prop_template.Name] - elif data_type == "integer": - new.int_value = 0 if new.is_null else data[prop_template.Name] - elif data_type == "float": - new.float_value = 0.0 if new.is_null else data[prop_template.Name] - elif data_type == "boolean": - new.bool_value = False if new.is_null else data[prop_template.Name] - if prop_template.TemplateType == "P_ENUMERATEDVALUE": + def load_single_value(self, prop_template, data): + try: + data_type = ifcopenshell.util.attribute.get_primitive_type( + IfcStore.get_schema().declaration_by_name(prop_template.PrimaryMeasureType or "IfcLabel") + ) + except: + # TODO: Occurs if the data type is something that exists in + # IFC4 and not in IFC2X3. To fully fix this we need to + # generate the IFC2X3 pset template definitions. + return - new.set_value(prop_template.Enumerators.EnumerationValues[0].wrappedValue) - - for enum in enum_items: - new_enum = new.enumerated_values.add() - data_type = new.get_value_name() - setattr(new_enum, data_type, enum) - if data.get(prop_template.Name): - new_enum.is_selected = enum in data[prop_template.Name] + prop = self.props.properties.add() + prop.value_type = "IfcPropertySingleValue" + metadata = prop.metadata + metadata.name = prop_template.Name + metadata.is_null = data.get(prop_template.Name, None) is None + metadata.is_optional = True + metadata.is_uri = prop_template.PrimaryMeasureType == "IfcURIReference" + metadata.data_type = data_type + + if data_type == "string": + metadata.string_value = "" if metadata.is_null else data[prop_template.Name] + elif data_type == "integer": + metadata.int_value = 0 if metadata.is_null else data[prop_template.Name] + elif data_type == "float": + metadata.float_value = 0.0 if metadata.is_null else data[prop_template.Name] + elif data_type == "boolean": + metadata.bool_value = False if metadata.is_null else data[prop_template.Name] + + def load_enumerated_value(self, prop_template, data): + enum_items = [v.wrappedValue for v in prop_template.Enumerators.EnumerationValues] + selected_enum_items = data.get(prop_template.Name, []) + + prop = self.props.properties.add() + prop.value_type = "IfcPropertyEnumeratedValue" + metadata = prop.metadata + metadata.name = prop_template.Name + metadata.is_null = data.get(prop_template.Name, None) is None + metadata.is_optional = True + metadata.is_uri = prop_template.PrimaryMeasureType == "IfcURIReference" + + # Cute hack to abuse the metadata to find the Blender data_type + metadata.set_value(enum_items[0]) + data_type = metadata.get_value_name() + + for enum in enum_items: + new = prop.enumerated_value.enumerated_values.add() + setattr(new, data_type, enum) + new.is_selected = enum in selected_enum_items def load_from_pset_data(self, pset_data): for prop_id in pset_data["Properties"]: prop = Data.properties[prop_id] - + if prop["type"] == "IfcPropertyEnumeratedValue": - new = self.props.properties.add() - new.name = prop["Name"] - new.is_null = new.enumerated_values is None - new.is_optional = True - new.set_value(prop["EnumerationReference"].EnumerationValues[0].wrappedValue) - - enum_ref = [v.wrappedValue for v in prop["EnumerationReference"].EnumerationValues] - enum_vals = [v.wrappedValue for v in prop["EnumerationValues"]] - for enum in enum_ref: - new_enum = new.enumerated_values.add() - data_type = new.get_value_name() - setattr(new_enum, data_type, enum) - if enum in enum_vals: - new_enum.is_selected = True - else: - new_enum.is_selected = False - + simple_prop = self.props.properties.add() + simple_prop.value_type = "IfcPropertyEnumeratedValue" + metadata = simple_prop.metadata + metadata.name = prop["Name"] + metadata.is_null = len(simple_prop.enumerated_value.enumerated_values) == 0 + metadata.is_optional = True + metadata.set_value(prop["EnumerationReference"].EnumerationValues[0].wrappedValue) + + enum_items = [v.wrappedValue for v in prop["EnumerationReference"].EnumerationValues] + selected_enum_items = [v.wrappedValue for v in prop["EnumerationValues"]] + data_type = metadata.get_value_name() + + for enum in enum_items: + new = simple_prop.enumerated_value.enumerated_values.add() + setattr(new, data_type, enum) + new.is_selected = enum in selected_enum_items else: value = prop["NominalValue"] - new = self.props.properties.add() - new.set_value(value) - new.name = prop["Name"] - new.is_null = value is None - new.is_optional = True - new.set_value(new.get_value_default() if new.is_null else value) - + prop = self.props.properties.add() + metadata = prop.metadata + metadata.set_value(value) + metadata.name = prop["Name"] + metadata.is_null = value is None + metadata.is_optional = True + metadata.set_value(metadata.get_value_default() if metadata.is_null else value) class DisablePsetEditing(bpy.types.Operator, Operator): @@ -236,11 +242,13 @@ class EditPset(bpy.types.Operator, Operator): else: data = Data.psets if pset_id in Data.psets else Data.qtos for prop in props.properties: - if len(prop.enumerated_values) != 0: - value_name = prop.get_value_name() - properties[prop.name] = [e[value_name] for e in prop.enumerated_values if e.is_selected] - else: - properties[prop.name] = prop.get_value() + if prop.value_type == "IfcPropertySingleValue": + properties[prop.metadata.name] = prop.metadata.get_value() + elif prop.value_type == "IfcPropertyEnumeratedValue": + value_name = prop.metadata.get_value_name() + properties[prop.metadata.name] = [ + e[value_name] for e in prop.enumerated_value.enumerated_values if e.is_selected + ] if pset_id in Data.psets: ifcopenshell.api.run( @@ -507,15 +515,15 @@ class BIM_OT_add_edit_custom_property(bpy.types.Operator): continue ifc_element = tool.Ifc.get().by_id(ifc_definition_id) - for prop in props: + for prop in props: value = getattr(prop, prop.get_value_name()) - primary_measure_type = prop.primary_measure_type - + primary_measure_type = prop.primary_measure_type + if prop.template_type == "IfcPropertyEnumeratedValue": value_ifc_entity = self.generate_enum_entity(prop) elif prop.template_type == "IfcPropertySingleValue": value_ifc_entity = getattr(self.file, f"create{primary_measure_type}")(value) - + new_pset = ifcopenshell.api.run("pset.add_pset", self.file, product=ifc_element, name=prop.pset_name) ifcopenshell.api.run( "pset.edit_pset", self.file, pset=new_pset, properties={prop.property_name: value_ifc_entity} @@ -523,22 +531,26 @@ class BIM_OT_add_edit_custom_property(bpy.types.Operator): Data.load(IfcStore.get_file(), ifc_definition_id) self.report({"INFO"}, "Finished applying changes") return {"FINISHED"} - + def generate_enum_entity(self, prop): prop_type = prop.get_value_name() prop_enum = self.file.create_entity( - "IFCPROPERTYENUMERATION", - Name=prop.property_name, - EnumerationValues=tuple(self.file.create_entity( - prop.primary_measure_type, ev[prop_type]) for ev in prop.enum_values) - ) + "IFCPROPERTYENUMERATION", + Name=prop.property_name, + EnumerationValues=tuple( + self.file.create_entity(prop.primary_measure_type, ev[prop_type]) for ev in prop.enum_values + ), + ) prop_enum_value = self.file.create_entity( - "IFCPROPERTYENUMERATEDVALUE", - Name=prop.property_name, - EnumerationValues=tuple(self.file.create_entity( - prop.primary_measure_type, ev[prop_type]) for ev in prop.enum_values if ev.is_selected == True), - EnumerationReference=prop_enum - ) + "IFCPROPERTYENUMERATEDVALUE", + Name=prop.property_name, + EnumerationValues=tuple( + self.file.create_entity(prop.primary_measure_type, ev[prop_type]) + for ev in prop.enum_values + if ev.is_selected == True + ), + EnumerationReference=prop_enum, + ) return prop_enum_value diff --git a/src/blenderbim/blenderbim/bim/module/pset/prop.py b/src/blenderbim/blenderbim/bim/module/pset/prop.py index 9510329013..7bf754e389 100644 --- a/src/blenderbim/blenderbim/bim/module/pset/prop.py +++ b/src/blenderbim/blenderbim/bim/module/pset/prop.py @@ -139,26 +139,22 @@ def get_primary_measure_type(self, context): return AddEditCustomPropertiesData.data["primary_measure_type"] -class EnumerationValues(PropertyGroup): - string_value: StringProperty(name="Value") - bool_value: BoolProperty(name="Value") - int_value: IntProperty(name="Value") - float_value: FloatProperty(name="Value") - is_selected: BoolProperty(default=False) +class IfcPropertyEnumeratedValue(PropertyGroup): + enumerated_values: CollectionProperty(type=Attribute) -class IfcSimpleProperty(Attribute): - # bounded_values: - enumerated_values: CollectionProperty(type=EnumerationValues) - # list_values: - # reference_values: - # table_values: +class IfcProperty(PropertyGroup): + metadata: PointerProperty(type=Attribute) + value_type: EnumProperty( + items=[(v, v, v) for v in ("IfcPropertySingleValue", "IfcPropertyEnumeratedValue")], name="Value Type" + ) + enumerated_value: PointerProperty(type=IfcPropertyEnumeratedValue) class PsetProperties(PropertyGroup): active_pset_id: IntProperty(name="Active Pset ID") active_pset_name: StringProperty(name="Pset Name") - properties: CollectionProperty(name="Properties", type=IfcSimpleProperty) + properties: CollectionProperty(name="Properties", type=IfcProperty) pset_name: EnumProperty(items=get_pset_names, name="Pset Name") qto_name: EnumProperty(items=get_qto_names, name="Qto Name") @@ -225,7 +221,7 @@ class AddEditProperties(PropertyGroup): ], name="Template Type", ) - enum_values: CollectionProperty(name="Enum Values", type=EnumerationValues) + enum_values: CollectionProperty(name="Enum Values", type=Attribute) getter_enum = { "primary_measure_type": get_primary_measure_type, diff --git a/src/blenderbim/blenderbim/bim/module/pset/ui.py b/src/blenderbim/blenderbim/bim/module/pset/ui.py index ebc421420c..7f6f4d7cf0 100644 --- a/src/blenderbim/blenderbim/bim/module/pset/ui.py +++ b/src/blenderbim/blenderbim/bim/module/pset/ui.py @@ -19,7 +19,6 @@ from bpy.types import Panel from blenderbim.bim.ifc import IfcStore from blenderbim.bim.ui import prop_with_search -from blenderbim.bim.helper import draw_attribute from blenderbim.bim.module.pset.data import ( ObjectPsetsData, ObjectQtosData, @@ -32,6 +31,45 @@ from blenderbim.bim.module.pset.data import ( ) +def draw_property(prop, layout, copy_operator=None): + if prop.value_type == "IfcPropertySingleValue": + draw_single_property(prop, layout, copy_operator) + elif prop.value_type == "IfcPropertyEnumeratedValue": + draw_enumerated_property(prop, layout, copy_operator) + + +def draw_single_property(prop, layout, copy_operator=None): + value_name = prop.metadata.get_value_name() + if not value_name: + layout.label(text=prop.metadata.name) + return + layout.prop( + prop.metadata, + value_name, + text=prop.metadata.name, + ) + if prop.metadata.is_optional: + layout.prop(prop.metadata, "is_null", icon="RADIOBUT_OFF" if prop.metadata.is_null else "RADIOBUT_ON", text="") + if copy_operator: + op = layout.operator(f"{copy_operator}", text="", icon="COPYDOWN") + op.name = prop.metadata.name + if prop.metadata.is_uri: + op = layout.operator("bim.select_uri_prop", text="", icon="FILE_FOLDER") + op.data_path = prop.metadata.path_from_id("string_value") + + +def draw_enumerated_property(prop, layout, copy_operator=None): + value_name = prop.metadata.get_value_name() + if not value_name: + layout.label(text=prop.metadata.name) + return + if len(prop.enumerated_value.enumerated_values) != 0: + layout.label(text=prop.metadata.name) + grid = layout.column_flow(columns=3) + for e in prop.enumerated_value.enumerated_values: + grid.prop(e, "is_selected", text=str(e[value_name])) + + def get_active_pset_obj_name(context, obj_type): if obj_type == "Object": return context.active_object.name @@ -96,7 +134,7 @@ def draw_psetqto_ui(context, pset_id, pset, props, layout, obj_type): def draw_psetqto_editable_ui(box, props, prop): row = box.row(align=True) - draw_attribute(prop, row, copy_operator="bim.copy_property_to_selection") + draw_property(prop, row, copy_operator="bim.copy_property_to_selection") if ( "length" in prop.name.lower() or "width" in prop.name.lower() From 7eac5397cdf4dd32ed5b3a6eb22b2ea727befded Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Wed, 6 Jul 2022 18:29:22 +1000 Subject: [PATCH 13/24] Run black --- .../blenderbim/bim/module/brick/prop.py | 2 +- .../blenderbim/bim/module/debug/operator.py | 1 + .../blenderbim/bim/module/drawing/operator.py | 4 +- .../blenderbim/bim/module/drawing/prop.py | 1 + .../blenderbim/bim/module/drawing/sheeter.py | 2 +- .../bim/module/drawing/svgwriter.py | 46 +++++++++++---- .../bim/module/geometry/operator.py | 5 +- .../blenderbim/bim/module/material/data.py | 4 +- .../blenderbim/bim/module/material/prop.py | 4 +- .../blenderbim/bim/module/model/mep.py | 12 ++-- .../blenderbim/bim/module/model/product.py | 4 +- .../blenderbim/bim/module/owner/data.py | 11 ++-- .../blenderbim/bim/module/project/operator.py | 2 +- .../bim/module/pset_template/operator.py | 57 ++++++++++--------- .../bim/module/pset_template/prop.py | 7 +-- .../blenderbim/bim/module/pset_template/ui.py | 29 +++++----- .../bim/module/sequence/operator.py | 1 + .../blenderbim/bim/module/style/ui.py | 2 +- .../blenderbim/bim/module/unit/data.py | 2 +- src/blenderbim/blenderbim/bim/operator.py | 2 +- src/blenderbim/blenderbim/bim/prop.py | 1 + src/blenderbim/blenderbim/tool/drawing.py | 8 +-- src/blenderbim/blenderbim/tool/material.py | 4 +- src/blenderbim/test/core/test_system.py | 1 - src/blenderbim/test/tool/test_georeference.py | 33 +++++------ 25 files changed, 134 insertions(+), 111 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/brick/prop.py b/src/blenderbim/blenderbim/bim/module/brick/prop.py index 0d4eec7a6d..8d523b68df 100644 --- a/src/blenderbim/blenderbim/bim/module/brick/prop.py +++ b/src/blenderbim/blenderbim/bim/module/brick/prop.py @@ -69,7 +69,7 @@ class BIMBrickProperties(PropertyGroup): libraries: EnumProperty(name="Libraries", items=get_libraries) namespace: EnumProperty(name="Namespace", items=get_namespaces) brick_equipment_class: EnumProperty(name="Brick Equipment Class", items=get_brick_equipment_classes) - + getter_enum = { "libraries": get_libraries, "namespace": get_namespaces, diff --git a/src/blenderbim/blenderbim/bim/module/debug/operator.py b/src/blenderbim/blenderbim/bim/module/debug/operator.py index bdf852b568..5d723020ea 100644 --- a/src/blenderbim/blenderbim/bim/module/debug/operator.py +++ b/src/blenderbim/blenderbim/bim/module/debug/operator.py @@ -112,6 +112,7 @@ class CreateAllShapes(bpy.types.Operator): def execute(self, context): self.file = IfcStore.get_file() elements = self.file.by_type("IfcElement") + self.file.by_type("IfcSpace") + total = len(elements) settings = ifcopenshell.geom.settings() failures = [] diff --git a/src/blenderbim/blenderbim/bim/module/drawing/operator.py b/src/blenderbim/blenderbim/bim/module/drawing/operator.py index 7dc4ab2428..eca88ec09d 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/operator.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/operator.py @@ -152,13 +152,13 @@ class CreateDrawing(bpy.types.Operator): with profile("Generate underlay"): underlay_svg = self.generate_underlay(context) - + with profile("Generate linework"): linework_svg = self.generate_linework(context) with profile("Generate annotation"): annotation_svg = self.generate_annotation(context) - + with profile("Combine SVG layers"): svg_path = self.combine_svgs(context, underlay_svg, linework_svg, annotation_svg) diff --git a/src/blenderbim/blenderbim/bim/module/drawing/prop.py b/src/blenderbim/blenderbim/bim/module/drawing/prop.py index 2016f23dd2..b20f871d11 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/prop.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/prop.py @@ -392,6 +392,7 @@ class BIMTextProperties(PropertyGroup): name="Font Size", ) + class BIMAssignedProductProperties(PropertyGroup): is_editing_product: BoolProperty(name="Is Editing Product", default=False) relating_product: PointerProperty(name="Relating Product", type=bpy.types.Object) diff --git a/src/blenderbim/blenderbim/bim/module/drawing/sheeter.py b/src/blenderbim/blenderbim/bim/module/drawing/sheeter.py index 7855e6067c..4df0f4e9f9 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/sheeter.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/sheeter.py @@ -118,7 +118,7 @@ class SheetBuilder: sheet_tree = ET.parse(sheet_path) sheet_root = sheet_tree.getroot() - for g in sheet_root.findall('{http://www.w3.org/2000/svg}g'): + for g in sheet_root.findall("{http://www.w3.org/2000/svg}g"): if g.attrib.get("data-id") == str(reference.id()): sheet_root.remove(g) break diff --git a/src/blenderbim/blenderbim/bim/module/drawing/svgwriter.py b/src/blenderbim/blenderbim/bim/module/drawing/svgwriter.py index 891b8f2092..74b3b06642 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/svgwriter.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/svgwriter.py @@ -70,7 +70,7 @@ class SvgWriter: viewBox=("0 0 {} {}".format(self.width, self.height)), id="root", data_scale=self.human_scale, - debug=False, # Disable validation so that we can insert the IFC namespace + debug=False, # Disable validation so that we can insert the IFC namespace ) self.svg.attribs["xmlns:ifc"] = "http://www.ifcopenshell.org/ns" return self @@ -81,7 +81,9 @@ class SvgWriter: def draw_underlay(self, image): self.svg.add( self.svg.image( - os.path.join("..", "diagrams", os.path.basename(image)), width=self.width, height=self.height, + os.path.join("..", "diagrams", os.path.basename(image)), + width=self.width, + height=self.height, ) ) return self @@ -252,7 +254,9 @@ class SvgWriter: end = Vector(((x_offset + v1.x), (y_offset - v1.y))) vector = end - start line = self.svg.add( - self.svg.line(start=tuple(start * self.svg_scale), end=tuple(end * self.svg_scale), class_=" ".join(classes)) + self.svg.line( + start=tuple(start * self.svg_scale), end=tuple(end * self.svg_scale), class_=" ".join(classes) + ) ) line["stroke-dasharray"] = "12.5, 3, 3, 3" axis_tag = tool.Ifc.get_entity(obj).Name @@ -361,7 +365,9 @@ class SvgWriter: end = Vector(((x_offset + v1.x), (y_offset - v1.y))) vector = end - start line = self.svg.add( - self.svg.line(start=tuple(start * self.svg_scale), end=tuple(end * self.svg_scale), class_=" ".join(classes)) + self.svg.line( + start=tuple(start * self.svg_scale), end=tuple(end * self.svg_scale), class_=" ".join(classes) + ) ) def draw_leader_annotation(self, obj): @@ -427,7 +433,9 @@ class SvgWriter: (symbol_position * self.svg_scale)[1], ) - self.svg.add(self.svg.use("#elevation-arrow", insert=tuple(symbol_position * self.svg_scale), transform=transform)) + self.svg.add( + self.svg.use("#elevation-arrow", insert=tuple(symbol_position * self.svg_scale), transform=transform) + ) self.svg.add(self.svg.use("#elevation-tag", insert=tuple(symbol_position * self.svg_scale))) reference_id, sheet_id = self.get_reference_and_sheet_id_from_annotation(tool.Ifc.get_entity(obj)) @@ -666,7 +674,7 @@ class SvgWriter: dir2 = ((arc_matrix.inverted() @ arc_end_pts[1]) - (arc_matrix.inverted() @ center)).normalized() angle = -dir1.xy.angle_signed(dir2.xy) - #if is_reflex: + # if is_reflex: # angle = angle % (math.pi * 2) # Center of gravity of all vertices, used to help position the text @@ -680,7 +688,9 @@ class SvgWriter: arc_midpoint = center + ((cog - center).normalized() * radius) text_position = self.project_point_onto_camera(arc_midpoint) - text_position = Vector(((x_offset + text_position.x) * self.svg_scale, (y_offset - text_position.y) * self.svg_scale)) + text_position = Vector( + ((x_offset + text_position.x) * self.svg_scale, (y_offset - text_position.y) * self.svg_scale) + ) center_projected = self.project_point_onto_camera(center) center_position = Vector( @@ -704,8 +714,12 @@ class SvgWriter: # Draw SVG arc, see for details: http://xahlee.info/js/svg_circle_arc.html arc_proj_end_pts = [self.project_point_onto_camera(v) for v in arc_end_pts] - p1 = Vector(((x_offset + arc_proj_end_pts[0].x) * self.svg_scale, (y_offset - arc_proj_end_pts[0].y) * self.svg_scale)) - p2 = Vector(((x_offset + arc_proj_end_pts[1].x) * self.svg_scale, (y_offset - arc_proj_end_pts[1].y) * self.svg_scale)) + p1 = Vector( + ((x_offset + arc_proj_end_pts[0].x) * self.svg_scale, (y_offset - arc_proj_end_pts[0].y) * self.svg_scale) + ) + p2 = Vector( + ((x_offset + arc_proj_end_pts[1].x) * self.svg_scale, (y_offset - arc_proj_end_pts[1].y) * self.svg_scale) + ) r = radius * self.svg_scale # reflex = 1 if angle > math.pi else 0 reflex = is_reflex @@ -735,10 +749,16 @@ class SvgWriter: path = self.svg.add(self.svg.path(d=d, class_=" ".join(classes))) p0 = Vector( - ((x_offset + projected_points[0].x) * self.svg_scale, (y_offset - projected_points[0].y) * self.svg_scale) + ( + (x_offset + projected_points[0].x) * self.svg_scale, + (y_offset - projected_points[0].y) * self.svg_scale, + ) ) p1 = Vector( - ((x_offset + projected_points[1].x) * self.svg_scale, (y_offset - projected_points[1].y) * self.svg_scale) + ( + (x_offset + projected_points[1].x) * self.svg_scale, + (y_offset - projected_points[1].y) * self.svg_scale, + ) ) text_offset = (p0 - p1).xy.normalized() * 5 text_position = projected_points[0] @@ -823,7 +843,9 @@ class SvgWriter: text_position = (mid * self.svg_scale) + perpendicular rotation = math.degrees(vector.angle_signed(Vector((1, 0)))) line = self.svg.add( - self.svg.line(start=tuple(start * self.svg_scale), end=tuple(end * self.svg_scale), class_=" ".join(classes)) + self.svg.line( + start=tuple(start * self.svg_scale), end=tuple(end * self.svg_scale), class_=" ".join(classes) + ) ) if text_override is not None: text = text_override diff --git a/src/blenderbim/blenderbim/bim/module/geometry/operator.py b/src/blenderbim/blenderbim/bim/module/geometry/operator.py index 541cb0a92d..81b78dd4a2 100644 --- a/src/blenderbim/blenderbim/bim/module/geometry/operator.py +++ b/src/blenderbim/blenderbim/bim/module/geometry/operator.py @@ -207,7 +207,10 @@ class UpdateRepresentation(bpy.types.Operator): new_representation = ifcopenshell.api.run("geometry.add_representation", self.file, **representation_data) if tool.Geometry.is_body_representation(new_representation): - [tool.Geometry.run_style_add_style(obj=mat) for mat in tool.Geometry.get_object_materials_without_styles(obj)] + [ + tool.Geometry.run_style_add_style(obj=mat) + for mat in tool.Geometry.get_object_materials_without_styles(obj) + ] ifcopenshell.api.run( "style.assign_representation_styles", self.file, diff --git a/src/blenderbim/blenderbim/bim/module/material/data.py b/src/blenderbim/blenderbim/bim/module/material/data.py index 4d90a29408..78ef924562 100644 --- a/src/blenderbim/blenderbim/bim/module/material/data.py +++ b/src/blenderbim/blenderbim/bim/module/material/data.py @@ -84,7 +84,9 @@ class ObjectMaterialData: @classmethod def materials(cls): - return sorted([(str(m.id()), m.Name or "Unnamed", "") for m in tool.Ifc.get().by_type("IfcMaterial")], key=lambda x: x[1]) + return sorted( + [(str(m.id()), m.Name or "Unnamed", "") for m in tool.Ifc.get().by_type("IfcMaterial")], key=lambda x: x[1] + ) @classmethod def type_material(cls): diff --git a/src/blenderbim/blenderbim/bim/module/material/prop.py b/src/blenderbim/blenderbim/bim/module/material/prop.py index 88b85fa0ee..1795156ebe 100644 --- a/src/blenderbim/blenderbim/bim/module/material/prop.py +++ b/src/blenderbim/blenderbim/bim/module/material/prop.py @@ -138,6 +138,4 @@ class BIMObjectMaterialProperties(PropertyGroup): items=getParameterizedProfileClasses, name="Parameterized Profile Classes" ) - getter_enum = { - "material": get_materials - } + getter_enum = {"material": get_materials} diff --git a/src/blenderbim/blenderbim/bim/module/model/mep.py b/src/blenderbim/blenderbim/bim/module/model/mep.py index 3fe07c3fe8..e8b02b97e6 100644 --- a/src/blenderbim/blenderbim/bim/module/model/mep.py +++ b/src/blenderbim/blenderbim/bim/module/model/mep.py @@ -65,14 +65,14 @@ class MepGenerator: def create_rectangle_segment(self): verts = [ - Vector((- self.width / 2, self.height / 2, 0)), - Vector((- self.width / 2, - self.height / 2, 0)), - Vector((- self.width / 2, self.height / 2, self.length)), - Vector((- self.width / 2, - self.height / 2, self.length)), + Vector((-self.width / 2, self.height / 2, 0)), + Vector((-self.width / 2, -self.height / 2, 0)), + Vector((-self.width / 2, self.height / 2, self.length)), + Vector((-self.width / 2, -self.height / 2, self.length)), Vector((self.width / 2, self.height / 2, 0)), - Vector((self.width / 2, - self.height / 2, 0)), + Vector((self.width / 2, -self.height / 2, 0)), Vector((self.width / 2, self.height / 2, self.length)), - Vector((self.width / 2, - self.height / 2, self.length)), + Vector((self.width / 2, -self.height / 2, self.length)), ] faces = [ [1, 3, 2, 0], diff --git a/src/blenderbim/blenderbim/bim/module/model/product.py b/src/blenderbim/blenderbim/bim/module/model/product.py index b56712216d..6a383c6d41 100644 --- a/src/blenderbim/blenderbim/bim/module/model/product.py +++ b/src/blenderbim/blenderbim/bim/module/model/product.py @@ -120,9 +120,7 @@ class AddTypeInstance(bpy.types.Operator): collection_obj = bpy.data.objects.get(collection.name) bpy.ops.bim.assign_class(obj=obj.name, ifc_class=instance_class) element = tool.Ifc.get_entity(obj) - blenderbim.core.type.assign_type( - tool.Ifc, tool.Type, element=element, type=relating_type - ) + blenderbim.core.type.assign_type(tool.Ifc, tool.Type, element=element, type=relating_type) if building_obj: if instance_class in ["IfcWindow", "IfcDoor"]: diff --git a/src/blenderbim/blenderbim/bim/module/owner/data.py b/src/blenderbim/blenderbim/bim/module/owner/data.py index be1cae0192..068bf74164 100644 --- a/src/blenderbim/blenderbim/bim/module/owner/data.py +++ b/src/blenderbim/blenderbim/bim/module/owner/data.py @@ -253,10 +253,7 @@ class ObjectActorData: @classmethod def load(cls): cls.is_loaded = True - cls.data = { - "actor": cls.actor(), - "actors": cls.actors() - } + cls.data = {"actor": cls.actor(), "actors": cls.actors()} @classmethod def actor(cls): @@ -279,9 +276,9 @@ class ObjectActorData: roles = cls.get_roles(actor.TheActor.ThePerson) roles.extend(cls.get_roles(actor.TheActor.TheOrganization)) role = ", ".join(roles) - results.append({ - "id": actor.id(), "name": actor.Name or "Unnamed", "role": role, "ifc_class": actor.is_a() - }) + results.append( + {"id": actor.id(), "name": actor.Name or "Unnamed", "role": role, "ifc_class": actor.is_a()} + ) return results @classmethod diff --git a/src/blenderbim/blenderbim/bim/module/project/operator.py b/src/blenderbim/blenderbim/bim/module/project/operator.py index f311ff50d5..dc2539db54 100644 --- a/src/blenderbim/blenderbim/bim/module/project/operator.py +++ b/src/blenderbim/blenderbim/bim/module/project/operator.py @@ -732,7 +732,7 @@ class ToggleLinkVisibility(bpy.types.Operator): def toggle_wireframe(self, link): objs = filter(lambda obj: "IfcOpeningElement" not in obj.name, link.collection.all_objects) - for i,obj in enumerate(objs): + for i, obj in enumerate(objs): if i == 0: if obj.display_type == "WIRE": display_type = "TEXTURED" diff --git a/src/blenderbim/blenderbim/bim/module/pset_template/operator.py b/src/blenderbim/blenderbim/bim/module/pset_template/operator.py index 9013a6901f..c01aefe847 100644 --- a/src/blenderbim/blenderbim/bim/module/pset_template/operator.py +++ b/src/blenderbim/blenderbim/bim/module/pset_template/operator.py @@ -28,31 +28,31 @@ from ifcopenshell.api.pset_template.data import Data from blenderbim.bim.ifc import IfcStore -#This is just a temporary operator until -#@Moult performs some of his refactor-magic ;) - vulevukusej +# This is just a temporary operator until +# @Moult performs some of his refactor-magic ;) - vulevukusej class RefreshPsetTemplates(bpy.types.Operator): bl_idname = "bim.refresh_psettemplates" bl_label = "Refresh the data for PsetTemplates" bl_options = {"REGISTER", "UNDO"} - + def execute(self, context): purge_templates() - purge_psets() - return {"FINISHED"} - - + purge_psets() + return {"FINISHED"} + + class AddPsetFile(bpy.types.Operator): bl_idname = "bim.add_pset_file" bl_label = "Add Pset File" bl_options = {"REGISTER", "UNDO"} - + def invoke(self, context, event): return context.window_manager.invoke_props_dialog(self, width=250) - + def draw(self, context): self.props = context.scene.BIMPsetTemplateProperties self.layout.prop(self.props, "new_template_filename", text="Filename:") - + def execute(self, context): template = ifcopenshell.file() filepath = os.path.join( @@ -60,7 +60,7 @@ class AddPsetFile(bpy.types.Operator): "pset", self.props.new_template_filename + ".ifc", ) - + template.create_entity( "IFCPROPERTYSETTEMPLATE", **{ @@ -68,14 +68,14 @@ class AddPsetFile(bpy.types.Operator): "Name": "Name", "Description": "Description", "TemplateType": "PSET_TYPEDRIVENONLY", - "ApplicableEntity": "IfcTypeObject" + "ApplicableEntity": "IfcTypeObject", } ) template.write(filepath) self.props.new_template_filename = "" return {"FINISHED"} - - + + class AddPsetTemplate(bpy.types.Operator): bl_idname = "bim.add_pset_template" bl_label = "Add Pset Template" @@ -190,33 +190,35 @@ class EnableEditingPropTemplate(bpy.types.Operator): props.active_prop_template.primary_measure_type = template["PrimaryMeasureType"] props.active_prop_template.template_type = template["TemplateType"] props.active_prop_template.enum_values.clear() - + if template["Enumerators"]: props.active_prop_template.enum_values.clear() data_type = props.active_prop_template.get_value_name() for e in template["Enumerators"].EnumerationValues: new = props.active_prop_template.enum_values.add() setattr(new, data_type, e.wrappedValue) - + return {"FINISHED"} - + + class DeletePropEnum(bpy.types.Operator): bl_idname = "bim.delete_prop_enum" bl_label = "delete property enumeration" bl_options = {"REGISTER", "UNDO"} index: bpy.props.IntProperty() - + def execute(self, context): active_prop = context.scene.BIMPsetTemplateProperties.active_prop_template active_prop.enum_values.remove(self.index) return {"FINISHED"} + class AddPropEnum(bpy.types.Operator): bl_idname = "bim.add_prop_enum" bl_label = "add property enumeration" bl_options = {"REGISTER", "UNDO"} index: bpy.props.IntProperty() - + def execute(self, context): active_prop = context.scene.BIMPsetTemplateProperties.active_prop_template active_prop.enum_values.add() @@ -380,26 +382,27 @@ class EditPropTemplate(bpy.types.Operator): "Description": props.active_prop_template.description, "PrimaryMeasureType": props.active_prop_template.primary_measure_type, "TemplateType": props.active_prop_template.template_type, - "Enumerators": enumerator + "Enumerators": enumerator, }, } ) Data.load(IfcStore.pset_template_file) bpy.ops.bim.disable_editing_prop_template() return {"FINISHED"} - - #TODO -This will need to go into the + + # TODO -This will need to go into the # api code at some point - vulevukusej def generate_prop_enum(self, props): self.file = IfcStore.pset_template_file data_type = props.active_prop_template.get_value_name() prop = props.active_prop_template prop_enum = self.file.create_entity( - "IFCPROPERTYENUMERATION", - Name=prop.name, - EnumerationValues=tuple(self.file.create_entity( - prop.primary_measure_type, ev[data_type]) for ev in prop.enum_values) - ) + "IFCPROPERTYENUMERATION", + Name=prop.name, + EnumerationValues=tuple( + self.file.create_entity(prop.primary_measure_type, ev[data_type]) for ev in prop.enum_values + ), + ) return prop_enum def rollback(self, data): diff --git a/src/blenderbim/blenderbim/bim/module/pset_template/prop.py b/src/blenderbim/blenderbim/bim/module/pset_template/prop.py index 94acb6c234..62a6bcf474 100644 --- a/src/blenderbim/blenderbim/bim/module/pset_template/prop.py +++ b/src/blenderbim/blenderbim/bim/module/pset_template/prop.py @@ -164,11 +164,8 @@ class PropTemplate(PropertyGroup): description: StringProperty(name="Description") primary_measure_type: EnumProperty(items=get_primary_measure_type, name="Primary Measure Type") template_type: EnumProperty( - items=[ - ("P_SINGLEVALUE","P_SINGLEVALUE",""), - ("P_ENUMERATEDVALUE","P_ENUMERATEDVALUE","") - ], - name="Template Type" + items=[("P_SINGLEVALUE", "P_SINGLEVALUE", ""), ("P_ENUMERATEDVALUE", "P_ENUMERATEDVALUE", "")], + name="Template Type", ) enum_values: CollectionProperty(type=EnumerationValues) getter_enum = { diff --git a/src/blenderbim/blenderbim/bim/module/pset_template/ui.py b/src/blenderbim/blenderbim/bim/module/pset_template/ui.py index 1c914f83d3..4fa0b67644 100644 --- a/src/blenderbim/blenderbim/bim/module/pset_template/ui.py +++ b/src/blenderbim/blenderbim/bim/module/pset_template/ui.py @@ -38,13 +38,13 @@ class BIM_PT_pset_template(Panel): def draw(self, context): layout = self.layout props = context.scene.BIMPsetTemplateProperties - + row = layout.row(align=True) prop_with_search(row, props, "pset_template_files", text="") row.operator("bim.save_pset_template_file", text="", icon="EXPORT") - row.operator("bim.add_pset_file",icon="ADD",text="") + row.operator("bim.add_pset_file", icon="ADD", text="") row.operator("bim.refresh_psettemplates", icon="FILE_REFRESH", text="") - + row = layout.row(align=True) if bool(getPsetTemplates(props, context)): @@ -75,7 +75,7 @@ class BIM_PT_pset_template(Panel): prop_with_search(layout, props.active_pset_template, "template_type") row = layout.row() row.prop(props.active_pset_template, "applicable_entity") - else: + else: pset_template = Data.pset_templates[int(props.pset_templates)] for name, value in pset_template.items(): if name == "id" or name == "type" or name == "HasPropertyTemplates": @@ -87,7 +87,7 @@ class BIM_PT_pset_template(Panel): row = layout.row(align=True) row.label(text="Property Templates", icon="COPY_ID") row.operator("bim.add_prop_template", icon="ADD", text="") - + row = layout.row() row.label(text="Name | Description | PrimaryMeasureType | TemplateType") @@ -100,26 +100,27 @@ class BIM_PT_pset_template(Panel): row.prop(props.active_prop_template, "description", text="") prop_with_search(row, props.active_prop_template, "primary_measure_type", text="") row.prop(props.active_prop_template, "template_type", text="") - + if props.active_prop_template.template_type == "P_ENUMERATEDVALUE": row = layout.row(align=True) split = row.split(factor=0.2) - c=split.column() - c.label(text="Enumerations:",) - - c=split.column() + c = split.column() + c.label( + text="Enumerations:", + ) + + c = split.column() box = c.box() grid = box.column_flow(columns=4) value_name = props.active_prop_template.get_value_name() r = grid.row() r.operator("bim.add_prop_enum", text="Add Enum") - for k,v in enumerate(props.active_prop_template.enum_values): - r = grid.row(align=True) + for k, v in enumerate(props.active_prop_template.enum_values): + r = grid.row(align=True) r.prop(v, value_name, text="") op = r.operator("bim.delete_prop_enum", icon="X", text="") op.index = k - - + else: row.label(text=prop_template["Name"]) row.label(text=prop_template["Description"]) diff --git a/src/blenderbim/blenderbim/bim/module/sequence/operator.py b/src/blenderbim/blenderbim/bim/module/sequence/operator.py index d7082cfa9e..cd67c76fc3 100644 --- a/src/blenderbim/blenderbim/bim/module/sequence/operator.py +++ b/src/blenderbim/blenderbim/bim/module/sequence/operator.py @@ -624,6 +624,7 @@ class EditTaskTime(bpy.types.Operator): if prop.is_null: attributes[prop.name] = None return True + # TODO make this parse PT32 as P4D attributes[prop.name] = helper.parse_duration(prop.string_value) return True diff --git a/src/blenderbim/blenderbim/bim/module/style/ui.py b/src/blenderbim/blenderbim/bim/module/style/ui.py index 86f4261866..b5a0cfe586 100644 --- a/src/blenderbim/blenderbim/bim/module/style/ui.py +++ b/src/blenderbim/blenderbim/bim/module/style/ui.py @@ -54,7 +54,7 @@ class BIM_PT_styles(Panel): row = self.layout.row(align=True) row.alignment = "RIGHT" - #row.operator("bim.add_presentation_style", text="", icon="ADD") + # row.operator("bim.add_presentation_style", text="", icon="ADD") if self.props.styles and self.props.active_style_index < len(self.props.styles): style = self.props.styles[self.props.active_style_index] op = row.operator("bim.select_by_style", text="", icon="RESTRICT_SELECT_OFF") diff --git a/src/blenderbim/blenderbim/bim/module/unit/data.py b/src/blenderbim/blenderbim/bim/module/unit/data.py index 971e57b03a..9fa647e08c 100644 --- a/src/blenderbim/blenderbim/bim/module/unit/data.py +++ b/src/blenderbim/blenderbim/bim/module/unit/data.py @@ -37,7 +37,7 @@ class UnitsData: "unit_classes": cls.unit_classes(), "named_unit_types": cls.named_unit_types(), "conversion_unit_types": cls.conversion_unit_types(), - "total_units": cls.get_total_units() + "total_units": cls.get_total_units(), } cls.is_loaded = True diff --git a/src/blenderbim/blenderbim/bim/operator.py b/src/blenderbim/blenderbim/bim/operator.py index 17ec6ed626..91131d772f 100644 --- a/src/blenderbim/blenderbim/bim/operator.py +++ b/src/blenderbim/blenderbim/bim/operator.py @@ -560,5 +560,5 @@ class BIM_OT_enum_property_search(bpy.types.Operator): def draw(self, context): # Mandatory to access context.data in update : - self.layout.context_pointer_set(name="data", data=self.data) + self.layout.context_pointer_set(name="data", data=self.data) self.layout.prop_search(self, "dummy_name", self, "collection_name") diff --git a/src/blenderbim/blenderbim/bim/prop.py b/src/blenderbim/blenderbim/bim/prop.py index 50817c4487..ffdfc8bb27 100644 --- a/src/blenderbim/blenderbim/bim/prop.py +++ b/src/blenderbim/blenderbim/bim/prop.py @@ -195,6 +195,7 @@ class Attribute(PropertyGroup): is_null: BoolProperty(name="Is Null") is_optional: BoolProperty(name="Is Optional") is_uri: BoolProperty(name="Is Uri", default=False) + is_selected: BoolProperty(name="Is Selected", default=False) def get_value(self): if self.is_null: diff --git a/src/blenderbim/blenderbim/tool/drawing.py b/src/blenderbim/blenderbim/tool/drawing.py index 34d9a153bf..62388b23b7 100644 --- a/src/blenderbim/blenderbim/tool/drawing.py +++ b/src/blenderbim/blenderbim/tool/drawing.py @@ -375,15 +375,11 @@ class Drawing(blenderbim.core.tool.Drawing): @classmethod def open_spreadsheet(cls, uri): - cls.open_with_user_command( - bpy.context.preferences.addons["blenderbim"].preferences.spreadsheet_command, uri - ) + cls.open_with_user_command(bpy.context.preferences.addons["blenderbim"].preferences.spreadsheet_command, uri) @classmethod def open_svg(cls, uri): - cls.open_with_user_command( - bpy.context.preferences.addons["blenderbim"].preferences.svg_command, uri - ) + cls.open_with_user_command(bpy.context.preferences.addons["blenderbim"].preferences.svg_command, uri) @classmethod def run_root_assign_class( diff --git a/src/blenderbim/blenderbim/tool/material.py b/src/blenderbim/blenderbim/tool/material.py index 0b3832ca24..42d70eb35d 100644 --- a/src/blenderbim/blenderbim/tool/material.py +++ b/src/blenderbim/blenderbim/tool/material.py @@ -75,7 +75,9 @@ class Material(blenderbim.core.tool.Material): new = props.materials.add() new.ifc_definition_id = material.id() new.name = get_name(material) - new.total_elements = len(ifcopenshell.util.element.get_elements_by_material(tool.Ifc.get(), material)) + new.total_elements = len( + ifcopenshell.util.element.get_elements_by_material(tool.Ifc.get(), material) + ) return for material in materials: new = props.materials.add() diff --git a/src/blenderbim/test/core/test_system.py b/src/blenderbim/test/core/test_system.py index 01c4171def..a27d0f90e5 100644 --- a/src/blenderbim/test/core/test_system.py +++ b/src/blenderbim/test/core/test_system.py @@ -125,7 +125,6 @@ class TestHidePorts: system.delete_element_objects(["port"]).should_be_called() subject.hide_ports(ifc, system, element="element") - def test_syncing_locations_if_objects_moved_prior_to_hiding_ports(self, ifc, system): ifc.get_object("element").should_be_called().will_return("obj") ifc.is_moved("obj").should_be_called().will_return(True) diff --git a/src/blenderbim/test/tool/test_georeference.py b/src/blenderbim/test/tool/test_georeference.py index 4dd8661e25..bddb670fbb 100644 --- a/src/blenderbim/test/tool/test_georeference.py +++ b/src/blenderbim/test/tool/test_georeference.py @@ -163,6 +163,7 @@ class TestGetMapConversionAttributes(NewFile): "Scale": 6.0, } + class TestGetTrueNorthAttributes(NewFile): def test_run(self): TestImportTrueNorth().test_run() @@ -185,18 +186,18 @@ class TestDisableEditing(NewFile): class TestSetCoordinates(NewFile): def test_run(self): - subject.set_coordinates("input", [1., 2., 3.]) + subject.set_coordinates("input", [1.0, 2.0, 3.0]) assert bpy.context.scene.BIMGeoreferenceProperties.coordinate_input == "1.0,2.0,3.0" - subject.set_coordinates("output", [4., 5., 6.]) + subject.set_coordinates("output", [4.0, 5.0, 6.0]) assert bpy.context.scene.BIMGeoreferenceProperties.coordinate_output == "4.0,5.0,6.0" class TestGetCoordinates(NewFile): def test_run(self): bpy.context.scene.BIMGeoreferenceProperties.coordinate_input = "1.0,2.0,3.0" - assert subject.get_coordinates("input") == [1., 2., 3.] + assert subject.get_coordinates("input") == [1.0, 2.0, 3.0] bpy.context.scene.BIMGeoreferenceProperties.coordinate_output = "4.0,5.0,6.0" - assert subject.get_coordinates("output") == [4., 5., 6.] + assert subject.get_coordinates("output") == [4.0, 5.0, 6.0] class TestGetCursorLocation(NewFile): @@ -207,8 +208,8 @@ class TestGetCursorLocation(NewFile): ifcopenshell.api.run("context.add_context", ifc, context_type="Model") unit = ifcopenshell.api.run("unit.add_si_unit", ifc, unit_type="LENGTHUNIT", prefix="MILLI", name="METRE") ifcopenshell.api.run("unit.assign_unit", ifc, units=[unit]) - bpy.context.scene.cursor.location = (1., 2., 3.) - assert subject.get_cursor_location() == [1000., 2000., 3000.] + bpy.context.scene.cursor.location = (1.0, 2.0, 3.0) + assert subject.get_cursor_location() == [1000.0, 2000.0, 3000.0] class TestSetCursorLocation(NewFile): @@ -219,8 +220,8 @@ class TestSetCursorLocation(NewFile): ifcopenshell.api.run("context.add_context", ifc, context_type="Model") unit = ifcopenshell.api.run("unit.add_si_unit", ifc, unit_type="LENGTHUNIT", prefix="MILLI", name="METRE") ifcopenshell.api.run("unit.assign_unit", ifc, units=[unit]) - subject.set_cursor_location([1000., 2000., 3000.]) - assert list(bpy.context.scene.cursor.location) == [1., 2., 3.] + subject.set_cursor_location([1000.0, 2000.0, 3000.0]) + assert list(bpy.context.scene.cursor.location) == [1.0, 2.0, 3.0] class TestSetIfcTrueNorth(NewFile): @@ -258,13 +259,13 @@ class TestGetMapConversion(NewFile): class TestXyz2Enh(NewFile): def test_run(self): - assert subject.xyz2enh([0., 0., 0.], None) == [0., 0., 0.] + assert subject.xyz2enh([0.0, 0.0, 0.0], None) == [0.0, 0.0, 0.0] def test_using_the_blender_offset(self): props = bpy.context.scene.BIMGeoreferenceProperties props.has_blender_offset = True props.blender_eastings = "1.0" - assert subject.xyz2enh([0., 0., 0.], None) == (1., 0., 0.) + assert subject.xyz2enh([0.0, 0.0, 0.0], None) == (1.0, 0.0, 0.0) def test_using_the_map_conversion(self): ifc = ifcopenshell.file() @@ -274,7 +275,7 @@ class TestXyz2Enh(NewFile): ifcopenshell.api.run("georeference.add_georeferencing", ifc) map_conversion = ifc.by_type("IfcMapConversion")[0] map_conversion.Eastings = 1.0 - assert subject.xyz2enh([0., 0., 0.], map_conversion) == (1., 0., 0.) + assert subject.xyz2enh([0.0, 0.0, 0.0], map_conversion) == (1.0, 0.0, 0.0) def test_applying_both_blender_offset_and_map_conversion(self): props = bpy.context.scene.BIMGeoreferenceProperties @@ -287,18 +288,18 @@ class TestXyz2Enh(NewFile): ifcopenshell.api.run("georeference.add_georeferencing", ifc) map_conversion = ifc.by_type("IfcMapConversion")[0] map_conversion.Northings = 1.0 - assert subject.xyz2enh([0., 0., 0.], map_conversion) == (1., 1., 0.) + assert subject.xyz2enh([0.0, 0.0, 0.0], map_conversion) == (1.0, 1.0, 0.0) class TestEnh2Xyz(NewFile): def test_run(self): - assert subject.enh2xyz([0., 0., 0.], None) == [0., 0., 0.] + assert subject.enh2xyz([0.0, 0.0, 0.0], None) == [0.0, 0.0, 0.0] def test_using_the_blender_offset(self): props = bpy.context.scene.BIMGeoreferenceProperties props.has_blender_offset = True props.blender_eastings = "1.0" - assert subject.enh2xyz([0., 0., 0.], None) == (-1., 0., 0.) + assert subject.enh2xyz([0.0, 0.0, 0.0], None) == (-1.0, 0.0, 0.0) def test_using_the_map_conversion(self): ifc = ifcopenshell.file() @@ -308,7 +309,7 @@ class TestEnh2Xyz(NewFile): ifcopenshell.api.run("georeference.add_georeferencing", ifc) map_conversion = ifc.by_type("IfcMapConversion")[0] map_conversion.Eastings = 1.0 - assert subject.enh2xyz([0., 0., 0.], map_conversion) == (-1., 0., 0.) + assert subject.enh2xyz([0.0, 0.0, 0.0], map_conversion) == (-1.0, 0.0, 0.0) def test_applying_both_blender_offset_and_map_conversion(self): props = bpy.context.scene.BIMGeoreferenceProperties @@ -321,7 +322,7 @@ class TestEnh2Xyz(NewFile): ifcopenshell.api.run("georeference.add_georeferencing", ifc) map_conversion = ifc.by_type("IfcMapConversion")[0] map_conversion.Northings = 1.0 - assert subject.enh2xyz([0., 0., 0.], map_conversion) == (-1., -1., 0.) + assert subject.enh2xyz([0.0, 0.0, 0.0], map_conversion) == (-1.0, -1.0, 0.0) class TestSetIfcGridNorth(NewFile): From 4195d41e4c45ca05b5277853df003d2eaf427004 Mon Sep 17 00:00:00 2001 From: Gorgious56 Date: Wed, 6 Jul 2022 12:09:37 +0200 Subject: [PATCH 14/24] Enums from attributes can now be searched by name --- src/blenderbim/blenderbim/bim/helper.py | 23 +++++++++++++++---- .../blenderbim/bim/module/brick/ui.py | 2 +- .../blenderbim/bim/module/geometry/ui.py | 2 +- .../blenderbim/bim/module/material/ui.py | 2 +- .../blenderbim/bim/module/patch/ui.py | 2 +- .../blenderbim/bim/module/project/ui.py | 2 +- .../blenderbim/bim/module/pset/ui.py | 2 +- .../blenderbim/bim/module/pset_template/ui.py | 2 +- .../blenderbim/bim/module/root/ui.py | 2 +- .../blenderbim/bim/module/unit/ui.py | 2 +- src/blenderbim/blenderbim/bim/prop.py | 4 ++++ src/blenderbim/blenderbim/bim/ui.py | 9 -------- 12 files changed, 31 insertions(+), 23 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/helper.py b/src/blenderbim/blenderbim/bim/helper.py index f0dab98427..6b11944f87 100644 --- a/src/blenderbim/blenderbim/bim/helper.py +++ b/src/blenderbim/blenderbim/bim/helper.py @@ -38,11 +38,14 @@ def draw_attribute(attribute, layout, copy_operator=None): if not value_name: layout.label(text=attribute.name) return - layout.prop( - attribute, - value_name, - text=attribute.name, - ) + if value_name == "enum_value": + prop_with_search(layout, attribute, "enum_value", text=attribute.name) + else: + layout.prop( + attribute, + value_name, + text=attribute.name, + ) if attribute.is_optional: layout.prop(attribute, "is_null", icon="RADIOBUT_OFF" if attribute.is_null else "RADIOBUT_ON", text="") if copy_operator: @@ -105,6 +108,16 @@ def export_attributes(props, callback=None): return attributes +def prop_with_search(layout, data, prop_name, **kwargs): + # kwargs are layout.prop arguments (text, icon, etc.) + row = layout.row(align=True) + # Magick courtesy of https://blender.stackexchange.com/a/203443/86891 + row.context_pointer_set(name="data", data=data) + row.prop(data, prop_name, **kwargs) + op = row.operator("bim.enum_property_search", text="", icon="VIEWZOOM") + op.prop_name = prop_name + + class IfcHeaderExtractor: def __init__(self, filepath: str): self.filepath = filepath diff --git a/src/blenderbim/blenderbim/bim/module/brick/ui.py b/src/blenderbim/blenderbim/bim/module/brick/ui.py index f0b1cedce7..bb8898b2c0 100644 --- a/src/blenderbim/blenderbim/bim/module/brick/ui.py +++ b/src/blenderbim/blenderbim/bim/module/brick/ui.py @@ -18,7 +18,7 @@ import blenderbim.tool as tool from bpy.types import Panel, UIList -from blenderbim.bim.ui import prop_with_search +from blenderbim.bim.helper import prop_with_search from blenderbim.bim.module.brick.data import BrickschemaData, BrickschemaReferencesData diff --git a/src/blenderbim/blenderbim/bim/module/geometry/ui.py b/src/blenderbim/blenderbim/bim/module/geometry/ui.py index 4ce050ffb9..5f7c918de0 100644 --- a/src/blenderbim/blenderbim/bim/module/geometry/ui.py +++ b/src/blenderbim/blenderbim/bim/module/geometry/ui.py @@ -19,7 +19,7 @@ import bpy from bpy.types import Panel from blenderbim.bim.ifc import IfcStore -from blenderbim.bim.ui import prop_with_search +from blenderbim.bim.helper import prop_with_search from blenderbim.bim.module.geometry.data import RepresentationsData, DerivedPlacementsData diff --git a/src/blenderbim/blenderbim/bim/module/material/ui.py b/src/blenderbim/blenderbim/bim/module/material/ui.py index f657ab0a40..cddd181189 100644 --- a/src/blenderbim/blenderbim/bim/module/material/ui.py +++ b/src/blenderbim/blenderbim/bim/module/material/ui.py @@ -22,7 +22,7 @@ from ifcopenshell.api.material.data import Data from ifcopenshell.api.profile.data import Data as ProfileData from blenderbim.bim.ifc import IfcStore from blenderbim.bim.helper import draw_attributes -from blenderbim.bim.ui import prop_with_search +from blenderbim.bim.helper import prop_with_search from blenderbim.bim.module.material.data import MaterialsData, ObjectMaterialData diff --git a/src/blenderbim/blenderbim/bim/module/patch/ui.py b/src/blenderbim/blenderbim/bim/module/patch/ui.py index 9d58971d7d..9e7a241e51 100644 --- a/src/blenderbim/blenderbim/bim/module/patch/ui.py +++ b/src/blenderbim/blenderbim/bim/module/patch/ui.py @@ -16,7 +16,7 @@ # You should have received a copy of the GNU General Public License # along with BlenderBIM Add-on. If not, see . -from blenderbim.bim.ui import prop_with_search +from blenderbim.bim.helper import prop_with_search import bpy from blenderbim.bim.helper import draw_attributes diff --git a/src/blenderbim/blenderbim/bim/module/project/ui.py b/src/blenderbim/blenderbim/bim/module/project/ui.py index 8a0a21f109..4aff3bb1d3 100644 --- a/src/blenderbim/blenderbim/bim/module/project/ui.py +++ b/src/blenderbim/blenderbim/bim/module/project/ui.py @@ -17,7 +17,7 @@ # along with BlenderBIM Add-on. If not, see . import os -from blenderbim.bim.ui import prop_with_search +from blenderbim.bim.helper import prop_with_search from bpy.types import Panel, UIList from blenderbim.bim.ifc import IfcStore from blenderbim.bim.module.project.data import ProjectData diff --git a/src/blenderbim/blenderbim/bim/module/pset/ui.py b/src/blenderbim/blenderbim/bim/module/pset/ui.py index 7f6f4d7cf0..b6c67b1611 100644 --- a/src/blenderbim/blenderbim/bim/module/pset/ui.py +++ b/src/blenderbim/blenderbim/bim/module/pset/ui.py @@ -18,7 +18,7 @@ from bpy.types import Panel from blenderbim.bim.ifc import IfcStore -from blenderbim.bim.ui import prop_with_search +from blenderbim.bim.helper import prop_with_search from blenderbim.bim.module.pset.data import ( ObjectPsetsData, ObjectQtosData, diff --git a/src/blenderbim/blenderbim/bim/module/pset_template/ui.py b/src/blenderbim/blenderbim/bim/module/pset_template/ui.py index 4fa0b67644..b15ca05bd4 100644 --- a/src/blenderbim/blenderbim/bim/module/pset_template/ui.py +++ b/src/blenderbim/blenderbim/bim/module/pset_template/ui.py @@ -19,7 +19,7 @@ import bpy from bpy.types import Panel from blenderbim.bim.ifc import IfcStore -from blenderbim.bim.ui import prop_with_search +from blenderbim.bim.helper import prop_with_search from blenderbim.bim.module.pset_template.prop import ( getPsetTemplates, ) diff --git a/src/blenderbim/blenderbim/bim/module/root/ui.py b/src/blenderbim/blenderbim/bim/module/root/ui.py index b6a5f99268..18ca900cea 100644 --- a/src/blenderbim/blenderbim/bim/module/root/ui.py +++ b/src/blenderbim/blenderbim/bim/module/root/ui.py @@ -20,7 +20,7 @@ import bpy import blenderbim.bim.module.root.prop as root_prop from bpy.types import Panel from blenderbim.bim.ifc import IfcStore -from blenderbim.bim.ui import prop_with_search +from blenderbim.bim.helper import prop_with_search from blenderbim.bim.module.root.data import IfcClassData diff --git a/src/blenderbim/blenderbim/bim/module/unit/ui.py b/src/blenderbim/blenderbim/bim/module/unit/ui.py index 183ed5cbe7..10a3682296 100644 --- a/src/blenderbim/blenderbim/bim/module/unit/ui.py +++ b/src/blenderbim/blenderbim/bim/module/unit/ui.py @@ -19,7 +19,7 @@ import blenderbim.bim.helper from bpy.types import Panel, UIList from blenderbim.bim.ifc import IfcStore -from blenderbim.bim.ui import prop_with_search +from blenderbim.bim.helper import prop_with_search from blenderbim.bim.module.unit.data import UnitsData diff --git a/src/blenderbim/blenderbim/bim/prop.py b/src/blenderbim/blenderbim/bim/prop.py index ffdfc8bb27..e86896fd39 100644 --- a/src/blenderbim/blenderbim/bim/prop.py +++ b/src/blenderbim/blenderbim/bim/prop.py @@ -240,6 +240,10 @@ class Attribute(PropertyGroup): value = str(value) setattr(self, self.get_value_name(), value) + getter_enum = { + "enum_value": getAttributeEnumValues, + } + class ModuleVisibility(PropertyGroup): name: StringProperty(name="Name") diff --git a/src/blenderbim/blenderbim/bim/ui.py b/src/blenderbim/blenderbim/bim/ui.py index e04e05d5be..2457cd99bf 100644 --- a/src/blenderbim/blenderbim/bim/ui.py +++ b/src/blenderbim/blenderbim/bim/ui.py @@ -170,15 +170,6 @@ class BIM_ADDON_preferences(bpy.types.AddonPreferences): row.operator("bim.configure_visibility") -def prop_with_search(layout, data, prop_name, **kwargs): # Kwargs are layout.prop arguments (text, icon, etc.) - row = layout.row(align=True) - # Magick courtesy of https://blender.stackexchange.com/a/203443/86891 - row.context_pointer_set(name="data", data=data) - row.prop(data, prop_name, **kwargs) - op = row.operator("bim.enum_property_search", text="", icon="VIEWZOOM") - op.prop_name = prop_name - - def ifc_units(self, context): scene = context.scene props = scene.BIMProperties From 57fe895ae0d59a5d2d8f1b48c121e3cf0c5a125c Mon Sep 17 00:00:00 2001 From: Vukas Pajic <83825269+vulevukusej@users.noreply.github.com> Date: Wed, 6 Jul 2022 13:56:24 +0200 Subject: [PATCH 15/24] ensure modules are installed to blender python thankyou to @Gorgious56 for help on this one ;) https://blender.stackexchange.com/a/238995/130742 --- src/blenderbim/scripts/setup_pytest.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/blenderbim/scripts/setup_pytest.py b/src/blenderbim/scripts/setup_pytest.py index 552dbf55b0..262f97587f 100644 --- a/src/blenderbim/scripts/setup_pytest.py +++ b/src/blenderbim/scripts/setup_pytest.py @@ -18,11 +18,14 @@ import subprocess import sys +from pathlib import Path py_exec = str(sys.executable) +lib = Path(py_exec).parent.parent / "lib" + subprocess.call([py_exec, "-m", "ensurepip", "--user"]) -subprocess.call([py_exec, "-m", "pip", "install", "--upgrade", "pip"]) -subprocess.call([py_exec, "-m", "pip", "install", "pytest"]) -subprocess.call([py_exec, "-m", "pip", "install", "pytest-blender"]) -subprocess.call([py_exec, "-m", "pip", "install", "pytest-bdd"]) -subprocess.call([py_exec, "-m", "pip", "install", "pygments"]) +subprocess.call([py_exec, "-m", "pip", "install", "--upgrade", "pip"]) +subprocess.call([py_exec, "-m", "pip", "install", f"--target={str(lib)}", "pytest"]) +subprocess.call([py_exec, "-m", "pip", "install", f"--target={str(lib)}", "pytest-blender"]) +subprocess.call([py_exec, "-m", "pip", "install", f"--target={str(lib)}", "pytest-bdd"]) +subprocess.call([py_exec, "-m", "pip", "install", f"--target={str(lib)}", "pygments"]) From 6b6ac38f9651333ec42c28527e37ee576e57af80 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Wed, 6 Jul 2022 16:06:16 +0200 Subject: [PATCH 16/24] Link serializers also with only BUILD_IFCPYTHON --- cmake/CMakeLists.txt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index f19c4eafd0..8990315c9d 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -666,7 +666,7 @@ if (BUILD_IFCGEOM) endforeach() set(IFCOPENSHELL_LIBRARIES ${IFCOPENSHELL_LIBRARIES} IfcGeom ${IFCGEOM_SCHEMA_LIBRARIES} IfcGeom ${IFCGEOM_SCHEMA_LIBRARIES}) endif() -if (BUILD_CONVERT) +if (BUILD_CONVERT or BUILD_IFCPYTHON) foreach(s ${SCHEMA_VERSIONS}) set(SERIALIZER_SCHEMA_LIBRARIES ${SERIALIZER_SCHEMA_LIBRARIES} Serializers_ifc${s}) endforeach() @@ -739,7 +739,7 @@ TARGET_LINK_LIBRARIES(IfcGeom IfcParse ${IFCGEOM_SCHEMA_LIBRARIES} ${CMAKE_THREA endif(BUILD_IFCGEOM) -if (BUILD_CONVERT) +if (BUILD_CONVERT or BUILD_IFCPYTHON) # Serializers file(GLOB SERIALIZERS_H_FILES ../src/serializers/*.h) @@ -760,6 +760,10 @@ set_target_properties(Serializers PROPERTIES COMPILE_FLAGS "-DIFC_GEOM_EXPORTS $ TARGET_LINK_LIBRARIES(Serializers ${SERIALIZER_SCHEMA_LIBRARIES} ${OPENCOLLADA_LIBRARIES}) +endif(BUILD_CONVERT or BUILD_IFCPYTHON) + +if (BUILD_CONVERT) + # IfcConvert file(GLOB IFCCONVERT_CPP_FILES ../src/ifcconvert/*.cpp) file(GLOB IFCCONVERT_H_FILES ../src/ifcconvert/*.h) From b479d82251190cf3a82a449f8c5589ffe44a8fb3 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Wed, 6 Jul 2022 16:09:52 +0200 Subject: [PATCH 17/24] CI workflow with BUILD_CONVERT=Off --- .github/workflows/ci-py-only.yml | 95 ++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 .github/workflows/ci-py-only.yml diff --git a/.github/workflows/ci-py-only.yml b/.github/workflows/ci-py-only.yml new file mode 100644 index 0000000000..a312244159 --- /dev/null +++ b/.github/workflows/ci-py-only.yml @@ -0,0 +1,95 @@ +name: ci + +on: + push: + paths: + - 'src/**' + - 'test/**' + - 'conda/**' + - 'cmake/**' + - '.github/workflows/ci.yml' + pull_request: + +jobs: + activate: + runs-on: ubuntu-latest + if: | + github.repository == 'IfcOpenShell/IfcOpenShell' && + !contains(github.event.head_commit.message, 'skip ci') + steps: + - run: echo ok go + + build: + runs-on: ubuntu-20.04 + needs: activate + steps: + - uses: actions/checkout@v2 + with: + submodules: recursive + - name: Install C++ dependencies + run: | + sudo apt update + sudo apt-get install --no-install-recommends \ + git cmake gcc g++ \ + libboost-date-time-dev \ + libboost-filesystem-dev \ + libboost-iostreams-dev \ + libboost-program-options-dev \ + libboost-regex-dev \ + libboost-system-dev \ + libboost-thread-dev \ + python3-all-dev python3-pip \ + swig libpcre3-dev libxml2-dev \ + libtbb-dev nlohmann-json3-dev \ + libocct-foundation-dev libocct-modeling-algorithms-dev libocct-modeling-data-dev libocct-ocaf-dev libocct-visualization-dev libocct-data-exchange-dev \ + libhdf5-dev libcgal-dev + + - name: ccache + uses: hendrikmuhs/ccache-action@v1 + + - name: Build ifcopenshell + run: | + mkdir build && cd build + cmake \ + -DCMAKE_C_COMPILER_LAUNCHER=ccache \ + -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_PREFIX_PATH=/usr \ + -DCMAKE_SYSTEM_PREFIX_PATH=/usr \ + -DOCC_INCLUDE_DIR=/usr/include/opencascade \ + -DOCC_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu \ + -DPYTHON_EXECUTABLE:FILEPATH=/usr/bin/python3 \ + -DPYTHON_INCLUDE_DIR:PATH=/usr/include/python3.8 \ + -DPYTHON_LIBRARY:FILEPATH=/usr/lib/x86_64-linux-gnu/libpython3.8.so \ + -DCOLLADA_SUPPORT=Off \ + "-DSCHEMA_VERSIONS=2x3;4" \ + -DBUILD_CONVERT=Off \ + -DGLTF_SUPPORT=On \ + -DJSON_INCLUDE_DIR=/usr/include \ + -DCGAL_INCLUDE_DIR=/usr/include \ + -DGMP_INCLUDE_DIR=/usr/include \ + -DMPFR_INCLUDE_DIR=/usr/include \ + -DGMP_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu \ + -DMPFR_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu \ + -DHDF5_INCLUDE_DIR=/usr/include/hdf5/serial \ + ../cmake + sudo make -j $(nproc) + sudo make install + + - name: Install Python dependencies + run: | + sudo /usr/bin/python -m pip install -U pip + sudo /usr/bin/python -m pip install xmlschema numpy lxml + sudo /usr/bin/python -m pip install src/bcf + sudo /usr/bin/python -m pip install pytest + sudo /usr/bin/python -m pip install isodate + sudo /usr/bin/python -m pip install lark + sudo /usr/bin/python -m pip install networkx + + - name: Test + run: | + cd test + sudo /usr/bin/python tests.py + cd ../src/ifcopenshell-python + mv ifcopenshell ifcopenshell-local # Force testing on installed module + make test From 1d0e8c59d252263f41fba5e783a6ff4fad6173c2 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Wed, 6 Jul 2022 16:19:57 +0200 Subject: [PATCH 18/24] Capital OR --- cmake/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 8990315c9d..514c3acdb6 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -666,7 +666,7 @@ if (BUILD_IFCGEOM) endforeach() set(IFCOPENSHELL_LIBRARIES ${IFCOPENSHELL_LIBRARIES} IfcGeom ${IFCGEOM_SCHEMA_LIBRARIES} IfcGeom ${IFCGEOM_SCHEMA_LIBRARIES}) endif() -if (BUILD_CONVERT or BUILD_IFCPYTHON) +if (BUILD_CONVERT OR BUILD_IFCPYTHON) foreach(s ${SCHEMA_VERSIONS}) set(SERIALIZER_SCHEMA_LIBRARIES ${SERIALIZER_SCHEMA_LIBRARIES} Serializers_ifc${s}) endforeach() @@ -739,7 +739,7 @@ TARGET_LINK_LIBRARIES(IfcGeom IfcParse ${IFCGEOM_SCHEMA_LIBRARIES} ${CMAKE_THREA endif(BUILD_IFCGEOM) -if (BUILD_CONVERT or BUILD_IFCPYTHON) +if (BUILD_CONVERT OR BUILD_IFCPYTHON) # Serializers file(GLOB SERIALIZERS_H_FILES ../src/serializers/*.h) From 9b59d24fc766fd6614ec9c3aec240b7b7a8bb4f0 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Wed, 6 Jul 2022 18:20:25 +0200 Subject: [PATCH 19/24] Update test_wall_opening.py --- src/ifcopenshell-python/test/test_wall_opening.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ifcopenshell-python/test/test_wall_opening.py b/src/ifcopenshell-python/test/test_wall_opening.py index 71e6c945ea..75da8af33d 100644 --- a/src/ifcopenshell-python/test/test_wall_opening.py +++ b/src/ifcopenshell-python/test/test_wall_opening.py @@ -145,6 +145,7 @@ def create_case(fn, openings): class TestWallOpenings: + @pytest.mark.skipif(shutil.which("IfcConvert"), reason="Requires IfcConvert in path") def test_all(self): cases = [ From 1029271e9194306716c18b0dd81ffcb14465b14c Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Wed, 6 Jul 2022 18:20:32 +0200 Subject: [PATCH 20/24] Update ci-py-only.yml --- .github/workflows/ci-py-only.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-py-only.yml b/.github/workflows/ci-py-only.yml index a312244159..ac57d8e473 100644 --- a/.github/workflows/ci-py-only.yml +++ b/.github/workflows/ci-py-only.yml @@ -1,4 +1,4 @@ -name: ci +name: ci_py_only on: push: From 158c62bdca913d1d998a8f59519ade68f1dc8835 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Wed, 6 Jul 2022 22:01:15 +0200 Subject: [PATCH 21/24] Update ci-py-only.yml --- .github/workflows/ci-py-only.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-py-only.yml b/.github/workflows/ci-py-only.yml index ac57d8e473..b427954ac8 100644 --- a/.github/workflows/ci-py-only.yml +++ b/.github/workflows/ci-py-only.yml @@ -7,7 +7,7 @@ on: - 'test/**' - 'conda/**' - 'cmake/**' - - '.github/workflows/ci.yml' + - '.github/workflows/ci_py_only.yml' pull_request: jobs: From 07c152f5139f8c584ebaad0eebb99f5fc36801cb Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Wed, 6 Jul 2022 22:07:57 +0200 Subject: [PATCH 22/24] Submodule --- .gitmodules | 2 +- src/ifcopenshell-python/test/Sample-BIM-Files | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index ccec1ac990..e15dfb45d8 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,4 +10,4 @@ url = https://github.com/IfcOpenShell/svgfill [submodule "src/ifcopenshell-python/test/Sample-BIM-Files"] path = src/ifcopenshell-python/test/Sample-BIM-Files - url = https://github.com/atomczak/Sample-BIM-Files + url = https://github.com/IfcOpenShell/ids-test-files \ No newline at end of file diff --git a/src/ifcopenshell-python/test/Sample-BIM-Files b/src/ifcopenshell-python/test/Sample-BIM-Files index 2daf6c46ed..adadc7740b 160000 --- a/src/ifcopenshell-python/test/Sample-BIM-Files +++ b/src/ifcopenshell-python/test/Sample-BIM-Files @@ -1 +1 @@ -Subproject commit 2daf6c46ed9fc7a17259ef6d4c17c3553ef642cd +Subproject commit adadc7740b7337f4cb0935ec8e84ba30ed4ca10d From 2f6ac0be9f2ff81fae3827db9be1c05eb3edf307 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Thu, 7 Jul 2022 08:46:38 +0200 Subject: [PATCH 23/24] Fix test_wall_opening invocation --- src/ifcopenshell-python/test/test_wall_opening.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ifcopenshell-python/test/test_wall_opening.py b/src/ifcopenshell-python/test/test_wall_opening.py index 75da8af33d..f331297e73 100644 --- a/src/ifcopenshell-python/test/test_wall_opening.py +++ b/src/ifcopenshell-python/test/test_wall_opening.py @@ -145,7 +145,7 @@ def create_case(fn, openings): class TestWallOpenings: - @pytest.mark.skipif(shutil.which("IfcConvert"), reason="Requires IfcConvert in path") + @pytest.mark.skipif(shutil.which("IfcConvert") is None, reason="Requires IfcConvert in path") def test_all(self): cases = [ @@ -245,4 +245,4 @@ class TestWallOpenings: if __name__ == "__main__": - TestWallOpenings().test_all() + pytest.main(["-x", __file__]) From 443af3f7e7be3622ffd498826b9381545d18edd5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 7 Jul 2022 06:51:04 +0000 Subject: [PATCH 24/24] Bump lxml from 4.6.5 to 4.9.1 in /src/ifcopenshell-python/ifcopenshell Bumps [lxml](https://github.com/lxml/lxml) from 4.6.5 to 4.9.1. - [Release notes](https://github.com/lxml/lxml/releases) - [Changelog](https://github.com/lxml/lxml/blob/master/CHANGES.txt) - [Commits](https://github.com/lxml/lxml/compare/lxml-4.6.5...lxml-4.9.1) --- updated-dependencies: - dependency-name: lxml dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- src/ifcopenshell-python/ifcopenshell/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ifcopenshell-python/ifcopenshell/requirements.txt b/src/ifcopenshell-python/ifcopenshell/requirements.txt index 29dd91befd..61483c9779 100644 --- a/src/ifcopenshell-python/ifcopenshell/requirements.txt +++ b/src/ifcopenshell-python/ifcopenshell/requirements.txt @@ -1,4 +1,4 @@ -lxml==4.6.5 +lxml==4.9.1 numpy==1.22.0 regex==2021.4.4 xmlschema==1.6.4 \ No newline at end of file