New UI to create, manage, and run clash sets within BlenderBIM Add-on

This commit is contained in:
Dion Moult
2020-05-19 15:08:54 +10:00
parent e45f5d867b
commit bc56196f27
5 changed files with 175 additions and 20 deletions
@@ -96,6 +96,11 @@ if bpy is not None:
operator.OpenView,
operator.ActivateView,
operator.ExecuteIfcDiff,
operator.AddClashSet,
operator.RemoveClashSet,
operator.AddClashSource,
operator.RemoveClashSource,
operator.SelectClashSource,
operator.ExecuteIfcClash,
operator.AssignContext,
operator.SwitchContext,
@@ -138,6 +143,8 @@ if bpy is not None:
prop.PropertyTemplate,
prop.DocumentInformation,
prop.DocumentReference,
prop.ClashSource,
prop.ClashSet,
prop.BcfTopic,
prop.BcfTopicLabel,
prop.BcfTopicFile,
@@ -186,6 +193,7 @@ if bpy is not None:
ui.BIM_PT_documents,
ui.BIM_PT_camera,
ui.BIM_PT_text,
ui.BIM_UL_clash_sets,
ui.BIM_UL_document_information,
ui.BIM_UL_document_references,
ui.BIM_UL_topics,
@@ -1153,6 +1153,67 @@ class ExecuteIfcDiff(bpy.types.Operator):
return {'FINISHED'}
class AddClashSet(bpy.types.Operator):
bl_idname = 'bim.add_clash_set'
bl_label = 'Add Clash Set'
def execute(self, context):
new = bpy.context.scene.BIMProperties.clash_sets.add()
new.name = 'New Clash Set'
new.tolerance = 0.01
return {'FINISHED'}
class RemoveClashSet(bpy.types.Operator):
bl_idname = 'bim.remove_clash_set'
bl_label = 'Remove Clash Set'
index: bpy.props.IntProperty()
def execute(self, context):
bpy.context.scene.BIMProperties.clash_sets.remove(self.index)
return {'FINISHED'}
class AddClashSource(bpy.types.Operator):
bl_idname = 'bim.add_clash_source'
bl_label = 'Add Clash Source'
group: bpy.props.StringProperty()
def execute(self, context):
clash_set = bpy.context.scene.BIMProperties.clash_sets[bpy.context.scene.BIMProperties.active_clash_set_index]
source = getattr(clash_set, self.group).add()
return {'FINISHED'}
class RemoveClashSource(bpy.types.Operator):
bl_idname = 'bim.remove_clash_source'
bl_label = 'Remove Clash Source'
index: bpy.props.IntProperty()
group: bpy.props.StringProperty()
def execute(self, context):
clash_set = bpy.context.scene.BIMProperties.clash_sets[bpy.context.scene.BIMProperties.active_clash_set_index]
getattr(clash_set, self.group).remove(self.index)
return {'FINISHED'}
class SelectClashSource(bpy.types.Operator):
bl_idname = "bim.select_clash_source"
bl_label = "Select Clash Source"
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
index: bpy.props.IntProperty()
group: bpy.props.StringProperty()
def execute(self, context):
clash_set = bpy.context.scene.BIMProperties.clash_sets[bpy.context.scene.BIMProperties.active_clash_set_index]
getattr(clash_set, self.group)[self.index].name = self.filepath
return {'FINISHED'}
def invoke(self, context, event):
context.window_manager.fileselect_add(self)
return {'RUNNING_MODAL'}
class ExecuteIfcClash(bpy.types.Operator):
bl_idname = 'bim.execute_ifc_clash'
bl_label = 'Execute IFC Clash'
@@ -1172,8 +1233,24 @@ class ExecuteIfcClash(bpy.types.Operator):
settings.output = self.filepath
settings.logger = logging.getLogger('Clash')
settings.logger.setLevel(logging.DEBUG)
ifc_clasher = ifcclash.IfcClasher(
bpy.context.scene.BIMProperties.ifc_clash_a, bpy.context.scene.BIMProperties.ifc_clash_b, settings)
ifc_clasher = ifcclash.IfcClasher(settings)
ifc_clasher.clash_sets = []
for clash_set in bpy.context.scene.BIMProperties.clash_sets:
self.a = []
self.b = []
for ab in ['a', 'b']:
for data in getattr(clash_set, ab):
clash_source = { 'file': data.name }
if data.selector:
clash_source['selector'] = data.selector
clash_source['mode'] = data.mode
getattr(self, ab).append(clash_source)
ifc_clasher.clash_sets.append({
'name': clash_set.name,
'tolerance': clash_set.tolerance,
'a': self.a,
'b': self.b
})
ifc_clasher.clash()
ifc_clasher.export()
return {'FINISHED'}
+18 -2
View File
@@ -467,6 +467,22 @@ class DocumentReference(PropertyGroup):
referenced_document: StringProperty(name="Referenced Document")
class ClashSource(PropertyGroup):
name: StringProperty(name='File')
selector: StringProperty(name='Selector')
mode: EnumProperty(items=[
('i', 'Include', 'Only the selected objects are included for clashing'),
('e', 'Exclude', 'All objects except the selected objects are included for clashing')
], name='Mode')
class ClashSet(PropertyGroup):
name: StringProperty(name='Name')
tolerance: FloatProperty(name='Tolerance')
a: CollectionProperty(name='Group A', type=ClashSource)
b: CollectionProperty(name='Group B', type=ClashSource)
class BcfTopic(PropertyGroup):
name: StringProperty(name='Name')
@@ -929,8 +945,8 @@ class BIMProperties(PropertyGroup):
active_document_information_index: IntProperty(name='Active Document Information Index')
document_references: CollectionProperty(name='Document References', type=DocumentReference)
active_document_reference_index: IntProperty(name='Active Document Reference Index')
ifc_clash_a: StringProperty(name="IFC Clash A")
ifc_clash_b: StringProperty(name="IFC Clash B")
clash_sets: CollectionProperty(name='Clash Sets', type=ClashSet)
active_clash_set_index: IntProperty(name='Active Clash Set Index')
class BCFProperties(PropertyGroup):
+65 -8
View File
@@ -1225,6 +1225,15 @@ class BIM_UL_topics(bpy.types.UIList):
layout.label(text="", translate=False)
class BIM_UL_clash_sets(bpy.types.UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
ob = data
if item:
layout.prop(item, 'name', text='', emboss=False)
else:
layout.label(text="", translate=False)
class BIM_UL_document_information(bpy.types.UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
ob = data
@@ -1284,16 +1293,64 @@ class BIM_PT_ifcclash(Panel):
def draw(self, context):
layout = self.layout
layout.use_property_split = True
scene = context.scene
props = scene.BIMProperties
row = layout.row(align=True)
row.prop(props, 'ifc_clash_a')
row = layout.row(align=True)
row.prop(props, 'ifc_clash_b')
row = layout.row()
row.operator('bim.execute_ifc_clash')
row.operator('bim.add_clash_set')
if not props.clash_sets:
return
layout.template_list('BIM_UL_clash_sets', '', props, 'clash_sets', props, 'active_clash_set_index')
if props.active_clash_set_index < len(props.clash_sets):
clash_set = props.clash_sets[props.active_clash_set_index]
row = layout.row(align=True)
row.prop(clash_set, 'name')
row.operator('bim.remove_clash_set', icon='X', text='').index = props.active_clash_set_index
row = layout.row(align=True)
row.prop(clash_set, 'tolerance')
layout.label(text="Group A:")
row = layout.row()
row.operator('bim.add_clash_source').group = 'a'
for index, source in enumerate(clash_set.a):
row = layout.row(align=True)
row.prop(source, 'name', text='')
op = row.operator('bim.select_clash_source', icon='FILE_FOLDER', text='')
op.index = index
op.group = 'a'
op = row.operator('bim.remove_clash_source', icon='X', text='')
op.index = index
op.group = 'a'
row = layout.row(align=True)
row.prop(source, 'mode', text='')
row.prop(source, 'selector', text='')
layout.label(text="Group B:")
row = layout.row()
row.operator('bim.add_clash_source').group = 'b'
for index, source in enumerate(clash_set.b):
row = layout.row(align=True)
row.prop(source, 'name', text='')
op = row.operator('bim.select_clash_source', icon='FILE_FOLDER', text='')
op.index = index
op.group = 'b'
op = row.operator('bim.remove_clash_source', icon='X', text='')
op.index = index
op.group = 'b'
row = layout.row(align=True)
row.prop(source, 'mode', text='')
row.prop(source, 'selector', text='')
row = layout.row()
row.operator('bim.execute_ifc_clash')
+5 -8
View File
@@ -83,14 +83,11 @@ class IfcClasher:
for result in results:
del result['a_cm']
del result['b_cm']
for data in result['a']:
del data['ifc']
del data['meshes']
for data in result['b']:
del data['ifc']
del data['meshes']
print(results)
for ab in ['a', 'b']:
for data in result[ab]:
for key in ['ifc', 'meshes']:
if key in data:
del data[key]
with open(self.settings.output, 'w', encoding='utf-8') as clashes_file:
json.dump(results, clashes_file, indent=4)