2022-10-10 09:01:00 +02:00
import bpy
2021-08-17 08:39:38 +10:00
2022-10-10 09:01:00 +02:00
# from helper import SayHello
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
2021-08-17 08:39:38 +10:00
2020-10-01 14:47:42 +10:00
import bpy
import ifcopenshell
2022-10-10 09:01:00 +02:00
2022-10-24 00:08:59 +02:00
from bpy . props import StringProperty , EnumProperty , IntProperty , BoolProperty
2020-10-01 14:47:42 +10:00
from sverchok . node_tree import SverchCustomTreeNode
2022-10-10 09:01:00 +02:00
from sverchok . data_structure import updateNode , flatten_data , repeat_last_for_length
input_map = { }
2020-10-01 14:47:42 +10:00
class SvIfcCreateEntity ( bpy . types . Node , SverchCustomTreeNode , ifcsverchok . helper . SvIfcCore ) :
bl_idname = " SvIfcCreateEntity "
bl_label = " IFC Create Entity "
2022-10-10 09:01:00 +02:00
node_dict = { }
is_scene_dependent = True # if True and is_interactive then the node will be updated upon scene changes
def refresh_node ( self , context ) :
if self . refresh_local :
self . process ( )
self . refresh_local = False
refresh_local : BoolProperty ( name = " Update Node " , description = " Update Node " , update = refresh_node )
Names : StringProperty ( name = " Names " , default = " " , update = updateNode )
Descriptions : StringProperty ( name = " Descriptions " , default = " " , update = updateNode )
IfcClass : StringProperty ( name = " IfcClass " , update = updateNode )
Representations : StringProperty ( name = " Representations " , default = " " , update = updateNode )
2022-10-24 00:08:59 +02:00
# Locations: FloatVectorProperty(name="Locations", default="", update=updateNode)
2022-10-10 09:01:00 +02:00
Properties : StringProperty ( name = " properties " , update = updateNode )
2020-10-01 14:47:42 +10:00
def sv_init ( self , context ) :
2022-10-10 09:01:00 +02:00
self . inputs . new ( " SvStringsSocket " , " Names " ) . prop_name = " Names "
self . inputs . new ( " SvStringsSocket " , " Descriptions " ) . prop_name = " Descriptions "
self . inputs . new ( " SvStringsSocket " , " IfcClass " ) . prop_name = " IfcClass "
self . inputs . new ( " SvStringsSocket " , " Representations " ) . prop_name = " Representations "
2022-10-24 00:08:59 +02:00
self . inputs . new ( " SvMatrixSocket " , " Locations " ) . is_mandatory = False
2022-10-10 09:01:00 +02:00
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 ) ] = { }
2020-10-01 14:47:42 +10:00
2022-10-21 00:11:45 +02:00
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. \n If ' 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 ' )
2020-10-01 14:47:42 +10:00
def process ( self ) :
2022-10-10 09:01:00 +02:00
print ( " # " * 20 , " \n running create_entity3 PROCESS()... \n " , " # " * 20 , )
print ( " # " * 20 , " \n hash(self): " , hash ( self ) , " \n " , " # " * 20 , )
2020-10-01 14:47:42 +10:00
2022-10-21 00:11:45 +02:00
self . names = flatten_data ( self . inputs [ " Names " ] . sv_get ( ) , target_level = 1 )
self . descriptions = flatten_data ( self . inputs [ " Descriptions " ] . sv_get ( ) , target_level = 1 )
2022-10-10 09:01:00 +02:00
self . ifc_class = self . inputs [ " IfcClass " ] . sv_get ( ) [ 0 ] [ 0 ]
2022-10-21 00:11:45 +02:00
self . representations = flatten_data ( self . inputs [ " Representations " ] . sv_get ( ) , target_level = 1 )
2022-10-24 00:08:59 +02:00
self . locations = flatten_data ( self . inputs [ " Locations " ] . sv_get ( default = [ ] ) , target_level = 1 )
2022-10-10 09:01:00 +02:00
self . properties = self . inputs [ " Properties " ] . sv_get ( )
2022-08-25 22:01:35 +02:00
2022-10-10 09:01:00 +02:00
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 )
if not self . inputs [ " IfcClass " ] . sv_get ( ) [ 0 ] [ 0 ] :
raise Exception ( " Insert IfcClass " )
return
edit = False
for i in range ( len ( self . inputs ) ) :
2022-10-24 00:08:59 +02:00
# 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 = [ ] )
2022-10-10 09:01:00 +02:00
# 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
if self . refresh_local :
edit = True
2022-10-21 00:11:45 +02:00
print ( " \n representations before convert: " , self . representations )
self . file = SvIfcStore . get_file ( )
if self . representations [ 0 ] :
self . representations = [ self . file . by_id ( step_id ) for step_id in self . representations ]
self . names = self . repeat_input_unique ( self . names , len ( self . representations ) )
self . descriptions = self . repeat_input_unique ( self . descriptions , len ( self . representations ) )
elif not self . representations [ 0 ] :
self . descriptions = self . repeat_input_unique ( self . descriptions , len ( self . names ) )
2022-10-10 09:01:00 +02:00
# print("REPRESENTATION: ", self.representations)
# print("IfcClass: ",self.ifc_class)
print ( " Names: " , self . names )
print ( " Descriptions: " , self . descriptions )
2022-10-21 00:11:45 +02:00
# print("\nrepresentations after convert: ", self.representations)
2022-10-10 09:01:00 +02:00
if self . node_id not in SvIfcStore . id_map :
2022-10-21 00:11:45 +02:00
entities = self . create ( )
2022-10-10 09:01:00 +02:00
else :
if edit is True :
2022-10-21 00:11:45 +02:00
entities = self . edit ( )
2022-10-10 09:01:00 +02:00
else :
2022-10-21 00:11:45 +02:00
# entities = self.get_existing_element()
entities = SvIfcStore . id_map [ self . node_id ]
2022-10-10 09:01:00 +02:00
2022-10-21 00:11:45 +02:00
print ( " Entities: " , entities )
2022-10-10 09:01:00 +02:00
print ( " SvIfcStore.id_map: " , SvIfcStore . id_map )
2022-10-21 00:11:45 +02:00
self . outputs [ " Entities " ] . sv_set ( entities )
2022-10-10 09:01:00 +02:00
self . outputs [ " file " ] . sv_set ( [ [ self . file ] ] )
2022-10-21 00:11:45 +02:00
def create ( self , index = None ) :
entities_ids = [ ]
iterator = range ( len ( self . names ) )
if index is not None :
iterator = [ index ]
for i in iterator :
2020-10-01 14:47:42 +10:00
try :
2022-10-21 00:11:45 +02:00
entity = ifcopenshell . api . run ( " root.create_entity " , self . file , ifc_class = self . ifc_class , name = self . names [ i ] , description = self . descriptions [ i ] )
2022-10-10 09:01:00 +02:00
try :
2022-10-21 00:11:45 +02:00
ifcopenshell . api . run ( " geometry.assign_representation " , self . file , product = entity , representation = self . representations [ i ] )
2022-10-10 09:01:00 +02:00
except IndexError :
pass
2022-10-24 00:08:59 +02:00
try :
print ( " LOCATION[i]: " , self . locations [ i ] )
ifcopenshell . api . run ( " geometry.edit_object_placement " , self . file , product = entity , matrix = self . locations [ i ] )
except IndexError :
pass
2022-10-21 00:11:45 +02:00
entities_ids . append ( entity . id ( ) )
SvIfcStore . id_map . setdefault ( self . node_id , [ ] ) . append ( entity . id ( ) )
except Exception as e :
raise Exception ( " Something went wrong. Cannot create entity. " , e )
return entities_ids
2022-10-10 09:01:00 +02:00
def edit ( self ) :
2022-10-21 00:11:45 +02:00
entities_ids = [ ]
2022-10-10 09:01:00 +02:00
id_map_copy = SvIfcStore . id_map [ self . node_id ] . copy ( )
2022-10-21 00:11:45 +02:00
for i , _ in enumerate ( self . names ) :
try :
step_id = id_map_copy [ i ]
except IndexError :
id = self . create ( index = i )
entities_ids . append ( id [ 0 ] )
continue
entity = self . file . by_id ( step_id )
entity . Name = self . names [ i ]
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 ] :
entity . Representation = self . representations [ i ]
except IndexError :
2022-10-10 09:01:00 +02:00
pass
2022-10-24 00:08:59 +02:00
try :
print ( " LOCATION[i]: " , self . locations [ i ] )
ifcopenshell . api . run ( " geometry.edit_object_placement " , self . file , product = entity , matrix = self . locations [ i ] )
except IndexError :
pass
2022-10-21 00:11:45 +02:00
if entity . is_a ( ) != self . ifc_class :
2022-10-10 09:01:00 +02:00
SvIfcStore . id_map [ self . node_id ] . remove ( step_id )
2022-10-21 00:11:45 +02:00
entity = ifcopenshell . util . schema . reassign_class ( self . file , entity , self . ifc_class )
SvIfcStore . id_map . setdefault ( self . node_id , [ ] ) . append ( entity . id ( ) )
entities_ids . append ( entity . id ( ) )
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
return input
2022-10-10 09:01:00 +02:00
def get_existing_element ( self ) :
results = [ ]
for i , step_id in enumerate ( SvIfcStore . id_map [ self . node_id ] ) :
2022-10-21 00:11:45 +02:00
entity = self . file . by_id ( step_id )
results . append ( [ entity ] )
2022-10-10 09:01:00 +02:00
return results
def sv_free ( self ) :
try :
del SvIfcStore . id_map [ self . node_id ]
del self . node_dict [ hash ( self ) ]
print ( ' Node was deleted ' )
except KeyError or AttributeError :
pass
2020-10-01 14:47:42 +10:00
2020-11-01 19:24:01 +07:00
2020-10-01 14:47:42 +10:00
def register ( ) :
bpy . utils . register_class ( SvIfcCreateEntity )
2020-11-01 19:24:01 +07:00
2020-10-01 14:47:42 +10:00
def unregister ( ) :
bpy . utils . unregister_class ( SvIfcCreateEntity )