diff --git a/src/ifcblenderexport/blenderbim/bim/module/type/__init__.py b/src/ifcblenderexport/blenderbim/bim/module/type/__init__.py index ce91070bc3..4c0a895510 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/type/__init__.py +++ b/src/ifcblenderexport/blenderbim/bim/module/type/__init__.py @@ -7,6 +7,7 @@ classes = ( operator.EnableEditingType, operator.DisableEditingType, operator.SelectSimilarType, + operator.AddTypeInstance, prop.BIMTypeProperties, ui.BIM_PT_type, ) @@ -14,7 +15,9 @@ classes = ( def register(): bpy.types.Object.BIMTypeProperties = bpy.props.PointerProperty(type=prop.BIMTypeProperties) + bpy.types.VIEW3D_MT_mesh_add.append(ui.add_object_button) def unregister(): del bpy.types.Object.BIMTypeProperties + bpy.types.VIEW3D_MT_mesh_add.remove(ui.add_object_button) diff --git a/src/ifcblenderexport/blenderbim/bim/module/type/operator.py b/src/ifcblenderexport/blenderbim/bim/module/type/operator.py index 9f1edb5c05..342bfd1c05 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/type/operator.py +++ b/src/ifcblenderexport/blenderbim/bim/module/type/operator.py @@ -1,10 +1,13 @@ import bpy import ifcopenshell.util.schema +import ifcopenshell.util.type import blenderbim.bim.module.type.assign_type as assign_type import blenderbim.bim.module.type.unassign_type as unassign_type import blenderbim.bim.module.type.get_related_objects as get_related_objects from blenderbim.bim.ifc import IfcStore from blenderbim.bim.module.type.data import Data +from blenderbim.bim.module.type.prop import getIfcTypes, getAvailableTypes, updateTypeInstanceIfcClass +from mathutils import Vector class AssignType(bpy.types.Operator): @@ -12,7 +15,6 @@ class AssignType(bpy.types.Operator): bl_label = "Assign Type" relating_type: bpy.props.IntProperty() related_object: bpy.props.StringProperty() - should_map_representations: bpy.props.BoolProperty() def execute(self, context): self.file = IfcStore.get_file() @@ -29,7 +31,7 @@ class AssignType(bpy.types.Operator): ).execute() Data.load(oprops.ifc_definition_id) - if self.should_map_representations: + if self.file.by_id(relating_type).RepresentationMaps: bpy.ops.bim.map_representations(product_id=oprops.ifc_definition_id, type_product_id=relating_type) bpy.ops.bim.disable_editing_type(obj=related_object.name) @@ -98,3 +100,47 @@ class SelectSimilarType(bpy.types.Operator): if obj.BIMObjectProperties.ifc_definition_id in related_objects: obj.select_set(True) return {"FINISHED"} + + +class AddTypeInstance(bpy.types.Operator): + bl_idname = "bim.add_type_instance" + bl_label = "Add Type Instance" + ifc_class: bpy.props.EnumProperty(items=getIfcTypes, name="IFC Class", update=updateTypeInstanceIfcClass) + relating_type: bpy.props.EnumProperty(items=getAvailableTypes, name="Relating Type") + + def execute(self, context): + if not self.ifc_class or not self.relating_type: + return {"FINISHED"} + # A cube + verts = [ + Vector((-1, -1, -1)), + Vector((-1, -1, 1)), + Vector((-1, 1, -1)), + Vector((-1, 1, 1)), + Vector((1, -1, -1)), + Vector((1, -1, 1)), + Vector((1, 1, -1)), + Vector((1, 1, 1)), + ] + edges = [] + faces = [ + [0, 2, 3, 1], + [2, 3, 7, 6], + [4, 5, 7, 6], + [0, 1, 5, 4], + [1, 3, 7, 5], + ] + mesh = bpy.data.meshes.new(name="Instance") + mesh.from_pydata(verts, edges, faces) + obj = bpy.data.objects.new("Instance", mesh) + obj.location = context.scene.cursor.location + context.view_layer.active_layer_collection.collection.objects.link(obj) + self.file = IfcStore.get_file() + instance_class = ifcopenshell.util.type.get_applicable_entities(self.ifc_class, self.file.schema)[0] + bpy.ops.bim.assign_class(obj=obj.name, ifc_class=instance_class) + bpy.ops.bim.assign_type(relating_type=int(self.relating_type), related_object=obj.name) + return {"FINISHED"} + + def invoke(self, context, event): + wm = context.window_manager + return wm.invoke_props_dialog(self) diff --git a/src/ifcblenderexport/blenderbim/bim/module/type/prop.py b/src/ifcblenderexport/blenderbim/bim/module/type/prop.py index d1422a17ff..9fdce92635 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/type/prop.py +++ b/src/ifcblenderexport/blenderbim/bim/module/type/prop.py @@ -16,6 +16,40 @@ from bpy.props import ( applicable_types_enum = [] relating_types_enum = [] +type_classes_enum = [] +available_types_enum = [] + + +def getIfcTypes(self, context): + global type_classes_enum + file = IfcStore.get_file() + if len(type_classes_enum) < 1 and file: + declaration = IfcStore.get_schema().declaration_by_name("IfcElementType") + + def get_classes(declaration): + results = [] + if not declaration.is_abstract(): + results.append(declaration.name()) + for subtype in declaration.subtypes(): + results.extend(get_classes(subtype)) + return results + + classes = get_classes(declaration) + type_classes_enum.extend([(c, c, "") for c in sorted(classes)]) + return type_classes_enum + + +def getAvailableTypes(self, context): + global available_types_enum + if len(available_types_enum) < 1: + elements = IfcStore.get_file().by_type(self.ifc_class) + available_types_enum.extend((str(e.id()), e.Name, "") for e in elements) + return available_types_enum + + +def updateTypeInstanceIfcClass(self, context): + global available_types_enum + available_types_enum.clear() def getApplicableTypes(self, context): @@ -48,4 +82,3 @@ class BIMTypeProperties(PropertyGroup): relating_type: EnumProperty(items=getRelatingTypes, name="Relating Type") # This is purely a UX thing blank_relating_type: EnumProperty(items=[("None", "No Types Found", "")], name="Relating Type") - should_map_representations: BoolProperty(name="Should Map Representations") diff --git a/src/ifcblenderexport/blenderbim/bim/module/type/ui.py b/src/ifcblenderexport/blenderbim/bim/module/type/ui.py index 32d3f6a9c4..3a4a88215f 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/type/ui.py +++ b/src/ifcblenderexport/blenderbim/bim/module/type/ui.py @@ -35,14 +35,10 @@ class BIM_PT_type(Panel): row.prop(props, "relating_type_class", text="") if props.relating_type: row.prop(props, "relating_type", text="") - op = row.operator("bim.assign_type", icon="CHECKMARK", text="") - op.should_map_representations = props.should_map_representations + row.operator("bim.assign_type", icon="CHECKMARK", text="") else: row.prop(props, "blank_relating_type", text="") row.operator("bim.disable_editing_type", icon="X", text="") - - row = self.layout.row(align=True) - row.prop(props, "should_map_representations") else: row = self.layout.row(align=True) name = "{}/{}".format( @@ -57,3 +53,7 @@ class BIM_PT_type(Panel): row.operator("bim.enable_editing_type", icon="GREASEPENCIL", text="") if name != "None/None": row.operator("bim.unassign_type", icon="X", text="") + + +def add_object_button(self, context): + self.layout.operator("bim.add_type_instance", icon="PLUGIN")