diff --git a/src/ifcsverchok/__init__.py b/src/ifcsverchok/__init__.py index a747a7aa34..8a420fa3ef 100644 --- a/src/ifcsverchok/__init__.py +++ b/src/ifcsverchok/__init__.py @@ -1,5 +1,5 @@ # IfcSverchok - IFC Sverchok extension -# Copyright (C) 2020, 2021 Dion Moult +# Copyright (C) 2022 Martina Jakubowska # # This file is part of IfcSverchok. # @@ -28,21 +28,18 @@ bl_info = { "warning": "", } -import sys import importlib import nodeitems_utils -import sverchok -from sverchok.core import sv_registration_utils, make_node_list +from sverchok.core import make_node_list from sverchok.utils import auto_gather_node_classes, get_node_class_reference -from sverchok.menu import SverchNodeItem, SverchNodeCategory, register_node_panels +from sverchok.menu import SverchNodeItem, SverchNodeCategory from sverchok.utils.extra_categories import ( register_extra_category_provider, unregister_extra_category_provider, ) from sverchok.ui.nodeview_space_menu import make_extra_category_menus from sverchok.utils.logging import info, debug -import asyncio -import time + def nodes_index(): return [ @@ -73,8 +70,7 @@ def nodes_index(): ("ifc.bmesh_to_ifc", "SvIfcBMeshToIfcRepr"), ("ifc.sverchok_to_ifc", "SvIfcSverchokToIfcRepr"), ("ifc.create_project", "SvIfcCreateProject"), - ("ifc.quick_project_setup", "SvIfcQuickProjectSetup") - + ("ifc.quick_project_setup", "SvIfcQuickProjectSetup"), ], ) ] @@ -96,26 +92,23 @@ imported_modules = make_node_list() reload_event = False import bpy -import os -from os.path import abspath, splitext +from os.path import splitext import ifcopenshell from ifcsverchok.ifcstore import SvIfcStore -from sverchok.data_structure import flatten_data + class IFC_Sv_UpdateCurrent(bpy.types.Operator): """Update current Sverchok node tree""" + bl_idname = "ifc.sverchok_update_current" bl_label = "Update current node tree" - bl_options = {'REGISTER', 'UNDO', 'INTERNAL'} + bl_options = {"REGISTER", "UNDO", "INTERNAL"} node_group: bpy.props.StringProperty(default="") force_mode: bpy.props.BoolProperty(default=False) def execute(self, context): - print("#"*10, "Update current node tree") self.file = SvIfcStore.purge() - self.file = SvIfcStore.get_file() - self.file.write("/Users/martina/Documents/GSoC/CodeTests/IfcFileTest_7_11_purged.ifc") node_tree = context.space_data.node_tree if node_tree: if self.force_mode or node_tree.sv_process: @@ -125,7 +118,8 @@ class IFC_Sv_UpdateCurrent(bpy.types.Operator): finally: bpy.context.window.cursor_set("DEFAULT") self.report({"INFO"}, "Node tree updated.") - return {'FINISHED'} + return {"FINISHED"} + class IFC_Sv_write_file(bpy.types.Operator): bl_idname = "ifc.write_file_panel" @@ -141,43 +135,52 @@ class IFC_Sv_write_file(bpy.types.Operator): return any("IFC" in n for n in context.space_data.edit_tree.nodes.keys()) def ensure_hirarchy(self, file): - elements_in_buildings = [] - if not 0 <= 0 < len(file.by_type("IfcBuilding")): + elements_in_buildings = set() + if len(file.by_type("IfcBuilding")) == 0: my_building = ifcopenshell.api.run("root.create_entity", file, ifc_class="IfcBuilding", name="My Building") elements = ifcopenshell.util.element.get_decomposition(my_building) else: for building in file.by_type("IfcBuilding"): elements = ifcopenshell.util.element.get_decomposition(building) - elements_in_buildings.extend(elements) + elements_in_buildings.update(elements) - for spatial in (file.by_type("IfcSpatialElement") or file.by_type("IfcSpatialStructureElement")): - if (not (spatial.is_a("IfcSite") or spatial.is_a("IfcBuilding")) and (spatial not in elements_in_buildings)): + for spatial in file.by_type("IfcSpatialElement") or file.by_type("IfcSpatialStructureElement"): + if not (spatial.is_a("IfcSite") or spatial.is_a("IfcBuilding")) and (spatial not in elements_in_buildings): elements = ifcopenshell.util.element.get_decomposition(spatial) - ifcopenshell.api.run("aggregate.assign_object", file, product=spatial, relating_object=file.by_type("IfcBuilding")[0]) + ifcopenshell.api.run( + "aggregate.assign_object", file, product=spatial, relating_object=file.by_type("IfcBuilding")[0] + ) - elements_in_buildings_after = [] for building in file.by_type("IfcBuilding"): elements = ifcopenshell.util.element.get_decomposition(building) - elements_in_buildings_after.extend(elements) + elements_in_buildings.update(elements) elements = file.by_type("IfcElement") for element in elements: if element not in elements_in_buildings: - ifcopenshell.api.run("spatial.assign_container", file, product=element, relating_structure=file.by_type("IfcBuilding")[0]) - + ifcopenshell.api.run( + "spatial.assign_container", file, product=element, relating_structure=file.by_type("IfcBuilding")[0] + ) for building in file.by_type("IfcBuilding"): elements = ifcopenshell.util.element.get_decomposition(building) if not building.Decomposes: - if not 0 <= 0 < len(file.by_type("IfcSite")): + if len(file.by_type("IfcSite")) == 0: ifcopenshell.api.run("root.create_entity", file, ifc_class="IfcSite", name="My Site") - ifcopenshell.api.run("aggregate.assign_object", file, product=building, relating_object=file.by_type("IfcSite")[0]) + ifcopenshell.api.run( + "aggregate.assign_object", file, product=building, relating_object=file.by_type("IfcSite")[0] + ) try: if file.by_type("IfcSite")[0].Decomposes[0].RelatingObject.is_a("IfcProject"): continue except IndexError: pass - ifcopenshell.api.run("aggregate.assign_object", file, product=file.by_type("IfcSite")[0], relating_object=file.by_type("IfcProject")[0]) + ifcopenshell.api.run( + "aggregate.assign_object", + file, + product=file.by_type("IfcSite")[0], + relating_object=file.by_type("IfcProject")[0], + ) self.file = file return @@ -198,6 +201,7 @@ class IFC_Sv_write_file(bpy.types.Operator): context.window_manager.fileselect_add(self) return {"RUNNING_MODAL"} + class IFC_PT_write_file_panel(bpy.types.Panel): bl_idname = "IFC_PT_write_file_panel" bl_label = "Write IFC to file" @@ -217,10 +221,12 @@ class IFC_PT_write_file_panel(bpy.types.Panel): row = layout.split(factor=0.2, align=True) row = layout.row() row2 = layout.row() - row.operator('ifc.sverchok_update_current', text='IFC Re-run all nodes') + row.operator("ifc.sverchok_update_current", text="IFC Re-run all nodes") row2.operator("ifc.write_file_panel") -CLASSES = [IFC_Sv_UpdateCurrent,IFC_Sv_write_file, IFC_PT_write_file_panel] + +CLASSES = [IFC_Sv_UpdateCurrent, IFC_Sv_write_file, IFC_PT_write_file_panel] + def register_nodes(): node_modules = make_node_list() @@ -281,9 +287,7 @@ def register(): auto_gather_node_classes(extra_nodes) menu = make_menu() menu_category_provider = SvExCategoryProvider("IFCSVERCHOK", menu) - register_extra_category_provider( - menu_category_provider - ) # if 'IFCSVERCHOK' in nodeitems_utils._node_categories: + register_extra_category_provider(menu_category_provider) # if 'IFCSVERCHOK' in nodeitems_utils._node_categories: nodeitems_utils.register_node_categories("IFCSVERCHOK", menu) our_menu_classes = make_extra_category_menus() diff --git a/src/ifcsverchok/helper.py b/src/ifcsverchok/helper.py index fc19144865..edcd723836 100644 --- a/src/ifcsverchok/helper.py +++ b/src/ifcsverchok/helper.py @@ -1,6 +1,5 @@ - # IfcSverchok - IFC Sverchok extension -# Copyright (C) 2020, 2021 Dion Moult +# Copyright (C) 2020, 2021, 2022 Dion Moult # # This file is part of IfcSverchok. # diff --git a/src/ifcsverchok/ifcstore.py b/src/ifcsverchok/ifcstore.py index 9efff80ec6..d812994b04 100644 --- a/src/ifcsverchok/ifcstore.py +++ b/src/ifcsverchok/ifcstore.py @@ -1,13 +1,25 @@ -# import os +# IfcSverchok - IFC Sverchok extension +# Copyright (C) 2022 Martina Jakubowska +# +# This file is part of IfcSverchok. +# +# IfcSverchok is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# IfcSverchok is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with IfcSverchok. If not, see . + import bpy -# import uuid -# import hashlib -# import zipfile -# import tempfile import ifcopenshell from ifcopenshell import template -# import blenderbim.bim.handler -# from pathlib import Path + class SvIfcStore: path = "" @@ -52,7 +64,6 @@ class SvIfcStore: SvIfcStore.future = [] SvIfcStore.schema_identifiers = ["IFC4", "IFC2X3"] - @staticmethod def create_boilerplate(): @@ -61,11 +72,10 @@ class SvIfcStore: organization=None, creator=None, project_name="IfcSverchokDemoProject", - ) - if bpy.context.scene.unit_settings.system == 'IMPERIAL': - #TODO change units to imperial + ) + if bpy.context.scene.unit_settings.system == "IMPERIAL": + # TODO change units to imperial pass - # model = ifcopenshell.api.run("context.add_context", file, context_type="Model") model = ifcopenshell.util.representation.get_context(file, context="Model") print("model: ", model) context = ifcopenshell.api.run( @@ -76,22 +86,9 @@ class SvIfcStore: target_view="MODEL_VIEW", parent=model, ) - # site = ifcopenshell.api.run("root.create_entity", file, ifc_class="IfcSite", name="My Site") - # building = ifcopenshell.api.run( - # "root.create_entity", file, ifc_class="IfcBuilding", name="My Building" - # ) - # building_storey = ifcopenshell.api.run( - # "root.create_entity", file, ifc_class="IfcBuildingStorey", name="My Storey" - # ) - - # ifcopenshell.api.run("aggregate.assign_object", file, product=site, relating_object=file.by_type("IfcProject")[0]) - # ifcopenshell.api.run("aggregate.assign_object", file, product=building, relating_object=site) - # ifcopenshell.api.run("aggregate.assign_object", file, product=building_storey, relating_object=building) SvIfcStore.file = file return SvIfcStore.file - - @staticmethod def get_file(): diff --git a/src/ifcsverchok/nodes/__init__.py b/src/ifcsverchok/nodes/__init__.py index ec93090e2d..36613dfd23 100644 --- a/src/ifcsverchok/nodes/__init__.py +++ b/src/ifcsverchok/nodes/__init__.py @@ -1,6 +1,5 @@ - # IfcSverchok - IFC Sverchok extension -# Copyright (C) 2020, 2021 Dion Moult +# Copyright (C) 2020, 2021, 2022 Dion Moult # # This file is part of IfcSverchok. # @@ -16,4 +15,3 @@ # # You should have received a copy of the GNU General Public License # along with IfcSverchok. If not, see . - diff --git a/src/ifcsverchok/nodes/ifc/__init__.py b/src/ifcsverchok/nodes/ifc/__init__.py index ec93090e2d..36613dfd23 100644 --- a/src/ifcsverchok/nodes/ifc/__init__.py +++ b/src/ifcsverchok/nodes/ifc/__init__.py @@ -1,6 +1,5 @@ - # IfcSverchok - IFC Sverchok extension -# Copyright (C) 2020, 2021 Dion Moult +# Copyright (C) 2020, 2021, 2022 Dion Moult # # This file is part of IfcSverchok. # @@ -16,4 +15,3 @@ # # You should have received a copy of the GNU General Public License # along with IfcSverchok. If not, see . - diff --git a/src/ifcsverchok/nodes/ifc/add.py b/src/ifcsverchok/nodes/ifc/add.py index 53f049087b..ec312f1de0 100644 --- a/src/ifcsverchok/nodes/ifc/add.py +++ b/src/ifcsverchok/nodes/ifc/add.py @@ -1,6 +1,5 @@ - # IfcSverchok - IFC Sverchok extension -# Copyright (C) 2020, 2021 Dion Moult +# Copyright (C) 2020, 2021, 2022 Dion Moult # # This file is part of IfcSverchok. # diff --git a/src/ifcsverchok/nodes/ifc/add_pset.py b/src/ifcsverchok/nodes/ifc/add_pset.py index bb56caffd1..c0fba2f6c7 100644 --- a/src/ifcsverchok/nodes/ifc/add_pset.py +++ b/src/ifcsverchok/nodes/ifc/add_pset.py @@ -1,3 +1,21 @@ +# IfcSverchok - IFC Sverchok extension +# Copyright (C) 2022 Martina Jakubowska +# +# This file is part of IfcSverchok. +# +# IfcSverchok is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# IfcSverchok is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with IfcSverchok. If not, see . + import bpy import ifcopenshell diff --git a/src/ifcsverchok/nodes/ifc/add_spatial_element.py b/src/ifcsverchok/nodes/ifc/add_spatial_element.py index 228982facc..0cb641158c 100644 --- a/src/ifcsverchok/nodes/ifc/add_spatial_element.py +++ b/src/ifcsverchok/nodes/ifc/add_spatial_element.py @@ -1,3 +1,21 @@ +# IfcSverchok - IFC Sverchok extension +# Copyright (C) 2022 Martina Jakubowska +# +# This file is part of IfcSverchok. +# +# IfcSverchok is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# IfcSverchok is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with IfcSverchok. If not, see . + import bpy import ifcopenshell @@ -13,7 +31,7 @@ class SvIfcAddSpatialElement(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h 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) @@ -24,14 +42,14 @@ class SvIfcAddSpatialElement(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h self.inputs.new("SvStringsSocket", "Elements").prop_name = "Elements" self.outputs.new("SvStringsSocket", "Entities") 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." 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)) @@ -40,8 +58,11 @@ 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 =[]) - if isinstance(self.node_dict[hash(self)][self.inputs[i].name], list) and input != self.node_dict[hash(self)][self.inputs[i].name]: + 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] + ): edit = True if self.inputs[i].name == "Elements": edit_elements = True @@ -83,7 +104,9 @@ class SvIfcAddSpatialElement(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h 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) + ifcopenshell.api.run( + "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()) return spatial_ids @@ -106,15 +129,25 @@ 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"): - ifcopenshell.api.run("aggregate.unassign_object", self.file, product=removed_element, relating_object=result) + 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 + ) else: - ifcopenshell.api.run("spatial.unassign_container", self.file, product=removed_element, relating_object=result) + ifcopenshell.api.run( + "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"): - ifcopenshell.api.run("aggregate.assign_object", self.file, product=added_element, relating_object=result) + ifcopenshell.api.run( + "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) + ifcopenshell.api.run( + "spatial.assign_container", self.file, product=added_element, relating_structure=result + ) spatial_ids.append(result.id()) SvIfcStore.id_map[self.node_id] = spatial_ids return spatial_ids @@ -129,17 +162,20 @@ class SvIfcAddSpatialElement(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h def repeat_input_unique(self, input, count): 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)] # add number to duplicates + 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 def sv_free(self): try: del SvIfcStore.id_map[self.node_id] del self.node_dict[hash(self)] - print('Node was deleted') + # print('Node was deleted') except KeyError or AttributeError: pass + def register(): bpy.utils.register_class(SvIfcAddSpatialElement) diff --git a/src/ifcsverchok/nodes/ifc/api.py b/src/ifcsverchok/nodes/ifc/api.py index 7dbcc77acf..2c61a46c2e 100644 --- a/src/ifcsverchok/nodes/ifc/api.py +++ b/src/ifcsverchok/nodes/ifc/api.py @@ -1,6 +1,5 @@ - # IfcSverchok - IFC Sverchok extension -# Copyright (C) 2020, 2021 Dion Moult +# Copyright (C) 2020, 2021, 2022 Dion Moult # # This file is part of IfcSverchok. # @@ -105,4 +104,4 @@ def register(): def unregister(): bpy.utils.unregister_class(SvIfcApi) - bpy.utils.unregister_class(SvIfcTooltip) \ No newline at end of file + bpy.utils.unregister_class(SvIfcTooltip) diff --git a/src/ifcsverchok/nodes/ifc/api_WIP.py b/src/ifcsverchok/nodes/ifc/api_WIP.py index c546d07a64..3c4d7122af 100644 --- a/src/ifcsverchok/nodes/ifc/api_WIP.py +++ b/src/ifcsverchok/nodes/ifc/api_WIP.py @@ -1,6 +1,5 @@ - # IfcSverchok - IFC Sverchok extension -# Copyright (C) 2020, 2021 Dion Moult +# Copyright (C) 2022 Martina Jakubowska # # This file is part of IfcSverchok. # @@ -21,13 +20,12 @@ import bpy import ifcopenshell import ifcopenshell.api import ifcsverchok.helper -from bpy.props import StringProperty, EnumProperty +from bpy.props import StringProperty from sverchok.node_tree import SverchCustomTreeNode from sverchok.data_structure import updateNode import importlib - class SvIfcTooltip(bpy.types.Operator): bl_idname = "node.sv_ifc_tooltip" bl_label = "IFC Info" @@ -43,12 +41,6 @@ class SvIfcTooltip(bpy.types.Operator): class SvIfcApiWIP(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore): - # def update_usecase(self, context): - # # update_usecase is not getting run rn -# module_usecase = self.get_module_usecase() -# if module_usecase: -# self.generate_node(*module_usecase) - bl_idname = "SvIfcApiWIP" bl_label = "IFC API WIP" tooltip: StringProperty(name="Tooltip") @@ -57,11 +49,13 @@ class SvIfcApiWIP(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfc def sv_init(self, context): self.inputs.new("SvStringsSocket", "usecase").prop_name = "usecase" - #input_socket.tooltip = "ifcopenshell.api usecase, written like 'module.usecase' \n E.g.: 'project.create_file'" + # input_socket.tooltip = "ifcopenshell.api usecase, written like 'module.usecase' \n E.g.: 'project.create_file'" self.outputs.new("SvVerticesSocket", "file") def draw_buttons(self, context, layout): - op = layout.operator("node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False).tooltip = "ifcopenshell.api usecase, written like 'module.usecase' \n E.g.: 'project.create_file" + op = layout.operator( + "node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False + ).tooltip = "ifcopenshell.api usecase, written like 'module.usecase' \n E.g.: 'project.create_file" # op.tooltip = self.tooltip def process(self): @@ -71,11 +65,9 @@ class SvIfcApiWIP(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfc try: module_usecase = self.get_module_usecase() except: - raise Exception( - f"Couldn't run generate_node(). Module usecase: {module_usecase}" - ) - if '.'.join(module_usecase) != self.current_usecase: - self.generate_node(*module_usecase) + raise Exception(f"Couldn't run generate_node(). Module usecase: {module_usecase}") + if ".".join(module_usecase) != self.current_usecase: + self.generate_node(*module_usecase) try: for i in range(0, len(self.inputs)): input = self.inputs[i].sv_get() @@ -85,8 +77,7 @@ class SvIfcApiWIP(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfc self.sv_input_names = [i.name for i in self.inputs] - super().process() # super().process() uses zip_long_repeat() which doesn't take objects like bmesh - + super().process() # super().process() uses zip_long_repeat() which doesn't take objects like bmesh def get_module_usecase(self): usecase = self.inputs["usecase"].sv_get()[0][0] @@ -102,10 +93,10 @@ class SvIfcApiWIP(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfc node_inputs["file"] = None node_inputs.update(getattr(local_module.Usecase(local_module), "settings", {})) # print("node inputs: ", node_inputs) - + while len(self.inputs) > 1: self.inputs.remove(self.inputs[-1]) - + if node_inputs: self.tooltip = "" for name, data in node_inputs.items(): @@ -116,11 +107,10 @@ class SvIfcApiWIP(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfc else: self.tooltip = f"{name}: None\n" self.tooltip = self.tooltip.strip() - self.current_usecase = '.'.join([module, usecase]) - + self.current_usecase = ".".join([module, usecase]) def process_ifc(self, usecase, *setting_values): - + if usecase and setting_values: settings = dict(zip(self.sv_input_names[1:], setting_values)) settings = {k: v for k, v in settings.items() if v != ""} @@ -133,8 +123,6 @@ class SvIfcApiWIP(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfc self.outputs["file"].sv_set([ifcopenshell.api.run(usecase, **settings)]) except: raise Exception(f"Couldn't run usecase.") - - def register(): @@ -144,4 +132,4 @@ def register(): def unregister(): bpy.utils.unregister_class(SvIfcApiWIP) - bpy.utils.unregister_class(SvIfcTooltip) \ No newline at end of file + bpy.utils.unregister_class(SvIfcTooltip) diff --git a/src/ifcsverchok/nodes/ifc/bmesh_to_ifc.py b/src/ifcsverchok/nodes/ifc/bmesh_to_ifc.py index 426804d5d4..874e236b5c 100644 --- a/src/ifcsverchok/nodes/ifc/bmesh_to_ifc.py +++ b/src/ifcsverchok/nodes/ifc/bmesh_to_ifc.py @@ -1,5 +1,5 @@ # IfcSverchok - IFC Sverchok extension -# Copyright (C) 2020, 2021 Dion Moult +# Copyright (C) 2022 Martina Jakubowska # # This file is part of IfcSverchok. # @@ -28,18 +28,20 @@ import blenderbim.tool as tool import blenderbim.core.geometry as core 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 sverchok.data_structure import updateNode, flatten_data, fixed_iter, flat_iter from blenderbim.bim.module.root.prop import get_contexts from sverchok.data_structure import zip_long_repeat, node_id from sverchok.core.socket_data import sv_get_socket from itertools import chain, cycle + class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore): """ Triggers: BMesh to Ifc Repr Tooltip: Blender mesh to Ifc Shape Representation """ + bl_idname = "SvIfcBMeshToIfcRepr" bl_label = "IFC Blender Mesh to IFC Repr" node_dict = {} @@ -54,61 +56,81 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help refresh_local: BoolProperty(name="Update Node", description="Update Node", update=refresh_node) context_types = [ - ('Model', 'Model', 'Context type: Model', 0), - ('Plan', 'Plan', 'Context type: Plan', 1), + ("Model", "Model", "Context type: Model", 0), + ("Plan", "Plan", "Context type: Plan", 1), ] context_identifiers = [ - ('Body', 'Body', 'Context identifier: Body', 0), - ('Annotation', 'Annotation', 'Context identifier: Annotation', 1), - ('Box', 'Box', 'Context identifier: Box', 2), - ('Axis', 'Axis', 'Context identifier: Axis', 3), + ("Body", "Body", "Context identifier: Body", 0), + ("Annotation", "Annotation", "Context identifier: Annotation", 1), + ("Box", "Box", "Context identifier: Box", 2), + ("Axis", "Axis", "Context identifier: Axis", 3), ] target_views = [ - ('MODEL_VIEW', 'MODEL_VIEW', 'Target View: MODEL_VIEW', 0), - ('PLAN_VIEW', 'PLAN_VIEW', 'Target View: PLAN_VIEW', 1), - ('GRAPH_VIEW', 'GRAPH_VIEW', 'Target View: GRAPH_VIEW', 2), - ('SKETCH_VIEW', 'SKETCH_VIEW', 'Target View: SKETCH_VIEW', 3), + ("MODEL_VIEW", "MODEL_VIEW", "Target View: MODEL_VIEW", 0), + ("PLAN_VIEW", "PLAN_VIEW", "Target View: PLAN_VIEW", 1), + ("GRAPH_VIEW", "GRAPH_VIEW", "Target View: GRAPH_VIEW", 2), + ("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) - context_type: EnumProperty(name="Context Type", description="Default: Model", default="Model",items=context_types,update=updateNode) - context_identifier: EnumProperty(name="Context Identifier", description="Default: Body", default="Body", items=context_identifiers, update=updateNode) - target_view: EnumProperty(name="Target View", description="Default: MODEL VIEW", default="MODEL_VIEW",items=target_views, update=updateNode) + blender_objects: PointerProperty( + 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 + ) + context_identifier: EnumProperty( + name="Context Identifier", + description="Default: Body", + default="Body", + items=context_identifiers, + update=updateNode, + ) + target_view: EnumProperty( + name="Target View", + description="Default: MODEL VIEW", + default="MODEL_VIEW", + items=target_views, + update=updateNode, + ) tooltip: StringProperty(name="Tooltip") - 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", "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." - + layout.operator( + "node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False + ).tooltip = "Blender mesh to Ifc Shape Representation. \nTakes one or multiple geometries." + row = layout.row(align=True) - row.prop(self, 'is_interactive', icon='SCENE_DATA', icon_only=True) - row.prop(self, 'refresh_local', icon='FILE_REFRESH') + row.prop(self, "is_interactive", icon="SCENE_DATA", icon_only=True) + row.prop(self, "refresh_local", icon="FILE_REFRESH") 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)) - + if not self.inputs["blender_objects"].sv_get()[0]: return edit = False for i in range(len(self.inputs)): input = self.inputs[i].sv_get(deepcopy=True) - if isinstance(self.node_dict[hash(self)][self.inputs[i].name], list) and input != self.node_dict[hash(self)][self.inputs[i].name]: + if ( + isinstance(self.node_dict[hash(self)][self.inputs[i].name], list) + and input != self.node_dict[hash(self)][self.inputs[i].name] + ): edit = True self.node_dict[hash(self)][self.inputs[i].name] = input.copy() - + blender_objects = self.inputs["blender_objects"].sv_get() self.file = SvIfcStore.get_file() @@ -124,8 +146,7 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help representations = SvIfcStore.id_map[self.node_id]["Representations"] locations = SvIfcStore.id_map[self.node_id]["Locations"] - print("representations: ", representations) - print("locations: ", locations) + # print("representations: ", representations) self.outputs["Representations"].sv_set(representations) self.outputs["Locations"].sv_set(locations) @@ -134,41 +155,63 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help representations_ids = [] locations = [] for blender_object in blender_objects: - if blender_object.type == 'MESH': - bpy.ops.object.mode_set(mode='OBJECT') - bpy.ops.object.select_all(action='DESELECT') + if blender_object.type == "MESH": + try: + bpy.ops.object.mode_set(mode="OBJECT") + except: + pass + bpy.ops.object.select_all(action="DESELECT") blender_object.select_set(True) - bpy.ops.object.mode_set(mode='EDIT') - bpy.ops.mesh.separate(type='LOOSE') + try: + bpy.ops.object.mode_set(mode="EDIT") + except: + pass + bpy.ops.mesh.separate(type="LOOSE") + representations_ids_obj = [] + locations_obj = [] for obj in bpy.context.selected_objects: - representation = ifcopenshell.api.run("geometry.add_representation", self.file, should_run_listeners=False,blender_object = obj, geometry=obj.data, context = self.get_context()) + representation = ifcopenshell.api.run( + "geometry.add_representation", + self.file, + should_run_listeners=False, + blender_object=obj, + geometry=obj.data, + context=self.get_context(), + ) if not representation: raise Exception("Couldn't create representation. Possibly wrong context.") - representations_ids.append(representation.id()) - SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault("Representations", []).append(representation.id()) - locations.append(blender_object.matrix_world) - SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault("Locations", []).append(blender_object.matrix_world) - bpy.ops.object.mode_set(mode='OBJECT') - bpy.ops.object.select_all(action='DESELECT') + + 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) + try: + bpy.ops.object.mode_set(mode="OBJECT") + except: + pass + bpy.ops.object.select_all(action="DESELECT") return representations_ids, locations def edit(self): if "Representations" not in SvIfcStore.id_map[self.node_id]: return - 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)) + 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) + ) del SvIfcStore.id_map[self.node_id]["Representations"] del SvIfcStore.id_map[self.node_id]["Locations"] return - def get_existing_element(self): - results = [] - for step_id in SvIfcStore.id_map[self.node_id]["Representations"]: - results.append(self.file.by_id(step_id)) - return results - def get_context(self): - context = ifcopenshell.util.representation.get_context(self.file, self.context_type, self.context_identifier, self.target_view) + context = ifcopenshell.util.representation.get_context( + 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) if not parent: @@ -184,13 +227,15 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault("Contexts", []).append(context.id()) return context - def sv_free(self): try: self.file = SvIfcStore.get_file() 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)) + 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) + ) if "Contexts" in SvIfcStore.id_map[self.node_id]: for context_id in SvIfcStore.id_map[self.node_id]["Contexts"]: @@ -202,11 +247,11 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help if parent: if not self.file.get_inverse(parent): ifcopenshell.api.run("context.remove_context", self.file, context=parent) - print("Removed context with step ID: ", context_id) + # 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] del self.node_dict[hash(self)] - print('Node was deleted') + # print('Node was deleted') except KeyError or AttributeError: pass diff --git a/src/ifcsverchok/nodes/ifc/by_guid.py b/src/ifcsverchok/nodes/ifc/by_guid.py index f632459f36..44fdc5e9da 100644 --- a/src/ifcsverchok/nodes/ifc/by_guid.py +++ b/src/ifcsverchok/nodes/ifc/by_guid.py @@ -1,6 +1,5 @@ - # IfcSverchok - IFC Sverchok extension -# Copyright (C) 2020, 2021 Dion Moult +# Copyright (C) 2020, 2021, 2022 Dion Moult # # This file is part of IfcSverchok. # diff --git a/src/ifcsverchok/nodes/ifc/by_id.py b/src/ifcsverchok/nodes/ifc/by_id.py index c67ac956a9..edc40a19a1 100644 --- a/src/ifcsverchok/nodes/ifc/by_id.py +++ b/src/ifcsverchok/nodes/ifc/by_id.py @@ -1,6 +1,5 @@ - # IfcSverchok - IFC Sverchok extension -# Copyright (C) 2020, 2021 Dion Moult +# Copyright (C) 2022 Martina Jakubowska # # This file is part of IfcSverchok. # @@ -17,8 +16,8 @@ # You should have received a copy of the GNU General Public License # along with IfcSverchok. If not, see . + import bpy -import ifcopenshell import ifcsverchok.helper from ifcsverchok.ifcstore import SvIfcStore from bpy.props import StringProperty @@ -29,24 +28,29 @@ from sverchok.data_structure import updateNode, flatten_data class SvIfcById(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore): bl_idname = "SvIfcById" bl_label = "IFC By Id" - id: StringProperty(name="Id(s)", update=updateNode, ) + id: StringProperty( + name="Id(s)", + update=updateNode, + ) def sv_init(self, context): self.inputs.new("SvStringsSocket", "id").prop_name = "id" 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 step id. Takes one or multiple step ids." + layout.operator( + "node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False + ).tooltip = "Get IFC element by step id. Takes one or multiple step ids." def process(self): self.ids = flatten_data(self.inputs["id"].sv_get(), target_level=1) - print(self.ids) if not self.ids[0]: return self.file = SvIfcStore.get_file() self.entities = [self.file.by_id(int(step_id)) for step_id in self.ids] self.outputs["Entities"].sv_set(self.entities) + def register(): bpy.utils.register_class(SvIfcById) diff --git a/src/ifcsverchok/nodes/ifc/by_query.py b/src/ifcsverchok/nodes/ifc/by_query.py index 6b9c6d22ed..81b133cab5 100644 --- a/src/ifcsverchok/nodes/ifc/by_query.py +++ b/src/ifcsverchok/nodes/ifc/by_query.py @@ -1,6 +1,5 @@ - # IfcSverchok - IFC Sverchok extension -# Copyright (C) 2020, 2021 Dion Moult +# Copyright (C) 2020, 2021, 2022 Dion Moult # # This file is part of IfcSverchok. # diff --git a/src/ifcsverchok/nodes/ifc/by_type.py b/src/ifcsverchok/nodes/ifc/by_type.py index b6ed6bc7b1..ffed83bd5d 100644 --- a/src/ifcsverchok/nodes/ifc/by_type.py +++ b/src/ifcsverchok/nodes/ifc/by_type.py @@ -1,6 +1,5 @@ - # IfcSverchok - IFC Sverchok extension -# Copyright (C) 2020, 2021 Dion Moult +# Copyright (C) 2022 Martina Jakubowska # # This file is part of IfcSverchok. # @@ -23,8 +22,8 @@ import ifcsverchok.helper from bpy.props import StringProperty, EnumProperty from ifcsverchok.ifcstore import SvIfcStore from sverchok.node_tree import SverchCustomTreeNode -from sverchok.data_structure import updateNode, flatten_data -from sverchok.utils.handle_blender_data import keep_enum_reference +from sverchok.data_structure import updateNode + def get_ifc_products(self, context): ifc_products = getattr(self, "ifc_products", []) @@ -57,6 +56,7 @@ def update_ifc_products(self, context): if hasattr(self, "ifc_classes"): self.ifc_classes.clear() + def get_ifc_classes(self, context): ifc_classes = getattr(self, "ifc_classes", []) if ifc_classes: @@ -83,9 +83,18 @@ def get_ifc_classes(self, context): class SvIfcByType(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore): bl_idname = "SvIfcByType" bl_label = "IFC By Type" - ifc_product: EnumProperty(items=get_ifc_products, name="IfcProduct", description="Pick an IfcProduct from drop-down.", update=update_ifc_products) - ifc_class: EnumProperty(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) + ifc_product: EnumProperty( + items=get_ifc_products, + name="IfcProduct", + description="Pick an IfcProduct from drop-down.", + update=update_ifc_products, + ) + ifc_class: EnumProperty( + 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 + ) def sv_init(self, context): self.inputs.new("SvStringsSocket", "ifc_product").prop_name = "ifc_product" @@ -93,9 +102,13 @@ class SvIfcByType(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfc self.inputs.new("SvStringsSocket", "custom_ifc_class").prop_name = "custom_ifc_class" self.outputs.new("SvStringsSocket", "Entity") 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." + 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." + ) def process(self): self.file = SvIfcStore.get_file() @@ -119,4 +132,4 @@ def register(): def unregister(): - bpy.utils.unregister_class(SvIfcByType) \ No newline at end of file + bpy.utils.unregister_class(SvIfcByType) diff --git a/src/ifcsverchok/nodes/ifc/create_entity.py b/src/ifcsverchok/nodes/ifc/create_entity.py index 0889fe1198..72a1b6201b 100644 --- a/src/ifcsverchok/nodes/ifc/create_entity.py +++ b/src/ifcsverchok/nodes/ifc/create_entity.py @@ -1,20 +1,30 @@ +# IfcSverchok - IFC Sverchok extension +# Copyright (C) 2022 Martina Jakubowska +# +# This file is part of IfcSverchok. +# +# IfcSverchok is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# IfcSverchok is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with IfcSverchok. If not, see . + import bpy -from mathutils import Matrix, Vector +from mathutils import Matrix import ifcopenshell import ifcsverchok.helper from ifcsverchok.ifcstore import SvIfcStore -# import ifcsverchok.ifc_store -# from bpy.props import StringProperty -# from sverchok.node_tree import SverchCustomTreeNode -# from sverchok.data_structure import updateNode - -import bpy -import ifcopenshell - -from bpy.props import StringProperty, EnumProperty, IntProperty, BoolProperty +from bpy.props import StringProperty, BoolProperty from sverchok.node_tree import SverchCustomTreeNode -from sverchok.data_structure import updateNode, flatten_data, repeat_last_for_length +from sverchok.data_structure import updateNode, flatten_data, repeat_last_for_length, ensure_min_nesting class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore): @@ -43,32 +53,33 @@ class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper 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("SvMatrixSocket", "Locations").is_mandatory=False + self.inputs.new("SvMatrixSocket", "Locations").is_mandatory = False self.inputs.new("SvStringsSocket", "Properties").prop_name = "Properties" self.outputs.new("SvStringsSocket", "Entities") self.node_dict[hash(self)] = {} def draw_buttons(self, context, layout): - layout.operator("node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False).tooltip = "Create IFC Entity. Takes one or multiple inputs. \nIf 'Representation(s)' is given, that determines number of output entities. Otherwise, 'Names' is used." - + layout.operator( + "node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False + ).tooltip = "Create IFC Entity. Takes one or multiple inputs. \nIf 'Representation(s)' is given, that determines number of output entities. Otherwise, 'Names' is used." + row = layout.row(align=True) - row.prop(self, 'is_interactive', icon='SCENE_DATA', icon_only=True) - row.prop(self, 'refresh_local', icon='FILE_REFRESH') + row.prop(self, "is_interactive", icon="SCENE_DATA", icon_only=True) + row.prop(self, "refresh_local", icon="FILE_REFRESH") 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 = flatten_data(self.inputs["Representations"].sv_get(), target_level=1) - self.locations = flatten_data(self.inputs["Locations"].sv_get(default=[]), target_level=1) + 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.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]: @@ -76,18 +87,24 @@ 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 =[]) - if isinstance(self.node_dict[hash(self)][self.inputs[i].name], list) and input != self.node_dict[hash(self)][self.inputs[i].name]: + 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] + ): edit = True self.node_dict[hash(self)][self.inputs[i].name] = input.copy() if self.refresh_local: edit = True - + self.file = SvIfcStore.get_file() - if self.representations[0]: + if self.representations[0][0]: 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 self.representations] + 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)) @@ -102,9 +119,8 @@ class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper entities = self.edit() else: entities = SvIfcStore.id_map[self.node_id] - - print("Entities: ", entities) + # print("Entities: ", entities) self.outputs["Entities"].sv_set(entities) def create(self, index=None): @@ -114,20 +130,32 @@ class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper iterator = [index] for i in iterator: try: - entity = ifcopenshell.api.run("root.create_entity", self.file, ifc_class=self.ifc_class, name=self.names[i], description=self.descriptions[i]) + entity = ifcopenshell.api.run( + "root.create_entity", + self.file, + ifc_class=self.ifc_class, + name=self.names[i], + description=self.descriptions[i], + ) try: - if self.representations[i]: - ifcopenshell.api.run("geometry.assign_representation", self.file, product=entity, representation=self.representations[i]) + for repr in self.representations[i]: + if self.representations[i]: + ifcopenshell.api.run( + "geometry.assign_representation", self.file, product=entity, representation=repr + ) except IndexError: pass try: - if isinstance(self.locations[i], Matrix): - ifcopenshell.api.run("geometry.edit_object_placement", self.file, product=entity, matrix=self.locations[i]) + for loc in self.locations[i]: + if isinstance(self.locations[i], Matrix): + ifcopenshell.api.run( + "geometry.edit_object_placement", self.file, product=entity, matrix=loc + ) except IndexError: pass entities_ids.append(entity.id()) SvIfcStore.id_map.setdefault(self.node_id, []).append(entity.id()) - except Exception as e: + except Exception as e: raise Exception("Something went wrong. Cannot create entity.", e) return entities_ids @@ -146,15 +174,19 @@ class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper entity.Description = self.descriptions[i] try: - if self.representations[i] and self.representations[i].is_a('IfcProductDefinitionShape'): - entity.Representation = self.representations[i] - elif self.representations[i]: - ifcopenshell.api.run("geometry.assign_representation", self.file, product=entity, representation=self.representations[i]) + for repr in self.representations[i]: + if repr and repr.is_a("IfcProductDefinitionShape"): + entity.Representation = repr + elif repr: + ifcopenshell.api.run( + "geometry.assign_representation", self.file, product=entity, representation=repr + ) except IndexError: pass try: - if isinstance(self.locations[i], Matrix): - ifcopenshell.api.run("geometry.edit_object_placement", self.file, product=entity, matrix=self.locations[i]) + for loc in self.locations[i]: + if isinstance(loc, Matrix): + ifcopenshell.api.run("geometry.edit_object_placement", self.file, product=entity, matrix=loc) except IndexError: pass if entity.is_a() != self.ifc_class: @@ -163,21 +195,23 @@ class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper SvIfcStore.id_map.setdefault(self.node_id, []).append(entity.id()) entities_ids.append(entity.id()) - if id_map_copy>entities_ids: + if id_map_copy > entities_ids: SvIfcStore.id_map[self.node_id] = entities_ids return entities_ids def repeat_input_unique(self, input, count): 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)] # add number to duplicates + 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 - + def sv_free(self): try: del SvIfcStore.id_map[self.node_id] del self.node_dict[hash(self)] - print('Node was deleted') + # print('Node was deleted') except KeyError or AttributeError: pass diff --git a/src/ifcsverchok/nodes/ifc/create_file.py b/src/ifcsverchok/nodes/ifc/create_file.py index 4005190af7..71f0263a95 100644 --- a/src/ifcsverchok/nodes/ifc/create_file.py +++ b/src/ifcsverchok/nodes/ifc/create_file.py @@ -1,5 +1,5 @@ # IfcSverchok - IFC Sverchok extension -# Copyright (C) 2020, 2021 Dion Moult +# Copyright (C) 2020, 2021, 2022 Dion Moult # # This file is part of IfcSverchok. # diff --git a/src/ifcsverchok/nodes/ifc/create_project.py b/src/ifcsverchok/nodes/ifc/create_project.py index e61ac0697a..b2db663c5d 100644 --- a/src/ifcsverchok/nodes/ifc/create_project.py +++ b/src/ifcsverchok/nodes/ifc/create_project.py @@ -1,5 +1,5 @@ # IfcSverchok - IFC Sverchok extension -# Copyright (C) 2020, 2021 Dion Moult +# Copyright (C) 2022 Martina Jakubowska # # This file is part of IfcSverchok. # @@ -19,10 +19,8 @@ import bpy import ifcopenshell import ifcsverchok.helper -from bpy.props import StringProperty from sverchok.node_tree import SverchCustomTreeNode -from sverchok.data_structure import updateNode -# from ifcopenshell import template + class SvIfcCreateProject(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore): bl_idname = "SvIfcCreateProject" @@ -36,25 +34,26 @@ class SvIfcCreateProject(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helpe self.outputs.new("SvVerticesSocket", "file") def draw_buttons(self, context, layout): - op = layout.operator("node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False).tooltip = "Adds project, unit and context to IFC file" - #op.tooltip = self.tooltip + op = layout.operator( + "node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False + ).tooltip = "Adds project, unit and context to IFC file" + # op.tooltip = self.tooltip def process(self): - #file + # file file = self.inputs["file"].sv_get()[0][0] if file: schema_name = file.wrapped_data.schema else: schema_name = "IFC4" - - #project name + + # project name project_name = self.inputs["project_name"].sv_get()[0][0] self.process_ifc(file, project_name) - def process_ifc(self, file, project_name): - - # create project + + # create project project = ifcopenshell.api.run("root.create_entity", file, ifc_class="IfcProject", name=str(project_name)) lengthunit = ifcopenshell.api.run("unit.add_si_unit", file, unit_type="LENGTHUNIT", name="METRE") ifcopenshell.api.run("unit.assign_unit", file, units=[lengthunit]) diff --git a/src/ifcsverchok/nodes/ifc/create_shape.py b/src/ifcsverchok/nodes/ifc/create_shape.py index 220cc2d6e4..a16d5049c7 100644 --- a/src/ifcsverchok/nodes/ifc/create_shape.py +++ b/src/ifcsverchok/nodes/ifc/create_shape.py @@ -1,6 +1,5 @@ - # IfcSverchok - IFC Sverchok extension -# Copyright (C) 2020, 2021 Dion Moult +# Copyright (C) 2022 Martina Jakubowska # # This file is part of IfcSverchok. # @@ -28,29 +27,16 @@ from sverchok.node_tree import SverchCustomTreeNode from sverchok.data_structure import updateNode, flatten_data -# class SvIfcCreateShapeRefresh(bpy.types.Operator): -# bl_idname = "node.sv_ifc_create_shape_refresh" -# bl_label = "IFC Create Shape Refresh" -# bl_options = {"UNDO"} - - -# tree_name: StringProperty(default="") -# node_name: StringProperty(default="") - -# def execute(self, context): -# node = bpy.data.node_groups[self.tree_name].nodes[self.node_name] -# node.process() -# return {"FINISHED"} - - class SvIfcCreateShape(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore): """ Triggers: Ifc create shape by entity Tooltip: Create Blender shape by Ifc Entity """ + is_scene_dependent = True is_interactive = False node_dict = {} + def refresh_node(self, context): if self.refresh_local: self.process() @@ -61,22 +47,23 @@ class SvIfcCreateShape(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper. bl_idname = "SvIfcCreateShape" bl_label = "IFC Create Blender Shape" entity: StringProperty(name="Entities", update=updateNode) - def sv_init(self, context): self.inputs.new("SvStringsSocket", "Entities").prop_name = "entity" - self.outputs.new('SvStringsSocket', "Object(s)") + self.outputs.new("SvStringsSocket", "Object(s)") def draw_buttons(self, context, layout): 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." - row.prop(self, 'refresh_local', icon='FILE_REFRESH') + row.operator( + "node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False + ).tooltip = "Create Blender shape from IfcEntity ID. Takes one or multiple IfcEntity IDs." + row.prop(self, "refresh_local", icon="FILE_REFRESH") def process(self): - self.entities = flatten_data(self.inputs["Entities"].sv_get(), target_level = 1) + self.entities = flatten_data(self.inputs["Entities"].sv_get(), target_level=1) if not self.entities[0]: return - + if self.refresh_local or hash(self) not in self.node_dict: self.file = SvIfcStore.get_file() try: @@ -87,7 +74,7 @@ class SvIfcCreateShape(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper. self.node_dict[hash(self)] = blender_objects else: blender_objects = self.node_dict[hash(self)] - + self.outputs["Object(s)"].sv_set(blender_objects) def create(self): @@ -110,6 +97,7 @@ class SvIfcCreateShape(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper. raise Exception("Entity could not be converted into a shape. Entity: {}".format(entity)) return blender_objects + def register(): # bpy.utils.register_class(SvIfcCreateShapeRefresh) bpy.utils.register_class(SvIfcCreateShape) diff --git a/src/ifcsverchok/nodes/ifc/generate_guid.py b/src/ifcsverchok/nodes/ifc/generate_guid.py index 391e57c383..893a1b972f 100644 --- a/src/ifcsverchok/nodes/ifc/generate_guid.py +++ b/src/ifcsverchok/nodes/ifc/generate_guid.py @@ -1,6 +1,5 @@ - # IfcSverchok - IFC Sverchok extension -# Copyright (C) 2020, 2021 Dion Moult +# Copyright (C) 2020, 2021, 2022 Dion Moult # # This file is part of IfcSverchok. # @@ -20,9 +19,7 @@ import bpy import ifcopenshell import ifcsverchok.helper -from bpy.props import StringProperty from sverchok.node_tree import SverchCustomTreeNode -from sverchok.data_structure import updateNode class SvIfcGenerateGuid(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore): diff --git a/src/ifcsverchok/nodes/ifc/get_attribute.py b/src/ifcsverchok/nodes/ifc/get_attribute.py index deb9b8083e..976e40d142 100644 --- a/src/ifcsverchok/nodes/ifc/get_attribute.py +++ b/src/ifcsverchok/nodes/ifc/get_attribute.py @@ -1,6 +1,5 @@ - # IfcSverchok - IFC Sverchok extension -# Copyright (C) 2020, 2021 Dion Moult +# Copyright (C) 2020, 2021, 2022 Dion Moult # # This file is part of IfcSverchok. # diff --git a/src/ifcsverchok/nodes/ifc/get_property.py b/src/ifcsverchok/nodes/ifc/get_property.py index e889e52c1b..1d86866814 100644 --- a/src/ifcsverchok/nodes/ifc/get_property.py +++ b/src/ifcsverchok/nodes/ifc/get_property.py @@ -1,6 +1,5 @@ - # IfcSverchok - IFC Sverchok extension -# Copyright (C) 2020, 2021 Dion Moult +# Copyright (C) 2020, 2021, 2022 Dion Moult # # This file is part of IfcSverchok. # diff --git a/src/ifcsverchok/nodes/ifc/pick_ifc_class.py b/src/ifcsverchok/nodes/ifc/pick_ifc_class.py index 3b292d86c3..5cf24b9602 100644 --- a/src/ifcsverchok/nodes/ifc/pick_ifc_class.py +++ b/src/ifcsverchok/nodes/ifc/pick_ifc_class.py @@ -1,6 +1,5 @@ - # IfcSverchok - IFC Sverchok extension -# Copyright (C) 2020, 2021 Dion Moult +# Copyright (C) 2022 Martina Jakubowska # # This file is part of IfcSverchok. # @@ -20,11 +19,12 @@ import bpy import ifcopenshell import ifcsverchok.helper -from bpy.props import StringProperty, EnumProperty +from bpy.props import EnumProperty from ifcsverchok.ifcstore import SvIfcStore from sverchok.node_tree import SverchCustomTreeNode from sverchok.data_structure import updateNode + def get_ifc_products(self, context): ifc_products = getattr(self, "ifc_products", []) file = SvIfcStore.get_file() @@ -83,15 +83,22 @@ def get_ifc_classes(self, context): class SvIfcPickIfcClass(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore): bl_idname = "SvIfcPickIfcClass" bl_label = "IFC Class Picker" - ifc_product: EnumProperty(items=get_ifc_products, name="IfcProduct", description="Pick an IfcProduct from drop-down.", update=update_ifc_products) - ifc_class: EnumProperty(items=get_ifc_classes, name="IfcClass", description="Pick an IfcClass from drop-down.", update=updateNode) + ifc_product: EnumProperty( + items=get_ifc_products, + name="IfcProduct", + description="Pick an IfcProduct from drop-down.", + update=update_ifc_products, + ) + ifc_class: EnumProperty( + items=get_ifc_classes, name="IfcClass", description="Pick an IfcClass from drop-down.", 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.outputs.new("SvStringsSocket", "IfcClass") self.width = 200 - + def draw_buttons(self, context, layout): layout.operator("node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False).tooltip = "Ifc Class Picker" diff --git a/src/ifcsverchok/nodes/ifc/quick_project_setup.py b/src/ifcsverchok/nodes/ifc/quick_project_setup.py index fe3bb07450..435f8150bb 100644 --- a/src/ifcsverchok/nodes/ifc/quick_project_setup.py +++ b/src/ifcsverchok/nodes/ifc/quick_project_setup.py @@ -1,5 +1,5 @@ # IfcSverchok - IFC Sverchok extension -# Copyright (C) 2020, 2021 Dion Moult +# Copyright (C) 2022 Martina Jakubowska # # This file is part of IfcSverchok. # @@ -16,6 +16,7 @@ # You should have received a copy of the GNU General Public License # along with IfcSverchok. If not, see . + from email.mime import application import bpy import ifcopenshell @@ -25,6 +26,7 @@ from sverchok.node_tree import SverchCustomTreeNode from sverchok.data_structure import updateNode from ifcopenshell import template + class SvIfcQuickProjectSetup(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore): bl_idname = "SvIfcQuickProjectSetup" bl_label = "IFC Quick Project Setup" @@ -33,7 +35,6 @@ class SvIfcQuickProjectSetup(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h application: StringProperty(name="application", update=updateNode) application_version: StringProperty(name="application_version", update=updateNode) timestamp: StringProperty(name="timestamp", update=updateNode) - def sv_init(self, context): input_socket = self.inputs.new("SvStringsSocket", "filename") @@ -59,8 +60,10 @@ class SvIfcQuickProjectSetup(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h self.outputs.new("SvVerticesSocket", "file") def draw_buttons(self, context, layout): - op = layout.operator("node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False).tooltip = "Quick Project Setup: creates Ifc file and sets up a basic project" - #op.tooltip = self.tooltip + op = layout.operator( + "node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False + ).tooltip = "Quick Project Setup: creates Ifc file and sets up a basic project" + # op.tooltip = self.tooltip def process(self): self.sv_input_names = [i.name for i in self.inputs] @@ -70,17 +73,17 @@ class SvIfcQuickProjectSetup(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h settings = dict(zip(self.sv_input_names, setting_values)) settings = {k: v for k, v in settings.items() if v != ""} file = template.create( - filename=settings['filename'], - timestring=settings['timestring'], - organization=settings['organization'], - creator=settings['creator'], - schema_identifier=settings['schema_identifier'], - application_version=settings['application_version'], - timestamp=settings['timestamp'], - application=settings['application'], - project_globalid=settings['project_globalid'], - project_name=settings['project_name'], - ) + filename=settings["filename"], + timestring=settings["timestring"], + organization=settings["organization"], + creator=settings["creator"], + schema_identifier=settings["schema_identifier"], + application_version=settings["application_version"], + timestamp=settings["timestamp"], + application=settings["application"], + project_globalid=settings["project_globalid"], + project_name=settings["project_name"], + ) self.outputs["file"].sv_set([[file]]) diff --git a/src/ifcsverchok/nodes/ifc/read_entity.py b/src/ifcsverchok/nodes/ifc/read_entity.py index 50e721385f..47a2eb83d9 100644 --- a/src/ifcsverchok/nodes/ifc/read_entity.py +++ b/src/ifcsverchok/nodes/ifc/read_entity.py @@ -1,6 +1,5 @@ - # IfcSverchok - IFC Sverchok extension -# Copyright (C) 2020, 2021 Dion Moult +# Copyright (C) 2020, 2021, 2022 Dion Moult # # This file is part of IfcSverchok. # @@ -63,7 +62,7 @@ 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, file, entity): + 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()): diff --git a/src/ifcsverchok/nodes/ifc/read_file.py b/src/ifcsverchok/nodes/ifc/read_file.py index 1f10056c55..5b3432a71e 100644 --- a/src/ifcsverchok/nodes/ifc/read_file.py +++ b/src/ifcsverchok/nodes/ifc/read_file.py @@ -1,6 +1,5 @@ - # IfcSverchok - IFC Sverchok extension -# Copyright (C) 2020, 2021 Dion Moult +# Copyright (C) 2020, 2021, 2022 Dion Moult # # This file is part of IfcSverchok. # diff --git a/src/ifcsverchok/nodes/ifc/remove.py b/src/ifcsverchok/nodes/ifc/remove.py index 4a7e76db75..58c2d8a5c3 100644 --- a/src/ifcsverchok/nodes/ifc/remove.py +++ b/src/ifcsverchok/nodes/ifc/remove.py @@ -1,6 +1,5 @@ - # IfcSverchok - IFC Sverchok extension -# Copyright (C) 2020, 2021 Dion Moult +# Copyright (C) 2020, 2021, 2022 Dion Moult # # This file is part of IfcSverchok. # diff --git a/src/ifcsverchok/nodes/ifc/select_blender_objects.py b/src/ifcsverchok/nodes/ifc/select_blender_objects.py index 797eac5081..f6a6e52476 100644 --- a/src/ifcsverchok/nodes/ifc/select_blender_objects.py +++ b/src/ifcsverchok/nodes/ifc/select_blender_objects.py @@ -1,6 +1,5 @@ - # IfcSverchok - IFC Sverchok extension -# Copyright (C) 2020, 2021 Dion Moult +# Copyright (C) 2020, 2021, 2022 Dion Moult # # This file is part of IfcSverchok. # diff --git a/src/ifcsverchok/nodes/ifc/sverchok_to_ifc.py b/src/ifcsverchok/nodes/ifc/sverchok_to_ifc.py index 925ce9ee41..d2dcd38160 100644 --- a/src/ifcsverchok/nodes/ifc/sverchok_to_ifc.py +++ b/src/ifcsverchok/nodes/ifc/sverchok_to_ifc.py @@ -1,5 +1,5 @@ # IfcSverchok - IFC Sverchok extension -# Copyright (C) 2022 Dion Moult +# Copyright (C) 2022 Martina Jakubowska # # This file is part of IfcSverchok. # @@ -15,7 +15,7 @@ # # You should have received a copy of the GNU General Public License # along with IfcSverchok. If not, see . - + from copy import deepcopy import bpy import ifcopenshell @@ -26,124 +26,146 @@ import blenderbim.tool as tool import blenderbim.core.geometry as core from bpy.props import StringProperty, EnumProperty, IntProperty, FloatVectorProperty from sverchok.node_tree import SverchCustomTreeNode -from sverchok.data_structure import updateNode - - +from sverchok.data_structure import updateNode, ensure_min_nesting + + class SvIfcSverchokToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore): """ Triggers: Sv to Ifc Repr Tooltip: Sverchok geometry to Ifc Shape Representation """ + bl_idname = "SvIfcSverchokToIfcRepr" bl_label = "IFC Sverchok to IFC Repr" node_dict = {} - + n_id: StringProperty() context_types = [ - ('Model', 'Model', 'Context type: Model', 0), - ('Plan', 'Plan', 'Context type: Plan', 1), + ("Model", "Model", "Context type: Model", 0), + ("Plan", "Plan", "Context type: Plan", 1), ] - + context_identifiers = [ - ('Body', 'Body', 'Context identifier: Body', 0), - ('Annotation', 'Annotation', 'Context identifier: Annotation', 1), - ('Box', 'Box', 'Context identifier: Box', 2), - ('Axis', 'Axis', 'Context identifier: Axis', 3), + ("Body", "Body", "Context identifier: Body", 0), + ("Annotation", "Annotation", "Context identifier: Annotation", 1), + ("Box", "Box", "Context identifier: Box", 2), + ("Axis", "Axis", "Context identifier: Axis", 3), ] target_views = [ - ('MODEL_VIEW', 'MODEL_VIEW', 'Target View: MODEL_VIEW', 0), - ('PLAN_VIEW', 'PLAN_VIEW', 'Target View: PLAN_VIEW', 1), - ('GRAPH_VIEW', 'GRAPH_VIEW', 'Target View: GRAPH_VIEW', 2), - ('SKETCH_VIEW', 'SKETCH_VIEW', 'Target View: SKETCH_VIEW', 3), + ("MODEL_VIEW", "MODEL_VIEW", "Target View: MODEL_VIEW", 0), + ("PLAN_VIEW", "PLAN_VIEW", "Target View: PLAN_VIEW", 1), + ("GRAPH_VIEW", "GRAPH_VIEW", "Target View: GRAPH_VIEW", 2), + ("SKETCH_VIEW", "SKETCH_VIEW", "Target View: SKETCH_VIEW", 3), ] - - context_type: EnumProperty(name="Context Type", description="Default: Model", default="Model",items=context_types,update=updateNode) - context_identifier: EnumProperty(name="Context Identifier", description="Default: Body", default="Body", items=context_identifiers, update=updateNode) - target_view: EnumProperty(name="Target View", description="Default: MODEL VIEW", default="MODEL_VIEW",items=target_views, update=updateNode) - + + context_type: EnumProperty( + name="Context Type", description="Default: Model", default="Model", items=context_types, update=updateNode + ) + context_identifier: EnumProperty( + name="Context Identifier", + description="Default: Body", + default="Body", + items=context_identifiers, + update=updateNode, + ) + target_view: EnumProperty( + name="Target View", + description="Default: MODEL VIEW", + default="MODEL_VIEW", + items=target_views, + update=updateNode, + ) + 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", "target_view").prop_name = "target_view" self.inputs.new("SvVerticesSocket", "Vertices") self.inputs.new("SvStringsSocket", "Edges") - self.inputs.new("SvStringsSocket", "Faces") + self.inputs.new("SvStringsSocket", "Faces") self.outputs.new("SvVerticesSocket", "Representation(s)") self.width = 210 self.node_dict[hash(self)] = {} - + def draw_buttons(self, context, layout): op = layout.operator( "node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False ).tooltip = "Sverchok geometry to Ifc Shape Representation. \nTakes one or multiple geometries." - + def process(self): if not any(socket.is_linked for socket in self.inputs): return - self.file = SvIfcStore.get_file() 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)) edit = False for i in range(len(self.inputs)): input = self.inputs[i].sv_get(deepcopy=False) - if isinstance(self.node_dict[hash(self)][self.inputs[i].name], list) and input != self.node_dict[hash(self)][self.inputs[i].name]: + if ( + isinstance(self.node_dict[hash(self)][self.inputs[i].name], list) + and input != self.node_dict[hash(self)][self.inputs[i].name] + ): edit = True self.node_dict[hash(self)][self.inputs[i].name] = input - self.vertices = self.inputs["Vertices"].sv_get(deepcopy=False) - self.edges = self.inputs["Edges"].sv_get(deepcopy=False) - self.faces = self.inputs["Faces"].sv_get(deepcopy=False) - geo_data = list(zip(self.vertices, self.edges, self.faces)) + 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)) + objects = [] + for object in data: + objects.append(list(zip(object[0], object[1], object[2]))) if self.node_id not in SvIfcStore.id_map: - - representations = self.create(geo_data) + representations = self.create(objects) else: if edit is True: self.edit() - representations = self.create(geo_data) + representations = self.create(objects) else: - # representations = self.get_existing_element() representations = SvIfcStore.id_map[self.node_id]["Representations"] - self.outputs["Representation(s)"].sv_set(representations) - + def create(self, geo_data): representations_ids = [] self.context = self.get_context() - for item in geo_data: - representation = ifcopenshell.api.run( - "geometry.add_sverchok_representation", - self.file, - should_run_listeners=False, - context=self.context, - vertices=[item[0]], - edges=[item[1]], - faces=[item[2]], + for obj in geo_data: + representations_ids_obj = [] + for item in obj: + representation = ifcopenshell.api.run( + "geometry.add_sverchok_representation", + self.file, + should_run_listeners=False, + context=self.context, + vertices=[list(map(tuple, item[0]))], + edges=[list(map(tuple, item[1]))], + faces=[list(map(tuple, item[2]))], + ) + if not representation: + 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 ) - if not representation: - raise Exception("Couldn't create representation. Possibly wrong context.") - representations_ids.append(representation.id()) - SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault("Representations", []).append(representation.id()) return representations_ids - + def edit(self): - # results = self.get_existing_element() if "Representations" not in SvIfcStore.id_map[self.node_id]: return - for step_id in SvIfcStore.id_map[self.node_id]["Representations"]: - ifcopenshell.api.run( + 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) ) del SvIfcStore.id_map[self.node_id]["Representations"] return - + def get_context(self): context = ifcopenshell.util.representation.get_context( self.file, self.context_type, self.context_identifier, self.target_view @@ -162,13 +184,15 @@ class SvIfcSverchokToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h ) SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault("Contexts", []).append(context.id()) return context - + def sv_free(self): try: self.file = SvIfcStore.get_file() 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)) + ifcopenshell.api.run( + "geometry.remove_representation", self.file, representation=self.file.by_id(step_id) + ) if "Contexts" in SvIfcStore.id_map[self.node_id]: for context_id in SvIfcStore.id_map[self.node_id]["Contexts"]: @@ -180,18 +204,18 @@ class SvIfcSverchokToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h if parent: if not self.file.get_inverse(parent): ifcopenshell.api.run("context.remove_context", self.file, context=parent) - print("Removed context with step ID: ", context_id) + # 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] del self.node_dict[hash(self)] - print('Node was deleted') + # print('Node was deleted') except KeyError or AttributeError: pass - - + + def register(): bpy.utils.register_class(SvIfcSverchokToIfcRepr) - - + + def unregister(): - bpy.utils.unregister_class(SvIfcSverchokToIfcRepr) \ No newline at end of file + bpy.utils.unregister_class(SvIfcSverchokToIfcRepr) diff --git a/src/ifcsverchok/nodes/ifc/write_file.py b/src/ifcsverchok/nodes/ifc/write_file.py index 554ae811be..bbe4680298 100644 --- a/src/ifcsverchok/nodes/ifc/write_file.py +++ b/src/ifcsverchok/nodes/ifc/write_file.py @@ -1,6 +1,5 @@ - # IfcSverchok - IFC Sverchok extension -# Copyright (C) 2020, 2021 Dion Moult +# Copyright (C) 2022 Martina Jakubowska # # This file is part of IfcSverchok. # @@ -32,29 +31,31 @@ class SvIfcWriteFile(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.Sv Triggers: Ifc write to file Tooltip: Write active Sverchok Ifc file to path """ + def refresh_node_local(self, context): if self.refresh_local: self.process() self.refresh_local = False - # out = "" refresh_local: BoolProperty(name="Write", description="Write to file", update=refresh_node_local) bl_idname = "SvIfcWriteFile" bl_label = "IFC Write File" - path: StringProperty(name="path", description="File path to write to. Can be relative.", update=updateNode) + path: StringProperty(name="path", description="File path to write to. Can be relative.", update=updateNode) def sv_init(self, context): self.inputs.new("SvStringsSocket", "path").prop_name = "path" self.outputs.new("SvStringsSocket", "output") - + def draw_buttons(self, context, layout): row = layout.row(align=True) - row.operator("node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False).tooltip = "Writes active Ifc file to path.\n It will overwrite an existing file.\n N.B.! It's recommended to create a fresh IFC File using the 're-run all nodes' button in IfcSverchok panel before saving." - row.prop(self, 'refresh_local', icon='FILE_REFRESH') + row.operator( + "node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False + ).tooltip = "Writes active Ifc file to path.\n It will overwrite an existing file.\n N.B.! It's recommended to create a fresh IFC File using the 're-run all nodes' button in IfcSverchok panel before saving." + row.prop(self, "refresh_local", icon="FILE_REFRESH") def process(self): - path = flatten_data(self.inputs["path"].sv_get(), target_level = 1)[0] + path = flatten_data(self.inputs["path"].sv_get(), target_level=1)[0] if not path: return path = abspath(path) @@ -66,7 +67,7 @@ class SvIfcWriteFile(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.Sv self.ensure_hirarchy(file) file.write(path) self.outputs["output"].sv_set(f"File written successfully to: {path}.") - + def ensure_hirarchy(self, file): elements_in_buildings = [] if not 0 <= 0 < len(file.by_type("IfcBuilding")): @@ -77,10 +78,12 @@ class SvIfcWriteFile(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.Sv elements = ifcopenshell.util.element.get_decomposition(building) elements_in_buildings.extend(elements) - for spatial in (file.by_type("IfcSpatialElement") or file.by_type("IfcSpatialStructureElement")): - if (not (spatial.is_a("IfcSite") or spatial.is_a("IfcBuilding")) and (spatial not in elements_in_buildings)): + for spatial in file.by_type("IfcSpatialElement") or file.by_type("IfcSpatialStructureElement"): + if not (spatial.is_a("IfcSite") or spatial.is_a("IfcBuilding")) and (spatial not in elements_in_buildings): elements = ifcopenshell.util.element.get_decomposition(spatial) - ifcopenshell.api.run("aggregate.assign_object", file, product=spatial, relating_object=file.by_type("IfcBuilding")[0]) + ifcopenshell.api.run( + "aggregate.assign_object", file, product=spatial, relating_object=file.by_type("IfcBuilding")[0] + ) elements_in_buildings_after = [] for building in file.by_type("IfcBuilding"): @@ -90,24 +93,31 @@ class SvIfcWriteFile(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.Sv elements = file.by_type("IfcElement") for element in elements: if element not in elements_in_buildings: - ifcopenshell.api.run("spatial.assign_container", file, product=element, relating_structure=file.by_type("IfcBuilding")[0]) - + ifcopenshell.api.run( + "spatial.assign_container", file, product=element, relating_structure=file.by_type("IfcBuilding")[0] + ) for building in file.by_type("IfcBuilding"): elements = ifcopenshell.util.element.get_decomposition(building) if not building.Decomposes: if not 0 <= 0 < len(file.by_type("IfcSite")): ifcopenshell.api.run("root.create_entity", file, ifc_class="IfcSite", name="My Site") - ifcopenshell.api.run("aggregate.assign_object", file, product=building, relating_object=file.by_type("IfcSite")[0]) + ifcopenshell.api.run( + "aggregate.assign_object", file, product=building, relating_object=file.by_type("IfcSite")[0] + ) try: if file.by_type("IfcSite")[0].Decomposes[0].RelatingObject.is_a("IfcProject"): continue except IndexError: pass - ifcopenshell.api.run("aggregate.assign_object", file, product=file.by_type("IfcSite")[0], relating_object=file.by_type("IfcProject")[0]) + ifcopenshell.api.run( + "aggregate.assign_object", + file, + product=file.by_type("IfcSite")[0], + relating_object=file.by_type("IfcProject")[0], + ) self.file = file return - def register():