From ab704aeb013628f2ff1a92642bbbc9eabd3f927d Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Fri, 26 Jan 2024 15:51:07 +0500 Subject: [PATCH] UI for changing representation item's shape aspect Example - https://imgur.com/a/tN7hCYz --- .../bim/module/geometry/__init__.py | 3 + .../blenderbim/bim/module/geometry/data.py | 18 ++++++ .../bim/module/geometry/operator.py | 46 +++++++++++++++ .../blenderbim/bim/module/geometry/prop.py | 8 +++ .../blenderbim/bim/module/geometry/ui.py | 14 +++-- src/blenderbim/blenderbim/tool/geometry.py | 56 +++++++++++++++++++ 6 files changed, 141 insertions(+), 4 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/geometry/__init__.py b/src/blenderbim/blenderbim/bim/module/geometry/__init__.py index 27e6de0790..34861bdb55 100644 --- a/src/blenderbim/blenderbim/bim/module/geometry/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/geometry/__init__.py @@ -53,6 +53,9 @@ classes = ( operator.EditRepresentationItemStyle, operator.DisableEditingRepresentationItemStyle, operator.UnassignRepresentationItemStyle, + operator.EnableEditingRepresentationItemShapeAspect, + operator.EditRepresentationItemShapeAspect, + operator.DisableEditingRepresentationItemShapeAspect, operator.RemoveRepresentationItemFromShapeAspect, prop.RepresentationItem, prop.BIMObjectGeometryProperties, diff --git a/src/blenderbim/blenderbim/bim/module/geometry/data.py b/src/blenderbim/blenderbim/bim/module/geometry/data.py index 51fa31206f..d72efb2934 100644 --- a/src/blenderbim/blenderbim/bim/module/geometry/data.py +++ b/src/blenderbim/blenderbim/bim/module/geometry/data.py @@ -38,6 +38,7 @@ class RepresentationsData: def load(cls): cls.data = {"representations": cls.representations()} cls.data["contexts"] = cls.contexts() + cls.data["shape_aspects"] = cls.shape_aspects() cls.is_loaded = True @classmethod @@ -92,6 +93,23 @@ class RepresentationsData: ) return results + @classmethod + def shape_aspects(cls): + obj = bpy.context.active_object + element = tool.Ifc.get_entity(obj) + active_representation_id = obj.data.BIMMeshProperties.ifc_definition_id + base_representation = tool.Ifc.get().by_id(active_representation_id) + + # shape aspects matching context of the active representation + matching_shape_aspects = [] + for shape_aspect in tool.Geometry.get_shape_aspects(element): + matching_representation = tool.Geometry.get_shape_aspect_representation(shape_aspect, base_representation) + if matching_representation: + matching_shape_aspects.append(shape_aspect) + + # blender enum items + return [(str(s.id()), s.Name or "Unnamed", "") for s in matching_shape_aspects] + class RepresentationItemsData: data = {} diff --git a/src/blenderbim/blenderbim/bim/module/geometry/operator.py b/src/blenderbim/blenderbim/bim/module/geometry/operator.py index e8e7075cfb..3781918d94 100644 --- a/src/blenderbim/blenderbim/bim/module/geometry/operator.py +++ b/src/blenderbim/blenderbim/bim/module/geometry/operator.py @@ -1688,6 +1688,52 @@ class UnassignRepresentationItemStyle(bpy.types.Operator, Operator): bpy.ops.bim.enable_editing_representation_items() +class EnableEditingRepresentationItemShapeAspect(bpy.types.Operator, Operator): + bl_idname = "bim.enable_editing_representation_item_shape_aspect" + bl_label = "Enable Editing Representation Item Shape Aspect" + bl_options = {"REGISTER", "UNDO"} + + def _execute(self, context): + props = context.active_object.BIMGeometryProperties + props.is_editing_item_shape_aspect = True + + # set dropdown to currently active style + shape_aspect_id = props.items[props.active_item_index].shape_aspect_id + if shape_aspect_id != 0: + props.representation_item_shape_aspect = str(shape_aspect_id) + + +class EditRepresentationItemShapeAspect(bpy.types.Operator, Operator): + bl_idname = "bim.edit_representation_item_shape_aspect" + bl_label = "Edit Representation Item Shape Aspect" + bl_options = {"REGISTER", "UNDO"} + + def _execute(self, context): + obj = context.active_object + props = obj.BIMGeometryProperties + props.is_editing_item_shape_aspect = False + ifc_file = tool.Ifc.get() + + shape_aspect = ifc_file.by_id(int(props.representation_item_shape_aspect)) + representation_item_id = props.items[props.active_item_index].ifc_definition_id + representation_item = ifc_file.by_id(representation_item_id) + + tool.Geometry.add_representation_item_to_shape_aspect(representation_item, shape_aspect) + # reload style ui + bpy.ops.bim.disable_editing_representation_items() + bpy.ops.bim.enable_editing_representation_items() + + +class DisableEditingRepresentationItemShapeAspect(bpy.types.Operator, Operator): + bl_idname = "bim.disable_editing_representation_item_shape_aspect" + bl_label = "Disable Editing Representation Item Shape Aspect" + bl_options = {"REGISTER", "UNDO"} + + def _execute(self, context): + props = context.active_object.BIMGeometryProperties + props.is_editing_item_shape_aspect = False + + class RemoveRepresentationItemFromShapeAspect(bpy.types.Operator, Operator): bl_idname = "bim.remove_representation_item_from_shape_aspect" bl_label = "Remove Representation Item From Shape Aspect" diff --git a/src/blenderbim/blenderbim/bim/module/geometry/prop.py b/src/blenderbim/blenderbim/bim/module/geometry/prop.py index 8877541044..0c6b88f4ed 100644 --- a/src/blenderbim/blenderbim/bim/module/geometry/prop.py +++ b/src/blenderbim/blenderbim/bim/module/geometry/prop.py @@ -56,6 +56,12 @@ def get_styles(self, context): return MaterialsData.data["styles"] +def get_shape_aspects(self, context): + if not RepresentationsData.is_loaded: + RepresentationsData.load() + return RepresentationsData.data["shape_aspects"] + + class RepresentationItem(PropertyGroup): name: StringProperty(name="Name") surface_style: StringProperty(name="Surface Style") @@ -72,6 +78,8 @@ class BIMObjectGeometryProperties(PropertyGroup): active_item_index: IntProperty(name="Active Representation Item Index") is_editing_item_style: BoolProperty(name="Is Editing Item's Style", default=False) representation_item_style: EnumProperty(items=get_styles, name="Representation Item Style") + is_editing_item_shape_aspect: BoolProperty(name="Is Editing Item's Shape Aspect", default=False) + representation_item_shape_aspect: EnumProperty(items=get_shape_aspects, name="Representation Item Shape Aspect") class BIMGeometryProperties(PropertyGroup): diff --git a/src/blenderbim/blenderbim/bim/module/geometry/ui.py b/src/blenderbim/blenderbim/bim/module/geometry/ui.py index 20a711a6f2..b59bbc92fc 100644 --- a/src/blenderbim/blenderbim/bim/module/geometry/ui.py +++ b/src/blenderbim/blenderbim/bim/module/geometry/ui.py @@ -213,10 +213,16 @@ class BIM_PT_representation_items(Panel): row = self.layout.row() row.label(text=active_item.layer or "No Presentation Layer", icon="STICKY_UVS_LOC") - row = self.layout.row() - row.label(text=shape_aspect or "No Shape Aspect", icon="SHAPEKEY_DATA") - if shape_aspect: - row.operator("bim.remove_representation_item_from_shape_aspect", icon="X", text="") + row = self.layout.row(align=True) + if props.is_editing_item_shape_aspect: + row.prop(props, "representation_item_shape_aspect", icon="SHAPEKEY_DATA", text="") + row.operator("bim.edit_representation_item_shape_aspect", icon="CHECKMARK", text="") + row.operator("bim.disable_editing_representation_item_shape_aspect", icon="CANCEL", text="") + else: + row.label(text=shape_aspect or "No Shape Aspect", icon="SHAPEKEY_DATA") + row.operator("bim.enable_editing_representation_item_shape_aspect", icon="GREASEPENCIL", text="") + if shape_aspect: + row.operator("bim.remove_representation_item_from_shape_aspect", icon="X", text="") class BIM_PT_connections(Panel): diff --git a/src/blenderbim/blenderbim/tool/geometry.py b/src/blenderbim/blenderbim/tool/geometry.py index 0f50c97068..03ee473a65 100644 --- a/src/blenderbim/blenderbim/tool/geometry.py +++ b/src/blenderbim/blenderbim/tool/geometry.py @@ -731,6 +731,18 @@ class Geometry(blenderbim.core.tool.Geometry): apply_openings=True, ) + @classmethod + def get_shape_aspects(cls, element): + # IfcProduct + if hasattr(element, "Representation"): + return element.Representation.ShapeOfProduct + + # IfcTypeProduct + shape_aspects = [] + for repersentation_map in element.RepresentationMaps: + shape_aspects += repersentation_map.HasShapeAspects + return shape_aspects + @classmethod def remove_representation_item_from_shape_aspect(cls, representation_item, shape_aspect): ifc_file = tool.Ifc.get() @@ -751,3 +763,47 @@ class Geometry(blenderbim.core.tool.Geometry): else: items = set(representation.Items) - {representation_item} representation.Items = tuple(items) + + @classmethod + def add_representation_item_to_shape_aspect(cls, representation_item, shape_aspect): + ifc_file = tool.Ifc.get() + previous_shape_aspect = None + for inverse in ifc_file.get_inverse(representation_item): + if inverse.is_a("IfcShapeRepresentation"): + if inverse.OfShapeAspect: + # item is already added to the shape aspect + if inverse.OfShapeAspect[0] == shape_aspect: + return + previous_shape_aspect = inverse.OfShapeAspect[0] + else: + base_representation = inverse + + # remove item from previous shape aspect + if previous_shape_aspect: + cls.remove_representation_item_from_shape_aspect(representation_item, previous_shape_aspect) + shape_aspect_representation = cls.get_shape_aspect_representation( + shape_aspect, base_representation, create_new=True + ) + shape_aspect_representation.Items = shape_aspect_representation.Items + (representation_item,) + + @classmethod + def get_shape_aspect_representation(cls, shape_aspect, base_representation, create_new=False): + for representation in shape_aspect.ShapeRepresentations: + if ( + representation.ContextOfItems == base_representation.ContextOfItems + and representation.RepresentationIdentifier == base_representation.RepresentationIdentifier + and representation.RepresentationType == base_representation.RepresentationType + ): + return representation + + if not create_new: + return None + + shape_aspect_representation = tool.Ifc.get().createIfcShapeRepresentation( + ContextOfItems=base_representation.ContextOfItems, + RepresentationIdentifier=base_representation.RepresentationIdentifier, + RepresentationType=base_representation.RepresentationType, + ) + shape_aspect.ShapeRepresentations = shape_aspect.ShapeRepresentations + (shape_aspect_representation,) + + return shape_aspect_representation