From 05633cd65711a7d29e472fbae95733585459d10d Mon Sep 17 00:00:00 2001 From: martinaCodes Date: Fri, 11 Nov 2022 02:50:30 +0100 Subject: [PATCH] Updated following nodes to work with the current workflow: add_pset, by_guid, get_attribute, get_property, read_entity. Added tooltips and other minor fixes --- src/ifcsverchok/nodes/ifc/add_pset.py | 80 ++++++++---- .../nodes/ifc/add_spatial_element.py | 111 +++++++++++++---- src/ifcsverchok/nodes/ifc/bmesh_to_ifc.py | 83 +++++++++---- src/ifcsverchok/nodes/ifc/by_guid.py | 35 ++++-- src/ifcsverchok/nodes/ifc/by_type.py | 37 ++++-- src/ifcsverchok/nodes/ifc/create_entity.py | 114 ++++++++++++++---- src/ifcsverchok/nodes/ifc/create_shape.py | 4 +- src/ifcsverchok/nodes/ifc/get_attribute.py | 40 +++++- src/ifcsverchok/nodes/ifc/get_property.py | 59 ++++++--- src/ifcsverchok/nodes/ifc/read_entity.py | 54 ++++++--- src/ifcsverchok/nodes/ifc/sverchok_to_ifc.py | 60 ++++++--- 11 files changed, 508 insertions(+), 169 deletions(-) diff --git a/src/ifcsverchok/nodes/ifc/add_pset.py b/src/ifcsverchok/nodes/ifc/add_pset.py index c0fba2f6c7..9927e06d62 100644 --- a/src/ifcsverchok/nodes/ifc/add_pset.py +++ b/src/ifcsverchok/nodes/ifc/add_pset.py @@ -28,22 +28,36 @@ import ifcopenshell from bpy.props import StringProperty from sverchok.node_tree import SverchCustomTreeNode -from sverchok.data_structure import updateNode +from sverchok.data_structure import updateNode, flatten_data class SvIfcAddPset(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore): bl_idname = "SvIfcAddPset" bl_label = "IFC Add Pset" - Name: StringProperty(name="Name", update=updateNode, default="My_Pset") - Properties: StringProperty(name="Properties", update=updateNode, default="{\"Foo\":\"Bar\"}") - Elements: StringProperty(name="Elements", update=updateNode) + Name: StringProperty( + name="Name", + description="Name of the property set. Eg. Pset_WallCommon.", + update=updateNode, + default="My_Pset", + ) + Properties: StringProperty( + name="Properties", + description='Propertied in a JSON key:value format.Eg. {"IsExternal":"True"}', + update=updateNode, + default='{"Foo":"Bar"}', + ) + Elements: StringProperty(name="Element Ids", update=updateNode) def sv_init(self, context): self.inputs.new("SvStringsSocket", "Name").prop_name = "Name" self.inputs.new("SvTextSocket", "Properties").prop_name = "Properties" self.inputs.new("SvStringsSocket", "Elements").prop_name = "Elements" - self.outputs.new("SvStringsSocket", "entity") - self.outputs.new("SvStringsSocket", "file") + self.outputs.new("SvStringsSocket", "Entity") + + def draw_buttons(self, context, layout): + layout.operator( + "node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False + ).tooltip = "Add a property set and corresponding properties to IfcElements." def process(self): if not any(socket.is_linked for socket in self.outputs): @@ -51,37 +65,59 @@ class SvIfcAddPset(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIf name = self.inputs["Name"].sv_get()[0][0] properties = self.inputs["Properties"].sv_get()[0][0] - elements = self.inputs["Elements"].sv_get()[0] + element_ids = flatten_data(self.inputs["Elements"].sv_get(), target_level=1) - if SvIfcStore.file is None: - SvIfcStore.file = SvIfcStore.create_boilerplate() self.file = SvIfcStore.get_file() + try: + elements = [self.file.by_id(int(step_id)) for step_id in element_ids] + print(elements[0]) + except Exception as e: + raise Exception("Instance ID not found", e) - if self.node_id not in SvIfcStore.id_map.values(): + if self.node_id not in SvIfcStore.id_map: element = self.create(name, properties, elements) else: element = self.edit(name, properties, elements) - self.outputs["entity"].sv_set([[element]]) - self.outputs["file"].sv_set([[self.file]]) + self.outputs["Entity"].sv_set([element]) def create(self, name, properties, elements): results = [] for element in elements: - result = ifcopenshell.api.run("pset.add_pset", self.file, product=element, name=name) - ifcopenshell.api.run("pset.edit_pset", self.file, pset=result, properties=json.loads(properties)) - SvIfcStore.id_map[result.id()] = self.node_id + print("element: ", element) + result = ifcopenshell.api.run( + "pset.add_pset", self.file, product=element, name=name + ) + ifcopenshell.api.run( + "pset.edit_pset", + self.file, + pset=result, + properties=json.loads(properties), + ) + print("result: ", result) + SvIfcStore.id_map.setdefault(self.node_id, []).append(result.id()) results.append(result) - return result + return results def edit(self, name, properties, elements): - result = self.get_existing_element() - ifcopenshell.api.run("pset.edit_pset", self.file, pset=result, name=name, properties=json.loads(properties)) - return result + result_ids = SvIfcStore.id_map[self.node_id] + results = [] + for result_id in result_ids: + result = self.file.by_id(result_id) + ifcopenshell.api.run( + "pset.edit_pset", + self.file, + pset=result, + name=name, + properties=json.loads(properties), + ) + results.append(result) + return results - def get_existing_element(self): - entity_id = list(SvIfcStore.id_map.keys())[list(SvIfcStore.id_map.values()).index(self.node_id)] - return self.file.by_id(entity_id) + # def get_existing_element(self): + # entity_id = list(SvIfcStore.id_map.keys())[list(SvIfcStore.id_map.values()).index(self.node_id)] + + # return self.file.by_id(entity_id) def register(): diff --git a/src/ifcsverchok/nodes/ifc/add_spatial_element.py b/src/ifcsverchok/nodes/ifc/add_spatial_element.py index 0cb641158c..04c47a673f 100644 --- a/src/ifcsverchok/nodes/ifc/add_spatial_element.py +++ b/src/ifcsverchok/nodes/ifc/add_spatial_element.py @@ -24,17 +24,37 @@ from ifcsverchok.ifcstore import SvIfcStore from bpy.props import StringProperty from sverchok.node_tree import SverchCustomTreeNode -from sverchok.data_structure import updateNode, flatten_data, repeat_last_for_length, ensure_min_nesting +from sverchok.data_structure import ( + updateNode, + flatten_data, + repeat_last_for_length, + ensure_min_nesting, +) -class SvIfcAddSpatialElement(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore): +class SvIfcAddSpatialElement( + bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore +): bl_idname = "SvIfcAddSpatialElement" bl_label = "IFC Add Spatial Element" node_dict = {} - Names: StringProperty(name="Name(s)", update=updateNode) - IfcClass: StringProperty(name="IFC Class", update=updateNode, default="IfcSpace") - Elements: StringProperty(name="Elements", update=updateNode) + Names: StringProperty( + name="Name(s)", + description="Name or list of names of the spacial element.", + update=updateNode, + ) + IfcClass: StringProperty( + name="IFC Class", + description='IfcClass of the spacial element. Eg. "IfcSpace".\nYou can use the "IFC Class Picker" node to find a relevant class.', + update=updateNode, + default="IfcSpace", + ) + Elements: StringProperty( + name="Elements", + description="The IfcElements you want to add to the spacial element.\nThis can also be a (list of) spacial elements. Eg. IfcSpaces aggregated to an IfcBuildingStorey.", + update=updateNode, + ) def sv_init(self, context): self.inputs.new("SvStringsSocket", "Names").prop_name = "Names" @@ -44,12 +64,16 @@ class SvIfcAddSpatialElement(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h self.node_dict[hash(self)] = {} def draw_buttons(self, context, layout): - layout.operator("node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False).tooltip = "Ifc entity by type." + layout.operator( + "node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False + ).tooltip = "Add IfcElements to an IfcSpatialElement." def process(self): self.sv_input_names = [i.name for i in self.inputs] if hash(self) not in self.node_dict: - self.node_dict[hash(self)] = {} # happens if node is already on canvas when blender loads + self.node_dict[ + hash(self) + ] = {} # happens if node is already on canvas when blender loads if not self.node_dict[hash(self)]: self.node_dict[hash(self)].update(dict.fromkeys(self.sv_input_names, 0)) @@ -58,7 +82,9 @@ class SvIfcAddSpatialElement(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h edit = False edit_elements = False for i in range(len(self.inputs)): - input = self.inputs[self.sv_input_names[i]].sv_get(deepcopy=True, default=[]) + input = self.inputs[self.sv_input_names[i]].sv_get( + deepcopy=True, default=[] + ) if ( isinstance(self.node_dict[hash(self)][self.inputs[i].name], list) and input != self.node_dict[hash(self)][self.inputs[i].name] @@ -69,20 +95,27 @@ class SvIfcAddSpatialElement(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h self.node_dict[hash(self)][self.inputs[i].name] = input.copy() self.names = flatten_data(self.inputs["Names"].sv_get(), target_level=1) - self.ifc_class = flatten_data(self.inputs["IfcClass"].sv_get(), target_level=1)[0] + self.ifc_class = flatten_data(self.inputs["IfcClass"].sv_get(), target_level=1)[ + 0 + ] self.elements = ensure_min_nesting(self.inputs["Elements"].sv_get(), 2) self.elements = flatten_data(self.elements, target_level=2) if not self.elements[0][0]: raise Exception('Mandatory input "Element(s)" is missing.') return self.file = SvIfcStore.get_file() - self.elements = [[self.file.by_id(step_id) for step_id in element] for element in self.elements] + self.elements = [ + [self.file.by_id(step_id) for step_id in element] + for element in self.elements + ] if "len" not in self.node_dict[hash(self)]: self.node_dict[hash(self)]["len"] = 0 self.names = self.repeat_input_unique(self.names, len(self.elements)) - if (self.node_id not in SvIfcStore.id_map) or (len(self.elements) != self.node_dict[hash(self)]["len"]): + if (self.node_id not in SvIfcStore.id_map) or ( + len(self.elements) != self.node_dict[hash(self)]["len"] + ): self.remove() elements = self.create() self.node_dict[hash(self)]["len"] = len(self.elements) @@ -99,13 +132,28 @@ class SvIfcAddSpatialElement(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h if index is not None: iterator = [index] for i in iterator: - result = ifcopenshell.api.run("root.create_entity", self.file, name=self.names[i], ifc_class=self.ifc_class) + result = ifcopenshell.api.run( + "root.create_entity", + self.file, + name=self.names[i], + ifc_class=self.ifc_class, + ) for items in self.elements[i]: - if items.is_a("IfcSpatialElement") or items.is_a("IfcSpatialStructureElement"): - ifcopenshell.api.run("aggregate.assign_object", self.file, product=items, relating_object=result) + if items.is_a("IfcSpatialElement") or items.is_a( + "IfcSpatialStructureElement" + ): + ifcopenshell.api.run( + "aggregate.assign_object", + self.file, + product=items, + relating_object=result, + ) else: ifcopenshell.api.run( - "spatial.assign_container", self.file, product=items, relating_structure=result + "spatial.assign_container", + self.file, + product=items, + relating_structure=result, ) SvIfcStore.id_map.setdefault(self.node_id, []).append(result.id()) spatial_ids.append(result.id()) @@ -129,24 +177,38 @@ class SvIfcAddSpatialElement(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h for element in self.elements[i]: element_set = set([element]) for removed_element in subelements - element_set: - if removed_element.is_a("IfcSpatialElement") or removed_element.is_a( - "IfcSpatialStructureElement" - ): + if removed_element.is_a( + "IfcSpatialElement" + ) or removed_element.is_a("IfcSpatialStructureElement"): ifcopenshell.api.run( - "aggregate.unassign_object", self.file, product=removed_element, relating_object=result + "aggregate.unassign_object", + self.file, + product=removed_element, + relating_object=result, ) else: ifcopenshell.api.run( - "spatial.unassign_container", self.file, product=removed_element, relating_object=result + "spatial.unassign_container", + self.file, + product=removed_element, + relating_object=result, ) for added_element in element_set - subelements: - if added_element.is_a("IfcSpatialElement") or added_element.is_a("IfcSpatialStructureElement"): + if added_element.is_a( + "IfcSpatialElement" + ) or added_element.is_a("IfcSpatialStructureElement"): ifcopenshell.api.run( - "aggregate.assign_object", self.file, product=added_element, relating_object=result + "aggregate.assign_object", + self.file, + product=added_element, + relating_object=result, ) else: ifcopenshell.api.run( - "spatial.assign_container", self.file, product=added_element, relating_structure=result + "spatial.assign_container", + self.file, + product=added_element, + relating_structure=result, ) spatial_ids.append(result.id()) SvIfcStore.id_map[self.node_id] = spatial_ids @@ -163,7 +225,8 @@ class SvIfcAddSpatialElement(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h input = repeat_last_for_length(input, count, deepcopy=False) if input[0]: input = [ - a if not (s := sum(j == a for j in input[:i])) else f"{a}-{s+1}" for i, a in enumerate(input) + a if not (s := sum(j == a for j in input[:i])) else f"{a}-{s+1}" + for i, a in enumerate(input) ] # add number to duplicates return input diff --git a/src/ifcsverchok/nodes/ifc/bmesh_to_ifc.py b/src/ifcsverchok/nodes/ifc/bmesh_to_ifc.py index 874e236b5c..133c118cc0 100644 --- a/src/ifcsverchok/nodes/ifc/bmesh_to_ifc.py +++ b/src/ifcsverchok/nodes/ifc/bmesh_to_ifc.py @@ -26,7 +26,13 @@ import ifcopenshell.api from ifcsverchok.ifcstore import SvIfcStore import blenderbim.tool as tool import blenderbim.core.geometry as core -from bpy.props import StringProperty, EnumProperty, IntProperty, BoolProperty, PointerProperty +from bpy.props import ( + StringProperty, + EnumProperty, + IntProperty, + BoolProperty, + PointerProperty, +) from sverchok.node_tree import SverchCustomTreeNode from sverchok.data_structure import updateNode, flatten_data, fixed_iter, flat_iter from blenderbim.bim.module.root.prop import get_contexts @@ -36,7 +42,9 @@ from sverchok.core.socket_data import sv_get_socket from itertools import chain, cycle -class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore): +class SvIfcBMeshToIfcRepr( + bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore +): """ Triggers: BMesh to Ifc Repr Tooltip: Blender mesh to Ifc Shape Representation @@ -53,7 +61,9 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help updateNode(self, context) self.refresh_local = False - refresh_local: BoolProperty(name="Update Node", description="Update Node", update=refresh_node) + refresh_local: BoolProperty( + name="Update Node", description="Update Node", update=refresh_node + ) context_types = [ ("Model", "Model", "Context type: Model", 0), @@ -73,10 +83,17 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help ("SKETCH_VIEW", "SKETCH_VIEW", "Target View: SKETCH_VIEW", 3), ] blender_objects: PointerProperty( - name="Blender Mesh(es)", description="Blender Mesh Object(s)", update=updateNode, type=bpy.types.Object + name="Blender Mesh(es)", + description="Blender Mesh Object(s)", + update=updateNode, + type=bpy.types.Object, ) context_type: EnumProperty( - name="Context Type", description="Default: Model", default="Model", items=context_types, update=updateNode + name="Context Type", + description="Default: Model", + default="Model", + items=context_types, + update=updateNode, ) context_identifier: EnumProperty( name="Context Identifier", @@ -96,16 +113,20 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help def sv_init(self, context): self.inputs.new("SvStringsSocket", "context_type").prop_name = "context_type" - self.inputs.new("SvStringsSocket", "context_identifier").prop_name = "context_identifier" + self.inputs.new( + "SvStringsSocket", "context_identifier" + ).prop_name = "context_identifier" self.inputs.new("SvStringsSocket", "target_view").prop_name = "target_view" - self.inputs.new("SvObjectSocket", "blender_objects").prop_name = "blender_objects" # no prop for now + self.inputs.new( + "SvObjectSocket", "blender_objects" + ).prop_name = "blender_objects" # no prop for now self.outputs.new("SvVerticesSocket", "Representations") self.outputs.new("SvMatrixSocket", "Locations") def draw_buttons(self, context, layout): layout.operator( "node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False - ).tooltip = "Blender mesh to Ifc Shape Representation. \nTakes one or multiple geometries." + ).tooltip = "Blender mesh to Ifc Shape Representation. \nTakes one or multiple geometries.\nDeconstructs joined geometries and creates a separate representation for each." row = layout.row(align=True) row.prop(self, "is_interactive", icon="SCENE_DATA", icon_only=True) @@ -115,7 +136,9 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help self.sv_input_names = [i.name for i in self.inputs] if hash(self) not in self.node_dict: - self.node_dict[hash(self)] = {} # happens if node is already on canvas when blender loads + self.node_dict[ + hash(self) + ] = {} # happens if node is already on canvas when blender loads if not self.node_dict[hash(self)]: self.node_dict[hash(self)].update(dict.fromkeys(self.sv_input_names, 0)) @@ -179,16 +202,20 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help context=self.get_context(), ) if not representation: - raise Exception("Couldn't create representation. Possibly wrong context.") + raise Exception( + "Couldn't create representation. Possibly wrong context." + ) representations_ids_obj.append(representation.id()) locations_obj.append(obj.matrix_world) representations_ids.append(representations_ids_obj) locations.append(locations_obj) - SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault("Representations", []).append( - representations_ids_obj - ) - SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault("Locations", []).append(locations_obj) + SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault( + "Representations", [] + ).append(representations_ids_obj) + SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault( + "Locations", [] + ).append(locations_obj) try: bpy.ops.object.mode_set(mode="OBJECT") except: @@ -202,7 +229,9 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help for obj in SvIfcStore.id_map[self.node_id]["Representations"]: for step_id in obj: ifcopenshell.api.run( - "geometry.remove_representation", self.file, representation=self.file.by_id(step_id) + "geometry.remove_representation", + self.file, + representation=self.file.by_id(step_id), ) del SvIfcStore.id_map[self.node_id]["Representations"] del SvIfcStore.id_map[self.node_id]["Locations"] @@ -213,9 +242,13 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help self.file, self.context_type, self.context_identifier, self.target_view ) if not context: - parent = ifcopenshell.util.representation.get_context(self.file, self.context_type) + parent = ifcopenshell.util.representation.get_context( + self.file, self.context_type + ) if not parent: - parent = ifcopenshell.api.run("context.add_context", self.file, context_type=self.context_type) + parent = ifcopenshell.api.run( + "context.add_context", self.file, context_type=self.context_type + ) context = ifcopenshell.api.run( "context.add_context", self.file, @@ -224,7 +257,9 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help target_view=self.target_view, parent=parent, ) - SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault("Contexts", []).append(context.id()) + SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault( + "Contexts", [] + ).append(context.id()) return context def sv_free(self): @@ -234,7 +269,9 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help for obj in SvIfcStore.id_map[self.node_id]["Representations"]: for step_id in obj: ifcopenshell.api.run( - "geometry.remove_representation", self.file, representation=self.file.by_id(step_id) + "geometry.remove_representation", + self.file, + representation=self.file.by_id(step_id), ) if "Contexts" in SvIfcStore.id_map[self.node_id]: @@ -243,10 +280,14 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help if not self.file.get_inverse(context): if self.file.by_id(context_id).ParentContext: parent = self.file.by_id(context_id).ParentContext - ifcopenshell.api.run("context.remove_context", self.file, context=context) + ifcopenshell.api.run( + "context.remove_context", self.file, context=context + ) if parent: if not self.file.get_inverse(parent): - ifcopenshell.api.run("context.remove_context", self.file, context=parent) + ifcopenshell.api.run( + "context.remove_context", self.file, context=parent + ) # print("Removed context with step ID: ", context_id) SvIfcStore.id_map[self.node_id]["Contexts"].remove(context_id) del SvIfcStore.id_map[self.node_id] diff --git a/src/ifcsverchok/nodes/ifc/by_guid.py b/src/ifcsverchok/nodes/ifc/by_guid.py index 44fdc5e9da..21fc332af9 100644 --- a/src/ifcsverchok/nodes/ifc/by_guid.py +++ b/src/ifcsverchok/nodes/ifc/by_guid.py @@ -16,31 +16,48 @@ # You should have received a copy of the GNU General Public License # along with IfcSverchok. If not, see . +import itertools + import bpy import ifcopenshell import ifcsverchok.helper +from ifcsverchok.ifcstore import SvIfcStore from bpy.props import StringProperty from sverchok.node_tree import SverchCustomTreeNode -from sverchok.data_structure import updateNode +from sverchok.data_structure import updateNode, flatten_data class SvIfcByGuid(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore): bl_idname = "SvIfcByGuid" bl_label = "IFC By Guid" - file: StringProperty(name="file", update=updateNode) - guid: StringProperty(name="guid", update=updateNode) + n_id: StringProperty(default="") + guid: StringProperty(name="Guid(s)", update=updateNode) + id_iter = itertools.count() def sv_init(self, context): - self.inputs.new("SvStringsSocket", "file").prop_name = "file" self.inputs.new("SvStringsSocket", "guid").prop_name = "guid" - self.outputs.new("SvStringsSocket", "entity") + self.outputs.new("SvStringsSocket", "Entities") + + def draw_buttons(self, context, layout): + layout.operator( + "node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False + ).tooltip = "Get IFC element by guid. Takes one or multiple guids." def process(self): - self.sv_input_names = ["file", "guid"] - super().process() + print("\n\n", "#" * 30, "Running SvIfcByGuid node", "#" * 30) + print("self: ", self) + print("id(self): ", id(self)) + print("hash(self): ", hash(self)) + print("node_id: ", self.node_id) + self.id = next(self.id_iter) + print("self.id (itertool counter): ", self.id) - def process_ifc(self, file, guid): - self.outputs["entity"].sv_set([[file.by_guid(guid)]]) + self.guids = flatten_data(self.inputs["guid"].sv_get(), target_level=1) + if not self.guids[0]: + return + self.file = SvIfcStore.get_file() + self.entities = [self.file.by_guid(guid) for guid in self.guids] + self.outputs["Entities"].sv_set(self.entities) def register(): diff --git a/src/ifcsverchok/nodes/ifc/by_type.py b/src/ifcsverchok/nodes/ifc/by_type.py index ffed83bd5d..15c500142d 100644 --- a/src/ifcsverchok/nodes/ifc/by_type.py +++ b/src/ifcsverchok/nodes/ifc/by_type.py @@ -48,7 +48,11 @@ def get_ifc_products(self, context): ] ) if file.schema == "IFC2X3": - ifc_products[2] = ("IfcSpatialStructureElement", "IfcSpatialStructureElement", "") + ifc_products[2] = ( + "IfcSpatialStructureElement", + "IfcSpatialStructureElement", + "", + ) return ifc_products @@ -90,25 +94,31 @@ class SvIfcByType(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfc update=update_ifc_products, ) ifc_class: EnumProperty( - items=get_ifc_classes, name="IfcClass", description="Pick an IfcClass from drop-down.", update=updateNode + items=get_ifc_classes, + name="IfcClass", + description="Pick an IfcClass from drop-down.", + update=updateNode, ) custom_ifc_class: StringProperty( - name="Custom IfcClass", description="Give the name of your custom IfcClass.", update=updateNode + name="Custom IfcClass", + description="Give the name of your custom IfcClass.", + update=updateNode, ) def sv_init(self, context): self.inputs.new("SvStringsSocket", "ifc_product").prop_name = "ifc_product" self.inputs.new("SvStringsSocket", "ifc_class").prop_name = "ifc_class" - self.inputs.new("SvStringsSocket", "custom_ifc_class").prop_name = "custom_ifc_class" - self.outputs.new("SvStringsSocket", "Entity") + self.inputs.new( + "SvStringsSocket", "custom_ifc_class" + ).prop_name = "custom_ifc_class" + self.outputs.new("SvStringsSocket", "Entities") + self.outputs.new("SvStringsSocket", "Entity Ids") self.width = 200 def draw_buttons(self, context, layout): layout.operator( "node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False - ).tooltip = ( - "Get IFC element(s) in file by type. \nPick an IfcProduct and an IfcClass or give a custom IfcClass." - ) + ).tooltip = "Get IFC element(s) in file by type. \nPick an IfcProduct and an IfcClass or give a custom IfcClass." def process(self): self.file = SvIfcStore.get_file() @@ -120,11 +130,16 @@ class SvIfcByType(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfc def process_ifc(self, ifc_product, ifc_class, custom_ifc_class): if custom_ifc_class: - self.outputs["Entity"].sv_set([self.file.by_type(custom_ifc_class)]) + entities = self.file.by_type(custom_ifc_class) + self.outputs["Entities"].sv_set(entities) + self.outputs["Entity Ids"].sv_set([e.id() for e in entities]) elif ifc_class: - self.outputs["Entity"].sv_set([self.file.by_type(ifc_class)]) + entities = self.file.by_type(ifc_class) + self.outputs["Entities"].sv_set(self.file.by_type(ifc_class)) + self.outputs["Entity Ids"].sv_set([e.id() for e in entities]) else: - self.outputs["Entity"].sv_set([]) + self.outputs["Entities"].sv_set([]) + self.outputs["Entity Ids"].sv_set([]) def register(): diff --git a/src/ifcsverchok/nodes/ifc/create_entity.py b/src/ifcsverchok/nodes/ifc/create_entity.py index 72a1b6201b..e9297251c4 100644 --- a/src/ifcsverchok/nodes/ifc/create_entity.py +++ b/src/ifcsverchok/nodes/ifc/create_entity.py @@ -24,10 +24,17 @@ from ifcsverchok.ifcstore import SvIfcStore from bpy.props import StringProperty, BoolProperty from sverchok.node_tree import SverchCustomTreeNode -from sverchok.data_structure import updateNode, flatten_data, repeat_last_for_length, ensure_min_nesting +from sverchok.data_structure import ( + updateNode, + flatten_data, + repeat_last_for_length, + ensure_min_nesting, +) -class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore): +class SvIfcCreateEntity( + bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore +): bl_idname = "SvIfcCreateEntity" bl_label = "IFC Create Entity" node_dict = {} @@ -39,12 +46,29 @@ class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper self.process() self.refresh_local = False - refresh_local: BoolProperty(name="Update Node", description="Update Node", update=refresh_node) + refresh_local: BoolProperty( + name="Update Node", description="Update Node", update=refresh_node + ) - Names: StringProperty(name="Names", default="", update=updateNode) - Descriptions: StringProperty(name="Descriptions", default="", update=updateNode) + Names: StringProperty( + name="Names", + default="", + description="Entity name or list of names.", + update=updateNode, + ) + Descriptions: StringProperty( + name="Descriptions", + default="", + description="Entity description or list of descriptions.", + update=updateNode, + ) IfcClass: StringProperty(name="IfcClass", update=updateNode) - Representations: StringProperty(name="Representations", default="", update=updateNode) + Representations: StringProperty( + name="Representations", + description='IfcRepresentation(s). Use eg. "IFC BMesh to IFC" or "IFC Sverchok to IFC" nodes to create representations.', + default="", + update=updateNode, + ) # Locations: FloatVectorProperty(name="Locations", default="", update=updateNode) Properties: StringProperty(name="properties", update=updateNode) @@ -52,7 +76,9 @@ class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper self.inputs.new("SvStringsSocket", "Names").prop_name = "Names" self.inputs.new("SvStringsSocket", "Descriptions").prop_name = "Descriptions" self.inputs.new("SvStringsSocket", "IfcClass").prop_name = "IfcClass" - self.inputs.new("SvStringsSocket", "Representations").prop_name = "Representations" + self.inputs.new( + "SvStringsSocket", "Representations" + ).prop_name = "Representations" self.inputs.new("SvMatrixSocket", "Locations").is_mandatory = False self.inputs.new("SvStringsSocket", "Properties").prop_name = "Properties" self.outputs.new("SvStringsSocket", "Entities") @@ -69,17 +95,27 @@ class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper def process(self): self.names = flatten_data(self.inputs["Names"].sv_get(), target_level=1) - self.descriptions = flatten_data(self.inputs["Descriptions"].sv_get(), target_level=1) - self.ifc_class = flatten_data(self.inputs["IfcClass"].sv_get(), target_level=1)[0] - self.representations = ensure_min_nesting(self.inputs["Representations"].sv_get(), 2) + self.descriptions = flatten_data( + self.inputs["Descriptions"].sv_get(), target_level=1 + ) + self.ifc_class = flatten_data(self.inputs["IfcClass"].sv_get(), target_level=1)[ + 0 + ] + self.representations = ensure_min_nesting( + self.inputs["Representations"].sv_get(), 2 + ) self.representations = flatten_data(self.representations, target_level=2) - self.locations = ensure_min_nesting(self.inputs["Locations"].sv_get(default=[]), 2) + self.locations = ensure_min_nesting( + self.inputs["Locations"].sv_get(default=[]), 2 + ) self.properties = self.inputs["Properties"].sv_get() self.sv_input_names = [i.name for i in self.inputs] if hash(self) not in self.node_dict: - self.node_dict[hash(self)] = {} # happens if node is already on canvas when blender loads + self.node_dict[ + hash(self) + ] = {} # happens if node is already on canvas when blender loads if not self.node_dict[hash(self)]: self.node_dict[hash(self)].update(dict.fromkeys(self.sv_input_names, 0)) if not self.inputs["IfcClass"].sv_get()[0][0]: @@ -87,7 +123,9 @@ class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper edit = False for i in range(len(self.inputs)): - input = self.inputs[self.sv_input_names[i]].sv_get(deepcopy=True, default=[]) + input = self.inputs[self.sv_input_names[i]].sv_get( + deepcopy=True, default=[] + ) if ( isinstance(self.node_dict[hash(self)][self.inputs[i].name], list) and input != self.node_dict[hash(self)][self.inputs[i].name] @@ -103,14 +141,19 @@ class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper try: # self.representations = [self.file.by_id(step_id) for step_id in self.representations] self.representations = [ - [self.file.by_id(step_id) for step_id in representation] for representation in self.representations + [self.file.by_id(step_id) for step_id in representation] + for representation in self.representations ] except Exception as e: raise self.names = self.repeat_input_unique(self.names, len(self.representations)) - self.descriptions = self.repeat_input_unique(self.descriptions, len(self.representations)) - elif not self.representations[0]: - self.descriptions = self.repeat_input_unique(self.descriptions, len(self.names)) + self.descriptions = self.repeat_input_unique( + self.descriptions, len(self.representations) + ) + elif not self.representations[0][0]: + self.descriptions = self.repeat_input_unique( + self.descriptions, len(self.names) + ) if self.node_id not in SvIfcStore.id_map: entities = self.create() @@ -137,19 +180,29 @@ class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper name=self.names[i], description=self.descriptions[i], ) + print("Entity: ", entity) try: + print("Representations: ", self.representations[i]) for repr in self.representations[i]: - if self.representations[i]: + print("Representation: ", repr) + if repr: ifcopenshell.api.run( - "geometry.assign_representation", self.file, product=entity, representation=repr + "geometry.assign_representation", + self.file, + product=entity, + representation=repr, ) except IndexError: pass try: for loc in self.locations[i]: - if isinstance(self.locations[i], Matrix): + print("Location: ", loc) + if isinstance(loc, Matrix): ifcopenshell.api.run( - "geometry.edit_object_placement", self.file, product=entity, matrix=loc + "geometry.edit_object_placement", + self.file, + product=entity, + matrix=loc, ) except IndexError: pass @@ -179,19 +232,29 @@ class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper entity.Representation = repr elif repr: ifcopenshell.api.run( - "geometry.assign_representation", self.file, product=entity, representation=repr + "geometry.assign_representation", + self.file, + product=entity, + representation=repr, ) except IndexError: pass try: for loc in self.locations[i]: if isinstance(loc, Matrix): - ifcopenshell.api.run("geometry.edit_object_placement", self.file, product=entity, matrix=loc) + ifcopenshell.api.run( + "geometry.edit_object_placement", + self.file, + product=entity, + matrix=loc, + ) except IndexError: pass if entity.is_a() != self.ifc_class: SvIfcStore.id_map[self.node_id].remove(step_id) - entity = ifcopenshell.util.schema.reassign_class(self.file, entity, self.ifc_class) + entity = ifcopenshell.util.schema.reassign_class( + self.file, entity, self.ifc_class + ) SvIfcStore.id_map.setdefault(self.node_id, []).append(entity.id()) entities_ids.append(entity.id()) @@ -203,7 +266,8 @@ class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper input = repeat_last_for_length(input, count, deepcopy=False) if input[0]: input = [ - a if not (s := sum(j == a for j in input[:i])) else f"{a}-{s+1}" for i, a in enumerate(input) + a if not (s := sum(j == a for j in input[:i])) else f"{a}-{s+1}" + for i, a in enumerate(input) ] # add number to duplicates return input diff --git a/src/ifcsverchok/nodes/ifc/create_shape.py b/src/ifcsverchok/nodes/ifc/create_shape.py index a16d5049c7..bfcc971b51 100644 --- a/src/ifcsverchok/nodes/ifc/create_shape.py +++ b/src/ifcsverchok/nodes/ifc/create_shape.py @@ -46,7 +46,7 @@ class SvIfcCreateShape(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper. bl_idname = "SvIfcCreateShape" bl_label = "IFC Create Blender Shape" - entity: StringProperty(name="Entities", update=updateNode) + entity: StringProperty(name="Entity Id(s)", update=updateNode) def sv_init(self, context): self.inputs.new("SvStringsSocket", "Entities").prop_name = "entity" @@ -56,7 +56,7 @@ class SvIfcCreateShape(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper. row = layout.row(align=True) row.operator( "node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False - ).tooltip = "Create Blender shape from IfcEntity ID. Takes one or multiple IfcEntity IDs." + ).tooltip = "Create Blender shape from IfcEntity Id. Takes one or multiple IfcEntity IDs." row.prop(self, "refresh_local", icon="FILE_REFRESH") def process(self): diff --git a/src/ifcsverchok/nodes/ifc/get_attribute.py b/src/ifcsverchok/nodes/ifc/get_attribute.py index 976e40d142..f625e10e2a 100644 --- a/src/ifcsverchok/nodes/ifc/get_attribute.py +++ b/src/ifcsverchok/nodes/ifc/get_attribute.py @@ -20,25 +20,53 @@ import bpy import ifcopenshell import ifcopenshell.util.element import ifcsverchok.helper +from ifcsverchok.ifcstore import SvIfcStore from bpy.props import StringProperty from sverchok.node_tree import SverchCustomTreeNode -from sverchok.data_structure import updateNode +from sverchok.data_structure import updateNode, flatten_data -class SvIfcGetAttribute(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore): +class SvIfcGetAttribute( + bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore +): bl_idname = "SvIfcGetAttribute" bl_label = "IFC Get Attribute" - entity: StringProperty(name="entity", update=updateNode) - attribute_name: StringProperty(name="attribute_name", update=updateNode) + entity: StringProperty(name="Entity Ids", update=updateNode) + attribute_name: StringProperty( + name="Attribute name", + description='Name of attribute, eg. "Name".', + update=updateNode, + ) def sv_init(self, context): self.inputs.new("SvStringsSocket", "entity").prop_name = "entity" - self.inputs.new("SvStringsSocket", "attribute_name").prop_name = "attribute_name" + self.inputs.new( + "SvStringsSocket", "attribute_name" + ).prop_name = "attribute_name" self.outputs.new("SvStringsSocket", "value") + def draw_buttons(self, context, layout): + layout.operator( + "node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False + ).tooltip = ( + "Get the value of an attribute of an IfcEntity. Can take multiple entities." + ) + def process(self): self.value_out = [] - entity_nested_inputs = self.inputs["entity"].sv_get() + entity_nested_input_ids = flatten_data( + self.inputs["entity"].sv_get(), target_level=1 + ) + if not entity_nested_input_ids[0]: + return + self.file = SvIfcStore.get_file() + try: + entity_nested_inputs = [ + self.file.by_id(int(step_id)) for step_id in entity_nested_input_ids + ] + print(entity_nested_inputs) + except Exception as e: + raise Exception("Instance ID not found", e) attribute_name = self.inputs["attribute_name"].sv_get()[0][0] for entities in entity_nested_inputs: if hasattr(entities, "__iter__"): diff --git a/src/ifcsverchok/nodes/ifc/get_property.py b/src/ifcsverchok/nodes/ifc/get_property.py index 1d86866814..47afde3862 100644 --- a/src/ifcsverchok/nodes/ifc/get_property.py +++ b/src/ifcsverchok/nodes/ifc/get_property.py @@ -20,35 +20,64 @@ import bpy import ifcopenshell import ifcopenshell.util.element import ifcsverchok.helper +from ifcsverchok.ifcstore import SvIfcStore from bpy.props import StringProperty from sverchok.node_tree import SverchCustomTreeNode -from sverchok.data_structure import updateNode +from sverchok.data_structure import updateNode, flatten_data -class SvIfcGetProperty(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore): +class SvIfcGetProperty( + bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore +): bl_idname = "SvIfcGetProperty" bl_label = "IFC Get Property" - entity: StringProperty(name="entity", update=updateNode) - pset_name: StringProperty(name="pset_name", update=updateNode) - prop_name: StringProperty(name="prop_name", update=updateNode) + entity: StringProperty(name="Entity Ids", update=updateNode) + pset_name: StringProperty( + name="Pset Name", + description='Name of the property set, eg. "Pset_WallCommon".', + update=updateNode, + ) + prop_name: StringProperty( + name="Prop Name", + description='Name of the property, eg. "IsExternal".', + update=updateNode, + ) def sv_init(self, context): - self.inputs.new("SvStringsSocket", "entity").prop_name = "entity" + self.inputs.new("SvStringsSocket", "entity_ids").prop_name = "entity" self.inputs.new("SvStringsSocket", "pset_name").prop_name = "pset_name" self.inputs.new("SvStringsSocket", "prop_name").prop_name = "prop_name" self.outputs.new("SvStringsSocket", "value") - def process(self): - self.sv_input_names = ["entity", "pset_name", "prop_name"] - self.value_out = [] - super().process() - self.outputs["value"].sv_set(self.value_out) + def draw_buttons(self, context, layout): + layout.operator( + "node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False + ).tooltip = ( + "Get the value of a property of an IfcEntity. Can take multiple entity ids." + ) - def process_ifc(self, entity, pset_name, prop_name): + def process(self): + self.sv_input_names = ["entity_ids", "pset_name", "prop_name"] + entities_ids = flatten_data(self.inputs["entity_ids"].sv_get(), target_level=1) + pset_name = flatten_data(self.inputs["pset_name"].sv_get(), target_level=1)[0] + prop_name = flatten_data(self.inputs["prop_name"].sv_get(), target_level=1)[0] + if not entities_ids[0]: + return + self.file = SvIfcStore.get_file() try: - self.value_out.append(ifcopenshell.util.element.get_psets(entity)[pset_name][prop_name]) - except: - pass + self.entities = [self.file.by_id(int(step_id)) for step_id in entities_ids] + except Exception as e: + raise Exception(f"Invalid entity id: {e}") + + self.value_out = [] + for entity in self.entities: + try: + self.value_out.append( + ifcopenshell.util.element.get_psets(entity)[pset_name][prop_name] + ) + except: + pass + self.outputs["value"].sv_set(self.value_out) def register(): diff --git a/src/ifcsverchok/nodes/ifc/read_entity.py b/src/ifcsverchok/nodes/ifc/read_entity.py index 47a2eb83d9..5ac742c54f 100644 --- a/src/ifcsverchok/nodes/ifc/read_entity.py +++ b/src/ifcsverchok/nodes/ifc/read_entity.py @@ -19,30 +19,50 @@ import bpy import ifcopenshell import ifcsverchok.helper +from ifcsverchok.ifcstore import SvIfcStore from bpy.props import StringProperty from sverchok.node_tree import SverchCustomTreeNode -from sverchok.data_structure import updateNode +from sverchok.data_structure import updateNode, ensure_min_nesting, flatten_data -class SvIfcReadEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore): +class SvIfcReadEntity( + bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore +): bl_idname = "SvIfcReadEntity" bl_label = "IFC Read Entity" - file: StringProperty(name="file", update=updateNode) - entity: StringProperty(name="entity", update=updateNode) + entity: StringProperty(name="Entity Id", update=updateNode) current_ifc_class: StringProperty(name="current_ifc_class") def sv_init(self, context): - self.inputs.new("SvStringsSocket", "file").prop_name = "file" self.inputs.new("SvStringsSocket", "entity").prop_name = "entity" self.outputs.new("SvStringsSocket", "id") self.outputs.new("SvStringsSocket", "is_a") + def draw_buttons(self, context, layout): + layout.operator( + "node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False + ).tooltip = ( + "Decompose an IfcEntity into its attributes. Takes one entity id as input" + ) + def process(self): - self.sv_input_names = ["file", "entity"] - ifc_class = self.inputs["entity"].sv_get()[0][0] - if ifc_class: - ifc_class = ifc_class.is_a() - file = self.inputs["file"].sv_get()[0][0] + self.sv_input_names = ["entity"] + # ifc_class = ensure_min_nesting(self.inputs["entity"].sv_get(), 1) + entity_id = flatten_data(self.inputs["entity"].sv_get(), target_level=1) + print("entity_id", entity_id) + if not entity_id[0]: + return + if len(entity_id) > 1: + raise Exception("Only one entity can be read at a time") + self.file = SvIfcStore.get_file() + try: + entity = self.file.by_id(entity_id[0]) + except Exception as e: + raise Exception("Instance with id {} not found".format(entity_id), e) + + if entity: + ifc_class = entity.is_a() + file = SvIfcStore.get_file() if file: schema_name = file.wrapped_data.schema else: @@ -52,7 +72,12 @@ class SvIfcReadEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.S if ifc_class != self.current_ifc_class: self.generate_outputs(ifc_class) - super().process() + + self.outputs["id"].sv_set([entity.id()]) + self.outputs["is_a"].sv_set([entity.is_a()]) + for i in range(0, self.entity_schema.attribute_count()): + name = self.entity_schema.attribute_by_index(i).name() + self.outputs[name].sv_set([entity[i]]) def generate_outputs(self, ifc_class): while len(self.outputs) > 2: @@ -62,13 +87,6 @@ class SvIfcReadEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.S self.outputs.new("SvStringsSocket", name).prop_name = name self.current_ifc_class = ifc_class - def process_ifc(self, entity): - self.outputs["id"].sv_set([[entity.id()]]) - self.outputs["is_a"].sv_set([[entity.is_a()]]) - for i in range(0, self.entity_schema.attribute_count()): - name = self.entity_schema.attribute_by_index(i).name() - self.outputs[name].sv_set([[entity[i]]]) - def register(): bpy.utils.register_class(SvIfcReadEntity) diff --git a/src/ifcsverchok/nodes/ifc/sverchok_to_ifc.py b/src/ifcsverchok/nodes/ifc/sverchok_to_ifc.py index d2dcd38160..aa2cd88954 100644 --- a/src/ifcsverchok/nodes/ifc/sverchok_to_ifc.py +++ b/src/ifcsverchok/nodes/ifc/sverchok_to_ifc.py @@ -29,7 +29,9 @@ from sverchok.node_tree import SverchCustomTreeNode from sverchok.data_structure import updateNode, ensure_min_nesting -class SvIfcSverchokToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore): +class SvIfcSverchokToIfcRepr( + bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore +): """ Triggers: Sv to Ifc Repr Tooltip: Sverchok geometry to Ifc Shape Representation @@ -59,7 +61,11 @@ class SvIfcSverchokToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h ] context_type: EnumProperty( - name="Context Type", description="Default: Model", default="Model", items=context_types, update=updateNode + name="Context Type", + description="Default: Model", + default="Model", + items=context_types, + update=updateNode, ) context_identifier: EnumProperty( name="Context Identifier", @@ -78,7 +84,9 @@ class SvIfcSverchokToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h def sv_init(self, context): self.inputs.new("SvStringsSocket", "context_type").prop_name = "context_type" - self.inputs.new("SvStringsSocket", "context_identifier").prop_name = "context_identifier" + self.inputs.new( + "SvStringsSocket", "context_identifier" + ).prop_name = "context_identifier" self.inputs.new("SvStringsSocket", "target_view").prop_name = "target_view" self.inputs.new("SvVerticesSocket", "Vertices") self.inputs.new("SvStringsSocket", "Edges") @@ -99,7 +107,9 @@ class SvIfcSverchokToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h self.sv_input_names = [i.name for i in self.inputs] if hash(self) not in self.node_dict: - self.node_dict[hash(self)] = {} # happens if node is already on canvas when blender loads + self.node_dict[ + hash(self) + ] = {} # happens if node is already on canvas when blender loads if not self.node_dict[hash(self)]: self.node_dict[hash(self)].update(dict.fromkeys(self.sv_input_names, 0)) @@ -113,7 +123,9 @@ class SvIfcSverchokToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h edit = True self.node_dict[hash(self)][self.inputs[i].name] = input - self.vertices = ensure_min_nesting(self.inputs["Vertices"].sv_get(deepcopy=False), 4) + self.vertices = ensure_min_nesting( + self.inputs["Vertices"].sv_get(deepcopy=False), 4 + ) self.edges = ensure_min_nesting(self.inputs["Edges"].sv_get(deepcopy=False), 4) self.faces = ensure_min_nesting(self.inputs["Faces"].sv_get(deepcopy=False), 4) data = list(zip(self.vertices, self.edges, self.faces)) @@ -147,12 +159,14 @@ class SvIfcSverchokToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h faces=[list(map(tuple, item[2]))], ) if not representation: - raise Exception("Couldn't create representation. Possibly wrong context.") + raise Exception( + "Couldn't create representation. Possibly wrong context." + ) representations_ids_obj.append(representation.id()) representations_ids.append(representations_ids_obj) - SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault("Representations", []).append( - representations_ids_obj - ) + SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault( + "Representations", [] + ).append(representations_ids_obj) return representations_ids def edit(self): @@ -161,7 +175,9 @@ class SvIfcSverchokToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h for obj in SvIfcStore.id_map[self.node_id]["Representations"]: for step_id in obj: ifcopenshell.api.run( - "geometry.remove_representation", self.file, representation=self.file.by_id(step_id) + "geometry.remove_representation", + self.file, + representation=self.file.by_id(step_id), ) del SvIfcStore.id_map[self.node_id]["Representations"] return @@ -171,9 +187,13 @@ class SvIfcSverchokToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h self.file, self.context_type, self.context_identifier, self.target_view ) if not context: - parent = ifcopenshell.util.representation.get_context(self.file, self.context_type) + parent = ifcopenshell.util.representation.get_context( + self.file, self.context_type + ) if not parent: - parent = ifcopenshell.api.run("context.add_context", self.file, context_type=self.context_type) + parent = ifcopenshell.api.run( + "context.add_context", self.file, context_type=self.context_type + ) context = ifcopenshell.api.run( "context.add_context", self.file, @@ -182,7 +202,9 @@ class SvIfcSverchokToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h target_view=self.target_view, parent=parent, ) - SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault("Contexts", []).append(context.id()) + SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault( + "Contexts", [] + ).append(context.id()) return context def sv_free(self): @@ -191,7 +213,9 @@ class SvIfcSverchokToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h if "Representations" in SvIfcStore.id_map[self.node_id]: for step_id in SvIfcStore.id_map[self.node_id]["Representations"]: ifcopenshell.api.run( - "geometry.remove_representation", self.file, representation=self.file.by_id(step_id) + "geometry.remove_representation", + self.file, + representation=self.file.by_id(step_id), ) if "Contexts" in SvIfcStore.id_map[self.node_id]: @@ -200,10 +224,14 @@ class SvIfcSverchokToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h if not self.file.get_inverse(context): if self.file.by_id(context_id).ParentContext: parent = self.file.by_id(context_id).ParentContext - ifcopenshell.api.run("context.remove_context", self.file, context=context) + ifcopenshell.api.run( + "context.remove_context", self.file, context=context + ) if parent: if not self.file.get_inverse(parent): - ifcopenshell.api.run("context.remove_context", self.file, context=parent) + ifcopenshell.api.run( + "context.remove_context", self.file, context=parent + ) # print("Removed context with step ID: ", context_id) SvIfcStore.id_map[self.node_id]["Contexts"].remove(context_id) del SvIfcStore.id_map[self.node_id]