Fix #1786. Swap out sub-operators with refactored core calls.

This commit is contained in:
Dion Moult
2021-10-13 10:49:28 +11:00
parent 13725411c9
commit dba6a8d0b4
8 changed files with 117 additions and 101 deletions
+1 -13
View File
@@ -21,6 +21,7 @@ import importlib
from . import handler, ui, prop, operator
modules = {
"lendlease": None,
"project": None,
"search": None,
"bcf": None,
@@ -74,8 +75,6 @@ classes = [
operator.SelectDataDir,
operator.SelectSchemaDir,
operator.SelectIfcFile,
operator.ExportIFC,
operator.ImportIFC,
operator.OpenUpstream,
operator.AddSectionPlane,
operator.RemoveSectionPlane,
@@ -105,13 +104,6 @@ for mod in modules.values():
classes.extend(mod.classes)
def menu_func_export(self, context):
self.layout.operator(operator.ExportIFC.bl_idname, text="Industry Foundation Classes (.ifc/.ifczip/.ifcjson)")
def menu_func_import(self, context):
self.layout.operator(operator.ImportIFC.bl_idname, text="Industry Foundation Classes (.ifc/.ifczip/.ifcxml)")
def on_register(scene):
handler.setDefaultProperties(scene)
@@ -129,8 +121,6 @@ def register():
bpy.app.handlers.load_post.append(handler.setDefaultProperties)
bpy.app.handlers.load_post.append(handler.loadIfcStore)
bpy.app.handlers.save_pre.append(handler.ensureIfcExported)
bpy.types.TOPBAR_MT_file_export.append(menu_func_export)
bpy.types.TOPBAR_MT_file_import.append(menu_func_import)
bpy.types.Scene.BIMProperties = bpy.props.PointerProperty(type=prop.BIMProperties)
bpy.types.Object.BIMObjectProperties = bpy.props.PointerProperty(type=prop.BIMObjectProperties)
bpy.types.Material.BIMObjectProperties = bpy.props.PointerProperty(type=prop.BIMObjectProperties)
@@ -151,8 +141,6 @@ def unregister():
bpy.app.handlers.load_post.remove(handler.setDefaultProperties)
bpy.app.handlers.load_post.remove(handler.loadIfcStore)
bpy.app.handlers.save_pre.remove(handler.ensureIfcExported)
bpy.types.TOPBAR_MT_file_export.remove(menu_func_export)
bpy.types.TOPBAR_MT_file_import.remove(menu_func_import)
del bpy.types.Scene.BIMProperties
del bpy.types.Object.BIMObjectProperties
del bpy.types.Material.BIMObjectProperties
+9 -3
View File
@@ -28,6 +28,8 @@ import ifcopenshell
import ifcopenshell.api
import ifcopenshell.util.placement
import blenderbim.tool as tool
import blenderbim.core.aggregate
import blenderbim.core.spatial
import blenderbim.core.style
from blenderbim.bim.ifc import IfcStore
@@ -135,7 +137,7 @@ class IfcExporter:
float(props.blender_x_axis_ordinate),
)
if not np.allclose(ifc_matrix, blender_matrix, atol=0.0001):
bpy.ops.bim.edit_object_placement(obj=obj.name)
blenderbim.core.geometry.edit_object_placement(tool.Ifc, tool.Surveyor, obj=obj)
def sync_object_container(self, guid, obj):
element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)
@@ -166,9 +168,13 @@ class IfcExporter:
if parent.is_a("IfcSpatialStructureElement") and not element.is_a("IfcSpatialStructureElement"):
if parent != ifcopenshell.util.element.get_container(element):
bpy.ops.bim.assign_container(relating_structure=parent.id(), related_element=obj.name)
blenderbim.core.spatial.assign_container(
tool.Ifc, tool.Collector, tool.Container, structure_obj=parent_obj, element_obj=obj
)
elif parent != ifcopenshell.util.element.get_aggregate(element):
bpy.ops.bim.assign_object(relating_object=parent_obj.name, related_object=obj.name)
blenderbim.core.aggregate.assign_object(
tool.Ifc, tool.Aggregate, tool.Collector, relating_obj=parent_obj, related_obj=obj
)
def should_delete(self, obj):
try:
@@ -305,7 +305,7 @@ class UpdateRepresentation(bpy.types.Operator):
ifcopenshell.api.run("grid.create_axis_curve", self.file, **{"axis_curve": obj, "grid_axis": product})
return
bpy.ops.bim.edit_object_placement(obj=obj.name)
core.edit_object_placement(tool.Ifc, tool.Surveyor, obj=obj)
old_representation = self.file.by_id(obj.data.BIMMeshProperties.ifc_definition_id)
context_of_items = old_representation.ContextOfItems
@@ -335,7 +335,7 @@ class UpdateRepresentation(bpy.types.Operator):
new_representation = ifcopenshell.api.run("geometry.add_representation", self.file, **representation_data)
[
bpy.ops.bim.add_style(material=s.material.name)
blenderbim.core.style.add_style(tool.Ifc, tool.Style, obj=s.material)
for s in obj.material_slots
if s.material and not s.material.BIMMaterialProperties.ifc_style_id
]
@@ -39,6 +39,8 @@ classes = (
operator.EnableEditingHeader,
operator.DisableEditingHeader,
operator.EditHeader,
operator.ExportIFC,
operator.ImportIFC,
prop.LibraryElement,
prop.FilterCategory,
prop.Link,
@@ -51,10 +53,21 @@ classes = (
ui.BIM_UL_links,
)
def menu_func_export(self, context):
self.layout.operator(operator.ExportIFC.bl_idname, text="Industry Foundation Classes (.ifc/.ifczip/.ifcjson)")
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)
def unregister():
bpy.types.TOPBAR_MT_file_export.remove(menu_func_export)
bpy.types.TOPBAR_MT_file_import.remove(menu_func_import)
del bpy.types.Scene.BIMProjectProperties
@@ -31,6 +31,7 @@ import blenderbim.core.context
import blenderbim.core.owner
from blenderbim.bim.ifc import IfcStore
from blenderbim.bim import import_ifc
from blenderbim.bim import export_ifc
class CreateProject(bpy.types.Operator):
@@ -729,3 +730,79 @@ class LoadLink(bpy.types.Operator):
link = context.scene.BIMProjectProperties.links.get(self.filepath)
link.is_loaded = True
return {"FINISHED"}
class ExportIFC(bpy.types.Operator):
bl_idname = "export_ifc.bim"
bl_label = "Export IFC"
bl_options = {"REGISTER", "UNDO"}
filename_ext = ".ifc"
filter_glob: bpy.props.StringProperty(default="*.ifc;*.ifczip;*.ifcxml;*.ifcjson", options={"HIDDEN"})
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
json_version: bpy.props.EnumProperty(items=[("4", "4", ""), ("5a", "5a", "")], name="IFC JSON Version")
json_compact: bpy.props.BoolProperty(name="Export Compact IFCJSON", default=False)
def invoke(self, context, event):
if not IfcStore.get_file():
self.report({"ERROR"}, "No IFC project is available for export - create or import a project first.")
return {"FINISHED"}
if context.scene.BIMProperties.ifc_file:
self.filepath = context.scene.BIMProperties.ifc_file
return self.execute(context)
if not self.filepath:
self.filepath = bpy.path.ensure_ext(bpy.data.filepath, ".ifc")
WindowManager = context.window_manager
WindowManager.fileselect_add(self)
return {"RUNNING_MODAL"}
def execute(self, context):
return IfcStore.execute_ifc_operator(self, context)
def _execute(self, context):
start = time.time()
logger = logging.getLogger("ExportIFC")
path_log = os.path.join(context.scene.BIMProperties.data_dir, "process.log")
if not os.access(context.scene.BIMProperties.data_dir, os.W_OK):
path_log = os.path.join(tempfile.mkdtemp(), "process.log")
logging.basicConfig(
filename=path_log,
filemode="a",
level=logging.DEBUG,
)
extension = self.filepath.split(".")[-1]
if extension == "ifczip":
output_file = bpy.path.ensure_ext(self.filepath, ".ifczip")
elif extension == "ifcjson":
output_file = bpy.path.ensure_ext(self.filepath, ".ifcjson")
else:
output_file = bpy.path.ensure_ext(self.filepath, ".ifc")
settings = export_ifc.IfcExportSettings.factory(context, output_file, logger)
settings.json_version = self.json_version
settings.json_compact = self.json_compact
ifc_exporter = export_ifc.IfcExporter(settings)
settings.logger.info("Starting export")
ifc_exporter.export()
settings.logger.info("Export finished in {:.2f} seconds".format(time.time() - start))
print("Export finished in {:.2f} seconds".format(time.time() - start))
scene = context.scene
if not scene.DocProperties.ifc_files:
new = scene.DocProperties.ifc_files.add()
new.name = output_file
if not scene.BIMProperties.ifc_file:
scene.BIMProperties.ifc_file = output_file
if bpy.data.is_saved and bpy.data.is_dirty and bpy.data.filepath:
bpy.ops.wm.save_mainfile(filepath=bpy.data.filepath)
blenderbim.bim.handler.purge_module_data()
return {"FINISHED"}
class ImportIFC(bpy.types.Operator):
bl_idname = "import_ifc.bim"
bl_label = "Import IFC"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
bpy.ops.bim.load_project("INVOKE_DEFAULT")
return {"FINISHED"}
@@ -43,11 +43,7 @@ class AssignContainer(bpy.types.Operator, Operator):
structure_obj = tool.Ifc.get_object(tool.Ifc.get().by_id(self.structure))
for element_obj in context.selected_objects:
core.assign_container(
tool.Ifc,
tool.Collector,
tool.Container,
structure_obj=structure_obj,
element_obj=element_obj,
tool.Ifc, tool.Collector, tool.Container, structure_obj=structure_obj, element_obj=element_obj
)
@@ -127,6 +123,8 @@ class CopyToContainer(bpy.types.Operator):
new_obj.data = obj.data.copy()
new_obj.matrix_world = container_obj.matrix_world @ local_position
bpy.ops.bim.copy_class(obj=new_obj.name)
bpy.ops.bim.assign_container(relating_structure=container_id, related_element=new_obj.name)
core.assign_container(
tool.Ifc, tool.Collector, tool.Container, structure_obj=container_obj, element_obj=new_obj
)
obj.BIMObjectSpatialProperties.is_editing = False
return {"FINISHED"}
-77
View File
@@ -25,89 +25,12 @@ import logging
import webbrowser
import ifcopenshell
import blenderbim.bim.handler
from . import export_ifc
from . import schema
from blenderbim.bim.ifc import IfcStore
from mathutils import Vector, Matrix, Euler
from math import radians
class ExportIFC(bpy.types.Operator):
bl_idname = "export_ifc.bim"
bl_label = "Export IFC"
bl_options = {"REGISTER", "UNDO"}
filename_ext = ".ifc"
filter_glob: bpy.props.StringProperty(default="*.ifc;*.ifczip;*.ifcxml;*.ifcjson", options={"HIDDEN"})
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
json_version: bpy.props.EnumProperty(items=[("4", "4", ""), ("5a", "5a", "")], name="IFC JSON Version")
json_compact: bpy.props.BoolProperty(name="Export Compact IFCJSON", default=False)
def invoke(self, context, event):
if not IfcStore.get_file():
self.report({"ERROR"}, "No IFC project is available for export - create or import a project first.")
return {"FINISHED"}
if context.scene.BIMProperties.ifc_file:
self.filepath = context.scene.BIMProperties.ifc_file
return self.execute(context)
if not self.filepath:
self.filepath = bpy.path.ensure_ext(bpy.data.filepath, ".ifc")
WindowManager = context.window_manager
WindowManager.fileselect_add(self)
return {"RUNNING_MODAL"}
def execute(self, context):
return IfcStore.execute_ifc_operator(self, context)
def _execute(self, context):
start = time.time()
logger = logging.getLogger("ExportIFC")
path_log = os.path.join(context.scene.BIMProperties.data_dir, "process.log")
if not os.access(context.scene.BIMProperties.data_dir, os.W_OK):
path_log = os.path.join(tempfile.mkdtemp(), "process.log")
logging.basicConfig(
filename=path_log,
filemode="a",
level=logging.DEBUG,
)
extension = self.filepath.split(".")[-1]
if extension == "ifczip":
output_file = bpy.path.ensure_ext(self.filepath, ".ifczip")
elif extension == "ifcjson":
output_file = bpy.path.ensure_ext(self.filepath, ".ifcjson")
else:
output_file = bpy.path.ensure_ext(self.filepath, ".ifc")
settings = export_ifc.IfcExportSettings.factory(context, output_file, logger)
settings.json_version = self.json_version
settings.json_compact = self.json_compact
ifc_exporter = export_ifc.IfcExporter(settings)
settings.logger.info("Starting export")
ifc_exporter.export()
settings.logger.info("Export finished in {:.2f} seconds".format(time.time() - start))
print("Export finished in {:.2f} seconds".format(time.time() - start))
scene = context.scene
if not scene.DocProperties.ifc_files:
new = scene.DocProperties.ifc_files.add()
new.name = output_file
if not scene.BIMProperties.ifc_file:
scene.BIMProperties.ifc_file = output_file
if bpy.data.is_saved and bpy.data.is_dirty and bpy.data.filepath:
bpy.ops.wm.save_mainfile(filepath=bpy.data.filepath)
blenderbim.bim.handler.purge_module_data()
return {"FINISHED"}
class ImportIFC(bpy.types.Operator):
bl_idname = "import_ifc.bim"
bl_label = "Import IFC"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
bpy.ops.bim.load_project("INVOKE_DEFAULT")
return {"FINISHED"}
class OpenUri(bpy.types.Operator):
bl_idname = "bim.open_uri"
bl_label = "Open URI"
@@ -275,3 +275,14 @@ Scenario: Unlink IFC
When I press "bim.unlink_ifc(filepath='{cwd}/test/files/basic.blend')"
Then "scene.BIMProjectProperties.links.get('{cwd}/test/files/basic.blend')" is "None"
And "scene.collection.children.get('IfcProject/My Project')" is "None"
Scenario: Export IFC - blank project
Given an empty IFC project
When I press "export_ifc.bim(filepath='{cwd}/test/files/export.ifc')"
Then nothing happens
Scenario: Export IFC - with basic contents
Given an empty Blender session
And I press "bim.load_project(filepath='{cwd}/test/files/basic.ifc')"
When I press "export_ifc.bim(filepath='{cwd}/test/files/export.ifc')"
Then nothing happens