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
This commit is contained in:
Dion Moult
2023-07-08 14:39:39 +10:00
parent 8e053de4e5
commit 44ff5b12cd
4 changed files with 94 additions and 22 deletions
@@ -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
@@ -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")
@@ -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):
@@ -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