From 671f1ab9cf6bc0507ee7873be7a2c10db8426bf9 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Fri, 13 Aug 2021 14:58:25 +1000 Subject: [PATCH] New feature to toggle default project unit assignment --- src/blenderbim/blenderbim/bim/helper.py | 34 ++++++++++--------- .../blenderbim/bim/module/unit/__init__.py | 1 + .../blenderbim/bim/module/unit/operator.py | 32 ++++++++++++++--- .../blenderbim/bim/module/unit/prop.py | 1 + .../blenderbim/bim/module/unit/ui.py | 7 ++++ .../ifcopenshell/api/unit/data.py | 3 ++ .../ifcopenshell/api/unit/unassign_unit.py | 17 ++++++++++ .../recipes/DowngradeIndexedPolyCurve.py | 2 ++ 8 files changed, 77 insertions(+), 20 deletions(-) create mode 100644 src/ifcopenshell-python/ifcopenshell/api/unit/unassign_unit.py diff --git a/src/blenderbim/blenderbim/bim/helper.py b/src/blenderbim/blenderbim/bim/helper.py index 63e0a75112..fefb377c45 100644 --- a/src/blenderbim/blenderbim/bim/helper.py +++ b/src/blenderbim/blenderbim/bim/helper.py @@ -38,6 +38,7 @@ def import_attributes(ifc_class, props, data, callback=None): for attribute in IfcStore.get_schema().declaration_by_name(ifc_class).all_attributes(): data_type = ifcopenshell.util.attribute.get_primitive_type(attribute) if data_type == "entity" or (isinstance(data_type, tuple) and "entity" in ".".join(data_type)): + callback(attribute.name(), None, data) if callback else None continue new = props.add() new.name = attribute.name() @@ -65,20 +66,21 @@ def import_attributes(ifc_class, props, data, callback=None): def export_attributes(props, callback=None): attributes = {} - for attribute in props: - is_handled_by_callback = callback(attributes, attribute) if callback else False - if attribute.is_null: - attributes[attribute.name] = None - elif is_handled_by_callback: - pass # Our job is done - elif attribute.data_type == "string": - attributes[attribute.name] = attribute.string_value - elif attribute.data_type == "boolean": - attributes[attribute.name] = attribute.bool_value - elif attribute.data_type == "integer": - attributes[attribute.name] = attribute.int_value - elif attribute.data_type == "float": - attributes[attribute.name] = attribute.float_value - elif attribute.data_type == "enum": - attributes[attribute.name] = attribute.enum_value + for prop in props: + is_handled_by_callback = callback(attributes, prop) if callback else False + if is_handled_by_callback: + continue # Our job is done + + if prop.is_null: + attributes[prop.name] = None + elif prop.data_type == "string": + attributes[prop.name] = prop.string_value + elif prop.data_type == "boolean": + attributes[prop.name] = prop.bool_value + elif prop.data_type == "integer": + attributes[prop.name] = prop.int_value + elif prop.data_type == "float": + attributes[prop.name] = prop.float_value + elif prop.data_type == "enum": + attributes[prop.name] = prop.enum_value return attributes diff --git a/src/blenderbim/blenderbim/bim/module/unit/__init__.py b/src/blenderbim/blenderbim/bim/module/unit/__init__.py index f4a0f265ec..c687cffdef 100644 --- a/src/blenderbim/blenderbim/bim/module/unit/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/unit/__init__.py @@ -3,6 +3,7 @@ from . import ui, prop, operator classes = ( operator.AssignUnit, + operator.UnassignUnit, operator.LoadUnits, operator.DisableUnitEditingUI, operator.RemoveUnit, diff --git a/src/blenderbim/blenderbim/bim/module/unit/operator.py b/src/blenderbim/blenderbim/bim/module/unit/operator.py index 78c738e2b9..f8bd288822 100644 --- a/src/blenderbim/blenderbim/bim/module/unit/operator.py +++ b/src/blenderbim/blenderbim/bim/module/unit/operator.py @@ -9,13 +9,20 @@ class AssignUnit(bpy.types.Operator): bl_idname = "bim.assign_unit" bl_label = "Assign Unit" bl_options = {"REGISTER", "UNDO"} + unit: bpy.props.IntProperty() def execute(self, context): return IfcStore.execute_ifc_operator(self, context) def _execute(self, context): - ifcopenshell.api.run("unit.assign_unit", IfcStore.get_file(), **self.get_units(context)) - Data.load(IfcStore.get_file()) + self.file = IfcStore.get_file() + if self.unit: + ifcopenshell.api.run("unit.assign_unit", self.file, units=[self.file.by_id(self.unit)]) + else: + ifcopenshell.api.run("unit.assign_unit", self.file, **self.get_units(context)) + Data.load(self.file) + if self.unit: + bpy.ops.bim.load_units() return {"FINISHED"} def get_units(self, context): @@ -46,6 +53,23 @@ class AssignUnit(bpy.types.Operator): return units +class UnassignUnit(bpy.types.Operator): + bl_idname = "bim.unassign_unit" + bl_label = "Unassign Unit" + bl_options = {"REGISTER", "UNDO"} + unit: bpy.props.IntProperty() + + def execute(self, context): + return IfcStore.execute_ifc_operator(self, context) + + def _execute(self, context): + self.file = IfcStore.get_file() + ifcopenshell.api.run("unit.unassign_unit", IfcStore.get_file(), units=[self.file.by_id(self.unit)]) + Data.load(self.file) + bpy.ops.bim.load_units() + return {"FINISHED"} + + class LoadUnits(bpy.types.Operator): bl_idname = "bim.load_units" bl_label = "Load Units" @@ -56,8 +80,7 @@ class LoadUnits(bpy.types.Operator): while len(props.units) > 0: props.units.remove(0) - for ifc_definition_id in Data.unit_assignment: - unit = Data.units[ifc_definition_id] + for ifc_definition_id, unit in Data.units.items(): name = unit.get("Name", "") if unit["type"] == "IfcMonetaryUnit": @@ -86,6 +109,7 @@ class LoadUnits(bpy.types.Operator): new.ifc_definition_id = ifc_definition_id new.name = name new.unit_type = unit_type + new.is_assigned = ifc_definition_id in Data.unit_assignment new.icon = icon props.is_editing = True diff --git a/src/blenderbim/blenderbim/bim/module/unit/prop.py b/src/blenderbim/blenderbim/bim/module/unit/prop.py index c43f2ec833..20056e3f84 100644 --- a/src/blenderbim/blenderbim/bim/module/unit/prop.py +++ b/src/blenderbim/blenderbim/bim/module/unit/prop.py @@ -36,6 +36,7 @@ def getUnitClasses(self, context): class Unit(PropertyGroup): name: StringProperty(name="Name") unit_type: StringProperty(name="Unit Type") + is_assigned: BoolProperty(name="Is Assigned") icon: StringProperty(name="Icon") ifc_definition_id: IntProperty(name="IFC Definition ID") diff --git a/src/blenderbim/blenderbim/bim/module/unit/ui.py b/src/blenderbim/blenderbim/bim/module/unit/ui.py index c61902b0d0..5235e5b868 100644 --- a/src/blenderbim/blenderbim/bim/module/unit/ui.py +++ b/src/blenderbim/blenderbim/bim/module/unit/ui.py @@ -67,6 +67,13 @@ class BIM_UL_units(UIList): row.label(text=item.unit_type or "No Type", icon=item.icon) row.label(text=item.name or "Unnamed") + if item.is_assigned: + op = row.operator("bim.unassign_unit", text="", icon="KEYFRAME_HLT", emboss=False) + op.unit = item.ifc_definition_id + else: + op = row.operator("bim.assign_unit", text="", icon="KEYFRAME", emboss=False) + op.unit = item.ifc_definition_id + if props.active_unit_id == item.ifc_definition_id: row.operator("bim.edit_unit", text="", icon="CHECKMARK") row.operator("bim.disable_editing_unit", text="", icon="CANCEL") diff --git a/src/ifcopenshell-python/ifcopenshell/api/unit/data.py b/src/ifcopenshell-python/ifcopenshell/api/unit/data.py index 893b302cff..33d89b49c7 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/unit/data.py +++ b/src/ifcopenshell-python/ifcopenshell/api/unit/data.py @@ -24,6 +24,9 @@ class Data: return for unit in unit_assignment[0].Units: cls.unit_assignment.append(unit.id()) + for unit in ( + cls.file.by_type("IfcDerivedUnit") + cls.file.by_type("IfcNamedUnit") + cls.file.by_type("IfcMonetaryUnit") + ): cls.load_unit(unit) cls.is_loaded = True diff --git a/src/ifcopenshell-python/ifcopenshell/api/unit/unassign_unit.py b/src/ifcopenshell-python/ifcopenshell/api/unit/unassign_unit.py new file mode 100644 index 0000000000..b5d181d1dd --- /dev/null +++ b/src/ifcopenshell-python/ifcopenshell/api/unit/unassign_unit.py @@ -0,0 +1,17 @@ +class Usecase: + def __init__(self, file, **settings): + self.file = file + self.settings = {"units": None} + for key, value in settings.items(): + self.settings[key] = value + + def execute(self): + unit_assignment = self.file.by_type("IfcUnitAssignment") + if not unit_assignment: + return + unit_assignment = unit_assignment[0] + units = set(unit_assignment.Units or []) + units = units - set(self.settings["units"]) + if units: + unit_assignment.Units = list(units) + return unit_assignment diff --git a/src/ifcpatch/ifcpatch/recipes/DowngradeIndexedPolyCurve.py b/src/ifcpatch/ifcpatch/recipes/DowngradeIndexedPolyCurve.py index 60bec8e701..ac358347e2 100644 --- a/src/ifcpatch/ifcpatch/recipes/DowngradeIndexedPolyCurve.py +++ b/src/ifcpatch/ifcpatch/recipes/DowngradeIndexedPolyCurve.py @@ -29,6 +29,8 @@ class Patcher: self.args = args def patch(self): + if self.file.schema == "IFC2X3": + return curve_map = {} for curve in self.file.by_type("IfcIndexedPolyCurve"):