From e9b791adaa81f124810801ecdf7994f86991f150 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Thu, 13 Aug 2020 20:17:51 +1000 Subject: [PATCH] Improve drawings management UI from a single dropdown to a proper list --- .../blenderbim/bim/__init__.py | 8 +- .../blenderbim/bim/operator.py | 74 +++++---- src/ifcblenderexport/blenderbim/bim/prop.py | 31 ++-- src/ifcblenderexport/blenderbim/bim/ui.py | 154 ++++++++++-------- 4 files changed, 148 insertions(+), 119 deletions(-) diff --git a/src/ifcblenderexport/blenderbim/bim/__init__.py b/src/ifcblenderexport/blenderbim/bim/__init__.py index 57ecf26d5f..49ede60bd5 100644 --- a/src/ifcblenderexport/blenderbim/bim/__init__.py +++ b/src/ifcblenderexport/blenderbim/bim/__init__.py @@ -119,8 +119,6 @@ if bpy is not None: operator.OpenCompiledSheet, operator.AddViewToSheet, operator.CreateSheets, - operator.GenerateDigitalTwin, - operator.CreateView, operator.OpenView, operator.ActivateView, operator.ExecuteIfcDiff, @@ -178,6 +176,8 @@ if bpy is not None: operator.CalculateObjectVolumes, operator.AddOpening, operator.SetOverrideColour, + operator.AddDrawing, + operator.RemoveDrawing, operator.AddDrawingStyle, operator.RemoveDrawingStyle, operator.SaveDrawingStyle, @@ -198,6 +198,7 @@ if bpy is not None: prop.ClashSource, prop.ClashSet, prop.Constraint, + prop.Drawing, prop.DrawingStyle, prop.BcfTopic, prop.BcfTopicLabel, @@ -224,7 +225,8 @@ if bpy is not None: prop.BIMCameraProperties, prop.BIMTextProperties, ui.BIM_PT_section_plane, - ui.BIM_PT_documentation, + ui.BIM_PT_drawings, + ui.BIM_PT_sheets, ui.BIM_PT_bim, ui.BIM_PT_psets, ui.BIM_PT_classifications, diff --git a/src/ifcblenderexport/blenderbim/bim/operator.py b/src/ifcblenderexport/blenderbim/bim/operator.py index 1576e23bc8..5ad38a53ee 100644 --- a/src/ifcblenderexport/blenderbim/bim/operator.py +++ b/src/ifcblenderexport/blenderbim/bim/operator.py @@ -2021,27 +2021,6 @@ class RemoveSubcontext(bpy.types.Operator): return {'FINISHED'} -class CreateView(bpy.types.Operator): - bl_idname = 'bim.create_view' - bl_label = 'Create View' - - def execute(self, context): - if not bpy.data.collections.get('Views'): - bpy.context.scene.collection.children.link(bpy.data.collections.new('Views')) - views_collection = bpy.data.collections.get('Views') - view_collection = bpy.data.collections.new('IfcGroup/' + bpy.context.scene.DocProperties.view_name) - views_collection.children.link(view_collection) - camera = bpy.data.objects.new('IfcGroup/' + bpy.context.scene.DocProperties.view_name, - bpy.data.cameras.new(bpy.context.scene.DocProperties.view_name)) - camera.data.type = 'ORTHO' - camera.data.BIMCameraProperties.diagram_scale = '1:100' - bpy.context.scene.camera = camera - view_collection.objects.link(camera) - area = next(area for area in bpy.context.screen.areas if area.type == 'VIEW_3D') - area.spaces[0].region_3d.view_perspective = 'CAMERA' - return {'FINISHED'} - - class OpenView(bpy.types.Operator): bl_idname = 'bim.open_view' bl_label = 'Open View' @@ -2243,21 +2222,12 @@ class CreateSheets(bpy.types.Operator): return {'FINISHED'} -class GenerateDigitalTwin(bpy.types.Operator): - bl_idname = 'bim.generate_digital_twin' - bl_label = 'Generate Digital Twin' - - def execute(self, context): - # Does absolutely nothing at all :D - return {'FINISHED'} - - class ActivateView(bpy.types.Operator): bl_idname = 'bim.activate_view' bl_label = 'Activate View' def execute(self, context): - camera = bpy.data.objects.get('IfcGroup/' + bpy.context.scene.DocProperties.available_views) + camera = bpy.context.scene.DocProperties.drawings[bpy.context.scene.DocProperties.active_drawing_index].camera if not camera: return {'FINISHED'} bpy.context.scene.camera = camera @@ -3487,3 +3457,45 @@ class ActivateDrawingStyle(bpy.types.Operator): bpy.context.scene.display.shading.single_color = style['bpy.context.scene.display.shading.single_color'] bpy.context.scene.view_settings.use_curve_mapping = style['bpy.context.scene.view_settings.use_curve_mapping'] return {'FINISHED'} + + +class AddDrawing(bpy.types.Operator): + bl_idname = 'bim.add_drawing' + bl_label = 'Add Drawing' + + def execute(self, context): + new = bpy.context.scene.DocProperties.drawings.add() + new.name = 'DRAWING {}'.format(len(bpy.context.scene.DocProperties.drawings)) + if not bpy.data.collections.get('Views'): + bpy.context.scene.collection.children.link(bpy.data.collections.new('Views')) + views_collection = bpy.data.collections.get('Views') + view_collection = bpy.data.collections.new('IfcGroup/' + new.name) + views_collection.children.link(view_collection) + camera = bpy.data.objects.new('IfcGroup/' + new.name, + bpy.data.cameras.new('IfcGroup/' + new.name)) + camera.location = (0, 0, 1.7) # The view shall be 1.7m above the origin + camera.data.type = 'ORTHO' + camera.data.ortho_scale = 50 # The default of 6m is too small + camera.data.BIMCameraProperties.diagram_scale = '1:100' + bpy.context.scene.camera = camera + view_collection.objects.link(camera) + area = next(area for area in bpy.context.screen.areas if area.type == 'VIEW_3D') + area.spaces[0].region_3d.view_perspective = 'CAMERA' + new.camera = camera + return {'FINISHED'} + + +class RemoveDrawing(bpy.types.Operator): + bl_idname = 'bim.remove_drawing' + bl_label = 'Remove Drawing' + index: bpy.props.IntProperty() + + def execute(self, context): + props = bpy.context.scene.DocProperties + camera = props.drawings[self.index].camera + collection = camera.users_collection[0] + for obj in collection.objects: + bpy.data.objects.remove(obj) + bpy.data.collections.remove(collection, do_unlink=True) + props.drawings.remove(self.index) + return {'FINISHED'} diff --git a/src/ifcblenderexport/blenderbim/bim/prop.py b/src/ifcblenderexport/blenderbim/bim/prop.py index 20c980b783..023818895c 100644 --- a/src/ifcblenderexport/blenderbim/bim/prop.py +++ b/src/ifcblenderexport/blenderbim/bim/prop.py @@ -48,7 +48,6 @@ subcontexts_enum = [] target_views_enum = [] persons_enum = [] organisations_enum = [] -views_enum = [] sheets_enum = [] bcfviewpoints_enum = [] @@ -149,6 +148,14 @@ def getDiagramScales(self, context): return diagram_scales_enum +def updateDrawingName(self, context): + if self.camera.name == self.name: + return + self.camera.name = 'IfcGroup/{}'.format(self.name) + self.camera.users_collection[0].name = self.camera.name + self.name = self.camera.name.split('/')[1] + + def getBoundaryConditionClasses(self, context): return [(c, c, '') for c in ['IfcBoundaryEdgeCondition', 'IfcBoundaryFaceCondition', @@ -393,19 +400,6 @@ def getTargetViews(self, context): return target_views_enum -def getViews(self, context): - global views_enum - views_enum.clear() - views_collection = bpy.data.collections.get('Views') - if not views_collection: - return views_enum - for collection in views_collection.children: - for obj in collection.objects: - if obj.type == 'CAMERA': - views_enum.append((obj.name.split('/')[1], obj.name.split('/')[1], '')) - return views_enum - - def refreshSheets(self, context): global sheets_enum sheets_enum.clear() @@ -441,6 +435,11 @@ class Subcontext(PropertyGroup): target_view: StringProperty(name='Target View') +class Drawing(PropertyGroup): + name: StringProperty(name='Name', update=updateDrawingName) + camera: PointerProperty(name='Camera', type=bpy.types.Object) + + class DrawingStyle(PropertyGroup): name: StringProperty(name='Name') raster_style: StringProperty(name='Raster Style') @@ -454,8 +453,8 @@ class DocProperties(PropertyGroup): should_recut_selected: BoolProperty(name="Should Recut Selected Only", default=False) should_render: BoolProperty(name="Should Render", default=True) should_extract: BoolProperty(name="Should Extract", default=True) - view_name: StringProperty(name="View Name") - available_views: EnumProperty(items=getViews, name="Available Views") + drawings: CollectionProperty(name='Drawings', type=Drawing) + active_drawing_index: IntProperty(name='Active Drawing Index') sheet_name: StringProperty(name="Sheet Name", update=refreshSheets) available_sheets: EnumProperty(items=getSheets, name="Available Sheets") ifc_files: CollectionProperty(name='IFCs', type=StrProperty) diff --git a/src/ifcblenderexport/blenderbim/bim/ui.py b/src/ifcblenderexport/blenderbim/bim/ui.py index 46230f6efa..cc3bb29448 100644 --- a/src/ifcblenderexport/blenderbim/bim/ui.py +++ b/src/ifcblenderexport/blenderbim/bim/ui.py @@ -716,9 +716,44 @@ class BIM_PT_gis(Panel): row.operator('bim.convert_local_to_global') -class BIM_PT_documentation(Panel): - bl_label = "Drawings and Sheets" - bl_idname = "BIM_PT_documentation" +class BIM_PT_drawings(Panel): + bl_label = "Drawings" + bl_idname = "BIM_PT_drawings" + bl_space_type = 'PROPERTIES' + bl_region_type = 'WINDOW' + bl_context = 'output' + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + props = bpy.context.scene.DocProperties + + if props.drawings: + row = layout.row(align=True) + row.operator('bim.add_drawing') + op = row.operator('bim.open_view', icon='URL', text='') + op.view = props.drawings[props.active_drawing_index].name + row.operator('bim.activate_view', icon='SCENE', text='') + row.operator('bim.remove_drawing', icon='X', text='').index = props.active_drawing_index + + layout.template_list('BIM_UL_generic', '', props, 'drawings', props, 'active_drawing_index') + else: + row = layout.row(align=True) + row.operator('bim.add_drawing') + + row = layout.row() + row.operator('bim.add_ifc_file') + + for index, ifc_file in enumerate(props.ifc_files): + row = layout.row(align=True) + row.prop(ifc_file, 'name', text='IFC #{}'.format(index + 1)) + row.operator('bim.select_doc_ifc_file', icon='FILE_FOLDER', text='') + row.operator('bim.remove_ifc_file', icon='X', text='').index = index + + +class BIM_PT_sheets(Panel): + bl_label = "Sheets" + bl_idname = "BIM_PT_sheets" bl_space_type = 'PROPERTIES' bl_region_type = 'WINDOW' bl_context = 'output' @@ -728,20 +763,10 @@ class BIM_PT_documentation(Panel): layout.use_property_split = True props = bpy.context.scene.DocProperties - row = layout.row() - row.prop(props, 'view_name', text='Drawing Name') - row.operator('bim.create_view', icon='ADD', text='') - row = layout.row() row.prop(props, 'sheet_name') row.operator('bim.create_sheet', icon='ADD', text='') - row = layout.row() - row.prop(props, 'available_views', text='Available Drawings') - op = row.operator('bim.open_view', icon='URL', text='') - op.view = bpy.context.scene.DocProperties.available_views - row.operator('bim.activate_view', icon='SCENE', text='') - row = layout.row() row.prop(props, 'available_sheets') row.operator('bim.open_sheet', icon='URL', text='') @@ -751,14 +776,53 @@ class BIM_PT_documentation(Panel): row.operator('bim.add_view_to_sheet') row.operator('bim.create_sheets') - row = layout.row() - row.operator('bim.add_ifc_file') - for index, ifc_file in enumerate(props.ifc_files): - row = layout.row(align=True) - row.prop(ifc_file, 'name', text='IFC #{}'.format(index + 1)) - row.operator('bim.select_doc_ifc_file', icon='FILE_FOLDER', text='') - row.operator('bim.remove_ifc_file', icon='X', text='').index = index +class BIM_PT_section_plane(Panel): + bl_label = "Temporary Section Cutaways" + bl_idname = "BIM_PT_section_plane" + bl_space_type = 'PROPERTIES' + bl_region_type = 'WINDOW' + bl_context = 'output' + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + props = bpy.context.scene.BIMProperties + + row = layout.row() + row.prop(props, 'should_section_selected_objects') + + row = layout.row() + row.prop(props, 'section_plane_colour') + + row = layout.row(align=True) + row.operator('bim.add_section_plane') + row.operator('bim.remove_section_plane') + + +class BIM_PT_camera(Panel): + bl_label = "Drawing Generation" + bl_idname = "BIM_PT_camera" + bl_space_type = 'PROPERTIES' + bl_region_type = 'WINDOW' + bl_context = 'data' + + @classmethod + def poll(cls, context): + engine = context.engine + return context.camera and \ + hasattr(context.active_object.data, "BIMCameraProperties") + + def draw(self, context): + layout = self.layout + + if '/' not in context.active_object.name: + layout.label(text="This is not a BIM camera.") + return + + layout.use_property_split = True + dprops = bpy.context.scene.DocProperties + props = context.active_object.data.BIMCameraProperties layout.label(text="Annotation:") row = layout.row(align=True) @@ -792,55 +856,7 @@ class BIM_PT_documentation(Panel): op.obj_name = 'Section Level' op.data_type = 'curve' - row = layout.row() - row.operator('bim.generate_digital_twin') - - -class BIM_PT_section_plane(Panel): - bl_label = "Temporary Section Cutaways" - bl_idname = "BIM_PT_section_plane" - bl_space_type = 'PROPERTIES' - bl_region_type = 'WINDOW' - bl_context = 'output' - - def draw(self, context): - layout = self.layout - layout.use_property_split = True - props = bpy.context.scene.BIMProperties - - row = layout.row() - row.prop(props, 'should_section_selected_objects') - - row = layout.row() - row.prop(props, 'section_plane_colour') - - row = layout.row(align=True) - row.operator('bim.add_section_plane') - row.operator('bim.remove_section_plane') - -class BIM_PT_camera(Panel): - bl_label = "Drawing Generation" - bl_idname = "BIM_PT_camera" - bl_space_type = 'PROPERTIES' - bl_region_type = 'WINDOW' - bl_context = 'data' - - @classmethod - def poll(cls, context): - engine = context.engine - return context.camera and \ - hasattr(context.active_object.data, "BIMCameraProperties") - - def draw(self, context): - layout = self.layout - - if '/' not in context.active_object.name: - layout.label(text="This is not a BIM camera.") - return - - layout.use_property_split = True - dprops = bpy.context.scene.DocProperties - props = context.active_object.data.BIMCameraProperties + layout.label(text="Generation Options:") row = layout.row() row.prop(dprops, 'should_recut')