From 52ac1090e9e6781b8df272a93350f57645e15052 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Sat, 8 Jul 2023 14:39:39 +1000 Subject: [PATCH] You can now create, open, and save projects from the file menu, with simple project presets. Also the scene is cleared so no more manual cube / light / camera deletion. Also poll prior to saving. No more import / export menu to confuse users. https://imgur.com/a/EIt2H5b --- .../blenderbim/bim/module/project/__init__.py | 19 ++---- .../blenderbim/bim/module/project/operator.py | 58 +++++++++++++++++++ .../blenderbim/bim/module/project/ui.py | 33 +++++++++-- .../blenderbim/bim/module/root/data.py | 6 +- 4 files changed, 94 insertions(+), 22 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/project/__init__.py b/src/blenderbim/blenderbim/bim/module/project/__init__.py index 417f8ab7dc..bbdf565d10 100644 --- a/src/blenderbim/blenderbim/bim/module/project/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/project/__init__.py @@ -22,6 +22,7 @@ from . import ui, prop, operator classes = ( operator.AppendLibraryElement, operator.AssignLibraryDeclaration, + operator.AppendEntireLibrary, operator.ChangeLibraryElement, operator.CreateProject, operator.DisableEditingHeader, @@ -33,10 +34,10 @@ classes = ( operator.LoadLink, operator.LoadProject, operator.LoadProjectElements, + operator.NewProject, operator.RefreshLibrary, operator.RewindLibrary, operator.SaveLibraryFile, - operator.AppendEntireLibrary, operator.SelectLibraryFile, operator.ToggleFilterCategories, operator.ToggleLinkVisibility, @@ -48,6 +49,7 @@ classes = ( prop.FilterCategory, prop.Link, prop.BIMProjectProperties, + ui.BIM_MT_project, ui.BIM_PT_project, ui.BIM_PT_project_library, ui.BIM_PT_links, @@ -57,22 +59,11 @@ classes = ( ) -def menu_func_export(self, context): - op = self.layout.operator(operator.ExportIFC.bl_idname, text="Industry Foundation Classes (.ifc/.ifczip/.ifcjson)") - op.should_save_as = True - - -def menu_func_import(self, context): - self.layout.operator(operator.ImportIFC.bl_idname, text="Industry Foundation Classes (.ifc/.ifczip/.ifcxml)") - - def register(): bpy.types.Scene.BIMProjectProperties = bpy.props.PointerProperty(type=prop.BIMProjectProperties) - bpy.types.TOPBAR_MT_file_export.append(menu_func_export) - bpy.types.TOPBAR_MT_file_import.append(menu_func_import) + bpy.types.TOPBAR_MT_file.prepend(ui.file_menu) def unregister(): - bpy.types.TOPBAR_MT_file_export.remove(menu_func_export) - bpy.types.TOPBAR_MT_file_import.remove(menu_func_import) + bpy.types.TOPBAR_MT_file.remove(ui.file_menu) del bpy.types.Scene.BIMProjectProperties diff --git a/src/blenderbim/blenderbim/bim/module/project/operator.py b/src/blenderbim/blenderbim/bim/module/project/operator.py index da047e53d7..4282dbdb32 100644 --- a/src/blenderbim/blenderbim/bim/module/project/operator.py +++ b/src/blenderbim/blenderbim/bim/module/project/operator.py @@ -38,6 +38,53 @@ from blenderbim.bim import export_ifc from pathlib import Path +class NewProject(bpy.types.Operator): + bl_idname = "bim.new_project" + bl_label = "New Project" + bl_options = {"REGISTER", "UNDO"} + bl_description = "Start a new IFC project in a fresh session" + preset: bpy.props.StringProperty() + + def execute(self, context): + bpy.ops.wm.read_homefile() + + for obj in bpy.data.objects: + bpy.data.objects.remove(obj) + + if self.preset == "metric_m": + bpy.context.scene.BIMProjectProperties.export_schema = "IFC4" + bpy.context.scene.unit_settings.system = "METRIC" + bpy.context.scene.unit_settings.length_unit = "METERS" + bpy.context.scene.BIMProperties.area_unit = "SQUARE_METRE" + bpy.context.scene.BIMProperties.volume_unit = "CUBIC_METRE" + bpy.context.scene.BIMProjectProperties.template_file = "0" + elif self.preset == "metric_mm": + bpy.context.scene.BIMProjectProperties.export_schema = "IFC4" + bpy.context.scene.unit_settings.system = "METRIC" + bpy.context.scene.unit_settings.length_unit = "MILLIMETERS" + bpy.context.scene.BIMProperties.area_unit = "SQUARE_METRE" + bpy.context.scene.BIMProperties.volume_unit = "CUBIC_METRE" + bpy.context.scene.BIMProjectProperties.template_file = "0" + elif self.preset == "imperial_ft": + bpy.context.scene.BIMProjectProperties.export_schema = "IFC4" + bpy.context.scene.unit_settings.system = "IMPERIAL" + bpy.context.scene.unit_settings.length_unit = "FEET" + bpy.context.scene.BIMProperties.area_unit = "square foot" + bpy.context.scene.BIMProperties.volume_unit = "cubic foot" + bpy.context.scene.BIMProjectProperties.template_file = "0" + elif self.preset == "demo": + bpy.context.scene.BIMProjectProperties.export_schema = "IFC4" + bpy.context.scene.unit_settings.system = "METRIC" + bpy.context.scene.unit_settings.length_unit = "MILLIMETERS" + bpy.context.scene.BIMProperties.area_unit = "SQUARE_METRE" + bpy.context.scene.BIMProperties.volume_unit = "CUBIC_METRE" + bpy.context.scene.BIMProjectProperties.template_file = "IFC4 Demo Library.ifc" + + if self.preset != "wizard": + bpy.ops.bim.create_project() + return {"FINISHED"} + + class CreateProject(bpy.types.Operator): bl_idname = "bim.create_project" bl_label = "Create Project" @@ -528,6 +575,7 @@ class LoadProject(bpy.types.Operator, IFCFileSelector): filter_glob: bpy.props.StringProperty(default="*.ifc;*.ifczip;*.ifcxml;*.ifcsqlite", options={"HIDDEN"}) is_advanced: bpy.props.BoolProperty(name="Enable Advanced Mode", default=False) use_relative_path: bpy.props.BoolProperty(name="Use Relative Path", default=False) + should_start_fresh_session: bpy.props.BoolProperty(name="Should Start Fresh Session", default=True) def execute(self, context): if not self.is_existing_ifc_file(): @@ -540,6 +588,12 @@ class LoadProject(bpy.types.Operator, IFCFileSelector): return {"FINISHED"} def invoke(self, context, event): + if self.should_start_fresh_session: + bpy.ops.wm.read_homefile() + + for obj in bpy.data.objects: + bpy.data.objects.remove(obj) + context.window_manager.fileselect_add(self) return {"RUNNING_MODAL"} @@ -828,6 +882,10 @@ class ExportIFC(bpy.types.Operator): use_relative_path: bpy.props.BoolProperty(name="Use Relative Path", default=False) save_as_invoked: bpy.props.BoolProperty(name="Save As Dialog Was Invoked", default=False, options={"HIDDEN"}) + @classmethod + def poll(cls, context): + return tool.Ifc.get() + def draw(self, context): layout = self.layout layout.prop(self, "json_version") diff --git a/src/blenderbim/blenderbim/bim/module/project/ui.py b/src/blenderbim/blenderbim/bim/module/project/ui.py index a57c097e25..c962fcf8df 100644 --- a/src/blenderbim/blenderbim/bim/module/project/ui.py +++ b/src/blenderbim/blenderbim/bim/module/project/ui.py @@ -18,11 +18,36 @@ import os from blenderbim.bim.helper import prop_with_search -from bpy.types import Panel, UIList +from bpy.types import Panel, Menu, UIList from blenderbim.bim.ifc import IfcStore from blenderbim.bim.module.project.data import ProjectData +class BIM_MT_project(Menu): + bl_idname = "BIM_MT_project" + bl_label = "New IFC Project" + + def draw(self, context): + layout = self.layout + layout.operator("bim.new_project", text="New Metric (m) Project").preset = "metric_m" + layout.operator("bim.new_project", text="New Metric (mm) Project").preset = "metric_mm" + layout.operator("bim.new_project", text="New Imperial (ft) Project").preset = "imperial_ft" + layout.operator("bim.new_project", text="New Demo Project").preset = "demo" + layout.operator("bim.new_project", text="New Project Wizard").preset = "wizard" + + +def file_menu(self, context): + self.layout.menu("BIM_MT_project", icon="COLLECTION_NEW") + op = self.layout.operator("bim.load_project", text="Open IFC Project", icon="FILEBROWSER") + op.should_start_fresh_session = True + self.layout.separator() + op = self.layout.operator("export_ifc.bim", icon="FILE_TICK", text="Save IFC Project") + op.should_save_as = False + op = self.layout.operator("export_ifc.bim", text="Save IFC Project As...") + op.should_save_as = True + self.layout.separator() + + class BIM_PT_project(Panel): bl_label = "IFC Project" bl_idname = "BIM_PT_project" @@ -160,10 +185,8 @@ class BIM_PT_project(Panel): row.operator("bim.select_ifc_file", icon="FILE_FOLDER", text="") row = self.layout.row(align=True) - op = row.operator("export_ifc.bim", icon="EXPORT", text="Save Project") + op = row.operator("export_ifc.bim", icon="FILE_TICK", text="Save Project") op.should_save_as = False - op = row.operator("export_ifc.bim", icon="FILE_TICK", text="Save As") - op.should_save_as = True row.operator("bim.unload_project", text="", icon="CANCEL") def draw_create_project_ui(self, context): @@ -182,7 +205,7 @@ class BIM_PT_project(Panel): row = self.layout.row(align=True) row.operator("bim.create_project") - row.operator("bim.load_project") + row.operator("bim.load_project").should_start_fresh_session = False class BIM_PT_project_library(Panel): diff --git a/src/blenderbim/blenderbim/bim/module/root/data.py b/src/blenderbim/blenderbim/bim/module/root/data.py index 4d4d9c4a8e..d77664249b 100644 --- a/src/blenderbim/blenderbim/bim/module/root/data.py +++ b/src/blenderbim/blenderbim/bim/module/root/data.py @@ -159,7 +159,7 @@ class IfcClassData: @classmethod def name(cls): - element = tool.Ifc.get_entity(bpy.context.active_object) + element = tool.Ifc.get_entity(bpy.context.view_layer.objects.active) if not element: return name = element.is_a() @@ -170,13 +170,13 @@ class IfcClassData: @classmethod def ifc_class(cls): - element = tool.Ifc.get_entity(bpy.context.active_object) + element = tool.Ifc.get_entity(bpy.context.view_layer.objects.active) if element: return element.is_a() @classmethod def can_reassign_class(cls): - element = tool.Ifc.get_entity(bpy.context.active_object) + element = tool.Ifc.get_entity(bpy.context.view_layer.objects.active) if element: if element.is_a("IfcOpeningElement") or element.is_a("IfcOpeningStandardCase"): return False