From d193e8a3eb91b0c195f5bcbec9a4938df0bc8703 Mon Sep 17 00:00:00 2001 From: martinaCodes Date: Mon, 7 Nov 2022 15:45:28 +0100 Subject: [PATCH] major changes primarily to file creation/saving logic. Bug fix in create entity. Other.. this commit is way to big and unstructured. --- src/ifcsverchok/__init__.py | 95 ++++++++- src/ifcsverchok/ifcstore.py | 24 ++- .../nodes/ifc/add_spatial_element.py | 198 ++++++++++++------ src/ifcsverchok/nodes/ifc/bmesh_to_ifc.py | 6 +- src/ifcsverchok/nodes/ifc/by_type.py | 30 +-- src/ifcsverchok/nodes/ifc/create_entity.py | 14 +- src/ifcsverchok/nodes/ifc/pick_ifc_class.py | 7 +- 7 files changed, 252 insertions(+), 122 deletions(-) diff --git a/src/ifcsverchok/__init__.py b/src/ifcsverchok/__init__.py index 7a376eb856..d01676e15c 100644 --- a/src/ifcsverchok/__init__.py +++ b/src/ifcsverchok/__init__.py @@ -41,6 +41,8 @@ from sverchok.utils.extra_categories import ( ) 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 [ @@ -100,17 +102,88 @@ 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'} + + 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: + print("### \tupdate tree", node_tree) + if self.force_mode or node_tree.sv_process: + print("### \tforce update") + try: + bpy.context.window.cursor_set("WAIT") + node_tree.force_update() + finally: + bpy.context.window.cursor_set("DEFAULT") + print("### \tupdate tree done") + self.report({"INFO"}, "Node tree updated") + return {'FINISHED'} + class IFC_Sv_write_file(bpy.types.Operator): bl_idname = "ifc.write_file_panel" bl_label = "Write File" bl_options = {"REGISTER", "UNDO"} bl_description = "File path to write to." filepath: bpy.props.StringProperty(subtype="FILE_PATH") + node_group: bpy.props.StringProperty(default="") + force_mode: bpy.props.BoolProperty(default=False) @classmethod def poll(cls, context): 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")): + 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) + + 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]) + + 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 = 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]) + + + 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]) + 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]) + self.file = file + return + def execute(self, context): self.file = SvIfcStore.file if not self.file: @@ -119,16 +192,18 @@ class IFC_Sv_write_file(bpy.types.Operator): if not ext: raise Exception("Bad path. Provide a path to a file.") else: - if not (self.file.by_type("IfcSpatialElement") or self.file.by_type("IfcSpatialStructureElement")): - print("No Ifc Spatial Element found. Adding all elements to IfcBuilding.") - elements = self.file.by_type("IfcElement") - building = ifcopenshell.api.run("root.create_entity", self.file, name="DefaultBuilding", ifc_class="IfcBuilding") - for element in elements: - ifcopenshell.api.run("spatial.assign_container", self.file, product=element, relating_structure=building) + self.ensure_hirarchy(self.file) + print("### \thirarchy ensured") + # if not (self.file.by_type("IfcSpatialElement") or self.file.by_type("IfcSpatialStructureElement")): + # self.report({"INFO"},"No Ifc Spatial Element found. Adding all elements to IfcBuilding.") + # elements = self.file.by_type("IfcElement") + # building = ifcopenshell.api.run("root.create_entity", self.file, name="DefaultBuilding", ifc_class="IfcBuilding") + # for element in elements: + # ifcopenshell.api.run("spatial.assign_container", self.file, product=element, relating_structure=building) self.file.write(self.filepath) - print(f"File written to: {self.filepath}") + self.report({"INFO"}, f"File written to: {self.filepath}") return {"FINISHED"} - + def invoke(self, context, event): context.window_manager.fileselect_add(self) return {"RUNNING_MODAL"} @@ -147,12 +222,14 @@ class IFC_PT_write_file_panel(bpy.types.Panel): return True def draw(self, context): + ng = context.space_data.node_tree layout = self.layout row = layout.split(factor=0.2, align=True) row = layout.row() + row.operator('ifc.sverchok_update_current', text='IFC Re-run all nodes') row.operator("ifc.write_file_panel") -CLASSES = [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() diff --git a/src/ifcsverchok/ifcstore.py b/src/ifcsverchok/ifcstore.py index c334e952fc..9efff80ec6 100644 --- a/src/ifcsverchok/ifcstore.py +++ b/src/ifcsverchok/ifcstore.py @@ -65,7 +65,9 @@ class SvIfcStore: 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.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( "context.add_context", file, @@ -74,17 +76,17 @@ 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" - ) + # 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) + # 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 diff --git a/src/ifcsverchok/nodes/ifc/add_spatial_element.py b/src/ifcsverchok/nodes/ifc/add_spatial_element.py index d474e9b309..0dcf4dcc7d 100644 --- a/src/ifcsverchok/nodes/ifc/add_spatial_element.py +++ b/src/ifcsverchok/nodes/ifc/add_spatial_element.py @@ -4,10 +4,6 @@ import ifcopenshell import ifcsverchok.helper from ifcsverchok.ifcstore import SvIfcStore -import bpy -import json -import ifcopenshell - 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 @@ -16,25 +12,55 @@ from sverchok.data_structure import updateNode, flatten_data, repeat_last_for_le class SvIfcAddSpatialElement(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore): bl_idname = "SvIfcAddSpatialElement" bl_label = "IFC Add Spatial Element" - node_dict = {} + node_dict2 = {} - n_id: StringProperty() - Name: StringProperty(name="Name(s)", update=updateNode) + Names: StringProperty(name="Name(s)", update=updateNode) IfcClass: StringProperty(name="IFC Class", update=updateNode, default="IfcSpace") Elements: StringProperty(name="Elements", update=updateNode) - len_elements = 0 def sv_init(self, context): - self.inputs.new("SvStringsSocket", "Names").prop_name = "Name" + self.inputs.new("SvStringsSocket", "Names").prop_name = "Names" self.inputs.new("SvStringsSocket", "IfcClass").prop_name = "IfcClass" self.inputs.new("SvStringsSocket", "Elements").prop_name = "Elements" self.outputs.new("SvStringsSocket", "Entities") + self.node_dict2[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): print("#"*20, "\n running add_spatial_element PROCESS()... \n", "#"*20,) print("#"*20, "\n hash(self):", hash(self), "\n", "#"*20,) + try: + print("SvIfcStore.id_map: ", SvIfcStore.id_map) + print("self-node_id: ",self.node_id) + print("#"*20, "\n node_dict2 before before... \n", self.node_dict2, "\n", "#"*20,) + except: + pass + self.sv_input_names = [i.name for i in self.inputs] + if hash(self) not in self.node_dict2: + self.node_dict2[hash(self)] = {} #happens if node is already on canvas when blender loads + if not self.node_dict2[hash(self)]: + self.node_dict2[hash(self)].update(dict.fromkeys(self.sv_input_names, 0)) + + print("#"*20, "\n node_dict2 before... \n", self.node_dict2, "\n", "#"*20,) if not any(socket.is_linked for socket in self.outputs): return + edit = False + edit_elements = False + for i in range(len(self.inputs)): + print(f"current node_dict2 iter:{i}: ", self.node_dict2[hash(self)]) + input = self.inputs[self.sv_input_names[i]].sv_get(deepcopy=True, default =[]) + print("current input: ", input) + print("previous input: ", self.node_dict2[hash(self)][self.inputs[i].name]) + if isinstance(self.node_dict2[hash(self)][self.inputs[i].name], list) and input != self.node_dict2[hash(self)][self.inputs[i].name]: + edit = True + print("Edit = True") + if self.inputs[i].name == "Elements": + edit_elements = True + print("edit_elements = True") + self.node_dict2[hash(self)][self.inputs[i].name] = input.copy() + print("#"*20, "\n node_dict2 after... \n", self.node_dict2,"\n", "#"*20,) 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] @@ -47,86 +73,119 @@ class SvIfcAddSpatialElement(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h self.file = SvIfcStore.get_file() self.elements = [[self.file.by_id(step_id) for step_id in element] for element in self.elements] - print("len elements: ", len(self.elements)) + + if "len" not in self.node_dict2[hash(self)]: + self.node_dict2[hash(self)]["len"] = 0 + print("len elements: ", len(self.elements), "stored len_elements: ", self.node_dict2[hash(self)]["len"]) print("elements: ", self.elements) self.names = self.repeat_input_unique(self.names, len(self.elements)) print("Names: ",self.names) print("IfcClass: ",self.ifc_class) - - 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 - if not self.node_dict[hash(self)]: - self.node_dict[hash(self)].update(dict.fromkeys(self.sv_input_names, 0)) - - print("node_dict: ", self.node_dict) - 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]: - edit = True - print("Edit = True") - self.node_dict[hash(self)][self.inputs[i].name] = input + print("node_dict2: ", self.node_dict2) - if (self.node_id not in SvIfcStore.id_map) or (len(self.elements) != self.len_elements): + if (self.node_id not in SvIfcStore.id_map) or (len(self.elements) != self.node_dict2[hash(self)]["len"]): print("\nRunning create") + self.remove() elements = self.create() - self.len_elements = len(self.elements) + self.node_dict2[hash(self)]["len"] = len(self.elements) + print("stored len_elements: ", self.node_dict2[hash(self)]["len"]) else: if edit is True: - elements = self.edit() + elements = self.edit(edit_elements) else: + print("No changes") elements = SvIfcStore.id_map[self.node_id] - print("\n ##### results: ", elements) + print("\n ##### spatial element results: ", elements) self.outputs["Entities"].sv_set(elements) - def create(self): - results = [] - for i, element in enumerate(self.elements): - print("element: ", element) + def create(self, index=None): + print("#"*20, "\n running add_spatial_element create()... \n", "#"*20,) + spatial_ids = [] + iterator = range(len(self.elements)) + if index is not None: + iterator = [index] + for i in iterator: + print("element: ", self.elements[i]) result = ifcopenshell.api.run("root.create_entity", self.file, name=self.names[i], ifc_class=self.ifc_class) - for items in element: + for items in self.elements[i]: print("items: ", items) 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) - SvIfcStore.id_map[result.id()] = self.node_id - SvIfcStore.id_map.setdefault(self.node_id, []).append(result.id()) - results.append(result.id()) - return results + # SvIfcStore.id_map[result.id()] = self.node_id + SvIfcStore.id_map.setdefault(self.node_id, []).append(result.id()) + spatial_ids.append(result.id()) + return spatial_ids - def edit(self): - results = [] - results_ids = SvIfcStore.id_map[self.node_id] + def edit(self, edit_elements): + spatial_ids = [] + id_map = SvIfcStore.id_map[self.node_id] + id_map_copy = SvIfcStore.id_map[self.node_id].copy() print("#"*20, "\n running add_spatial_element edit()... \n", "#"*20,) - print("#"*20, "\n results_ids:", results_ids, "\n", "#"*20,) - for result_id in results_ids: + print("#"*20, "\n id_map:", id_map, "\n", "#"*20,) + for i, element in enumerate(self.elements): + try: + result_id = id_map_copy[i] + except IndexError: + id = self.create(index=i) + spatial_ids.append(id[0]) + continue result = self.file.by_id(result_id) print("#"*20, "\n result", result, "\n", "#"*20,) - subelements = set(ifcopenshell.util.element.get_decomposition(result)) - for element in self.elements: - print("\n\n\n","#"*50) - print("\nElement: ", element) - element_set = set(element) - print("\nRESULT: ", result) + result.Name = self.names[i] + if edit_elements: + subelements = ifcopenshell.util.element.get_decomposition(result) print("subelements: ", subelements) - print("elements_set: ", element_set) - for removed_element in subelements - element_set: - # Just realised I don't have a spatial.unassign_container, but if so we'd do it here - 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: - pass - 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) - else: - ifcopenshell.api.run("spatial.assign_container", self.file, product=added_element, relating_structure=result) - print("assigned container") - results.append(result.id()) - return results + subelements = set(subelements) + print("subelements after: ", subelements) + for element in self.elements[i]: + print("\n\n\n","#"*50) + print("\nElement: ", element) + element_set = set([element]) + print("\nRESULT: ", result) + print("subelements: ", subelements) + print("elements_set: ", element_set) + for removed_element in subelements - element_set: + # Just realised I don't have a spatial.unassign_container, but if so we'd do it here + print("removed_element: ", removed_element) + 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) + self.unassign_container(removed_element) + for added_element in element_set - subelements: + print("added_element: ", added_element) + 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) + else: + ifcopenshell.api.run("spatial.assign_container", self.file, product=added_element, relating_structure=result) + print("assigned container") + spatial_ids.append(result.id()) + SvIfcStore.id_map[self.node_id] = spatial_ids + return spatial_ids + + def unassign_container(self, product): + for rel in product.ContainedInStructure or []: + related_elements = list(rel.RelatedElements) + related_elements.remove(product) + if related_elements: + rel.RelatedElements = related_elements + ifcopenshell.api.run("owner.update_owner_history", self.file, element=rel) + else: + self.file.remove(rel) + + def remove(self): + print("#"*20, "\n running add_spatial_element remove()... \n", "#"*20,) + if self.node_id in SvIfcStore.id_map: + print(SvIfcStore.id_map[self.node_id]) + for element_id in SvIfcStore.id_map[self.node_id]: + element = self.file.by_id(element_id) + print("\nremoving element: ", element) + self.file.write("/Users/martina/Documents/GSoC/CodeTests/IfcFileTest_6_11_before_remove.ifc") + ifcopenshell.api.run("root.remove_product", self.file, product=element) + del SvIfcStore.id_map[self.node_id] def repeat_input_unique(self, input, count): input = repeat_last_for_length(input, count, deepcopy=False) @@ -134,10 +193,13 @@ class SvIfcAddSpatialElement(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h 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 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 sv_free(self): + try: + del SvIfcStore.id_map[self.node_id] + del self.node_dict2[hash(self)] + print('Node was deleted') + except KeyError or AttributeError: + pass def register(): bpy.utils.register_class(SvIfcAddSpatialElement) diff --git a/src/ifcsverchok/nodes/ifc/bmesh_to_ifc.py b/src/ifcsverchok/nodes/ifc/bmesh_to_ifc.py index 344170d18d..664efbbc3e 100644 --- a/src/ifcsverchok/nodes/ifc/bmesh_to_ifc.py +++ b/src/ifcsverchok/nodes/ifc/bmesh_to_ifc.py @@ -48,7 +48,7 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help def refresh_node(self, context): if self.refresh_local: - self.process() + updateNode(self, context) self.refresh_local = False refresh_local: BoolProperty(name="Update Node", description="Update Node", update=refresh_node) @@ -114,10 +114,10 @@ class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.help return edit = False for i in range(len(self.inputs)): - input = self.inputs[i].sv_get(deepcopy=False) + 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]: edit = True - self.node_dict[hash(self)][self.inputs[i].name] = input + self.node_dict[hash(self)][self.inputs[i].name] = input.copy() blender_objects = self.inputs["blender_objects"].sv_get() self.file = SvIfcStore.get_file() diff --git a/src/ifcsverchok/nodes/ifc/by_type.py b/src/ifcsverchok/nodes/ifc/by_type.py index 4498ae767d..2222151759 100644 --- a/src/ifcsverchok/nodes/ifc/by_type.py +++ b/src/ifcsverchok/nodes/ifc/by_type.py @@ -24,9 +24,10 @@ 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 def get_ifc_products(self, context): + print("#"*20, "\n running get_ifc_products PROCESS()... \n", "#"*20,) ifc_products = getattr(self, "ifc_products", []) file = SvIfcStore.get_file() if not file: @@ -54,11 +55,12 @@ def get_ifc_products(self, context): def update_ifc_products(self, context): + print("#"*20, "\n by_type update_ifc_products()... \n", "#"*20,) if hasattr(self, "ifc_classes"): self.ifc_classes.clear() - def get_ifc_classes(self, context): + print("#"*20, "\n by_type get_ifc_classes()... \n", "#"*20,) ifc_classes = getattr(self, "ifc_classes", []) if ifc_classes: return self.ifc_classes @@ -103,27 +105,17 @@ class SvIfcByType(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfc if self.file: self.ifc_products = get_ifc_products(self, bpy.context) self.ifc_classes = get_ifc_classes(self, bpy.context) - # self.sv_input_names = ["ifc_product", "ifc_class", "custom_ifc_class"] - self.ifc_product = flatten_data(self.inputs["ifc_product"].sv_get(), target_level=1)[0] - self.ifc_class = flatten_data(self.inputs["ifc_class"].sv_get(), target_level=1)[0] - self.custom_ifc_class = flatten_data(self.inputs["custom_ifc_class"].sv_get(), target_level=1)[0] + self.sv_input_names = ["ifc_product", "ifc_class", "custom_ifc_class"] + super().process() - # super().process() - if self.custom_ifc_class: - self.outputs["Entity"].sv_set([self.file.by_type(self.custom_ifc_class)]) - elif self.ifc_class: - self.outputs["Entity"].sv_set([self.file.by_type(self.ifc_class)]) + 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)]) + elif ifc_class: + self.outputs["Entity"].sv_set([self.file.by_type(ifc_class)]) else: self.outputs["Entity"].sv_set([]) - # 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)]) - # elif ifc_class: - # self.outputs["Entity"].sv_set([self.file.by_type(ifc_class)]) - # else: - # self.outputs["Entity"].sv_set([]) - def register(): bpy.utils.register_class(SvIfcByType) diff --git a/src/ifcsverchok/nodes/ifc/create_entity.py b/src/ifcsverchok/nodes/ifc/create_entity.py index 4328c57dd8..d9ff9b6586 100644 --- a/src/ifcsverchok/nodes/ifc/create_entity.py +++ b/src/ifcsverchok/nodes/ifc/create_entity.py @@ -16,8 +16,6 @@ from bpy.props import StringProperty, EnumProperty, IntProperty, BoolProperty from sverchok.node_tree import SverchCustomTreeNode from sverchok.data_structure import updateNode, flatten_data, repeat_last_for_length -input_map = {} - class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore): bl_idname = "SvIfcCreateEntity" @@ -48,7 +46,6 @@ class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper self.inputs.new("SvMatrixSocket", "Locations").is_mandatory=False self.inputs.new("SvStringsSocket", "Properties").prop_name = "Properties" self.outputs.new("SvStringsSocket", "Entities") - self.outputs.new("SvStringsSocket", "file") # only for testing self.node_dict[hash(self)] = {} def draw_buttons(self, context, layout): @@ -85,12 +82,12 @@ class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper for i in range(len(self.inputs)): # if self.sv_input_names[i] == "Locations": # input = self.inputs[self.sv_input_names[i]].sv_get(deepcopy=False, default = []) - input = self.inputs[self.sv_input_names[i]].sv_get(deepcopy=False, default =[]) + input = self.inputs[self.sv_input_names[i]].sv_get(deepcopy=True, default =[]) # print("input: ", input) # print("self.node_dict[hash(self)][self.inputs[i].name]: ", 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.node_dict[hash(self)][self.inputs[i].name] = input.copy() if self.refresh_local: edit = True @@ -127,7 +124,6 @@ class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper print("SvIfcStore.id_map: ", SvIfcStore.id_map) self.outputs["Entities"].sv_set(entities) - self.outputs["file"].sv_set([[self.file]]) def create(self, index=None): entities_ids = [] @@ -171,10 +167,10 @@ class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper entity.Description = self.descriptions[i] try: - if self.representations[i] and not self.file.by_type("IFCPRODUCTDEFINITIONSHAPE"): - ifcopenshell.api.run("geometry.assign_representation", self.file, product=entity, representation=self.representations[i]) - elif self.representations[i]: + 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]) except IndexError: pass try: diff --git a/src/ifcsverchok/nodes/ifc/pick_ifc_class.py b/src/ifcsverchok/nodes/ifc/pick_ifc_class.py index 6b4fd5bd4b..44bef18512 100644 --- a/src/ifcsverchok/nodes/ifc/pick_ifc_class.py +++ b/src/ifcsverchok/nodes/ifc/pick_ifc_class.py @@ -24,8 +24,9 @@ from bpy.props import StringProperty, EnumProperty from ifcsverchok.ifcstore import SvIfcStore from sverchok.node_tree import SverchCustomTreeNode from sverchok.data_structure import updateNode +from sverchok.utils.handle_blender_data import keep_enum_reference - +@keep_enum_reference def get_ifc_products(self, context): ifc_products = getattr(self, "ifc_products", []) file = SvIfcStore.get_file() @@ -52,12 +53,12 @@ def get_ifc_products(self, context): ifc_products[2] = ("IfcSpatialStructureElement", "IfcSpatialStructureElement", "") return ifc_products - +@keep_enum_reference def update_ifc_products(self, context): if hasattr(self, "ifc_classes"): self.ifc_classes.clear() - +@keep_enum_reference def get_ifc_classes(self, context): ifc_classes = getattr(self, "ifc_classes", []) if ifc_classes: