From 72fdca9e822e5c7d81cf2fc1a4b319ca9370dab2 Mon Sep 17 00:00:00 2001 From: admin Date: Thu, 1 Apr 2021 16:41:28 +0800 Subject: [PATCH] merage --- Dockerfile | 37 +++ src/.gitattributes | 64 +++++ src/{ifcblenderexport => blenderbim}/Makefile | 3 +- .../README.md | 0 .../RenameObjects.py | 0 .../blender-screenshot.png | Bin .../blenderbim/__init__.py | 0 .../blenderbim/bim/.gitignore | 0 .../blenderbim/bim/__init__.py | 0 .../blenderbim/bim/annotation.py | 0 .../blenderbim/bim/cut_ifc.py | 134 +++++----- .../blenderbim/bim/decoration.py | 0 .../blenderbim/bim/export_ifc.py | 24 +- .../blenderbim/bim/gizmos.py | 0 .../blenderbim/bim/handler.py | 93 ++++++- .../blenderbim/bim/helper.py | 0 .../blenderbim/bim/ifc.py | 0 .../blenderbim/bim/import_ifc.py | 68 ++++-- .../bim/module/aggregate/__init__.py | 0 .../bim/module/aggregate/operator.py | 13 +- .../blenderbim/bim/module/aggregate/ui.py | 6 +- .../bim/module/attribute/__init__.py | 0 .../bim/module/attribute/operator.py | 15 +- .../blenderbim/bim/module/attribute/prop.py | 1 - .../blenderbim/bim/module/attribute/ui.py | 5 +- .../blenderbim/bim/module/augin/__init__.py | 0 .../blenderbim/bim/module/augin/operator.py | 0 .../blenderbim/bim/module/augin/prop.py | 0 .../blenderbim/bim/module/augin/ui.py | 0 .../blenderbim/bim/module/bcf/__init__.py | 0 .../blenderbim/bim/module/bcf/bcfstore.py | 0 .../blenderbim/bim/module/bcf/operator.py | 0 .../blenderbim/bim/module/bcf/prop.py | 0 .../blenderbim/bim/module/bcf/ui.py | 0 .../bim/module/bimtester/__init__.py | 0 .../bim/module/bimtester/operator.py | 0 .../blenderbim/bim/module/bimtester/prop.py | 0 .../blenderbim/bim/module/bimtester/ui.py | 0 .../blenderbim/bim/module/clash/__init__.py | 0 .../blenderbim/bim/module/clash/operator.py | 0 .../blenderbim/bim/module/clash/prop.py | 1 - .../blenderbim/bim/module/clash/ui.py | 0 .../bim/module/classification/__init__.py | 0 .../bim/module/classification/operator.py | 71 +++--- .../bim/module/classification/prop.py | 2 +- .../bim/module/classification/ui.py | 8 +- .../blenderbim/bim/module/cobie/__init__.py | 0 .../blenderbim/bim/module/cobie/operator.py | 0 .../blenderbim/bim/module/cobie/prop.py | 0 .../blenderbim/bim/module/cobie/ui.py | 0 .../bim/module/constraint/__init__.py | 0 .../bim/module/constraint/operator.py | 56 +++-- .../blenderbim/bim/module/constraint/prop.py | 0 .../blenderbim/bim/module/constraint/ui.py | 8 +- .../blenderbim/bim/module/context/__init__.py | 0 .../blenderbim/bim/module/context/operator.py | 21 +- .../blenderbim/bim/module/context/ui.py | 4 +- .../bim/module/covetool/__init__.py | 0 .../blenderbim/bim/module/covetool/api.py | 0 .../bim/module/covetool/operator.py | 0 .../blenderbim/bim/module/covetool/prop.py | 0 .../blenderbim/bim/module/covetool/ui.py | 0 .../blenderbim/bim/module/csv/__init__.py | 0 .../blenderbim/bim/module/csv/operator.py | 0 .../blenderbim/bim/module/csv/prop.py | 0 .../blenderbim/bim/module/csv/ui.py | 0 .../blenderbim/bim/module/debug/__init__.py | 0 .../blenderbim/bim/module/debug/operator.py | 0 .../blenderbim/bim/module/debug/prop.py | 0 .../blenderbim/bim/module/debug/ui.py | 3 + .../blenderbim/bim/module/diff/__init__.py | 0 .../blenderbim/bim/module/diff/operator.py | 0 .../blenderbim/bim/module/diff/prop.py | 0 .../blenderbim/bim/module/diff/ui.py | 0 .../bim/module/document/__init__.py | 0 .../bim/module/document/operator.py | 70 +++--- .../blenderbim/bim/module/document/prop.py | 0 .../blenderbim/bim/module/document/ui.py | 8 +- .../blenderbim/bim/module/drawing/__init__.py | 0 .../blenderbim/bim/module/drawing/operator.py | 4 +- .../blenderbim/bim/module/drawing/ui.py | 0 .../bim/module/geometry/__init__.py | 0 .../blenderbim/bim/module/geometry/helper.py | 0 .../bim/module/geometry/operator.py | 91 +++---- .../blenderbim/bim/module/geometry/prop.py | 0 .../blenderbim/bim/module/geometry/ui.py | 4 +- .../bim/module/georeference/__init__.py | 0 .../bim/module/georeference/operator.py | 28 +-- .../bim/module/georeference/prop.py | 0 .../blenderbim/bim/module/georeference/ui.py | 4 +- .../blenderbim/bim/module/group/__init__.py | 0 .../blenderbim/bim/module/group/operator.py | 52 ++-- .../blenderbim/bim/module/group/prop.py | 0 .../blenderbim/bim/module/group/ui.py | 4 +- .../blenderbim/bim/module/layer/__init__.py | 0 .../blenderbim/bim/module/layer/operator.py | 46 ++-- .../blenderbim/bim/module/layer/prop.py | 0 .../blenderbim/bim/module/layer/ui.py | 4 +- .../bim/module/material/__init__.py | 0 .../bim/module/material/operator.py | 124 +++++----- .../blenderbim/bim/module/material/prop.py | 2 +- .../blenderbim/bim/module/material/ui.py | 6 +- .../blenderbim/bim/module/model/__init__.py | 0 .../blenderbim/bim/module/model/door.py | 0 .../blenderbim/bim/module/model/grid.py | 23 +- .../blenderbim/bim/module/model/opening.py | 0 .../blenderbim/bim/module/model/pie.py | 0 .../blenderbim/bim/module/model/slab.py | 0 .../blenderbim/bim/module/model/stair.py | 0 .../blenderbim/bim/module/model/wall.py | 0 .../blenderbim/bim/module/model/window.py | 0 .../blenderbim/bim/module/owner/__init__.py | 0 .../blenderbim/bim/module/owner/operator.py | 109 ++++----- .../blenderbim/bim/module/owner/prop.py | 7 +- .../blenderbim/bim/module/owner/ui.py | 8 +- .../blenderbim/bim/module/patch/__init__.py | 0 .../blenderbim/bim/module/patch/operator.py | 0 .../blenderbim/bim/module/patch/prop.py | 0 .../blenderbim/bim/module/patch/ui.py | 0 .../blenderbim/bim/module/project/__init__.py | 0 .../blenderbim/bim/module/project/operator.py | 8 +- .../blenderbim/bim/module/project/prop.py | 0 .../blenderbim/bim/module/project/ui.py | 0 .../blenderbim/bim/module/pset/__init__.py | 0 .../blenderbim/bim/module/pset/operator.py | 51 ++-- .../blenderbim/bim/module/pset/prop.py | 2 +- .../bim/module/pset/qto_calculator.py | 0 .../blenderbim/bim/module/pset/ui.py | 14 +- .../bim/module/pset_template/__init__.py | 0 .../bim/module/pset_template/operator.py | 43 ++-- .../bim/module/pset_template/prop.py | 4 +- .../blenderbim/bim/module/pset_template/ui.py | 5 +- .../blenderbim/bim/module/qto/__init__.py | 0 .../blenderbim/bim/module/qto/operator.py | 0 .../blenderbim/bim/module/qto/prop.py | 1 - .../blenderbim/bim/module/qto/ui.py | 0 .../blenderbim/bim/module/root/__init__.py | 0 .../blenderbim/bim/module/root/operator.py | 36 ++- .../blenderbim/bim/module/root/prop.py | 0 .../blenderbim/bim/module/root/ui.py | 4 +- .../blenderbim/bim/module/search/__init__.py | 0 .../blenderbim/bim/module/search/operator.py | 4 +- .../blenderbim/bim/module/search/prop.py | 0 .../blenderbim/bim/module/search/ui.py | 0 .../bim/module/sequence/__init__.py | 3 + .../bim/module/sequence/operator.py | 26 +- .../blenderbim/bim/module/sequence/prop.py | 0 .../blenderbim/bim/module/sequence/ui.py | 30 ++- .../blenderbim/bim/module/spatial/__init__.py | 0 .../blenderbim/bim/module/spatial/operator.py | 20 +- .../blenderbim/bim/module/spatial/prop.py | 4 +- .../blenderbim/bim/module/spatial/ui.py | 7 +- .../bim/module/structural/__init__.py | 4 + .../bim/module/structural/operator.py | 191 +++++++++++---- .../blenderbim/bim/module/structural/prop.py | 5 +- .../blenderbim/bim/module/structural/ui.py | 158 ++++++------ .../blenderbim/bim/module/style/__init__.py | 0 .../blenderbim/bim/module/style/operator.py | 7 +- .../blenderbim/bim/module/style/ui.py | 0 .../blenderbim/bim/module/type/__init__.py | 0 .../blenderbim/bim/module/type/operator.py | 36 +-- .../blenderbim/bim/module/type/prop.py | 0 .../blenderbim/bim/module/type/ui.py | 7 +- .../blenderbim/bim/module/unit/__init__.py | 0 .../blenderbim/bim/module/unit/operator.py | 8 +- .../blenderbim/bim/module/unit/ui.py | 0 .../blenderbim/bim/module/void/__init__.py | 0 .../blenderbim/bim/module/void/operator.py | 41 ++-- .../blenderbim/bim/module/void/prop.py | 0 .../blenderbim/bim/module/void/ui.py | 4 +- .../blenderbim/bim/operator.py | 0 .../blenderbim/bim/prop.py | 16 +- .../blenderbim/bim/scheduler.py | 0 .../blenderbim/bim/schema.py | 0 .../bim/schema/IfcAnnotation_IFC4.json | 0 .../bim/schema/IfcBoundaryCondition_IFC4.json | 0 .../bim/schema/IfcElementType_IFC4.json | 0 .../bim/schema/IfcElement_IFC4.json | 0 .../blenderbim/bim/schema/IfcGroup_IFC4.json | 0 .../schema/IfcMaterialDefinition_IFC4.json | 0 .../IfcParameterizedProfileDef_IFC4.json | 0 .../schema/IfcPositioningElement_IFC4.json | 0 .../bim/schema/IfcSpatialElement_IFC4.json | 0 .../bim/schema/IfcStructural_IFC4.json | 0 .../schema/classifications/Omniclass_OCCS.ifc | 0 .../classifications/Uniclass2015_Jan2020.ifc | 0 .../bim/schema/entity_descriptions.json | 0 .../bim/schema/enum_descriptions.json | 0 .../blenderbim/bim/schema/ifc_types_IFC4.json | 0 .../blenderbim/bim/shaders.py | 0 .../blenderbim/bim/sheeter.py | 0 .../blenderbim/bim/svgwriter.py | 13 +- .../blenderbim/bim/ui.py | 0 .../blenderbim/libs/site/packages/OCC.pth | 0 .../libs/site/packages/ifcopenshell.pth | 0 .../libs/site/packages/svgwrite.pth | 0 .../docs/Makefile | 0 .../docs/bimserver-plugin.rst | 0 .../docs/bimtester.rst | 0 .../docs/blenderbim.rst | 0 .../docs/blenderbim/installation.rst | 2 +- .../docs/blenderbim/scene.rst | 0 .../docs/conf.py | 0 .../docs/ifcclash.rst | 0 .../docs/ifccobie.rst | 0 .../docs/ifcconvert.rst | 0 .../docs/ifcdiff.rst | 0 .../docs/ifcmax.rst | 0 .../docs/ifcopenshell-python.rst | 0 .../ifcopenshell-python/api-documentation.rst | 0 .../docs/ifcopenshell-python/quickstart.rst | 0 .../docs/ifcopenshell.rst | 0 .../docs/index.rst | 0 .../docs/make.bat | 0 .../dxf2ifc.py | 0 .../extract.py | 0 src/{ifcblenderexport => blenderbim}/gbxml.py | 0 .../generate_util_type_json.py | 4 + .../getIfcElements.py | 0 .../get_description.py | 2 +- .../get_volume_by_material.py | 0 .../ifc_to_gantt.py | 0 .../ifcopenshell-screenshot.png | Bin .../occ_utils.py | 0 .../p6_to_ifc.py | 0 .../runpytest.py | 0 .../tests/test_segment_clipping.py | 0 src/ifcbimtester/patch/model_core.patch | 2 +- src/ifcbimtester/patch/runner_util.patch | 2 +- .../bim/data/cache/shapes/.gitignore | 2 - .../blenderbim/bim/data/diagrams/.gitkeep | 0 .../bim/data/fonts/OpenGost Type B TT.ttf | Bin 54076 -> 0 bytes .../blenderbim/bim/data/mpass/Material.mpass | 8 - .../blenderbim/bim/data/mpass/shader.blend | Bin 563560 -> 0 bytes .../blenderbim/bim/data/schedules/.gitkeep | 0 .../blenderbim/bim/data/sheets/.gitkeep | 0 .../blenderbim/bim/data/styles/default.css | 27 --- .../blenderbim/bim/data/styles/sample.css | 10 - .../blenderbim/bim/data/templates/markers.svg | 62 ----- .../bim/data/templates/patterns.svg | 93 ------- .../blenderbim/bim/data/templates/symbols.svg | 10 - .../bim/data/templates/titleblocks/A1.svg | 208 ---------------- .../bim/data/templates/titleblocks/A2.svg | 203 ---------------- .../bim/data/templates/titleblocks/A3.svg | 207 ---------------- .../bim/data/templates/view-title.svg | 95 -------- .../typical/IfcWindowLiningProperties.csv | 2 - .../bim/module/owner/add_organisation.py | 6 - .../blenderbim/bim/module/owner/add_person.py | 6 - .../blenderbim/bim/module/owner/api.py | 62 ----- .../bim/module/owner/create_owner_history.py | 101 -------- .../bim/module/owner/update_owner_history.py | 99 -------- .../bim/module/root/remove_product.py | 11 - .../blenderbim/bim/module/sequence/data.py | 18 -- .../add_structural_analysis_model.py | 18 -- .../add_structural_boundary_condition.py | 15 -- .../blenderbim/bim/module/structural/data.py | 68 ------ src/ifccobie/get_maintainable_assets.py | 4 +- src/ifcconvert/IfcConvert.cpp | 14 ++ .../ifcopenshell/api/__init__.py | 11 + .../api}/aggregate/assign_object.py | 11 +- .../ifcopenshell/api}/aggregate/data.py | 6 +- .../ifcopenshell/api}/attribute/data.py | 7 +- .../api}/attribute/edit_attributes.py | 13 +- .../api}/classification/add_classification.py | 2 +- .../api}/classification/add_reference.py | 2 +- .../ifcopenshell/api}/classification/data.py | 5 +- .../classification/edit_classification.py | 2 +- .../api/classification}/edit_reference.py | 2 +- .../classification/remove_classification.py | 2 +- .../api}/classification/remove_reference.py | 2 +- .../api}/constraint/add_objective.py | 2 +- .../api}/constraint/assign_constraint.py | 2 +- .../ifcopenshell/api}/constraint/data.py | 5 +- .../api}/constraint/edit_objective.py | 2 +- .../api}/constraint/remove_constraint.py | 2 +- .../api}/constraint/unassign_constraint.py | 2 +- .../ifcopenshell/api}/context/add_context.py | 2 +- .../ifcopenshell/api}/context/data.py | 6 +- .../api}/context/remove_context.py | 2 +- .../api}/document/add_information.py | 2 +- .../api}/document/add_reference.py | 2 +- .../api}/document/assign_document.py | 2 +- .../ifcopenshell/api}/document/data.py | 5 +- .../api}/document/edit_information.py | 2 +- .../api/document}/edit_reference.py | 2 +- .../api}/document/remove_document.py | 2 +- .../api}/document/unassign_document.py | 2 +- .../api}/geometry/add_representation.py | 6 +- .../api}/geometry/assign_representation.py | 6 +- .../api}/geometry/assign_styles.py | 2 +- .../ifcopenshell/api}/geometry/data.py | 6 +- .../api}/geometry/edit_object_placement.py | 5 +- .../api}/geometry/map_representation.py | 2 +- .../api}/geometry/remove_representation.py | 2 +- .../api}/geometry/unassign_representation.py | 6 +- .../api}/georeference/add_georeferencing.py | 2 +- .../ifcopenshell/api}/georeference/data.py | 6 +- .../api}/georeference/edit_georeferencing.py | 2 +- .../georeference/remove_georeferencing.py | 2 +- .../api}/grid/create_axis_curve.py | 2 +- .../api}/grid/create_grid_axis.py | 2 +- .../ifcopenshell/api}/group/add_group.py | 6 +- .../ifcopenshell/api}/group/assign_group.py | 9 +- .../ifcopenshell/api}/group/data.py | 7 +- .../ifcopenshell/api}/group/edit_group.py | 2 +- .../ifcopenshell/api}/group/remove_group.py | 2 +- .../ifcopenshell/api}/group/unassign_group.py | 6 +- .../ifcopenshell/api}/layer/add_layer.py | 2 +- .../ifcopenshell/api}/layer/assign_layer.py | 2 +- .../ifcopenshell/api}/layer/data.py | 5 +- .../ifcopenshell/api}/layer/edit_layer.py | 2 +- .../ifcopenshell/api}/layer/remove_layer.py | 2 +- .../ifcopenshell/api}/layer/unassign_layer.py | 2 +- .../api}/material/add_constituent.py | 2 +- .../ifcopenshell/api}/material/add_layer.py | 2 +- .../api}/material/add_list_item.py | 2 +- .../api}/material/add_material.py | 2 +- .../api}/material/assign_material.py | 2 +- .../ifcopenshell/api}/material/data.py | 5 +- .../api}/material/edit_assigned_material.py | 2 +- .../api}/material/edit_constituent.py | 2 +- .../ifcopenshell/api}/material/edit_layer.py | 2 +- .../api}/material/edit_profile.py | 2 +- .../api}/material/remove_constituent.py | 2 +- .../api}/material/remove_layer.py | 2 +- .../api}/material/remove_list_item.py | 2 +- .../api}/material/remove_material.py | 2 +- .../api}/material/reorder_set_item.py | 2 +- .../api}/material/unassign_material.py | 2 +- .../ifcopenshell/api}/owner/add_address.py | 2 +- .../api/owner/add_organisation.py | 12 + .../ifcopenshell/api/owner/add_person.py | 13 + .../ifcopenshell/api}/owner/add_role.py | 2 +- .../api/owner/create_owner_history.py | 45 ++++ .../ifcopenshell/api}/owner/data.py | 6 +- .../ifcopenshell/api}/owner/edit_address.py | 2 +- .../api}/owner/edit_organisation.py | 2 +- .../ifcopenshell/api}/owner/edit_person.py | 2 +- .../ifcopenshell/api}/owner/edit_role.py | 2 +- .../ifcopenshell/api}/owner/remove_address.py | 2 +- .../api}/owner/remove_organisation.py | 2 +- .../ifcopenshell/api}/owner/remove_person.py | 2 +- .../ifcopenshell/api}/owner/remove_role.py | 2 +- .../ifcopenshell/api/owner/settings.py | 10 + .../api/owner/update_owner_history.py | 44 ++++ .../ifcopenshell/api}/project/create_file.py | 2 +- .../ifcopenshell/api}/pset/add_pset.py | 2 +- .../ifcopenshell/api}/pset/add_qto.py | 2 +- .../ifcopenshell/api}/pset/data.py | 8 +- .../ifcopenshell/api}/pset/edit_pset.py | 2 +- .../ifcopenshell/api}/pset/edit_qto.py | 2 +- .../ifcopenshell/api}/pset/remove_pset.py | 2 +- .../api}/pset_template/add_prop_template.py | 2 +- .../api}/pset_template/add_pset_template.py | 2 +- .../ifcopenshell/api}/pset_template/data.py | 7 +- .../api}/pset_template/edit_prop_template.py | 2 +- .../api}/pset_template/edit_pset_template.py | 2 +- .../pset_template/remove_prop_template.py | 2 +- .../pset_template/remove_pset_template.py | 2 +- .../ifcopenshell/api}/root/copy_class.py | 2 +- .../ifcopenshell/api/root/create_entity.py} | 6 +- .../ifcopenshell/api}/root/data.py | 6 +- .../ifcopenshell/api}/root/reassign_class.py | 2 +- .../ifcopenshell/api/root/remove_product.py | 26 ++ .../api/sequence/add_work_plan.py | 42 ++++ .../ifcopenshell/api/sequence/data.py | 31 +++ .../api/sequence/remove_work_plan.py | 14 ++ .../api}/spatial/assign_container.py | 7 +- .../ifcopenshell/api}/spatial/data.py | 15 +- .../api}/spatial/remove_container.py | 4 +- .../add_structural_analysis_model.py | 15 ++ .../add_structural_boundary_condition.py | 21 ++ .../add_structural_member_connection.py | 19 ++ .../assign_structural_analysis_model.py | 9 +- .../ifcopenshell/api/structural/data.py | 99 ++++++++ .../edit_structural_analysis_model.py | 2 +- .../edit_structural_boundary_condition.py | 2 +- .../remove_structural_analysis_model.py | 2 +- .../remove_structural_boundary_condition.py | 7 +- .../remove_structural_connection_condition.py | 19 ++ .../unassign_structural_analysis_model.py | 6 +- .../ifcopenshell/api}/style/add_style.py | 2 +- .../ifcopenshell/api}/style/edit_style.py | 2 +- .../ifcopenshell/api}/type/assign_type.py | 7 +- .../ifcopenshell/api}/type/data.py | 6 +- .../api}/type/get_related_objects.py | 2 +- .../ifcopenshell/api}/type/unassign_type.py | 4 +- .../ifcopenshell/api}/unit/assign_unit.py | 2 +- .../ifcopenshell/api}/unit/data.py | 6 +- .../ifcopenshell/api}/void/add_filling.py | 2 +- .../ifcopenshell/api}/void/add_opening.py | 4 +- .../ifcopenshell/api}/void/data.py | 6 +- .../ifcopenshell/api}/void/remove_filling.py | 2 +- .../ifcopenshell/api}/void/remove_opening.py | 2 +- .../ifcopenshell/util/attribute.py | 6 +- .../util/entity_to_type_map_4.json | 228 +++++++++--------- src/ifcwrap/IfcParseWrapper.i | 17 +- src/serializers/SvgSerializer.cpp | 197 +++++++++++++-- src/serializers/SvgSerializer.h | 17 +- 399 files changed, 2147 insertions(+), 2496 deletions(-) create mode 100644 Dockerfile create mode 100644 src/.gitattributes rename src/{ifcblenderexport => blenderbim}/Makefile (98%) rename src/{ifcblenderexport => blenderbim}/README.md (100%) rename src/{ifcblenderexport => blenderbim}/RenameObjects.py (100%) rename src/{ifcblenderexport => blenderbim}/blender-screenshot.png (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/__init__.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/.gitignore (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/__init__.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/annotation.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/cut_ifc.py (92%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/decoration.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/export_ifc.py (89%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/gizmos.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/handler.py (68%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/helper.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/ifc.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/import_ifc.py (96%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/aggregate/__init__.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/aggregate/operator.py (93%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/aggregate/ui.py (90%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/attribute/__init__.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/attribute/operator.py (93%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/attribute/prop.py (91%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/attribute/ui.py (96%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/augin/__init__.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/augin/operator.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/augin/prop.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/augin/ui.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/bcf/__init__.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/bcf/bcfstore.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/bcf/operator.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/bcf/prop.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/bcf/ui.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/bimtester/__init__.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/bimtester/operator.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/bimtester/prop.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/bimtester/ui.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/clash/__init__.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/clash/operator.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/clash/prop.py (97%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/clash/ui.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/classification/__init__.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/classification/operator.py (82%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/classification/prop.py (97%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/classification/ui.py (96%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/cobie/__init__.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/cobie/operator.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/cobie/prop.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/cobie/ui.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/constraint/__init__.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/constraint/operator.py (80%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/constraint/prop.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/constraint/ui.py (96%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/context/__init__.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/context/operator.py (70%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/context/ui.py (94%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/covetool/__init__.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/covetool/api.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/covetool/operator.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/covetool/prop.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/covetool/ui.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/csv/__init__.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/csv/operator.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/csv/prop.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/csv/ui.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/debug/__init__.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/debug/operator.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/debug/prop.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/debug/ui.py (93%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/diff/__init__.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/diff/operator.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/diff/prop.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/diff/ui.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/document/__init__.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/document/operator.py (82%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/document/prop.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/document/ui.py (97%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/drawing/__init__.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/drawing/operator.py (96%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/drawing/ui.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/geometry/__init__.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/geometry/helper.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/geometry/operator.py (86%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/geometry/prop.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/geometry/ui.py (97%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/georeference/__init__.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/georeference/operator.py (94%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/georeference/prop.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/georeference/ui.py (98%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/group/__init__.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/group/operator.py (77%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/group/prop.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/group/ui.py (97%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/layer/__init__.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/layer/operator.py (78%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/layer/prop.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/layer/ui.py (97%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/material/__init__.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/material/operator.py (85%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/material/prop.py (97%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/material/ui.py (98%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/model/__init__.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/model/door.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/model/grid.py (83%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/model/opening.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/model/pie.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/model/slab.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/model/stair.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/model/wall.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/model/window.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/owner/__init__.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/owner/operator.py (78%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/owner/prop.py (96%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/owner/ui.py (98%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/patch/__init__.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/patch/operator.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/patch/prop.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/patch/ui.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/project/__init__.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/project/operator.py (91%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/project/prop.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/project/ui.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/pset/__init__.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/pset/operator.py (91%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/pset/prop.py (97%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/pset/qto_calculator.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/pset/ui.py (94%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/pset_template/__init__.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/pset_template/operator.py (82%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/pset_template/prop.py (99%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/pset_template/ui.py (96%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/qto/__init__.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/qto/operator.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/qto/prop.py (88%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/qto/ui.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/root/__init__.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/root/operator.py (89%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/root/prop.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/root/ui.py (96%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/search/__init__.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/search/operator.py (98%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/search/prop.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/search/ui.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/sequence/__init__.py (82%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/sequence/operator.py (52%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/sequence/prop.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/sequence/ui.py (61%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/spatial/__init__.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/spatial/operator.py (90%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/spatial/prop.py (96%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/spatial/ui.py (91%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/structural/__init__.py (86%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/structural/operator.py (57%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/structural/prop.py (80%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/structural/ui.py (53%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/style/__init__.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/style/operator.py (90%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/style/ui.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/type/__init__.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/type/operator.py (85%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/type/prop.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/type/ui.py (90%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/unit/__init__.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/unit/operator.py (84%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/unit/ui.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/void/__init__.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/void/operator.py (79%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/void/prop.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/module/void/ui.py (96%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/operator.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/prop.py (98%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/scheduler.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/schema.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/schema/IfcAnnotation_IFC4.json (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/schema/IfcBoundaryCondition_IFC4.json (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/schema/IfcElementType_IFC4.json (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/schema/IfcElement_IFC4.json (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/schema/IfcGroup_IFC4.json (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/schema/IfcMaterialDefinition_IFC4.json (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/schema/IfcParameterizedProfileDef_IFC4.json (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/schema/IfcPositioningElement_IFC4.json (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/schema/IfcSpatialElement_IFC4.json (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/schema/IfcStructural_IFC4.json (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/schema/classifications/Omniclass_OCCS.ifc (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/schema/classifications/Uniclass2015_Jan2020.ifc (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/schema/entity_descriptions.json (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/schema/enum_descriptions.json (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/schema/ifc_types_IFC4.json (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/shaders.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/sheeter.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/svgwriter.py (98%) rename src/{ifcblenderexport => blenderbim}/blenderbim/bim/ui.py (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/libs/site/packages/OCC.pth (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/libs/site/packages/ifcopenshell.pth (100%) rename src/{ifcblenderexport => blenderbim}/blenderbim/libs/site/packages/svgwrite.pth (100%) rename src/{ifcblenderexport => blenderbim}/docs/Makefile (100%) rename src/{ifcblenderexport => blenderbim}/docs/bimserver-plugin.rst (100%) rename src/{ifcblenderexport => blenderbim}/docs/bimtester.rst (100%) rename src/{ifcblenderexport => blenderbim}/docs/blenderbim.rst (100%) rename src/{ifcblenderexport => blenderbim}/docs/blenderbim/installation.rst (97%) rename src/{ifcblenderexport => blenderbim}/docs/blenderbim/scene.rst (100%) rename src/{ifcblenderexport => blenderbim}/docs/conf.py (100%) rename src/{ifcblenderexport => blenderbim}/docs/ifcclash.rst (100%) rename src/{ifcblenderexport => blenderbim}/docs/ifccobie.rst (100%) rename src/{ifcblenderexport => blenderbim}/docs/ifcconvert.rst (100%) rename src/{ifcblenderexport => blenderbim}/docs/ifcdiff.rst (100%) rename src/{ifcblenderexport => blenderbim}/docs/ifcmax.rst (100%) rename src/{ifcblenderexport => blenderbim}/docs/ifcopenshell-python.rst (100%) rename src/{ifcblenderexport => blenderbim}/docs/ifcopenshell-python/api-documentation.rst (100%) rename src/{ifcblenderexport => blenderbim}/docs/ifcopenshell-python/quickstart.rst (100%) rename src/{ifcblenderexport => blenderbim}/docs/ifcopenshell.rst (100%) rename src/{ifcblenderexport => blenderbim}/docs/index.rst (100%) rename src/{ifcblenderexport => blenderbim}/docs/make.bat (100%) rename src/{ifcblenderexport => blenderbim}/dxf2ifc.py (100%) rename src/{ifcblenderexport => blenderbim}/extract.py (100%) rename src/{ifcblenderexport => blenderbim}/gbxml.py (100%) rename src/{ifcblenderexport => blenderbim}/generate_util_type_json.py (94%) rename src/{ifcblenderexport => blenderbim}/getIfcElements.py (100%) rename src/{ifcblenderexport => blenderbim}/get_description.py (96%) rename src/{ifcblenderexport => blenderbim}/get_volume_by_material.py (100%) rename src/{ifcblenderexport => blenderbim}/ifc_to_gantt.py (100%) rename src/{ifcblenderexport => blenderbim}/ifcopenshell-screenshot.png (100%) rename src/{ifcblenderexport => blenderbim}/occ_utils.py (100%) mode change 100755 => 100644 rename src/{ifcblenderexport => blenderbim}/p6_to_ifc.py (100%) rename src/{ifcblenderexport => blenderbim}/runpytest.py (100%) rename src/{ifcblenderexport => blenderbim}/tests/test_segment_clipping.py (100%) delete mode 100644 src/ifcblenderexport/blenderbim/bim/data/cache/shapes/.gitignore delete mode 100644 src/ifcblenderexport/blenderbim/bim/data/diagrams/.gitkeep delete mode 100644 src/ifcblenderexport/blenderbim/bim/data/fonts/OpenGost Type B TT.ttf delete mode 100644 src/ifcblenderexport/blenderbim/bim/data/mpass/Material.mpass delete mode 100644 src/ifcblenderexport/blenderbim/bim/data/mpass/shader.blend delete mode 100644 src/ifcblenderexport/blenderbim/bim/data/schedules/.gitkeep delete mode 100644 src/ifcblenderexport/blenderbim/bim/data/sheets/.gitkeep delete mode 100644 src/ifcblenderexport/blenderbim/bim/data/styles/default.css delete mode 100644 src/ifcblenderexport/blenderbim/bim/data/styles/sample.css delete mode 100644 src/ifcblenderexport/blenderbim/bim/data/templates/markers.svg delete mode 100644 src/ifcblenderexport/blenderbim/bim/data/templates/patterns.svg delete mode 100644 src/ifcblenderexport/blenderbim/bim/data/templates/symbols.svg delete mode 100644 src/ifcblenderexport/blenderbim/bim/data/templates/titleblocks/A1.svg delete mode 100644 src/ifcblenderexport/blenderbim/bim/data/templates/titleblocks/A2.svg delete mode 100644 src/ifcblenderexport/blenderbim/bim/data/templates/titleblocks/A3.svg delete mode 100644 src/ifcblenderexport/blenderbim/bim/data/templates/view-title.svg delete mode 100644 src/ifcblenderexport/blenderbim/bim/data/window/typical/IfcWindowLiningProperties.csv delete mode 100644 src/ifcblenderexport/blenderbim/bim/module/owner/add_organisation.py delete mode 100644 src/ifcblenderexport/blenderbim/bim/module/owner/add_person.py delete mode 100644 src/ifcblenderexport/blenderbim/bim/module/owner/api.py delete mode 100644 src/ifcblenderexport/blenderbim/bim/module/owner/create_owner_history.py delete mode 100644 src/ifcblenderexport/blenderbim/bim/module/owner/update_owner_history.py delete mode 100644 src/ifcblenderexport/blenderbim/bim/module/root/remove_product.py delete mode 100644 src/ifcblenderexport/blenderbim/bim/module/sequence/data.py delete mode 100644 src/ifcblenderexport/blenderbim/bim/module/structural/add_structural_analysis_model.py delete mode 100644 src/ifcblenderexport/blenderbim/bim/module/structural/add_structural_boundary_condition.py delete mode 100644 src/ifcblenderexport/blenderbim/bim/module/structural/data.py create mode 100644 src/ifcopenshell-python/ifcopenshell/api/__init__.py rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/aggregate/assign_object.py (80%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/aggregate/data.py (82%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/attribute/data.py (88%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/attribute/edit_attributes.py (53%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/classification/add_classification.py (97%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/classification/add_reference.py (98%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/classification/data.py (95%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/classification/edit_classification.py (89%) rename src/{ifcblenderexport/blenderbim/bim/module/document => ifcopenshell-python/ifcopenshell/api/classification}/edit_reference.py (89%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/classification/remove_classification.py (95%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/classification/remove_reference.py (96%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/constraint/add_objective.py (90%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/constraint/assign_constraint.py (95%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/constraint/data.py (92%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/constraint/edit_objective.py (89%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/constraint/remove_constraint.py (89%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/constraint/unassign_constraint.py (91%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/context/add_context.py (97%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/context/data.py (89%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/context/remove_context.py (89%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/document/add_information.py (91%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/document/add_reference.py (90%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/document/assign_document.py (97%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/document/data.py (95%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/document/edit_information.py (89%) rename src/{ifcblenderexport/blenderbim/bim/module/classification => ifcopenshell-python/ifcopenshell/api/document}/edit_reference.py (89%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/document/remove_document.py (89%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/document/unassign_document.py (91%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/geometry/add_representation.py (99%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/geometry/assign_representation.py (90%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/geometry/assign_styles.py (96%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/geometry/data.py (92%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/geometry/edit_object_placement.py (95%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/geometry/map_representation.py (96%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/geometry/remove_representation.py (97%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/geometry/unassign_representation.py (92%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/georeference/add_georeferencing.py (93%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/georeference/data.py (91%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/georeference/edit_georeferencing.py (97%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/georeference/remove_georeferencing.py (91%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/grid/create_axis_curve.py (97%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/grid/create_grid_axis.py (93%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/group/add_group.py (68%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/group/assign_group.py (74%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/group/data.py (80%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/group/edit_group.py (88%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/group/remove_group.py (88%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/group/unassign_group.py (79%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/layer/add_layer.py (87%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/layer/assign_layer.py (90%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/layer/data.py (89%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/layer/edit_layer.py (88%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/layer/remove_layer.py (83%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/layer/unassign_layer.py (91%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/material/add_constituent.py (92%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/material/add_layer.py (92%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/material/add_list_item.py (90%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/material/add_material.py (87%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/material/assign_material.py (98%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/material/data.py (96%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/material/edit_assigned_material.py (89%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/material/edit_constituent.py (91%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/material/edit_layer.py (91%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/material/edit_profile.py (91%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/material/remove_constituent.py (85%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/material/remove_layer.py (85%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/material/remove_list_item.py (89%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/material/remove_material.py (94%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/material/reorder_set_item.py (95%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/material/unassign_material.py (89%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/owner/add_address.py (91%) create mode 100644 src/ifcopenshell-python/ifcopenshell/api/owner/add_organisation.py create mode 100644 src/ifcopenshell-python/ifcopenshell/api/owner/add_person.py rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/owner/add_role.py (90%) create mode 100644 src/ifcopenshell-python/ifcopenshell/api/owner/create_owner_history.py rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/owner/data.py (95%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/owner/edit_address.py (88%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/owner/edit_organisation.py (89%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/owner/edit_person.py (88%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/owner/edit_role.py (88%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/owner/remove_address.py (84%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/owner/remove_organisation.py (84%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/owner/remove_person.py (84%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/owner/remove_role.py (83%) create mode 100644 src/ifcopenshell-python/ifcopenshell/api/owner/settings.py create mode 100644 src/ifcopenshell-python/ifcopenshell/api/owner/update_owner_history.py rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/project/create_file.py (96%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/pset/add_pset.py (97%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/pset/add_qto.py (94%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/pset/data.py (96%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/pset/edit_pset.py (98%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/pset/edit_qto.py (98%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/pset/remove_pset.py (95%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/pset_template/add_prop_template.py (94%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/pset_template/add_pset_template.py (91%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/pset_template/data.py (90%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/pset_template/edit_prop_template.py (88%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/pset_template/edit_pset_template.py (88%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/pset_template/remove_prop_template.py (94%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/pset_template/remove_pset_template.py (88%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/root/copy_class.py (97%) rename src/{ifcblenderexport/blenderbim/bim/module/root/create_product.py => ifcopenshell-python/ifcopenshell/api/root/create_entity.py} (86%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/root/data.py (81%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/root/reassign_class.py (94%) create mode 100644 src/ifcopenshell-python/ifcopenshell/api/root/remove_product.py create mode 100644 src/ifcopenshell-python/ifcopenshell/api/sequence/add_work_plan.py create mode 100644 src/ifcopenshell-python/ifcopenshell/api/sequence/data.py create mode 100644 src/ifcopenshell-python/ifcopenshell/api/sequence/remove_work_plan.py rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/spatial/assign_container.py (79%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/spatial/data.py (83%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/spatial/remove_container.py (77%) create mode 100644 src/ifcopenshell-python/ifcopenshell/api/structural/add_structural_analysis_model.py create mode 100644 src/ifcopenshell-python/ifcopenshell/api/structural/add_structural_boundary_condition.py create mode 100644 src/ifcopenshell-python/ifcopenshell/api/structural/add_structural_member_connection.py rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/structural/assign_structural_analysis_model.py (76%) create mode 100644 src/ifcopenshell-python/ifcopenshell/api/structural/data.py rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/structural/edit_structural_analysis_model.py (90%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/structural/edit_structural_boundary_condition.py (94%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/structural/remove_structural_analysis_model.py (90%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/structural/remove_structural_boundary_condition.py (73%) create mode 100644 src/ifcopenshell-python/ifcopenshell/api/structural/remove_structural_connection_condition.py rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/structural/unassign_structural_analysis_model.py (81%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/style/add_style.py (97%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/style/edit_style.py (98%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/type/assign_type.py (82%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/type/data.py (91%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/type/get_related_objects.py (96%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/type/unassign_type.py (85%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/unit/assign_unit.py (98%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/unit/data.py (82%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/void/add_filling.py (91%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/void/add_opening.py (75%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/void/data.py (95%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/void/remove_filling.py (89%) rename src/{ifcblenderexport/blenderbim/bim/module => ifcopenshell-python/ifcopenshell/api}/void/remove_opening.py (94%) diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000..c40c6cf0dd --- /dev/null +++ b/Dockerfile @@ -0,0 +1,37 @@ +# -*- mode: Dockerfile -*- + +FROM ubuntu:focal + +ARG CHANNEL +ENV CHANNEL=${CHANNEL:-latest} +RUN apt-get update \ + && apt-get install -y \ + vim \ + ssh \ + sudo \ + wget \ + software-properties-common ;\ + rm -rf /var/lib/apt/lists/* + +RUN useradd --user-group --create-home --shell /bin/bash IfcOpenShell ;\ + echo "IfcOpenShell ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers + + +ENV DEBIAN_FRONTEND=noninteractive +RUN echo "deb http://archive.ubuntu.com/ubuntu focal-proposed main restricted" | tee -a /etc/apt/sources.list; \ + echo "deb http://archive.ubuntu.com/ubuntu focal-proposed universe" | tee -a /etc/apt/sources.list; \ + echo "deb http://archive.ubuntu.com/ubuntu focal-proposed multiverse" | tee -a /etc/apt/sources.list; \ + apt-get -qq update; \ + apt-get -y install tzdata dos2unix rsync; \ + apt-get -y install python3 libxml2 liboce-foundation11 liboce-modeling11 liboce-ocaf11 liboce-visualization11 \ + liboce-ocaf-lite11 libpython3.8 libboost-system1.67.0 libboost-program-options1.67.0 \ + libboost-regex1.67.0 libboost-thread1.67.0 libboost-date-time1.67.0; \ + rm -rf /var/lib/apt/lists/* ; + +COPY . /home/IfcOpenShell/ +RUN ls -lrtR /home/IfcOpenShell + +RUN dpkg -i /home/IfcOpenShell/*.deb + +USER IfcOpenShell + diff --git a/src/.gitattributes b/src/.gitattributes new file mode 100644 index 0000000000..1f5bf09722 --- /dev/null +++ b/src/.gitattributes @@ -0,0 +1,64 @@ +# **************************************************************************** +# line endings + +# to suppress line ending changes in github, add ?w=1 at link end of a diff + +# for more information see +# FreeCAD source code src/Mod/.gitattributes +# FreeCAD forum topic https://forum.freecadweb.org/viewtopic.php?f=17&t=41117 +# FreeCAD pull request https://github.com/FreeCAD/FreeCAD/pull/2752 + + +# get all used file types + +# in a directory in a bash use +# find . -type f -name '*.*' | sed 's|.*\.||' | sort -u + +# search for a specific file ending +# find . -type f -name '*.ico' + + +# normalize the line endings of the following files +*.cpp text +*.css text +*.csv text +*.feature text +*.gitattributes text +*.gitignore text +*.gitkeep +*.h text +*.html text +*.ifc text +*.json text +*.md text +*.po text +*.pot text +*.py text +*.txt text + + +# files not normalized ATM +# bat +# bnf +# blend +# i +# ico +# mo +# mpass +# png +# pth +# pyc +# rst +# svg +# ttf +# xsd + + +# line endings of all directories will be normalized +# to exclude a directory from being normalized add it here +# example: to exclude dirctory ifcbimtester use the following line without # +# ifcbimtester/** -text + + +# use git to manually correct the file endings +# git add --renormalize . diff --git a/src/ifcblenderexport/Makefile b/src/blenderbim/Makefile similarity index 98% rename from src/ifcblenderexport/Makefile rename to src/blenderbim/Makefile index 857b535525..1548f6b72d 100644 --- a/src/ifcblenderexport/Makefile +++ b/src/blenderbim/Makefile @@ -61,7 +61,7 @@ endif cp -r dist/working/io_import_scene_ifc/ifcopenshell dist/blenderbim/libs/site/packages/ # See bug #812 - cd dist/working && wget https://raw.githubusercontent.com/IfcOpenShell/IfcOpenShell/v0.6.0/src/ifcblenderexport/occ_utils.py + cd dist/working && wget https://raw.githubusercontent.com/IfcOpenShell/IfcOpenShell/v0.6.0/src/blenderbim/occ_utils.py cd dist/working && mv occ_utils.py ../blenderbim/libs/site/packages/ifcopenshell/geom/occ_utils.py rm -rf dist/working @@ -142,6 +142,7 @@ endif cd dist/working && unzip v0.6.0.zip # IfcOpenBot sometimes lags behind, so we hotfix the Python utilities cp -r dist/working/IfcOpenShell-0.6.0/src/ifcopenshell-python/ifcopenshell/util/* dist/blenderbim/libs/site/packages/ifcopenshell/util/ + cp -r dist/working/IfcOpenShell-0.6.0/src/ifcopenshell-python/ifcopenshell/api dist/blenderbim/libs/site/packages/ifcopenshell/api # Provides bcf functionality cp -r dist/working/IfcOpenShell-0.6.0/src/bcf/bcf dist/blenderbim/libs/site/packages/ # Provides IFCClash functionality diff --git a/src/ifcblenderexport/README.md b/src/blenderbim/README.md similarity index 100% rename from src/ifcblenderexport/README.md rename to src/blenderbim/README.md diff --git a/src/ifcblenderexport/RenameObjects.py b/src/blenderbim/RenameObjects.py similarity index 100% rename from src/ifcblenderexport/RenameObjects.py rename to src/blenderbim/RenameObjects.py diff --git a/src/ifcblenderexport/blender-screenshot.png b/src/blenderbim/blender-screenshot.png similarity index 100% rename from src/ifcblenderexport/blender-screenshot.png rename to src/blenderbim/blender-screenshot.png diff --git a/src/ifcblenderexport/blenderbim/__init__.py b/src/blenderbim/blenderbim/__init__.py similarity index 100% rename from src/ifcblenderexport/blenderbim/__init__.py rename to src/blenderbim/blenderbim/__init__.py diff --git a/src/ifcblenderexport/blenderbim/bim/.gitignore b/src/blenderbim/blenderbim/bim/.gitignore similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/.gitignore rename to src/blenderbim/blenderbim/bim/.gitignore diff --git a/src/ifcblenderexport/blenderbim/bim/__init__.py b/src/blenderbim/blenderbim/bim/__init__.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/__init__.py rename to src/blenderbim/blenderbim/bim/__init__.py diff --git a/src/ifcblenderexport/blenderbim/bim/annotation.py b/src/blenderbim/blenderbim/bim/annotation.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/annotation.py rename to src/blenderbim/blenderbim/bim/annotation.py diff --git a/src/ifcblenderexport/blenderbim/bim/cut_ifc.py b/src/blenderbim/blenderbim/bim/cut_ifc.py similarity index 92% rename from src/ifcblenderexport/blenderbim/bim/cut_ifc.py rename to src/blenderbim/blenderbim/bim/cut_ifc.py index 7c54d2ca4c..2fbe91a29a 100644 --- a/src/ifcblenderexport/blenderbim/bim/cut_ifc.py +++ b/src/blenderbim/blenderbim/bim/cut_ifc.py @@ -6,68 +6,71 @@ import numpy import pickle import multiprocessing -try: - from OCC.Core import ( - gp, - Geom, - Bnd, - BRepBndLib, - BRep, - BRepPrimAPI, - BRepAlgoAPI, - BRepBuilderAPI, - TopOpeBRepTool, - TopOpeBRepBuild, - ShapeExtend, - GProp, - BRepGProp, - GC, - ShapeAnalysis, - TopTools, - TopExp, - TopAbs, - HLRAlgo, - HLRBRep, - TopLoc, - Bnd, - BRepBndLib, - BRepTools, - TopoDS, - GeomLProp, - IntCurvesFace, - ) - from OCC.Core.TopoDS import topods -except ImportError: - from OCC import ( - gp, - Geom, - Bnd, - BRepBndLib, - BRep, - BRepPrimAPI, - BRepAlgoAPI, - BRepBuilderAPI, - TopOpeBRepTool, - TopOpeBRepBuild, - ShapeExtend, - GProp, - BRepGProp, - GC, - ShapeAnalysis, - TopTools, - TopExp, - TopAbs, - HLRAlgo, - HLRBRep, - TopLoc, - Bnd, - BRepBndLib, - BRepTools, - TopoDS, - GeomLProp, - IntCurvesFace, - ) - from OCC.TopoDS import topods + +def load_occ(): + # Don't import until we really need to, as a temporary step before we can purge OCC + try: + from OCC.Core import ( + gp, + Geom, + Bnd, + BRepBndLib, + BRep, + BRepPrimAPI, + BRepAlgoAPI, + BRepBuilderAPI, + TopOpeBRepTool, + TopOpeBRepBuild, + ShapeExtend, + GProp, + BRepGProp, + GC, + ShapeAnalysis, + TopTools, + TopExp, + TopAbs, + HLRAlgo, + HLRBRep, + TopLoc, + Bnd, + BRepBndLib, + BRepTools, + TopoDS, + GeomLProp, + IntCurvesFace, + ) + from OCC.Core.TopoDS import topods + except ImportError: + from OCC import ( + gp, + Geom, + Bnd, + BRepBndLib, + BRep, + BRepPrimAPI, + BRepAlgoAPI, + BRepBuilderAPI, + TopOpeBRepTool, + TopOpeBRepBuild, + ShapeExtend, + GProp, + BRepGProp, + GC, + ShapeAnalysis, + TopTools, + TopExp, + TopAbs, + HLRAlgo, + HLRBRep, + TopLoc, + Bnd, + BRepBndLib, + BRepTools, + TopoDS, + GeomLProp, + IntCurvesFace, + ) + from OCC.TopoDS import topods import ifcopenshell import ifcopenshell.geom @@ -79,6 +82,7 @@ this_file = os.path.join(cwd, "cut_ifc.py") def get_booleaned_edges(shape): + load_occ() edges = [] exp = TopExp.TopExp_Explorer(shape, TopAbs.TopAbs_EDGE) while exp.More(): @@ -88,6 +92,7 @@ def get_booleaned_edges(shape): def connect_edges_into_wires(unconnected_edges): + load_occ() edges = TopTools.TopTools_HSequenceOfShape() edges_handle = TopTools.Handle_TopTools_HSequenceOfShape(edges) wires = TopTools.TopTools_HSequenceOfShape() @@ -101,6 +106,7 @@ def connect_edges_into_wires(unconnected_edges): def do_cut(process_data): + load_occ() global_id, shape, section, trsf_data = process_data axis = gp.gp_Ax2( @@ -320,6 +326,7 @@ class IfcCutter: return False def create_section_box(self): + load_occ() top_left_corner = gp.gp_Pnt( self.section_box["top_left_corner"][0], self.section_box["top_left_corner"][1], @@ -350,6 +357,7 @@ class IfcCutter: self.transformation.SetDisplacement(source, destination) def get_bbox(self, shape): + load_occ() bbox = Bnd.Bnd_Box() BRepBndLib.brepbndlib_Add(shape, bbox) return bbox @@ -361,6 +369,7 @@ class IfcCutter: return zpos, zmax def get_booleaned_edges(self, shape): + load_occ() edges = [] exp = TopExp.TopExp_Explorer(shape, TopAbs.TopAbs_EDGE) while exp.More(): @@ -377,6 +386,7 @@ class IfcCutter: def get_annotation(self): import mathutils + load_occ() self.annotation_objs = [] settings_2d = ifcopenshell.geom.settings() diff --git a/src/ifcblenderexport/blenderbim/bim/decoration.py b/src/blenderbim/blenderbim/bim/decoration.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/decoration.py rename to src/blenderbim/blenderbim/bim/decoration.py diff --git a/src/ifcblenderexport/blenderbim/bim/export_ifc.py b/src/blenderbim/blenderbim/bim/export_ifc.py similarity index 89% rename from src/ifcblenderexport/blenderbim/bim/export_ifc.py rename to src/blenderbim/blenderbim/bim/export_ifc.py index 7134b013c5..712fc73cdb 100644 --- a/src/ifcblenderexport/blenderbim/bim/export_ifc.py +++ b/src/blenderbim/blenderbim/bim/export_ifc.py @@ -7,6 +7,7 @@ import zipfile import tempfile import ifcopenshell import ifcopenshell.util.placement +import ifcopenshell.api from blenderbim.bim.ifc import IfcStore import addon_utils @@ -19,7 +20,7 @@ class IfcExporter: self.file = IfcStore.get_file() self.set_header() if bpy.context.scene.BIMProjectProperties.is_authoring: - self.sync_object_placements() + self.sync_object_placements_and_deletions() self.sync_edited_objects() extension = self.ifc_export_settings.output_file.split(".")[-1] if extension == "ifczip": @@ -74,13 +75,22 @@ class IfcExporter: # else: # self.file.wrapped_data.header.file_name.authorization = "Nobody" - def sync_object_placements(self): + def sync_object_placements_and_deletions(self): self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(self.file) - for obj in bpy.data.objects: + to_delete = [] + + for guid, obj in IfcStore.guid_map.items(): try: self.sync_object_placement(obj) except: pass + if self.should_delete(guid, obj): + to_delete.append(guid) + + for guid in to_delete: + product = self.file.by_id(guid) + IfcStore.unlink_element(product) + ifcopenshell.api.run("remove_product", self.file, **{"product": product}) def sync_edited_objects(self): for obj_name in IfcStore.edited_objs.copy(): @@ -114,6 +124,14 @@ class IfcExporter: if not np.allclose(ifc_matrix, blender_matrix, atol=0.0001): bpy.ops.bim.edit_object_placement(obj=obj.name) + def should_delete(self, guid, obj): + try: + # This will throw an exception if the Blender object no longer exists + foo = obj.name + return False + except: + return True + def get_application_name(self): return "BlenderBIM" diff --git a/src/ifcblenderexport/blenderbim/bim/gizmos.py b/src/blenderbim/blenderbim/bim/gizmos.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/gizmos.py rename to src/blenderbim/blenderbim/bim/gizmos.py diff --git a/src/ifcblenderexport/blenderbim/bim/handler.py b/src/blenderbim/blenderbim/bim/handler.py similarity index 68% rename from src/ifcblenderexport/blenderbim/bim/handler.py rename to src/blenderbim/blenderbim/bim/handler.py index a54440a62f..5f462f8a5e 100644 --- a/src/ifcblenderexport/blenderbim/bim/handler.py +++ b/src/blenderbim/blenderbim/bim/handler.py @@ -1,9 +1,11 @@ import bpy import json +import addon_utils import blenderbim.bim.decoration as decoration +import ifcopenshell.api.owner.settings from bpy.app.handlers import persistent from blenderbim.bim.ifc import IfcStore -from blenderbim.bim.module.attribute.data import Data as AttributeData +from ifcopenshell.api.attribute.data import Data as AttributeData def mode_callback(obj, data): @@ -28,7 +30,7 @@ def name_callback(obj, data): if not element.is_a("IfcRoot"): return element.Name = "/".join(obj.name.split("/")[1:]) - AttributeData.load(obj.BIMObjectProperties.ifc_definition_id) + AttributeData.load(IfcStore.get_file(), obj.BIMObjectProperties.ifc_definition_id) def subscribe_to(object, data_path, callback): @@ -46,14 +48,13 @@ def subscribe_to(object, data_path, callback): }, ) + def purge_module_data(): from blenderbim.bim import modules - for module in modules.values(): - if not module: - continue + for name in modules.keys(): try: - getattr(getattr(module, "data"), "Data").purge() + getattr(getattr(getattr(ifcopenshell.api, name), "data"), "Data").purge() except AttributeError: pass @@ -99,8 +100,88 @@ def storeIdMap(scene): bpy.context.scene.BIMProperties.guid_map = json.dumps({k: v.name for k, v in IfcStore.guid_map.items()}) +def get_application(ifc): + version = get_application_version() + for element in ifc.by_type("IfcApplication"): + if element.ApplicationIdentifier == "BlenderBIM" and element.Version == version: + return element + return ifc.create_entity( + "IfcApplication", + **{ + "ApplicationDeveloper": create_application_organisation(ifc), + "Version": get_application_version(), + "ApplicationFullName": "BlenderBIM Add-on", + "ApplicationIdentifier": "BlenderBIM", + }, + ) + + +def get_application_version(): + return ".".join( + [ + str(x) + for x in [ + addon.bl_info.get("version", (-1, -1, -1)) + for addon in addon_utils.modules() + if addon.bl_info["name"] == "BlenderBIM" + ][0] + ] + ) + + +def create_application_organisation(ifc): + return ifc.create_entity( + "IfcOrganization", + **{ + "Name": "IfcOpenShell", + "Description": "IfcOpenShell is an open source (LGPL) software library that helps users and software developers to work with the IFC file format.", + "Roles": [ifc.create_entity("IfcActorRole", **{"Role": "USERDEFINED", "UserDefinedRole": "CONTRIBUTOR"})], + "Addresses": [ + ifc.create_entity( + "IfcTelecomAddress", + **{ + "Purpose": "USERDEFINED", + "UserDefinedPurpose": "WEBPAGE", + "Description": "The main webpage of the software collection.", + "WWWHomePageURL": "https://ifcopenshell.org", + }, + ), + ifc.create_entity( + "IfcTelecomAddress", + **{ + "Purpose": "USERDEFINED", + "UserDefinedPurpose": "WEBPAGE", + "Description": "The BlenderBIM Add-on webpage of the software collection.", + "WWWHomePageURL": "https://blenderbim.org", + }, + ), + ifc.create_entity( + "IfcTelecomAddress", + **{ + "Purpose": "USERDEFINED", + "UserDefinedPurpose": "REPOSITORY", + "Description": "The source code repository of the software collection.", + "WWWHomePageURL": "https://github.com/IfcOpenShell/IfcOpenShell.git", + }, + ), + ], + }, + ) + + @persistent def setDefaultProperties(scene): + ifcopenshell.api.owner.settings.get_person = ( + lambda ifc : ifc.by_id(int(bpy.context.scene.BIMOwnerProperties.user_person)) + if bpy.context.scene.BIMOwnerProperties.user_person + else None + ) + ifcopenshell.api.owner.settings.get_organisation = ( + lambda ifc : ifc.by_id(int(bpy.context.scene.BIMOwnerProperties.user_organisation)) + if bpy.context.scene.BIMOwnerProperties.user_organisation + else None + ) + ifcopenshell.api.owner.settings.get_application = get_application if len(bpy.context.scene.DocProperties.drawing_styles) == 0: drawing_style = bpy.context.scene.DocProperties.drawing_styles.add() drawing_style.name = "Technical" diff --git a/src/ifcblenderexport/blenderbim/bim/helper.py b/src/blenderbim/blenderbim/bim/helper.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/helper.py rename to src/blenderbim/blenderbim/bim/helper.py diff --git a/src/ifcblenderexport/blenderbim/bim/ifc.py b/src/blenderbim/blenderbim/bim/ifc.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/ifc.py rename to src/blenderbim/blenderbim/bim/ifc.py diff --git a/src/ifcblenderexport/blenderbim/bim/import_ifc.py b/src/blenderbim/blenderbim/bim/import_ifc.py similarity index 96% rename from src/ifcblenderexport/blenderbim/bim/import_ifc.py rename to src/blenderbim/blenderbim/bim/import_ifc.py index b546d9c088..4a3ffa2d75 100644 --- a/src/ifcblenderexport/blenderbim/bim/import_ifc.py +++ b/src/blenderbim/blenderbim/bim/import_ifc.py @@ -21,7 +21,6 @@ import numpy as np from pathlib import Path from itertools import cycle from datetime import datetime -from blenderbim.bim.module.context.data import Data as ContextData from blenderbim.bim.ifc import IfcStore from . import schema @@ -420,7 +419,7 @@ class IfcImporter: representations = self.get_transformed_body_representations(element.Representation.Representations) # Single swept disk solids (e.g. rebar) are better natively represented as beveled curves - if [r for r in representations if self.is_native_swept_disk_solid(r)]: + if self.is_native_swept_disk_solid(representations): self.native_data[element.GlobalId] = { "representations": representations, "representation": self.get_body_representation(element.Representation.Representations), @@ -429,19 +428,26 @@ class IfcImporter: return True # FacetedBreps (without voids) are meshes. See #841. # Commented out as seems currently too slow. - # if [r for r in representations if self.is_native_faceted_brep(r)]: - # self.native_data[element.GlobalId] = { - # "representations": representations, - # "representation": self.get_body_representation(element.Representation.Representations), - # "type": "IfcFacetedBrep", - # } - # return True + # if self.is_native_faceted_brep(representations): + # self.native_data[element.GlobalId] = { + # "representations": representations, + # "representation": self.get_body_representation(element.Representation.Representations), + # "type": "IfcFacetedBrep", + # } + # return True - def is_native_swept_disk_solid(self, representation): - return len(representation["raw"].Items) == 1 and representation["raw"].Items[0].is_a("IfcSweptDiskSolid") + def is_native_swept_disk_solid(self, representations): + for representation in representations: + if len(representation["raw"].Items) > 1 or not representation["raw"].Items[0].is_a("IfcSweptDiskSolid"): + return False + return True - def is_native_faceted_brep(self, representation): - return bool([i for i in representation["raw"].Items if i.is_a() == "IfcFacetedBrep"]) + def is_native_faceted_brep(self, representations): + for representation in representations: + for i in representation["raw"].Items: + if i.is_a() != "IfcFacetedBrep": + return False + return True def get_products_from_shape_representation(self, element): products = [pr.ShapeOfProduct[0] for pr in element.OfProductRepresentation] @@ -634,6 +640,7 @@ class IfcImporter: def create_native_products(self): total = 0 checkpoint = time.time() + bm = bmesh.new() for element in self.native_elements: total += 1 if total % 250 == 0: @@ -641,6 +648,8 @@ class IfcImporter: checkpoint = time.time() native_data = self.native_data[element.GlobalId] representation = native_data["representation"] + if not representation: + continue context_id = representation.ContextOfItems.id() if hasattr(representation, "ContextOfItems") else 0 mesh_name = f"{context_id}/{representation.id()}" mesh = self.meshes.get(mesh_name) @@ -650,16 +659,17 @@ class IfcImporter: elif native_data["type"] == "IfcFacetedBrep": mesh = self.create_native_faceted_brep(element, mesh_name) mesh.BIMMeshProperties.ifc_definition_id = representation.id() + mesh.name = mesh_name self.meshes[mesh_name] = mesh self.create_product(element, mesh=mesh) if native_data["type"] == "IfcFacetedBrep": # The current implementation doesn't reuse vertices, so we weld it after assigning materials. # This welding isn't true to the representation, but is easy and seems inexpensive. - bm = bmesh.new() bm.from_mesh(mesh) bmesh.ops.remove_doubles(bm, verts=bm.verts, dist=0.001) bm.to_mesh(mesh) - bm.free() + bm.clear() + bm.free() print("Done creating geometry") @@ -715,21 +725,27 @@ class IfcImporter: def create_structural_point_connections(self): for product in self.file.by_type("IfcStructuralPointConnection"): + # TODO: make this based off ifcopenshell. See #1409 placement_matrix = ifcopenshell.util.placement.get_local_placement(product.ObjectPlacement) vertex = None - for subelement in self.file.traverse(product): + context = None + representation = None + for subelement in self.file.traverse(product.Representation): if subelement.is_a("IfcVertex") and subelement.VertexGeometry.is_a("IfcCartesianPoint"): vertex = list(subelement.VertexGeometry.Coordinates) - break - if not vertex: + elif subelement.is_a("IfcGeometricRepresentationContext"): + context = subelement + elif subelement.is_a("IfcTopologyRepresentation"): + representation = subelement + if not vertex or not context or not representation: continue # TODO implement non cartesian point vertexes - placement_matrix[0, 3] += vertex[0] * self.unit_scale - placement_matrix[1, 3] += vertex[1] * self.unit_scale - placement_matrix[2, 3] += vertex[2] * self.unit_scale - obj = bpy.data.objects.new("{}/{}".format(product.is_a(), product.Name), None) + + mesh_name = f"{context.id()}/{representation.id()}" + mesh = bpy.data.meshes.new(mesh_name) + mesh.from_pydata([mathutils.Vector(vertex) * self.unit_scale], [], []) + + obj = bpy.data.objects.new("{}/{}".format(product.is_a(), product.Name), mesh) obj.matrix_world = mathutils.Matrix(placement_matrix.tolist()) - obj.empty_display_type = "SPHERE" - obj.empty_display_size = 0.1 self.link_element(product, obj) def create_curve_products(self, products): @@ -843,7 +859,7 @@ class IfcImporter: points = outer_bound[0].copy() [points.extend(p) for p in inner_bounds] tessellated_polygons = mathutils.geometry.tessellate_polygon(outer_bound + inner_bounds) - tessellated_faces = [[{"Coordinates": points[pi]} for pi in t] for t in tessellated_polygons] + tessellated_faces = [({"Coordinates": points[pi]} for pi in t) for t in tessellated_polygons] else: tessellated_faces = [face["Bounds"][0]["Bound"]["Polygon"]] @@ -855,7 +871,7 @@ class IfcImporter: for point in tessellated_face: co.extend( representation["matrix"] - @ mathutils.Vector([c * self.unit_scale for c in point["Coordinates"]]) + @ mathutils.Vector((c * self.unit_scale for c in point["Coordinates"])) ) total_verts += 1 loop_count += 1 diff --git a/src/ifcblenderexport/blenderbim/bim/module/aggregate/__init__.py b/src/blenderbim/blenderbim/bim/module/aggregate/__init__.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/aggregate/__init__.py rename to src/blenderbim/blenderbim/bim/module/aggregate/__init__.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/aggregate/operator.py b/src/blenderbim/blenderbim/bim/module/aggregate/operator.py similarity index 93% rename from src/ifcblenderexport/blenderbim/bim/module/aggregate/operator.py rename to src/blenderbim/blenderbim/bim/module/aggregate/operator.py index 4c546a61bf..ef943fad44 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/aggregate/operator.py +++ b/src/blenderbim/blenderbim/bim/module/aggregate/operator.py @@ -1,7 +1,7 @@ import bpy -import blenderbim.bim.module.aggregate.assign_object as assign_object +import ifcopenshell.api from blenderbim.bim.ifc import IfcStore -from blenderbim.bim.module.aggregate.data import Data +from ifcopenshell.api.aggregate.data import Data class AssignObject(bpy.types.Operator): @@ -18,15 +18,16 @@ class AssignObject(bpy.types.Operator): if not relating_object or not relating_object.BIMObjectProperties.ifc_definition_id: return {"FINISHED"} product = self.file.by_id(props.ifc_definition_id) - assign_object.Usecase( + ifcopenshell.api.run( + "aggregate.assign_object", self.file, - { + **{ "product": product, "relating_object": self.file.by_id(relating_object.BIMObjectProperties.ifc_definition_id), }, - ).execute() + ) bpy.ops.bim.edit_object_placement(obj=related_object.name) - Data.load(props.ifc_definition_id) + Data.load(IfcStore.get_file(), props.ifc_definition_id) bpy.ops.bim.disable_editing_aggregate(obj=related_object.name) spatial_collection = bpy.data.collections.get(related_object.name) diff --git a/src/ifcblenderexport/blenderbim/bim/module/aggregate/ui.py b/src/blenderbim/blenderbim/bim/module/aggregate/ui.py similarity index 90% rename from src/ifcblenderexport/blenderbim/bim/module/aggregate/ui.py rename to src/blenderbim/blenderbim/bim/module/aggregate/ui.py index 6749a6b567..744e369350 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/aggregate/ui.py +++ b/src/blenderbim/blenderbim/bim/module/aggregate/ui.py @@ -1,5 +1,5 @@ from bpy.types import Panel -from blenderbim.bim.module.aggregate.data import Data +from ifcopenshell.api.aggregate.data import Data from blenderbim.bim.ifc import IfcStore @@ -19,7 +19,7 @@ class BIM_PT_aggregate(Panel): if not IfcStore.get_file().by_id(props.ifc_definition_id).is_a("IfcObjectDefinition"): return False if props.ifc_definition_id not in Data.products: - Data.load(props.ifc_definition_id) + Data.load(IfcStore.get_file(), props.ifc_definition_id) if not Data.products[props.ifc_definition_id]: return False return True @@ -29,7 +29,7 @@ class BIM_PT_aggregate(Panel): if not props.ifc_definition_id: return if props.ifc_definition_id not in Data.products: - Data.load(props.ifc_definition_id) + Data.load(IfcStore.get_file(), props.ifc_definition_id) if props.is_editing_aggregate: row = self.layout.row(align=True) diff --git a/src/ifcblenderexport/blenderbim/bim/module/attribute/__init__.py b/src/blenderbim/blenderbim/bim/module/attribute/__init__.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/attribute/__init__.py rename to src/blenderbim/blenderbim/bim/module/attribute/__init__.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/attribute/operator.py b/src/blenderbim/blenderbim/bim/module/attribute/operator.py similarity index 93% rename from src/ifcblenderexport/blenderbim/bim/module/attribute/operator.py rename to src/blenderbim/blenderbim/bim/module/attribute/operator.py index 531c5a6797..ae69fa26a6 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/attribute/operator.py +++ b/src/blenderbim/blenderbim/bim/module/attribute/operator.py @@ -1,9 +1,9 @@ import bpy import json import ifcopenshell -import blenderbim.bim.module.attribute.edit_attributes as edit_attributes +import ifcopenshell.api from blenderbim.bim.ifc import IfcStore -from blenderbim.bim.module.attribute.data import Data +from ifcopenshell.api.attribute.data import Data class EnableEditingAttributes(bpy.types.Operator): @@ -33,7 +33,7 @@ class EnableEditingAttributes(bpy.types.Operator): elif attribute["type"] == "integer": new.int_value = attribute["value"] or 0 elif attribute["type"] == "float": - new.float_value = attribute["value"] or 0. + new.float_value = attribute["value"] or 0.0 elif attribute["type"] == "enum": new.enum_items = json.dumps(attribute["enum_items"]) if attribute["value"]: @@ -95,17 +95,16 @@ class EditAttributes(bpy.types.Operator): elif attribute["type"] == "enum": attributes[attribute["name"]] = blender_attribute.enum_value product = self.file.by_id(oprops.ifc_definition_id) - edit_attributes.Usecase(self.file, { - "product": product, - "attributes": attributes - }).execute() + ifcopenshell.api.run( + "attribute.edit_attributes", self.file, **{"product": product, "attributes": attributes} + ) if "Name" in attributes: new_name = "{}/{}".format(product.is_a(), product.Name or "Unnamed") collection = bpy.data.collections.get(obj.name) if collection: collection.name = new_name obj.name = new_name - Data.load(oprops.ifc_definition_id) + Data.load(IfcStore.get_file(), oprops.ifc_definition_id) bpy.ops.bim.disable_editing_attributes(obj=obj.name, obj_type=self.obj_type) return {"FINISHED"} diff --git a/src/ifcblenderexport/blenderbim/bim/module/attribute/prop.py b/src/blenderbim/blenderbim/bim/module/attribute/prop.py similarity index 91% rename from src/ifcblenderexport/blenderbim/bim/module/attribute/prop.py rename to src/blenderbim/blenderbim/bim/module/attribute/prop.py index 8e57d7af72..4b95bf1865 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/attribute/prop.py +++ b/src/blenderbim/blenderbim/bim/module/attribute/prop.py @@ -1,6 +1,5 @@ import bpy import blenderbim.bim.schema # refactor -from blenderbim.bim.module.material.data import Data from blenderbim.bim.ifc import IfcStore from blenderbim.bim.prop import StrProperty, Attribute from bpy.types import PropertyGroup diff --git a/src/ifcblenderexport/blenderbim/bim/module/attribute/ui.py b/src/blenderbim/blenderbim/bim/module/attribute/ui.py similarity index 96% rename from src/ifcblenderexport/blenderbim/bim/module/attribute/ui.py rename to src/blenderbim/blenderbim/bim/module/attribute/ui.py index 0856d8bfdc..1d345d0fa2 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/attribute/ui.py +++ b/src/blenderbim/blenderbim/bim/module/attribute/ui.py @@ -1,5 +1,6 @@ from bpy.types import Panel -from blenderbim.bim.module.attribute.data import Data +from blenderbim.bim.ifc import IfcStore +from ifcopenshell.api.attribute.data import Data def draw_ui(context, layout, obj_type): @@ -7,7 +8,7 @@ def draw_ui(context, layout, obj_type): oprops = obj.BIMObjectProperties props = obj.BIMAttributeProperties if oprops.ifc_definition_id not in Data.products: - Data.load(oprops.ifc_definition_id) + Data.load(IfcStore.get_file(), oprops.ifc_definition_id) if props.is_editing_attributes: row = layout.row(align=True) diff --git a/src/ifcblenderexport/blenderbim/bim/module/augin/__init__.py b/src/blenderbim/blenderbim/bim/module/augin/__init__.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/augin/__init__.py rename to src/blenderbim/blenderbim/bim/module/augin/__init__.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/augin/operator.py b/src/blenderbim/blenderbim/bim/module/augin/operator.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/augin/operator.py rename to src/blenderbim/blenderbim/bim/module/augin/operator.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/augin/prop.py b/src/blenderbim/blenderbim/bim/module/augin/prop.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/augin/prop.py rename to src/blenderbim/blenderbim/bim/module/augin/prop.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/augin/ui.py b/src/blenderbim/blenderbim/bim/module/augin/ui.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/augin/ui.py rename to src/blenderbim/blenderbim/bim/module/augin/ui.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/bcf/__init__.py b/src/blenderbim/blenderbim/bim/module/bcf/__init__.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/bcf/__init__.py rename to src/blenderbim/blenderbim/bim/module/bcf/__init__.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/bcf/bcfstore.py b/src/blenderbim/blenderbim/bim/module/bcf/bcfstore.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/bcf/bcfstore.py rename to src/blenderbim/blenderbim/bim/module/bcf/bcfstore.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/bcf/operator.py b/src/blenderbim/blenderbim/bim/module/bcf/operator.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/bcf/operator.py rename to src/blenderbim/blenderbim/bim/module/bcf/operator.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/bcf/prop.py b/src/blenderbim/blenderbim/bim/module/bcf/prop.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/bcf/prop.py rename to src/blenderbim/blenderbim/bim/module/bcf/prop.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/bcf/ui.py b/src/blenderbim/blenderbim/bim/module/bcf/ui.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/bcf/ui.py rename to src/blenderbim/blenderbim/bim/module/bcf/ui.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/bimtester/__init__.py b/src/blenderbim/blenderbim/bim/module/bimtester/__init__.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/bimtester/__init__.py rename to src/blenderbim/blenderbim/bim/module/bimtester/__init__.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/bimtester/operator.py b/src/blenderbim/blenderbim/bim/module/bimtester/operator.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/bimtester/operator.py rename to src/blenderbim/blenderbim/bim/module/bimtester/operator.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/bimtester/prop.py b/src/blenderbim/blenderbim/bim/module/bimtester/prop.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/bimtester/prop.py rename to src/blenderbim/blenderbim/bim/module/bimtester/prop.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/bimtester/ui.py b/src/blenderbim/blenderbim/bim/module/bimtester/ui.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/bimtester/ui.py rename to src/blenderbim/blenderbim/bim/module/bimtester/ui.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/clash/__init__.py b/src/blenderbim/blenderbim/bim/module/clash/__init__.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/clash/__init__.py rename to src/blenderbim/blenderbim/bim/module/clash/__init__.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/clash/operator.py b/src/blenderbim/blenderbim/bim/module/clash/operator.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/clash/operator.py rename to src/blenderbim/blenderbim/bim/module/clash/operator.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/clash/prop.py b/src/blenderbim/blenderbim/bim/module/clash/prop.py similarity index 97% rename from src/ifcblenderexport/blenderbim/bim/module/clash/prop.py rename to src/blenderbim/blenderbim/bim/module/clash/prop.py index 185e9fe163..ba685b64d3 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/clash/prop.py +++ b/src/blenderbim/blenderbim/bim/module/clash/prop.py @@ -1,6 +1,5 @@ import bpy from blenderbim.bim.prop import StrProperty, Attribute -from blenderbim.bim.module.owner.data import Data from bpy.types import PropertyGroup from bpy.props import ( PointerProperty, diff --git a/src/ifcblenderexport/blenderbim/bim/module/clash/ui.py b/src/blenderbim/blenderbim/bim/module/clash/ui.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/clash/ui.py rename to src/blenderbim/blenderbim/bim/module/clash/ui.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/classification/__init__.py b/src/blenderbim/blenderbim/bim/module/classification/__init__.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/classification/__init__.py rename to src/blenderbim/blenderbim/bim/module/classification/__init__.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/classification/operator.py b/src/blenderbim/blenderbim/bim/module/classification/operator.py similarity index 82% rename from src/ifcblenderexport/blenderbim/bim/module/classification/operator.py rename to src/blenderbim/blenderbim/bim/module/classification/operator.py index 1150f138f3..014f6865f9 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/classification/operator.py +++ b/src/blenderbim/blenderbim/bim/module/classification/operator.py @@ -1,13 +1,8 @@ import bpy import json -import blenderbim.bim.module.classification.add_classification as add_classification -import blenderbim.bim.module.classification.remove_classification as remove_classification -import blenderbim.bim.module.classification.edit_classification as edit_classification -import blenderbim.bim.module.classification.add_reference as add_reference -import blenderbim.bim.module.classification.remove_reference as remove_reference -import blenderbim.bim.module.classification.edit_reference as edit_reference +import ifcopenshell.api from blenderbim.bim.ifc import IfcStore -from blenderbim.bim.module.classification.data import Data +from ifcopenshell.api.classification.data import Data from blenderbim.bim.module.classification.prop import getClassifications, getReferences @@ -34,10 +29,12 @@ class AddClassification(bpy.types.Operator): def execute(self, context): props = context.scene.BIMClassificationProperties - add_classification.Usecase( - IfcStore.get_file(), {"classification": Data.library_file.by_id(int(props.available_classifications))} - ).execute() - Data.load() + ifcopenshell.api.run( + "classification.add_classification", + IfcStore.get_file(), + **{"classification": Data.library_file.by_id(int(props.available_classifications))}, + ) + Data.load(IfcStore.get_file()) return {"FINISHED"} @@ -80,8 +77,12 @@ class RemoveClassification(bpy.types.Operator): def execute(self, context): self.file = IfcStore.get_file() - remove_classification.Usecase(self.file, {"classification": self.file.by_id(self.classification)}).execute() - Data.load() + ifcopenshell.api.run( + "classification.remove_classification", + self.file, + **{"classification": self.file.by_id(self.classification)}, + ) + Data.load(IfcStore.get_file()) return {"FINISHED"} @@ -100,10 +101,12 @@ class EditClassification(bpy.types.Operator): else: attributes[attribute.name] = attribute.string_value self.file = IfcStore.get_file() - edit_classification.Usecase( - self.file, {"classification": self.file.by_id(props.active_classification_id), "attributes": attributes} - ).execute() - Data.load() + ifcopenshell.api.run( + "classification.edit_classification", + self.file, + **{"classification": self.file.by_id(props.active_classification_id), "attributes": attributes}, + ) + Data.load(IfcStore.get_file()) bpy.ops.bim.disable_editing_classification() return {"FINISHED"} @@ -152,15 +155,16 @@ class RemoveClassificationReference(bpy.types.Operator): def execute(self, context): obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object self.file = IfcStore.get_file() - remove_reference.Usecase( + ifcopenshell.api.run( + "classification.remove_reference", self.file, - { + **{ "reference": self.file.by_id(self.reference), "product": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id), }, - ).execute() - Data.load(obj.BIMObjectProperties.ifc_definition_id) - Data.load() + ) + Data.load(IfcStore.get_file(), obj.BIMObjectProperties.ifc_definition_id) + Data.load(IfcStore.get_file()) return {"FINISHED"} @@ -179,10 +183,12 @@ class EditClassificationReference(bpy.types.Operator): else: attributes[attribute.name] = attribute.string_value self.file = IfcStore.get_file() - edit_reference.Usecase( - self.file, {"reference": self.file.by_id(props.active_reference_id), "attributes": attributes} - ).execute() - Data.load() + ifcopenshell.api.run( + "classification.edit_reference", + self.file, + **{"reference": self.file.by_id(props.active_reference_id), "attributes": attributes}, + ) + Data.load(IfcStore.get_file()) bpy.ops.bim.disable_editing_classification_reference() return {"FINISHED"} @@ -206,16 +212,17 @@ class AddClassificationReference(bpy.types.Operator): classification = self.file.by_id(classification_id) break - add_reference.Usecase( + ifcopenshell.api.run( + "classification.add_reference", self.file, - { + **{ "reference": Data.library_file.by_id(self.reference), "product": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id), - "classification": classification + "classification": classification, }, - ).execute() - Data.load(obj.BIMObjectProperties.ifc_definition_id) - Data.load() + ) + Data.load(IfcStore.get_file(), obj.BIMObjectProperties.ifc_definition_id) + Data.load(IfcStore.get_file()) return {"FINISHED"} diff --git a/src/ifcblenderexport/blenderbim/bim/module/classification/prop.py b/src/blenderbim/blenderbim/bim/module/classification/prop.py similarity index 97% rename from src/ifcblenderexport/blenderbim/bim/module/classification/prop.py rename to src/blenderbim/blenderbim/bim/module/classification/prop.py index 3793b29ec3..85ffb7ce8b 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/classification/prop.py +++ b/src/blenderbim/blenderbim/bim/module/classification/prop.py @@ -1,6 +1,6 @@ import bpy from blenderbim.bim.prop import StrProperty, Attribute -from blenderbim.bim.module.classification.data import Data +from ifcopenshell.api.classification.data import Data from bpy.types import PropertyGroup from bpy.props import ( PointerProperty, diff --git a/src/ifcblenderexport/blenderbim/bim/module/classification/ui.py b/src/blenderbim/blenderbim/bim/module/classification/ui.py similarity index 96% rename from src/ifcblenderexport/blenderbim/bim/module/classification/ui.py rename to src/blenderbim/blenderbim/bim/module/classification/ui.py index 122201c8e9..d0b65021a8 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/classification/ui.py +++ b/src/blenderbim/blenderbim/bim/module/classification/ui.py @@ -1,6 +1,6 @@ from bpy.types import Panel, UIList from blenderbim.bim.ifc import IfcStore -from blenderbim.bim.module.classification.data import Data +from ifcopenshell.api.classification.data import Data class BIM_PT_classifications(Panel): @@ -17,7 +17,7 @@ class BIM_PT_classifications(Panel): def draw(self, context): if not Data.is_loaded: - Data.load() + Data.load(IfcStore.get_file()) self.props = context.scene.BIMClassificationProperties @@ -79,9 +79,9 @@ class BIM_PT_classification_references(Panel): self.props = obj.BIMClassificationReferenceProperties self.file = IfcStore.get_file() if not Data.is_loaded: - Data.load() + Data.load(IfcStore.get_file()) if self.oprops.ifc_definition_id not in Data.products: - Data.load(self.oprops.ifc_definition_id) + Data.load(IfcStore.get_file(), self.oprops.ifc_definition_id) self.draw_add_ui() diff --git a/src/ifcblenderexport/blenderbim/bim/module/cobie/__init__.py b/src/blenderbim/blenderbim/bim/module/cobie/__init__.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/cobie/__init__.py rename to src/blenderbim/blenderbim/bim/module/cobie/__init__.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/cobie/operator.py b/src/blenderbim/blenderbim/bim/module/cobie/operator.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/cobie/operator.py rename to src/blenderbim/blenderbim/bim/module/cobie/operator.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/cobie/prop.py b/src/blenderbim/blenderbim/bim/module/cobie/prop.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/cobie/prop.py rename to src/blenderbim/blenderbim/bim/module/cobie/prop.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/cobie/ui.py b/src/blenderbim/blenderbim/bim/module/cobie/ui.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/cobie/ui.py rename to src/blenderbim/blenderbim/bim/module/cobie/ui.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/constraint/__init__.py b/src/blenderbim/blenderbim/bim/module/constraint/__init__.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/constraint/__init__.py rename to src/blenderbim/blenderbim/bim/module/constraint/__init__.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/constraint/operator.py b/src/blenderbim/blenderbim/bim/module/constraint/operator.py similarity index 80% rename from src/ifcblenderexport/blenderbim/bim/module/constraint/operator.py rename to src/blenderbim/blenderbim/bim/module/constraint/operator.py index 0bbcdc5f54..6998ed39d2 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/constraint/operator.py +++ b/src/blenderbim/blenderbim/bim/module/constraint/operator.py @@ -1,13 +1,9 @@ import bpy import json +import ifcopenshell.api import ifcopenshell.util.attribute -import blenderbim.bim.module.constraint.add_objective as add_objective -import blenderbim.bim.module.constraint.edit_objective as edit_objective -import blenderbim.bim.module.constraint.remove_constraint as remove_constraint -import blenderbim.bim.module.constraint.assign_constraint as assign_constraint -import blenderbim.bim.module.constraint.unassign_constraint as unassign_constraint from blenderbim.bim.ifc import IfcStore -from blenderbim.bim.module.constraint.data import Data +from ifcopenshell.api.constraint.data import Data class LoadObjectives(bpy.types.Operator): @@ -83,8 +79,8 @@ class AddObjective(bpy.types.Operator): bl_label = "Add Objective" def execute(self, context): - result = add_objective.Usecase(IfcStore.get_file()).execute() - Data.load() + result = ifcopenshell.api.run("constraint.add_objective", IfcStore.get_file()) + Data.load(IfcStore.get_file()) bpy.ops.bim.load_objectives() bpy.ops.bim.enable_editing_constraint(constraint=result.id()) return {"FINISHED"} @@ -105,10 +101,12 @@ class EditObjective(bpy.types.Operator): else: attributes[attribute.name] = attribute.string_value self.file = IfcStore.get_file() - edit_objective.Usecase( - self.file, {"objective": self.file.by_id(props.active_constraint_id), "attributes": attributes} - ).execute() - Data.load() + ifcopenshell.api.run( + "constraint.edit_objective", + self.file, + **{"objective": self.file.by_id(props.active_constraint_id), "attributes": attributes} + ) + Data.load(IfcStore.get_file()) bpy.ops.bim.load_objectives() return {"FINISHED"} @@ -121,8 +119,10 @@ class RemoveConstraint(bpy.types.Operator): def execute(self, context): props = context.scene.BIMConstraintProperties self.file = IfcStore.get_file() - remove_constraint.Usecase(self.file, {"constraint": self.file.by_id(self.constraint)}).execute() - Data.load() + ifcopenshell.api.run( + "constraint.remove_constraint", self.file, **{"constraint": self.file.by_id(self.constraint)} + ) + Data.load(IfcStore.get_file()) if props.is_editing == "IfcObjective": bpy.ops.bim.load_objectives() return {"FINISHED"} @@ -163,11 +163,15 @@ class AssignConstraint(bpy.types.Operator): def execute(self, context): obj = bpy.data.objects.get(self.obj) if self.obj else context.active_object self.file = IfcStore.get_file() - assign_constraint.Usecase(self.file, { - "product": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id), - "constraint": self.file.by_id(self.constraint) - }).execute() - Data.load(obj.BIMObjectProperties.ifc_definition_id) + ifcopenshell.api.run( + "constraint.assign_constraint", + self.file, + **{ + "product": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id), + "constraint": self.file.by_id(self.constraint), + } + ) + Data.load(IfcStore.get_file(), obj.BIMObjectProperties.ifc_definition_id) return {"FINISHED"} @@ -180,9 +184,13 @@ class UnassignConstraint(bpy.types.Operator): def execute(self, context): obj = bpy.data.objects.get(self.obj) if self.obj else context.active_object self.file = IfcStore.get_file() - unassign_constraint.Usecase(self.file, { - "product": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id), - "constraint": self.file.by_id(self.constraint) - }).execute() - Data.load(obj.BIMObjectProperties.ifc_definition_id) + ifcopenshell.api.run( + "constraint.unassign_constraint", + self.file, + **{ + "product": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id), + "constraint": self.file.by_id(self.constraint), + } + ) + Data.load(IfcStore.get_file(), obj.BIMObjectProperties.ifc_definition_id) return {"FINISHED"} diff --git a/src/ifcblenderexport/blenderbim/bim/module/constraint/prop.py b/src/blenderbim/blenderbim/bim/module/constraint/prop.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/constraint/prop.py rename to src/blenderbim/blenderbim/bim/module/constraint/prop.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/constraint/ui.py b/src/blenderbim/blenderbim/bim/module/constraint/ui.py similarity index 96% rename from src/ifcblenderexport/blenderbim/bim/module/constraint/ui.py rename to src/blenderbim/blenderbim/bim/module/constraint/ui.py index 329a203779..c6132dc43d 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/constraint/ui.py +++ b/src/blenderbim/blenderbim/bim/module/constraint/ui.py @@ -1,6 +1,6 @@ from bpy.types import Panel, UIList from blenderbim.bim.ifc import IfcStore -from blenderbim.bim.module.constraint.data import Data +from ifcopenshell.api.constraint.data import Data class BIM_PT_constraints(Panel): @@ -17,7 +17,7 @@ class BIM_PT_constraints(Panel): def draw(self, context): if not Data.is_loaded: - Data.load() + Data.load(IfcStore.get_file()) self.props = context.scene.BIMConstraintProperties @@ -73,9 +73,9 @@ class BIM_PT_object_constraints(Panel): self.props = obj.BIMObjectConstraintProperties self.file = IfcStore.get_file() if not Data.is_loaded: - Data.load() + Data.load(IfcStore.get_file()) if self.oprops.ifc_definition_id not in Data.products: - Data.load(self.oprops.ifc_definition_id) + Data.load(IfcStore.get_file(), self.oprops.ifc_definition_id) self.draw_add_ui() diff --git a/src/ifcblenderexport/blenderbim/bim/module/context/__init__.py b/src/blenderbim/blenderbim/bim/module/context/__init__.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/context/__init__.py rename to src/blenderbim/blenderbim/bim/module/context/__init__.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/context/operator.py b/src/blenderbim/blenderbim/bim/module/context/operator.py similarity index 70% rename from src/ifcblenderexport/blenderbim/bim/module/context/operator.py rename to src/blenderbim/blenderbim/bim/module/context/operator.py index 2fbdb94157..27ee39ec74 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/context/operator.py +++ b/src/blenderbim/blenderbim/bim/module/context/operator.py @@ -1,8 +1,7 @@ import bpy -import blenderbim.bim.module.context.add_context as add_context -import blenderbim.bim.module.context.remove_context as remove_context +import ifcopenshell.api from blenderbim.bim.ifc import IfcStore -from blenderbim.bim.module.context.data import Data +from ifcopenshell.api.context.data import Data class AddSubcontext(bpy.types.Operator): @@ -14,15 +13,16 @@ class AddSubcontext(bpy.types.Operator): def execute(self, context): self.file = IfcStore.get_file() - add_context.Usecase( + ifcopenshell.api.run( + "context.add_context", self.file, - { + **{ "context": self.context or bpy.context.scene.BIMProperties.available_contexts, "subcontext": self.subcontext or bpy.context.scene.BIMProperties.available_subcontexts, "target_view": self.target_view or bpy.context.scene.BIMProperties.available_target_views, }, - ).execute() - Data.load() + ) + Data.load(IfcStore.get_file()) return {"FINISHED"} @@ -33,7 +33,8 @@ class RemoveSubcontext(bpy.types.Operator): def execute(self, context): self.file = IfcStore.get_file() - usecase = remove_context.Usecase(self.file, {"context": self.file.by_id(self.ifc_definition_id)}) - usecase.execute() - Data.load() + ifcopenshell.api.run( + "context.remove_context", self.file, **{"context": self.file.by_id(self.ifc_definition_id)} + ) + Data.load(IfcStore.get_file()) return {"FINISHED"} diff --git a/src/ifcblenderexport/blenderbim/bim/module/context/ui.py b/src/blenderbim/blenderbim/bim/module/context/ui.py similarity index 94% rename from src/ifcblenderexport/blenderbim/bim/module/context/ui.py rename to src/blenderbim/blenderbim/bim/module/context/ui.py index 07182ab2ac..2573cfa80f 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/context/ui.py +++ b/src/blenderbim/blenderbim/bim/module/context/ui.py @@ -1,5 +1,5 @@ from bpy.types import Panel -from blenderbim.bim.module.context.data import Data +from ifcopenshell.api.context.data import Data from blenderbim.bim.ifc import IfcStore @@ -17,7 +17,7 @@ class BIM_PT_context(Panel): def draw(self, context): if not Data.is_loaded: - Data.load() + Data.load(IfcStore.get_file()) props = context.scene.BIMProperties diff --git a/src/ifcblenderexport/blenderbim/bim/module/covetool/__init__.py b/src/blenderbim/blenderbim/bim/module/covetool/__init__.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/covetool/__init__.py rename to src/blenderbim/blenderbim/bim/module/covetool/__init__.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/covetool/api.py b/src/blenderbim/blenderbim/bim/module/covetool/api.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/covetool/api.py rename to src/blenderbim/blenderbim/bim/module/covetool/api.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/covetool/operator.py b/src/blenderbim/blenderbim/bim/module/covetool/operator.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/covetool/operator.py rename to src/blenderbim/blenderbim/bim/module/covetool/operator.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/covetool/prop.py b/src/blenderbim/blenderbim/bim/module/covetool/prop.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/covetool/prop.py rename to src/blenderbim/blenderbim/bim/module/covetool/prop.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/covetool/ui.py b/src/blenderbim/blenderbim/bim/module/covetool/ui.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/covetool/ui.py rename to src/blenderbim/blenderbim/bim/module/covetool/ui.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/csv/__init__.py b/src/blenderbim/blenderbim/bim/module/csv/__init__.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/csv/__init__.py rename to src/blenderbim/blenderbim/bim/module/csv/__init__.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/csv/operator.py b/src/blenderbim/blenderbim/bim/module/csv/operator.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/csv/operator.py rename to src/blenderbim/blenderbim/bim/module/csv/operator.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/csv/prop.py b/src/blenderbim/blenderbim/bim/module/csv/prop.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/csv/prop.py rename to src/blenderbim/blenderbim/bim/module/csv/prop.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/csv/ui.py b/src/blenderbim/blenderbim/bim/module/csv/ui.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/csv/ui.py rename to src/blenderbim/blenderbim/bim/module/csv/ui.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/debug/__init__.py b/src/blenderbim/blenderbim/bim/module/debug/__init__.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/debug/__init__.py rename to src/blenderbim/blenderbim/bim/module/debug/__init__.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/debug/operator.py b/src/blenderbim/blenderbim/bim/module/debug/operator.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/debug/operator.py rename to src/blenderbim/blenderbim/bim/module/debug/operator.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/debug/prop.py b/src/blenderbim/blenderbim/bim/module/debug/prop.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/debug/prop.py rename to src/blenderbim/blenderbim/bim/module/debug/prop.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/debug/ui.py b/src/blenderbim/blenderbim/bim/module/debug/ui.py similarity index 93% rename from src/ifcblenderexport/blenderbim/bim/module/debug/ui.py rename to src/blenderbim/blenderbim/bim/module/debug/ui.py index 707a12e34e..8372ae76a0 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/debug/ui.py +++ b/src/blenderbim/blenderbim/bim/module/debug/ui.py @@ -53,6 +53,9 @@ class BIM_PT_debug(Panel): row = layout.row(align=True) row.prop(attribute, "name", text="") row.prop(attribute, "string_value", text="") + if attribute.name == "GlobalId": + op = row.operator("bim.select_global_id", icon="RESTRICT_SELECT_OFF", text="") + op.global_id = attribute.string_value if attribute.int_value: row.operator( "bim.inspect_from_step_id", icon="DISCLOSURE_TRI_RIGHT", text="" diff --git a/src/ifcblenderexport/blenderbim/bim/module/diff/__init__.py b/src/blenderbim/blenderbim/bim/module/diff/__init__.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/diff/__init__.py rename to src/blenderbim/blenderbim/bim/module/diff/__init__.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/diff/operator.py b/src/blenderbim/blenderbim/bim/module/diff/operator.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/diff/operator.py rename to src/blenderbim/blenderbim/bim/module/diff/operator.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/diff/prop.py b/src/blenderbim/blenderbim/bim/module/diff/prop.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/diff/prop.py rename to src/blenderbim/blenderbim/bim/module/diff/prop.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/diff/ui.py b/src/blenderbim/blenderbim/bim/module/diff/ui.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/diff/ui.py rename to src/blenderbim/blenderbim/bim/module/diff/ui.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/document/__init__.py b/src/blenderbim/blenderbim/bim/module/document/__init__.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/document/__init__.py rename to src/blenderbim/blenderbim/bim/module/document/__init__.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/document/operator.py b/src/blenderbim/blenderbim/bim/module/document/operator.py similarity index 82% rename from src/ifcblenderexport/blenderbim/bim/module/document/operator.py rename to src/blenderbim/blenderbim/bim/module/document/operator.py index f6e4e46714..d81b68877d 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/document/operator.py +++ b/src/blenderbim/blenderbim/bim/module/document/operator.py @@ -1,15 +1,9 @@ import bpy import json +import ifcopenshell.api import ifcopenshell.util.attribute -import blenderbim.bim.module.document.add_information as add_information -import blenderbim.bim.module.document.add_reference as add_reference -import blenderbim.bim.module.document.edit_information as edit_information -import blenderbim.bim.module.document.edit_reference as edit_reference -import blenderbim.bim.module.document.remove_document as remove_document -import blenderbim.bim.module.document.assign_document as assign_document -import blenderbim.bim.module.document.unassign_document as unassign_document from blenderbim.bim.ifc import IfcStore -from blenderbim.bim.module.document.data import Data +from ifcopenshell.api.document.data import Data class LoadInformation(bpy.types.Operator): @@ -116,8 +110,8 @@ class AddInformation(bpy.types.Operator): bl_label = "Add Information" def execute(self, context): - result = add_information.Usecase(IfcStore.get_file()).execute() - Data.load() + result = ifcopenshell.api.run("document.add_information", IfcStore.get_file()) + Data.load(IfcStore.get_file()) bpy.ops.bim.load_information() bpy.ops.bim.enable_editing_document(document=result.id()) return {"FINISHED"} @@ -128,8 +122,8 @@ class AddDocumentReference(bpy.types.Operator): bl_label = "Add Document Reference" def execute(self, context): - result = add_reference.Usecase(IfcStore.get_file()).execute() - Data.load() + result = ifcopenshell.api.run("document.add_reference", IfcStore.get_file()) + Data.load(IfcStore.get_file()) bpy.ops.bim.load_document_references() bpy.ops.bim.enable_editing_document(document=result.id()) return {"FINISHED"} @@ -150,10 +144,12 @@ class EditInformation(bpy.types.Operator): else: attributes[attribute.name] = attribute.string_value self.file = IfcStore.get_file() - edit_information.Usecase( - self.file, {"information": self.file.by_id(props.active_document_id), "attributes": attributes} - ).execute() - Data.load() + ifcopenshell.api.run( + "document.edit_information", + self.file, + **{"information": self.file.by_id(props.active_document_id), "attributes": attributes} + ) + Data.load(IfcStore.get_file()) bpy.ops.bim.load_information() return {"FINISHED"} @@ -171,10 +167,12 @@ class EditDocumentReference(bpy.types.Operator): else: attributes[attribute.name] = attribute.string_value self.file = IfcStore.get_file() - edit_reference.Usecase( - self.file, {"reference": self.file.by_id(props.active_document_id), "attributes": attributes} - ).execute() - Data.load() + ifcopenshell.api.run( + "document.edit_reference", + self.file, + **{"reference": self.file.by_id(props.active_document_id), "attributes": attributes} + ) + Data.load(IfcStore.get_file()) bpy.ops.bim.load_document_references() return {"FINISHED"} @@ -187,8 +185,8 @@ class RemoveDocument(bpy.types.Operator): def execute(self, context): props = context.scene.BIMDocumentProperties self.file = IfcStore.get_file() - remove_document.Usecase(self.file, {"document": self.file.by_id(self.document)}).execute() - Data.load() + ifcopenshell.api.run("document.remove_document", self.file, **{"document": self.file.by_id(self.document)}) + Data.load(IfcStore.get_file()) if props.is_editing == "information": bpy.ops.bim.load_information() elif props.is_editing == "reference": @@ -233,11 +231,15 @@ class AssignDocument(bpy.types.Operator): def execute(self, context): obj = bpy.data.objects.get(self.obj) if self.obj else context.active_object self.file = IfcStore.get_file() - assign_document.Usecase(self.file, { - "product": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id), - "document": self.file.by_id(self.document) - }).execute() - Data.load(obj.BIMObjectProperties.ifc_definition_id) + ifcopenshell.api.run( + "document.assign_document", + self.file, + **{ + "product": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id), + "document": self.file.by_id(self.document), + } + ) + Data.load(IfcStore.get_file(), obj.BIMObjectProperties.ifc_definition_id) return {"FINISHED"} @@ -250,9 +252,13 @@ class UnassignDocument(bpy.types.Operator): def execute(self, context): obj = bpy.data.objects.get(self.obj) if self.obj else context.active_object self.file = IfcStore.get_file() - unassign_document.Usecase(self.file, { - "product": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id), - "document": self.file.by_id(self.document) - }).execute() - Data.load(obj.BIMObjectProperties.ifc_definition_id) + ifcopenshell.api.run( + "document.unassign_document", + self.file, + **{ + "product": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id), + "document": self.file.by_id(self.document), + } + ) + Data.load(IfcStore.get_file(), obj.BIMObjectProperties.ifc_definition_id) return {"FINISHED"} diff --git a/src/ifcblenderexport/blenderbim/bim/module/document/prop.py b/src/blenderbim/blenderbim/bim/module/document/prop.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/document/prop.py rename to src/blenderbim/blenderbim/bim/module/document/prop.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/document/ui.py b/src/blenderbim/blenderbim/bim/module/document/ui.py similarity index 97% rename from src/ifcblenderexport/blenderbim/bim/module/document/ui.py rename to src/blenderbim/blenderbim/bim/module/document/ui.py index d1e713902d..1893fb620e 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/document/ui.py +++ b/src/blenderbim/blenderbim/bim/module/document/ui.py @@ -1,6 +1,6 @@ from bpy.types import Panel, UIList from blenderbim.bim.ifc import IfcStore -from blenderbim.bim.module.document.data import Data +from ifcopenshell.api.document.data import Data class BIM_PT_documents(Panel): @@ -17,7 +17,7 @@ class BIM_PT_documents(Panel): def draw(self, context): if not Data.is_loaded: - Data.load() + Data.load(IfcStore.get_file()) self.props = context.scene.BIMDocumentProperties @@ -77,9 +77,9 @@ class BIM_PT_object_documents(Panel): self.props = obj.BIMObjectDocumentProperties self.file = IfcStore.get_file() if not Data.is_loaded: - Data.load() + Data.load(IfcStore.get_file()) if self.oprops.ifc_definition_id not in Data.products: - Data.load(self.oprops.ifc_definition_id) + Data.load(IfcStore.get_file(), self.oprops.ifc_definition_id) self.draw_add_ui() diff --git a/src/ifcblenderexport/blenderbim/bim/module/drawing/__init__.py b/src/blenderbim/blenderbim/bim/module/drawing/__init__.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/drawing/__init__.py rename to src/blenderbim/blenderbim/bim/module/drawing/__init__.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/drawing/operator.py b/src/blenderbim/blenderbim/bim/module/drawing/operator.py similarity index 96% rename from src/ifcblenderexport/blenderbim/bim/module/drawing/operator.py rename to src/blenderbim/blenderbim/bim/module/drawing/operator.py index 72b3f7ccc8..909f654996 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/drawing/operator.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/operator.py @@ -5,8 +5,8 @@ import subprocess import webbrowser from blenderbim.bim.operator import open_with_user_command from blenderbim.bim.ifc import IfcStore -from blenderbim.bim.module.group.data import Data as GroupData -from blenderbim.bim.module.pset.data import Data as PsetData +from ifcopenshell.api.group.data import Data as GroupData +from ifcopenshell.api.pset.data import Data as PsetData cwd = os.path.dirname(os.path.realpath(__file__)) diff --git a/src/ifcblenderexport/blenderbim/bim/module/drawing/ui.py b/src/blenderbim/blenderbim/bim/module/drawing/ui.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/drawing/ui.py rename to src/blenderbim/blenderbim/bim/module/drawing/ui.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/geometry/__init__.py b/src/blenderbim/blenderbim/bim/module/geometry/__init__.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/geometry/__init__.py rename to src/blenderbim/blenderbim/bim/module/geometry/__init__.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/geometry/helper.py b/src/blenderbim/blenderbim/bim/module/geometry/helper.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/geometry/helper.py rename to src/blenderbim/blenderbim/bim/module/geometry/helper.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/geometry/operator.py b/src/blenderbim/blenderbim/bim/module/geometry/operator.py similarity index 86% rename from src/ifcblenderexport/blenderbim/bim/module/geometry/operator.py rename to src/blenderbim/blenderbim/bim/module/geometry/operator.py index 6119164df7..97c579c005 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/geometry/operator.py +++ b/src/blenderbim/blenderbim/bim/module/geometry/operator.py @@ -4,19 +4,12 @@ import ifcopenshell import ifcopenshell.util.unit import ifcopenshell.util.element import logging -import blenderbim.bim.module.geometry.edit_object_placement as edit_object_placement -import blenderbim.bim.module.geometry.add_representation as add_representation -import blenderbim.bim.module.geometry.map_representation as map_representation -import blenderbim.bim.module.geometry.assign_styles as assign_styles -import blenderbim.bim.module.geometry.assign_representation as assign_representation -import blenderbim.bim.module.geometry.unassign_representation as unassign_representation -import blenderbim.bim.module.geometry.remove_representation as remove_representation -import blenderbim.bim.module.grid.create_axis_curve as create_axis_curve +import ifcopenshell.api from blenderbim.bim.ifc import IfcStore from blenderbim.bim import import_ifc -from blenderbim.bim.module.geometry.data import Data -from blenderbim.bim.module.context.data import Data as ContextData -from blenderbim.bim.module.void.data import Data as VoidData +from ifcopenshell.api.geometry.data import Data +from ifcopenshell.api.context.data import Data as ContextData +from ifcopenshell.api.void.data import Data as VoidData from mathutils import Vector @@ -55,13 +48,14 @@ class EditObjectPlacement(bpy.types.Operator): float(props.blender_x_axis_ordinate), ) ) - edit_object_placement.Usecase( + ifcopenshell.api.run( + "geometry.edit_object_placement", self.file, - { + **{ "product": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id), "matrix": matrix, }, - ).execute() + ) return {"FINISHED"} @@ -103,7 +97,7 @@ class AddRepresentation(bpy.types.Operator): "should_force_triangulation": context.scene.BIMGeometryProperties.should_force_triangulation, } - result = add_representation.Usecase(self.file, representation_data).execute() + result = ifcopenshell.api.run("geometry.add_representation", self.file, **representation_data) if not result: print("Failed to write shape representation") @@ -117,12 +111,15 @@ class AddRepresentation(bpy.types.Operator): and context_of_items.ContextIdentifier == "Body" ): representation_data["context"] = self.file.by_id(box_context_id) - new_box = add_representation.Usecase(self.file, representation_data).execute() - assign_representation.Usecase(self.file, {"product": product, "representation": new_box}).execute() + new_box = ifcopenshell.api.run("geometry.add_representation", self.file, **representation_data) + ifcopenshell.api.run( + "geometry.assign_representation", self.file, **{"product": product, "representation": new_box} + ) - assign_styles.Usecase( + ifcopenshell.api.run( + "geometry.assign_styles", self.file, - { + **{ "shape_representation": result, "styles": [ self.file.by_id(s.material.BIMMaterialProperties.ifc_style_id) @@ -131,15 +128,17 @@ class AddRepresentation(bpy.types.Operator): ], "should_use_presentation_style_assignment": context.scene.BIMGeometryProperties.should_use_presentation_style_assignment, }, - ).execute() - assign_representation.Usecase(self.file, {"product": product, "representation": result}).execute() + ) + ifcopenshell.api.run( + "geometry.assign_representation", self.file, **{"product": product, "representation": result} + ) existing_mesh = obj.data mesh = obj.data.copy() mesh.name = "{}/{}".format(context_id, result.id()) mesh.BIMMeshProperties.ifc_definition_id = int(result.id()) obj.data = mesh - Data.load(obj.BIMObjectProperties.ifc_definition_id) + Data.load(IfcStore.get_file(), obj.BIMObjectProperties.ifc_definition_id) return {"FINISHED"} @@ -190,7 +189,7 @@ class SwitchRepresentation(bpy.types.Operator): if self.disable_opening_subtractions and self.context_of_items.ContextIdentifier == "Body": if self.oprops.ifc_definition_id not in VoidData.products: - VoidData.load(self.oprops.ifc_definition_id) + VoidData.load(IfcStore.get_file(), self.oprops.ifc_definition_id) for opening_id in VoidData.products[self.oprops.ifc_definition_id]: if opening_id in IfcStore.id_map: opening = IfcStore.id_map[opening_id] @@ -213,7 +212,6 @@ class RemoveRepresentation(bpy.types.Operator): self.file = IfcStore.get_file() representation = self.file.by_id(self.representation_id) obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object - product = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id) is_mapped_representation = representation.RepresentationType == "MappedRepresentation" if is_mapped_representation: mesh_name = "{}/{}".format( @@ -232,9 +230,11 @@ class RemoveRepresentation(bpy.types.Operator): if not is_mapped_representation: bpy.data.meshes.remove(mesh) product = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id) - unassign_representation.Usecase(self.file, {"product": product, "representation": representation}).execute() - remove_representation.Usecase(self.file, {"representation": representation}).execute() - Data.load(product.id()) + ifcopenshell.api.run( + "geometry.unassign_representation", self.file, **{"product": product, "representation": representation} + ) + ifcopenshell.api.run("geometry.remove_representation", self.file, **{"representation": representation}) + Data.load(IfcStore.get_file(), product.id()) return {"FINISHED"} @@ -248,13 +248,13 @@ class MapRepresentations(bpy.types.Operator): related_object = IfcStore.id_map[self.product_id] if self.product_id not in Data.products: - Data.load(self.product_id) + Data.load(IfcStore.get_file(), self.product_id) for representation_id in Data.products[self.product_id]: bpy.ops.bim.remove_representation(obj=related_object.name, representation_id=representation_id) if self.type_product_id not in Data.products: - Data.load(self.type_product_id) + Data.load(IfcStore.get_file(), self.type_product_id) for representation_id in Data.products[self.type_product_id]: bpy.ops.bim.map_representation( @@ -283,11 +283,13 @@ class MapRepresentation(bpy.types.Operator): product = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id) if obj_data: obj.data = obj_data - result = map_representation.Usecase( - self.file, {"representation": self.file.by_id(self.representation_id)} - ).execute() - assign_representation.Usecase(self.file, {"product": product, "representation": result}).execute() - Data.load(obj.BIMObjectProperties.ifc_definition_id) + result = ifcopenshell.api.run( + "geometry.map_representation", self.file, **{"representation": self.file.by_id(self.representation_id)} + ) + ifcopenshell.api.run( + "geometry.assign_representation", self.file, **{"product": product, "representation": result} + ) + Data.load(IfcStore.get_file(), obj.BIMObjectProperties.ifc_definition_id) return {"FINISHED"} @@ -299,7 +301,7 @@ class UpdateMeshRepresentation(bpy.types.Operator): def execute(self, context): if not ContextData.is_loaded: - ContextData.load() + ContextData.load(IfcStore.get_file()) objs = [bpy.data.objects.get(self.obj)] if self.obj else bpy.context.selected_objects self.file = IfcStore.get_file() @@ -313,7 +315,7 @@ class UpdateMeshRepresentation(bpy.types.Operator): product = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id) if product.is_a("IfcGridAxis"): - create_axis_curve.Usecase(self.file, {"AxisCurve": obj, "grid_axis": product}).execute() + ifcopenshell.api.run("grid.create_axis_curve", self.file, **{"AxisCurve": obj, "grid_axis": product}) return bpy.ops.bim.edit_object_placement(obj=obj.name) @@ -340,12 +342,12 @@ class UpdateMeshRepresentation(bpy.types.Operator): "total_items": max(1, len(obj.material_slots)), "should_force_faceted_brep": context.scene.BIMGeometryProperties.should_force_faceted_brep, "should_force_triangulation": context.scene.BIMGeometryProperties.should_force_triangulation, - "ifc_representation_class": self.ifc_representation_class + "ifc_representation_class": self.ifc_representation_class, } - new_representation = add_representation.Usecase(self.file, representation_data).execute() + new_representation = ifcopenshell.api.run("geometry.add_representation", self.file, **representation_data) - #if product.is_a("IfcWall"): + # if product.is_a("IfcWall"): # # Generate axis representation # axis_context_id = get_context_id("Model", "Axis", "MODEL_VIEW") # old_axis = ifcopenshell.util.element.get_representation(product, "Model", "Axis", "MODEL_VIEW") @@ -372,13 +374,14 @@ class UpdateMeshRepresentation(bpy.types.Operator): and context_of_items.ContextIdentifier == "Body" ): representation_data["context"] = self.file.by_id(box_context_id) - new_box = add_representation.Usecase(self.file, representation_data).execute() + new_box = ifcopenshell.api.run("geometry.add_representation", self.file, **representation_data) for inverse in self.file.get_inverse(old_box): ifcopenshell.util.element.replace_attribute(inverse, old_box, new_box) - assign_styles.Usecase( + ifcopenshell.api.run( + "geometry.assign_styles", self.file, - { + **{ "shape_representation": new_representation, "styles": [ self.file.by_id(s.material.BIMMaterialProperties.ifc_style_id) @@ -387,7 +390,7 @@ class UpdateMeshRepresentation(bpy.types.Operator): ], "should_use_presentation_style_assignment": context.scene.BIMGeometryProperties.should_use_presentation_style_assignment, }, - ).execute() + ) # TODO: move this into a replace_representation usecase or something for inverse in self.file.get_inverse(old_representation): @@ -396,7 +399,7 @@ class UpdateMeshRepresentation(bpy.types.Operator): obj.data.BIMMeshProperties.ifc_definition_id = int(new_representation.id()) obj.data.name = f"{old_representation.ContextOfItems.id()}/{new_representation.id()}" bpy.ops.bim.remove_representation(representation_id=old_representation.id()) - Data.load(obj.BIMObjectProperties.ifc_definition_id) + Data.load(IfcStore.get_file(), obj.BIMObjectProperties.ifc_definition_id) class UpdateParametricRepresentation(bpy.types.Operator): diff --git a/src/ifcblenderexport/blenderbim/bim/module/geometry/prop.py b/src/blenderbim/blenderbim/bim/module/geometry/prop.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/geometry/prop.py rename to src/blenderbim/blenderbim/bim/module/geometry/prop.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/geometry/ui.py b/src/blenderbim/blenderbim/bim/module/geometry/ui.py similarity index 97% rename from src/ifcblenderexport/blenderbim/bim/module/geometry/ui.py rename to src/blenderbim/blenderbim/bim/module/geometry/ui.py index 99e1c482cf..b07a8d1f82 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/geometry/ui.py +++ b/src/blenderbim/blenderbim/bim/module/geometry/ui.py @@ -1,6 +1,6 @@ import bpy from bpy.types import Panel -from blenderbim.bim.module.geometry.data import Data +from ifcopenshell.api.geometry.data import Data from blenderbim.bim.ifc import IfcStore @@ -21,7 +21,7 @@ class BIM_PT_representations(Panel): props = context.active_object.BIMObjectProperties if props.ifc_definition_id not in Data.products: - Data.load(props.ifc_definition_id) + Data.load(IfcStore.get_file(), props.ifc_definition_id) representations = Data.products[props.ifc_definition_id] if not representations: diff --git a/src/ifcblenderexport/blenderbim/bim/module/georeference/__init__.py b/src/blenderbim/blenderbim/bim/module/georeference/__init__.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/georeference/__init__.py rename to src/blenderbim/blenderbim/bim/module/georeference/__init__.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/georeference/operator.py b/src/blenderbim/blenderbim/bim/module/georeference/operator.py similarity index 94% rename from src/ifcblenderexport/blenderbim/bim/module/georeference/operator.py rename to src/blenderbim/blenderbim/bim/module/georeference/operator.py index 252a08e189..c8ec61e865 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/georeference/operator.py +++ b/src/blenderbim/blenderbim/bim/module/georeference/operator.py @@ -3,11 +3,9 @@ import json import ifcopenshell import ifcopenshell.util.unit import ifcopenshell.util.attribute -import blenderbim.bim.module.georeference.add_georeferencing as add_georeferencing -import blenderbim.bim.module.georeference.edit_georeferencing as edit_georeferencing -import blenderbim.bim.module.georeference.remove_georeferencing as remove_georeferencing +import ifcopenshell.api from blenderbim.bim.ifc import IfcStore -from blenderbim.bim.module.georeference.data import Data +from ifcopenshell.api.georeference.data import Data from math import radians, degrees, atan, tan, cos, sin @@ -131,10 +129,12 @@ class EditGeoreferencing(bpy.types.Operator): if not props.is_map_unit_null: map_unit = props.map_unit_si if props.map_unit_type == "IfcSIUnit" else props.map_unit_imperial - edit_georeferencing.Usecase( - self.file, {"map_conversion": map_conversion, "projected_crs": projected_crs, "map_unit": map_unit} - ).execute() - Data.load() + ifcopenshell.api.run( + "georeference.edit_georeferencing", + self.file, + **{"map_conversion": map_conversion, "projected_crs": projected_crs, "map_unit": map_unit} + ) + Data.load(IfcStore.get_file()) bpy.ops.bim.disable_editing_georeferencing() return {"FINISHED"} @@ -169,8 +169,8 @@ class RemoveGeoreferencing(bpy.types.Operator): bl_label = "Remove Georeferencing" def execute(self, context): - remove_georeferencing.Usecase(IfcStore.get_file()).execute() - Data.load() + ifcopenshell.api.run("georeference.remove_georeferencing", IfcStore.get_file()) + Data.load(IfcStore.get_file()) return {"FINISHED"} @@ -179,8 +179,8 @@ class AddGeoreferencing(bpy.types.Operator): bl_label = "Add Georeferencing" def execute(self, context): - add_georeferencing.Usecase(IfcStore.get_file()).execute() - Data.load() + ifcopenshell.api.run("georeference.add_georeferencing", IfcStore.get_file()) + Data.load(IfcStore.get_file()) return {"FINISHED"} @@ -190,7 +190,7 @@ class ConvertLocalToGlobal(bpy.types.Operator): def execute(self, context): if not Data.is_loaded: - Data.load() + Data.load(IfcStore.get_file()) props = context.scene.BIMGeoreferenceProperties x, y, z = [float(co) for co in props.coordinate_input.split(",")] @@ -240,7 +240,7 @@ class ConvertGlobalToLocal(bpy.types.Operator): def execute(self, context): if not Data.is_loaded: - Data.load() + Data.load(IfcStore.get_file()) props = context.scene.BIMGeoreferenceProperties x, y, z = [float(co) for co in props.coordinate_input.split(",")] diff --git a/src/ifcblenderexport/blenderbim/bim/module/georeference/prop.py b/src/blenderbim/blenderbim/bim/module/georeference/prop.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/georeference/prop.py rename to src/blenderbim/blenderbim/bim/module/georeference/prop.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/georeference/ui.py b/src/blenderbim/blenderbim/bim/module/georeference/ui.py similarity index 98% rename from src/ifcblenderexport/blenderbim/bim/module/georeference/ui.py rename to src/blenderbim/blenderbim/bim/module/georeference/ui.py index 6c2675d7bd..ddf04c40ff 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/georeference/ui.py +++ b/src/blenderbim/blenderbim/bim/module/georeference/ui.py @@ -1,5 +1,5 @@ from bpy.types import Panel -from blenderbim.bim.module.georeference.data import Data +from ifcopenshell.api.georeference.data import Data from blenderbim.bim.ifc import IfcStore class BIM_PT_gis(Panel): @@ -17,7 +17,7 @@ class BIM_PT_gis(Panel): def draw(self, context): props = context.scene.BIMGeoreferenceProperties if not Data.is_loaded: - Data.load() + Data.load(IfcStore.get_file()) if props.is_editing: return self.draw_editable_ui(context) diff --git a/src/ifcblenderexport/blenderbim/bim/module/group/__init__.py b/src/blenderbim/blenderbim/bim/module/group/__init__.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/group/__init__.py rename to src/blenderbim/blenderbim/bim/module/group/__init__.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/group/operator.py b/src/blenderbim/blenderbim/bim/module/group/operator.py similarity index 77% rename from src/ifcblenderexport/blenderbim/bim/module/group/operator.py rename to src/blenderbim/blenderbim/bim/module/group/operator.py index 42f91be230..6c4277aa40 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/group/operator.py +++ b/src/blenderbim/blenderbim/bim/module/group/operator.py @@ -1,12 +1,8 @@ import bpy import ifcopenshell.util.attribute -import blenderbim.bim.module.group.add_group as add_group -import blenderbim.bim.module.group.edit_group as edit_group -import blenderbim.bim.module.group.remove_group as remove_group -import blenderbim.bim.module.group.assign_group as assign_group -import blenderbim.bim.module.group.unassign_group as unassign_group +import ifcopenshell.api from blenderbim.bim.ifc import IfcStore -from blenderbim.bim.module.group.data import Data +from ifcopenshell.api.group.data import Data class LoadGroups(bpy.types.Operator): @@ -40,8 +36,8 @@ class AddGroup(bpy.types.Operator): bl_label = "Add Group" def execute(self, context): - result = add_group.Usecase(IfcStore.get_file()).execute() - Data.load() + result = ifcopenshell.api.run("group.add_group", IfcStore.get_file()) + Data.load(IfcStore.get_file()) bpy.ops.bim.load_groups() bpy.ops.bim.enable_editing_group(group=result.id()) return {"FINISHED"} @@ -60,10 +56,10 @@ class EditGroup(bpy.types.Operator): else: attributes[attribute.name] = attribute.string_value self.file = IfcStore.get_file() - edit_group.Usecase( - self.file, {"group": self.file.by_id(props.active_group_id), "attributes": attributes} - ).execute() - Data.load() + ifcopenshell.api.run( + "group.edit_group", self.file, **{"group": self.file.by_id(props.active_group_id), "attributes": attributes} + ) + Data.load(IfcStore.get_file()) bpy.ops.bim.load_groups() return {"FINISHED"} @@ -76,8 +72,8 @@ class RemoveGroup(bpy.types.Operator): def execute(self, context): props = context.scene.BIMGroupProperties self.file = IfcStore.get_file() - remove_group.Usecase(self.file, {"group": self.file.by_id(self.group)}).execute() - Data.load() + ifcopenshell.api.run("group.remove_group", self.file, **{"group": self.file.by_id(self.group)}) + Data.load(IfcStore.get_file()) bpy.ops.bim.load_groups() return {"FINISHED"} @@ -125,11 +121,15 @@ class AssignGroup(bpy.types.Operator): def execute(self, context): product = bpy.data.objects.get(self.product) if self.product else context.active_object self.file = IfcStore.get_file() - assign_group.Usecase(self.file, { - "product": self.file.by_id(product.BIMObjectProperties.ifc_definition_id), - "group": self.file.by_id(self.group) - }).execute() - Data.load() + ifcopenshell.api.run( + "group.assign_group", + self.file, + **{ + "product": self.file.by_id(product.BIMObjectProperties.ifc_definition_id), + "group": self.file.by_id(self.group), + } + ) + Data.load(IfcStore.get_file()) return {"FINISHED"} @@ -142,9 +142,13 @@ class UnassignGroup(bpy.types.Operator): def execute(self, context): product = bpy.data.objects.get(self.product) if self.product else context.active_object self.file = IfcStore.get_file() - unassign_group.Usecase(self.file, { - "product": self.file.by_id(product.BIMObjectProperties.ifc_definition_id), - "group": self.file.by_id(self.group) - }).execute() - Data.load() + ifcopenshell.api.run( + "group.unassign_group", + self.file, + **{ + "product": self.file.by_id(product.BIMObjectProperties.ifc_definition_id), + "group": self.file.by_id(self.group), + } + ) + Data.load(IfcStore.get_file()) return {"FINISHED"} diff --git a/src/ifcblenderexport/blenderbim/bim/module/group/prop.py b/src/blenderbim/blenderbim/bim/module/group/prop.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/group/prop.py rename to src/blenderbim/blenderbim/bim/module/group/prop.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/group/ui.py b/src/blenderbim/blenderbim/bim/module/group/ui.py similarity index 97% rename from src/ifcblenderexport/blenderbim/bim/module/group/ui.py rename to src/blenderbim/blenderbim/bim/module/group/ui.py index 499f67a8b8..21731dc0d0 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/group/ui.py +++ b/src/blenderbim/blenderbim/bim/module/group/ui.py @@ -1,6 +1,6 @@ from bpy.types import Panel, UIList from blenderbim.bim.ifc import IfcStore -from blenderbim.bim.module.group.data import Data +from ifcopenshell.api.group.data import Data class BIM_PT_groups(Panel): @@ -17,7 +17,7 @@ class BIM_PT_groups(Panel): def draw(self, context): if not Data.is_loaded: - Data.load() + Data.load(IfcStore.get_file()) self.props = context.scene.BIMGroupProperties row = self.layout.row(align=True) diff --git a/src/ifcblenderexport/blenderbim/bim/module/layer/__init__.py b/src/blenderbim/blenderbim/bim/module/layer/__init__.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/layer/__init__.py rename to src/blenderbim/blenderbim/bim/module/layer/__init__.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/layer/operator.py b/src/blenderbim/blenderbim/bim/module/layer/operator.py similarity index 78% rename from src/ifcblenderexport/blenderbim/bim/module/layer/operator.py rename to src/blenderbim/blenderbim/bim/module/layer/operator.py index 7b4b3e295f..7c930823e9 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/layer/operator.py +++ b/src/blenderbim/blenderbim/bim/module/layer/operator.py @@ -1,13 +1,9 @@ import bpy import json import ifcopenshell.util.attribute -import blenderbim.bim.module.layer.add_layer as add_layer -import blenderbim.bim.module.layer.edit_layer as edit_layer -import blenderbim.bim.module.layer.remove_layer as remove_layer -import blenderbim.bim.module.layer.assign_layer as assign_layer -import blenderbim.bim.module.layer.unassign_layer as unassign_layer +import ifcopenshell.api from blenderbim.bim.ifc import IfcStore -from blenderbim.bim.module.layer.data import Data +from ifcopenshell.api.layer.data import Data class LoadLayers(bpy.types.Operator): @@ -76,8 +72,8 @@ class AddPresentationLayer(bpy.types.Operator): bl_label = "Add Layer" def execute(self, context): - result = add_layer.Usecase(IfcStore.get_file()).execute() - Data.load() + result = ifcopenshell.api.run("layer.add_layer", IfcStore.get_file()) + Data.load(IfcStore.get_file()) bpy.ops.bim.load_layers() bpy.ops.bim.enable_editing_layer(layer=result.id()) return {"FINISHED"} @@ -96,10 +92,10 @@ class EditPresentationLayer(bpy.types.Operator): else: attributes[attribute.name] = attribute.string_value self.file = IfcStore.get_file() - edit_layer.Usecase( - self.file, {"layer": self.file.by_id(props.active_layer_id), "attributes": attributes} - ).execute() - Data.load() + ifcopenshell.api.run( + "layer.edit_layer", self.file, **{"layer": self.file.by_id(props.active_layer_id), "attributes": attributes} + ) + Data.load(IfcStore.get_file()) bpy.ops.bim.load_layers() return {"FINISHED"} @@ -112,8 +108,8 @@ class RemovePresentationLayer(bpy.types.Operator): def execute(self, context): props = context.scene.BIMLayerProperties self.file = IfcStore.get_file() - remove_layer.Usecase(self.file, {"layer": self.file.by_id(self.layer)}).execute() - Data.load() + ifcopenshell.api.run("layer.remove_layer", self.file, **{"layer": self.file.by_id(self.layer)}) + Data.load(IfcStore.get_file()) bpy.ops.bim.load_layers() return {"FINISHED"} @@ -127,11 +123,12 @@ class AssignPresentationLayer(bpy.types.Operator): def execute(self, context): item = bpy.data.meshes.get(self.item) if self.item else context.active_object.data self.file = IfcStore.get_file() - assign_layer.Usecase(self.file, { - "item": self.file.by_id(item.BIMMeshProperties.ifc_definition_id), - "layer": self.file.by_id(self.layer) - }).execute() - Data.load() + ifcopenshell.api.run( + "layer.assign_layer", + self.file, + **{"item": self.file.by_id(item.BIMMeshProperties.ifc_definition_id), "layer": self.file.by_id(self.layer)} + ) + Data.load(IfcStore.get_file()) return {"FINISHED"} @@ -144,9 +141,10 @@ class UnassignPresentationLayer(bpy.types.Operator): def execute(self, context): item = bpy.data.meshes.get(self.item) if self.item else context.active_object.data self.file = IfcStore.get_file() - unassign_layer.Usecase(self.file, { - "item": self.file.by_id(item.BIMMeshProperties.ifc_definition_id), - "layer": self.file.by_id(self.layer) - }).execute() - Data.load() + ifcopenshell.api.run( + "layer.unassign_layer", + self.file, + **{"item": self.file.by_id(item.BIMMeshProperties.ifc_definition_id), "layer": self.file.by_id(self.layer)} + ) + Data.load(IfcStore.get_file()) return {"FINISHED"} diff --git a/src/ifcblenderexport/blenderbim/bim/module/layer/prop.py b/src/blenderbim/blenderbim/bim/module/layer/prop.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/layer/prop.py rename to src/blenderbim/blenderbim/bim/module/layer/prop.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/layer/ui.py b/src/blenderbim/blenderbim/bim/module/layer/ui.py similarity index 97% rename from src/ifcblenderexport/blenderbim/bim/module/layer/ui.py rename to src/blenderbim/blenderbim/bim/module/layer/ui.py index 3c21e540c5..7ed1cc4da6 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/layer/ui.py +++ b/src/blenderbim/blenderbim/bim/module/layer/ui.py @@ -1,6 +1,6 @@ from bpy.types import Panel, UIList, Mesh from blenderbim.bim.ifc import IfcStore -from blenderbim.bim.module.layer.data import Data +from ifcopenshell.api.layer.data import Data class BIM_PT_layers(Panel): @@ -17,7 +17,7 @@ class BIM_PT_layers(Panel): def draw(self, context): if not Data.is_loaded: - Data.load() + Data.load(IfcStore.get_file()) self.props = context.scene.BIMLayerProperties diff --git a/src/ifcblenderexport/blenderbim/bim/module/material/__init__.py b/src/blenderbim/blenderbim/bim/module/material/__init__.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/material/__init__.py rename to src/blenderbim/blenderbim/bim/module/material/__init__.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/material/operator.py b/src/blenderbim/blenderbim/bim/module/material/operator.py similarity index 85% rename from src/ifcblenderexport/blenderbim/bim/module/material/operator.py rename to src/blenderbim/blenderbim/bim/module/material/operator.py index b784e7610f..bf7dde4867 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/material/operator.py +++ b/src/blenderbim/blenderbim/bim/module/material/operator.py @@ -1,20 +1,8 @@ import bpy +import ifcopenshell.api import ifcopenshell.util.attribute -import blenderbim.bim.module.material.add_material as add_material -import blenderbim.bim.module.material.remove_material as remove_material -import blenderbim.bim.module.material.assign_material as assign_material -import blenderbim.bim.module.material.unassign_material as unassign_material -import blenderbim.bim.module.material.add_constituent as add_constituent -import blenderbim.bim.module.material.remove_constituent as remove_constituent -import blenderbim.bim.module.material.add_layer as add_layer -import blenderbim.bim.module.material.edit_layer as edit_layer -import blenderbim.bim.module.material.remove_layer as remove_layer -import blenderbim.bim.module.material.reorder_set_item as reorder_set_item -import blenderbim.bim.module.material.add_list_item as add_list_item -import blenderbim.bim.module.material.remove_list_item as remove_list_item -import blenderbim.bim.module.material.edit_assigned_material as edit_assigned_material from blenderbim.bim.ifc import IfcStore -from blenderbim.bim.module.material.data import Data +from ifcopenshell.api.material.data import Data class AddMaterial(bpy.types.Operator): @@ -25,9 +13,9 @@ class AddMaterial(bpy.types.Operator): def execute(self, context): obj = bpy.data.materials.get(self.obj) if self.obj else bpy.context.active_object.active_material self.file = IfcStore.get_file() - result = add_material.Usecase(self.file, {"Name": obj.name}).execute() + result = ifcopenshell.api.run("material.add_material", self.file, **{"Name": obj.name}) obj.BIMObjectProperties.ifc_definition_id = result.id() - Data.load() + Data.load(IfcStore.get_file()) return {"FINISHED"} @@ -39,11 +27,13 @@ class RemoveMaterial(bpy.types.Operator): def execute(self, context): obj = bpy.data.materials.get(self.obj) if self.obj else bpy.context.active_object.active_material self.file = IfcStore.get_file() - result = remove_material.Usecase( - self.file, {"material": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)} - ).execute() + result = ifcopenshell.api.run( + "material.remove_material", + self.file, + **{"material": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)}, + ) obj.BIMObjectProperties.ifc_definition_id = 0 - Data.load() + Data.load(IfcStore.get_file()) return {"FINISHED"} @@ -57,16 +47,17 @@ class AssignMaterial(bpy.types.Operator): obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object material_type = self.material_type or obj.BIMObjectMaterialProperties.material_type self.file = IfcStore.get_file() - assign_material.Usecase( + ifcopenshell.api.run( + "material.assign_material", self.file, - { + **{ "product": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id), "type": material_type, "material": self.file.by_id(int(obj.BIMObjectMaterialProperties.material)), }, - ).execute() - Data.load() - Data.load(obj.BIMObjectProperties.ifc_definition_id) + ) + Data.load(IfcStore.get_file()) + Data.load(IfcStore.get_file(), obj.BIMObjectProperties.ifc_definition_id) return {"FINISHED"} @@ -78,10 +69,12 @@ class UnassignMaterial(bpy.types.Operator): def execute(self, context): obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object self.file = IfcStore.get_file() - unassign_material.Usecase( - self.file, {"product": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)} - ).execute() - Data.load(obj.BIMObjectProperties.ifc_definition_id) + ifcopenshell.api.run( + "material.unassign_material", + self.file, + **{"product": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)}, + ) + Data.load(IfcStore.get_file(), obj.BIMObjectProperties.ifc_definition_id) return {"FINISHED"} @@ -94,13 +87,14 @@ class AddConstituent(bpy.types.Operator): def execute(self, context): obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object self.file = IfcStore.get_file() - add_constituent.Usecase( + ifcopenshell.api.run( + "material.add_constituent", self.file, - { + **{ "constituent_set": self.file.by_id(self.constituent_set), "material": self.file.by_id(int(obj.BIMObjectMaterialProperties.material)), }, - ).execute() + ) Data.load_constituents() return {"FINISHED"} @@ -114,7 +108,9 @@ class RemoveConstituent(bpy.types.Operator): def execute(self, context): obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object self.file = IfcStore.get_file() - remove_constituent.Usecase(self.file, {"constituent": self.file.by_id(self.constituent)}).execute() + ifcopenshell.api.run( + "material.remove_constituent", self.file, **{"constituent": self.file.by_id(self.constituent)} + ) Data.load_constituents() return {"FINISHED"} @@ -128,13 +124,14 @@ class AddLayer(bpy.types.Operator): def execute(self, context): obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object self.file = IfcStore.get_file() - add_layer.Usecase( + ifcopenshell.api.run( + "material.add_layer", self.file, - { + **{ "layer_set": self.file.by_id(self.layer_set), "material": self.file.by_id(int(obj.BIMObjectMaterialProperties.material)), }, - ).execute() + ) Data.load_layers() return {"FINISHED"} @@ -151,14 +148,15 @@ class ReorderMaterialSetItem(bpy.types.Operator): obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object self.file = IfcStore.get_file() material_set = self.file.by_id(self.material_set) - reorder_set_item.Usecase( + ifcopenshell.api.run( + "material.reorder_set_item", self.file, - { + **{ "material_set": material_set, "old_index": self.old_index, "new_index": self.new_index, }, - ).execute() + ) if material_set.is_a("IfcMaterialConstituentSet"): Data.load_constituents() elif material_set.is_a("IfcMaterialLayerSet"): @@ -179,7 +177,7 @@ class RemoveLayer(bpy.types.Operator): def execute(self, context): obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object self.file = IfcStore.get_file() - remove_layer.Usecase(self.file, {"layer": self.file.by_id(self.layer)}).execute() + ifcopenshell.api.run("material.remove_layer", self.file, **{"layer": self.file.by_id(self.layer)}) Data.load_layers() return {"FINISHED"} @@ -193,13 +191,14 @@ class AddListItem(bpy.types.Operator): def execute(self, context): obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object self.file = IfcStore.get_file() - add_list_item.Usecase( + ifcopenshell.api.run( + "material.add_list_item", self.file, - { + **{ "material_list": self.file.by_id(self.list_item_set), "material": self.file.by_id(int(obj.BIMObjectMaterialProperties.material)), }, - ).execute() + ) Data.load_lists() return {"FINISHED"} @@ -214,13 +213,14 @@ class RemoveListItem(bpy.types.Operator): def execute(self, context): obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object self.file = IfcStore.get_file() - remove_list_item.Usecase( + ifcopenshell.api.run( + "material.remove_list_item", self.file, - { + **{ "material_list": self.file.by_id(self.list_item_set), "material": self.file.by_id(self.list_item), }, - ).execute() + ) Data.load_lists() return {"FINISHED"} @@ -298,21 +298,22 @@ class EditAssignedMaterial(bpy.types.Operator): if product_data["type"] == "IfcMaterial": bpy.ops.bim.unassign_material(obj=obj.name) bpy.ops.bim.assign_material(obj=obj.name, material_type="IfcMaterial") - Data.load(obj.BIMObjectProperties.ifc_definition_id) + Data.load(IfcStore.get_file(), obj.BIMObjectProperties.ifc_definition_id) bpy.ops.bim.disable_editing_assigned_material(obj=obj.name) return {"FINISHED"} attributes = {} for attribute in props.material_set_attributes: attributes[attribute.name] = None if attribute.is_null else attribute.string_value - edit_assigned_material.Usecase( + ifcopenshell.api.run( + "material.edit_assigned_material", self.file, - { + **{ "element": material_set, "attributes": attributes, }, - ).execute() - Data.load(obj.BIMObjectProperties.ifc_definition_id) + ) + Data.load(IfcStore.get_file(), obj.BIMObjectProperties.ifc_definition_id) if material_set.is_a("IfcMaterialConstituentSet"): Data.load_constituents() elif material_set.is_a("IfcMaterialLayerSet"): @@ -408,34 +409,37 @@ class EditMaterialSetItem(bpy.types.Operator): attributes[attribute.name] = None if attribute.is_null else value if product_data["type"] == "IfcMaterialConstituentSet": - edit_constituent.Usecase( + ifcopenshell.api.run( + "material.edit_constituent", self.file, - { + **{ "constituent": self.file.by_id(self.material_set_item), "attributes": attributes, "material": self.file.by_id(int(obj.BIMObjectMaterialProperties.material_set_item_material)), }, - ).execute() + ) Data.load_constituents() elif product_data["type"] == "IfcMaterialLayerSet" or product_data["type"] == "IfcMaterialLayerSetUsage": - edit_layer.Usecase( + ifcopenshell.api.run( + "material.edit_layer", self.file, - { + **{ "layer": self.file.by_id(self.material_set_item), "attributes": attributes, "material": self.file.by_id(int(obj.BIMObjectMaterialProperties.material_set_item_material)), }, - ).execute() + ) Data.load_layers() elif product_data["type"] == "IfcMaterialProfileSet": - edit_profile.Usecase( + ifcopenshell.api.run( + "material.edit_profile", self.file, - { + **{ "profile": self.file.by_id(self.material_set_item), "attributes": attributes, "material": self.file.by_id(int(obj.BIMObjectMaterialProperties.material_set_item_material)), }, - ).execute() + ) Data.load_profiles() else: pass diff --git a/src/ifcblenderexport/blenderbim/bim/module/material/prop.py b/src/blenderbim/blenderbim/bim/module/material/prop.py similarity index 97% rename from src/ifcblenderexport/blenderbim/bim/module/material/prop.py rename to src/blenderbim/blenderbim/bim/module/material/prop.py index 1e0f93a371..4795832bbc 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/material/prop.py +++ b/src/blenderbim/blenderbim/bim/module/material/prop.py @@ -1,6 +1,6 @@ import bpy import blenderbim.bim.schema # refactor -from blenderbim.bim.module.material.data import Data +from ifcopenshell.api.material.data import Data from blenderbim.bim.ifc import IfcStore from blenderbim.bim.prop import StrProperty, Attribute from bpy.types import PropertyGroup diff --git a/src/ifcblenderexport/blenderbim/bim/module/material/ui.py b/src/blenderbim/blenderbim/bim/module/material/ui.py similarity index 98% rename from src/ifcblenderexport/blenderbim/bim/module/material/ui.py rename to src/blenderbim/blenderbim/bim/module/material/ui.py index 60b2cec9da..6d432f673a 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/material/ui.py +++ b/src/blenderbim/blenderbim/bim/module/material/ui.py @@ -1,5 +1,5 @@ from bpy.types import Panel -from blenderbim.bim.module.material.data import Data +from ifcopenshell.api.material.data import Data from blenderbim.bim.ifc import IfcStore @@ -43,9 +43,9 @@ class BIM_PT_object_material(Panel): self.oprops = context.active_object.BIMObjectProperties self.props = context.active_object.BIMObjectMaterialProperties if not Data.is_loaded: - Data.load() + Data.load(IfcStore.get_file()) if self.oprops.ifc_definition_id not in Data.products: - Data.load(self.oprops.ifc_definition_id) + Data.load(IfcStore.get_file(), self.oprops.ifc_definition_id) self.product_data = Data.products[self.oprops.ifc_definition_id] if not Data.materials: diff --git a/src/ifcblenderexport/blenderbim/bim/module/model/__init__.py b/src/blenderbim/blenderbim/bim/module/model/__init__.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/model/__init__.py rename to src/blenderbim/blenderbim/bim/module/model/__init__.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/model/door.py b/src/blenderbim/blenderbim/bim/module/model/door.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/model/door.py rename to src/blenderbim/blenderbim/bim/module/model/door.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/model/grid.py b/src/blenderbim/blenderbim/bim/module/model/grid.py similarity index 83% rename from src/ifcblenderexport/blenderbim/bim/module/model/grid.py rename to src/blenderbim/blenderbim/bim/module/model/grid.py index 6f57f76ce3..17ffba617f 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/model/grid.py +++ b/src/blenderbim/blenderbim/bim/module/model/grid.py @@ -1,6 +1,5 @@ import bpy -import blenderbim.bim.module.grid.create_grid_axis as create_grid_axis -import blenderbim.bim.module.grid.create_axis_curve as create_axis_curve +import ifcopenshell.api from bpy.types import Operator from bpy.props import FloatProperty, IntProperty from mathutils import Vector @@ -54,10 +53,12 @@ def add_object(self, context): axes_collection.objects.link(obj) if self.file: - result = create_grid_axis.Usecase( - self.file, {"AxisTag": tag, "AxisCurve": obj, "UVWAxes": "UAxes", "Grid": grid} - ).execute() - create_axis_curve.Usecase(self.file, {"AxisCurve": obj, "grid_axis": result}).execute() + result = ifcopenshell.api.run( + "grid.create_grid_axis", + self.file, + **{"AxisTag": tag, "AxisCurve": obj, "UVWAxes": "UAxes", "Grid": grid}, + ) + ifcopenshell.api.run("grid.create_axis_curve", self.file, **{"AxisCurve": obj, "grid_axis": result}) obj.BIMObjectProperties.ifc_definition_id = result.id() axes_collection = bpy.data.collections.new("VAxes") @@ -77,10 +78,12 @@ def add_object(self, context): axes_collection.objects.link(obj) if IfcStore.get_file(): - result = create_grid_axis.Usecase( - self.file, {"AxisTag": tag, "AxisCurve": obj, "UVWAxes": "VAxes", "Grid": grid} - ).execute() - create_axis_curve.Usecase(self.file, {"AxisCurve": obj, "grid_axis": result}).execute() + result = ifcopenshell.api.run( + "grid.create_grid_axis", + self.file, + **{"AxisTag": tag, "AxisCurve": obj, "UVWAxes": "VAxes", "Grid": grid}, + ) + ifcopenshell.api.run("grid.create_axis_curve", self.file, **{"AxisCurve": obj, "grid_axis": result}) obj.BIMObjectProperties.ifc_definition_id = result.id() diff --git a/src/ifcblenderexport/blenderbim/bim/module/model/opening.py b/src/blenderbim/blenderbim/bim/module/model/opening.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/model/opening.py rename to src/blenderbim/blenderbim/bim/module/model/opening.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/model/pie.py b/src/blenderbim/blenderbim/bim/module/model/pie.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/model/pie.py rename to src/blenderbim/blenderbim/bim/module/model/pie.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/model/slab.py b/src/blenderbim/blenderbim/bim/module/model/slab.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/model/slab.py rename to src/blenderbim/blenderbim/bim/module/model/slab.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/model/stair.py b/src/blenderbim/blenderbim/bim/module/model/stair.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/model/stair.py rename to src/blenderbim/blenderbim/bim/module/model/stair.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/model/wall.py b/src/blenderbim/blenderbim/bim/module/model/wall.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/model/wall.py rename to src/blenderbim/blenderbim/bim/module/model/wall.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/model/window.py b/src/blenderbim/blenderbim/bim/module/model/window.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/model/window.py rename to src/blenderbim/blenderbim/bim/module/model/window.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/owner/__init__.py b/src/blenderbim/blenderbim/bim/module/owner/__init__.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/owner/__init__.py rename to src/blenderbim/blenderbim/bim/module/owner/__init__.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/owner/operator.py b/src/blenderbim/blenderbim/bim/module/owner/operator.py similarity index 78% rename from src/ifcblenderexport/blenderbim/bim/module/owner/operator.py rename to src/blenderbim/blenderbim/bim/module/owner/operator.py index 9fed15eb7c..8accd17301 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/owner/operator.py +++ b/src/blenderbim/blenderbim/bim/module/owner/operator.py @@ -1,19 +1,8 @@ import bpy import json -import blenderbim.bim.module.owner.add_person as add_person -import blenderbim.bim.module.owner.edit_person as edit_person -import blenderbim.bim.module.owner.remove_person as remove_person -import blenderbim.bim.module.owner.add_organisation as add_organisation -import blenderbim.bim.module.owner.edit_organisation as edit_organisation -import blenderbim.bim.module.owner.remove_organisation as remove_organisation -import blenderbim.bim.module.owner.add_role as add_role -import blenderbim.bim.module.owner.edit_role as edit_role -import blenderbim.bim.module.owner.remove_role as remove_role -import blenderbim.bim.module.owner.add_address as add_address -import blenderbim.bim.module.owner.edit_address as edit_address -import blenderbim.bim.module.owner.remove_address as remove_address +import ifcopenshell.api from blenderbim.bim.ifc import IfcStore -from blenderbim.bim.module.owner.data import Data +from ifcopenshell.api.owner.data import Data class EnableEditingPerson(bpy.types.Operator): @@ -50,8 +39,8 @@ class AddPerson(bpy.types.Operator): bl_label = "Add Person" def execute(self, context): - add_person.Usecase(IfcStore.get_file()).execute() - Data.load() + ifcopenshell.api.run("owner.add_person", IfcStore.get_file()) + Data.load(IfcStore.get_file()) return {"FINISHED"} @@ -73,10 +62,12 @@ class EditPerson(bpy.types.Operator): if self.file.schema == "IFC2X3": attributes["Id"] = attributes["Identification"] del attributes["Identification"] - edit_person.Usecase( - self.file, {"person": self.file.by_id(props.active_person_id), "attributes": attributes} - ).execute() - Data.load() + ifcopenshell.api.run( + "owner.edit_person", + self.file, + **{"person": self.file.by_id(props.active_person_id), "attributes": attributes} + ) + Data.load(IfcStore.get_file()) bpy.ops.bim.disable_editing_person() return {"FINISHED"} @@ -88,8 +79,8 @@ class RemovePerson(bpy.types.Operator): def execute(self, context): self.file = IfcStore.get_file() - remove_person.Usecase(self.file, {"person": self.file.by_id(self.person_id)}).execute() - Data.load() + ifcopenshell.api.run("owner.remove_person", self.file, **{"person": self.file.by_id(self.person_id)}) + Data.load(IfcStore.get_file()) return {"FINISHED"} @@ -125,8 +116,10 @@ class AddRole(bpy.types.Operator): def execute(self, context): self.file = IfcStore.get_file() - add_role.Usecase(self.file, {"assigned_object": self.file.by_id(self.assigned_object_id)}).execute() - Data.load() + ifcopenshell.api.run( + "owner.add_role", self.file, **{"assigned_object": self.file.by_id(self.assigned_object_id)} + ) + Data.load(IfcStore.get_file()) return {"FINISHED"} @@ -142,10 +135,10 @@ class EditRole(bpy.types.Operator): "UserDefinedRole": props.role.user_defined_role if props.role.name == "USERDEFINED" else None, "Description": props.role.description or None, } - edit_role.Usecase( - self.file, {"role": self.file.by_id(props.active_role_id), "attributes": attributes} - ).execute() - Data.load() + ifcopenshell.api.run( + "owner.edit_role", self.file, **{"role": self.file.by_id(props.active_role_id), "attributes": attributes} + ) + Data.load(IfcStore.get_file()) bpy.ops.bim.disable_editing_role() return {"FINISHED"} @@ -157,8 +150,8 @@ class RemoveRole(bpy.types.Operator): def execute(self, context): self.file = IfcStore.get_file() - remove_role.Usecase(self.file, {"role": self.file.by_id(self.role_id)}).execute() - Data.load() + ifcopenshell.api.run("owner.remove_role", self.file, **{"role": self.file.by_id(self.role_id)}) + Data.load(IfcStore.get_file()) return {"FINISHED"} @@ -170,10 +163,12 @@ class AddAddress(bpy.types.Operator): def execute(self, context): self.file = IfcStore.get_file() - add_address.Usecase( - self.file, {"assigned_object": self.file.by_id(self.assigned_object_id), "ifc_class": self.ifc_class} - ).execute() - Data.load() + ifcopenshell.api.run( + "owner.add_address", + self.file, + **{"assigned_object": self.file.by_id(self.assigned_object_id), "ifc_class": self.ifc_class} + ) + Data.load(IfcStore.get_file()) return {"FINISHED"} @@ -257,17 +252,19 @@ class EditAddress(bpy.types.Operator): if self.file.schema == "IFC2X3": del attributes["MessagingIDs"] elif address.is_a("IfcPostalAddress"): - attributes.update({ - "InternalLocation": props.address.internal_location or None, - "AddressLines": json.loads(props.address.address_lines) if props.address.address_lines else None, - "PostalBox": props.address.postal_box or None, - "Town": props.address.town or None, - "Region": props.address.region or None, - "PostalCode": props.address.postal_code or None, - "Country": props.address.country or None, - }) - edit_address.Usecase(self.file, {"address": address, "attributes": attributes}).execute() - Data.load() + attributes.update( + { + "InternalLocation": props.address.internal_location or None, + "AddressLines": json.loads(props.address.address_lines) if props.address.address_lines else None, + "PostalBox": props.address.postal_box or None, + "Town": props.address.town or None, + "Region": props.address.region or None, + "PostalCode": props.address.postal_code or None, + "Country": props.address.country or None, + } + ) + ifcopenshell.api.run("owner.edit_address", self.file, **{"address": address, "attributes": attributes}) + Data.load(IfcStore.get_file()) bpy.ops.bim.disable_editing_address() return {"FINISHED"} @@ -279,8 +276,8 @@ class RemoveAddress(bpy.types.Operator): def execute(self, context): self.file = IfcStore.get_file() - remove_address.Usecase(self.file, {"address": self.file.by_id(self.address_id)}).execute() - Data.load() + ifcopenshell.api.run("owner.remove_address", self.file, **{"address": self.file.by_id(self.address_id)}) + Data.load(IfcStore.get_file()) return {"FINISHED"} @@ -315,8 +312,8 @@ class AddOrganisation(bpy.types.Operator): bl_label = "Add Organisation" def execute(self, context): - add_organisation.Usecase(IfcStore.get_file()).execute() - Data.load() + ifcopenshell.api.run("owner.add_organisation", IfcStore.get_file()) + Data.load(IfcStore.get_file()) return {"FINISHED"} @@ -335,10 +332,12 @@ class EditOrganisation(bpy.types.Operator): if self.file.schema == "IFC2X3": attributes["Id"] = attributes["Identification"] del attributes["Identification"] - edit_organisation.Usecase( - self.file, {"organisation": self.file.by_id(props.active_organisation_id), "attributes": attributes} - ).execute() - Data.load() + ifcopenshell.api.run( + "owner.edit_organisation", + self.file, + **{"organisation": self.file.by_id(props.active_organisation_id), "attributes": attributes} + ) + Data.load(IfcStore.get_file()) bpy.ops.bim.disable_editing_organisation() return {"FINISHED"} @@ -350,6 +349,8 @@ class RemoveOrganisation(bpy.types.Operator): def execute(self, context): self.file = IfcStore.get_file() - remove_organisation.Usecase(self.file, {"organisation": self.file.by_id(self.organisation_id)}).execute() - Data.load() + ifcopenshell.api.run( + "owner.remove_organisation", self.file, **{"organisation": self.file.by_id(self.organisation_id)} + ) + Data.load(IfcStore.get_file()) return {"FINISHED"} diff --git a/src/ifcblenderexport/blenderbim/bim/module/owner/prop.py b/src/blenderbim/blenderbim/bim/module/owner/prop.py similarity index 96% rename from src/ifcblenderexport/blenderbim/bim/module/owner/prop.py rename to src/blenderbim/blenderbim/bim/module/owner/prop.py index da71f4b064..a92a6488fe 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/owner/prop.py +++ b/src/blenderbim/blenderbim/bim/module/owner/prop.py @@ -1,6 +1,7 @@ import bpy from blenderbim.bim.prop import StrProperty, Attribute -from blenderbim.bim.module.owner.data import Data +from blenderbim.bim.ifc import IfcStore +from ifcopenshell.api.owner.data import Data from bpy.types import PropertyGroup from bpy.props import ( PointerProperty, @@ -16,7 +17,7 @@ from bpy.props import ( def getPersons(self, context): if not Data.is_loaded: - Data.load() + Data.load(IfcStore.get_file()) results = [] for ifc_id, person in Data.people.items(): if "Id" in person: @@ -29,7 +30,7 @@ def getPersons(self, context): def getOrganisations(self, context): if not Data.is_loaded: - Data.load() + Data.load(IfcStore.get_file()) results = [] for ifc_id, organisation in Data.organisations.items(): results.append((str(ifc_id), organisation["Name"], "")) diff --git a/src/ifcblenderexport/blenderbim/bim/module/owner/ui.py b/src/blenderbim/blenderbim/bim/module/owner/ui.py similarity index 98% rename from src/ifcblenderexport/blenderbim/bim/module/owner/ui.py rename to src/blenderbim/blenderbim/bim/module/owner/ui.py index d0b82a39c0..d47cc605e5 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/owner/ui.py +++ b/src/blenderbim/blenderbim/bim/module/owner/ui.py @@ -1,6 +1,6 @@ import bpy from bpy.types import Panel -from blenderbim.bim.module.owner.data import Data +from ifcopenshell.api.owner.data import Data from blenderbim.bim.ifc import IfcStore @@ -106,7 +106,7 @@ class BIM_PT_people(Panel): def draw(self, context): if not Data.is_loaded: - Data.load() + Data.load(IfcStore.get_file()) self.file = IfcStore.get_file() self.layout.use_property_split = True @@ -166,7 +166,7 @@ class BIM_PT_organisations(Panel): def draw(self, context): if not Data.is_loaded: - Data.load() + Data.load(IfcStore.get_file()) self.file = IfcStore.get_file() self.layout.use_property_split = True @@ -215,7 +215,7 @@ class BIM_PT_owner(Panel): def draw(self, context): if not Data.is_loaded: - Data.load() + Data.load(IfcStore.get_file()) self.layout.use_property_split = True self.layout.use_property_decorate = False diff --git a/src/ifcblenderexport/blenderbim/bim/module/patch/__init__.py b/src/blenderbim/blenderbim/bim/module/patch/__init__.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/patch/__init__.py rename to src/blenderbim/blenderbim/bim/module/patch/__init__.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/patch/operator.py b/src/blenderbim/blenderbim/bim/module/patch/operator.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/patch/operator.py rename to src/blenderbim/blenderbim/bim/module/patch/operator.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/patch/prop.py b/src/blenderbim/blenderbim/bim/module/patch/prop.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/patch/prop.py rename to src/blenderbim/blenderbim/bim/module/patch/prop.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/patch/ui.py b/src/blenderbim/blenderbim/bim/module/patch/ui.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/patch/ui.py rename to src/blenderbim/blenderbim/bim/module/patch/ui.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/project/__init__.py b/src/blenderbim/blenderbim/bim/module/project/__init__.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/project/__init__.py rename to src/blenderbim/blenderbim/bim/module/project/__init__.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/project/operator.py b/src/blenderbim/blenderbim/bim/module/project/operator.py similarity index 91% rename from src/ifcblenderexport/blenderbim/bim/module/project/operator.py rename to src/blenderbim/blenderbim/bim/module/project/operator.py index b6ac9fbafe..6b56cd45cf 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/project/operator.py +++ b/src/blenderbim/blenderbim/bim/module/project/operator.py @@ -1,11 +1,11 @@ import bpy import logging import ifcopenshell -import blenderbim.bim.module.project.create_file as create_file +import ifcopenshell.api import bpy from blenderbim.bim.ifc import IfcStore -# from blenderbim.bim.module.project.data import Data +# from ifcopenshell.api.project.data import Data class CreateProject(bpy.types.Operator): @@ -17,7 +17,9 @@ class CreateProject(bpy.types.Operator): if self.file: return {"FINISHED"} - IfcStore.file = create_file.Usecase({"version": bpy.context.scene.BIMProperties.export_schema}).execute() + IfcStore.file = ifcopenshell.api.run( + "project.create_file", **{"version": bpy.context.scene.BIMProperties.export_schema} + ) self.file = IfcStore.get_file() bpy.ops.bim.add_person() diff --git a/src/ifcblenderexport/blenderbim/bim/module/project/prop.py b/src/blenderbim/blenderbim/bim/module/project/prop.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/project/prop.py rename to src/blenderbim/blenderbim/bim/module/project/prop.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/project/ui.py b/src/blenderbim/blenderbim/bim/module/project/ui.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/project/ui.py rename to src/blenderbim/blenderbim/bim/module/project/ui.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/pset/__init__.py b/src/blenderbim/blenderbim/bim/module/pset/__init__.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/pset/__init__.py rename to src/blenderbim/blenderbim/bim/module/pset/__init__.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/pset/operator.py b/src/blenderbim/blenderbim/bim/module/pset/operator.py similarity index 91% rename from src/ifcblenderexport/blenderbim/bim/module/pset/operator.py rename to src/blenderbim/blenderbim/bim/module/pset/operator.py index 7eaa907c3e..c5e53561fd 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/pset/operator.py +++ b/src/blenderbim/blenderbim/bim/module/pset/operator.py @@ -1,13 +1,9 @@ import bpy import json +import ifcopenshell.api import ifcopenshell.util.unit -import blenderbim.bim.module.pset.add_pset as add_pset -import blenderbim.bim.module.pset.edit_pset as edit_pset -import blenderbim.bim.module.pset.remove_pset as remove_pset -import blenderbim.bim.module.pset.add_qto as add_qto -import blenderbim.bim.module.pset.edit_qto as edit_qto from blenderbim.bim.ifc import IfcStore -from blenderbim.bim.module.pset.data import Data +from ifcopenshell.api.pset.data import Data from blenderbim.bim.module.pset.qto_calculator import QtoCalculator @@ -120,24 +116,26 @@ class EditPset(bpy.types.Operator): properties[prop["Name"]] = blender_prop.enum_value if pset_id in Data.psets: - edit_pset.Usecase( + ifcopenshell.api.run( + "pset.edit_pset", self.file, - { + **{ "pset": self.file.by_id(pset_id), "Name": props.active_pset_name, "Properties": properties, }, - ).execute() + ) else: - edit_qto.Usecase( + ifcopenshell.api.run( + "pset.edit_qto", self.file, - { + **{ "qto": self.file.by_id(pset_id), "Name": props.active_pset_name, "Properties": properties, }, - ).execute() - Data.load(oprops.ifc_definition_id) + ) + Data.load(IfcStore.get_file(), oprops.ifc_definition_id) bpy.ops.bim.disable_pset_editing(obj=self.obj, obj_type=self.obj_type) return {"FINISHED"} @@ -156,14 +154,15 @@ class RemovePset(bpy.types.Operator): elif self.obj_type == "Material": obj = bpy.data.materials.get(self.obj) props = obj.BIMObjectProperties - remove_pset.Usecase( + ifcopenshell.api.run( + "pset.remove_pset", self.file, - { + **{ "product": self.file.by_id(props.ifc_definition_id), "pset": self.file.by_id(self.pset_id), }, - ).execute() - Data.load(props.ifc_definition_id) + ) + Data.load(IfcStore.get_file(), props.ifc_definition_id) return {"FINISHED"} @@ -190,14 +189,15 @@ class AddPset(bpy.types.Operator): elif self.obj_type == "Material": pset_name = props.material_pset_name - add_pset.Usecase( + ifcopenshell.api.run( + "pset.add_pset", self.file, - { + **{ "product": self.file.by_id(oprops.ifc_definition_id), "Name": pset_name, }, - ).execute() - Data.load(oprops.ifc_definition_id) + ) + Data.load(IfcStore.get_file(), oprops.ifc_definition_id) return {"FINISHED"} @@ -210,14 +210,15 @@ class AddQto(bpy.types.Operator): obj = bpy.context.active_object oprops = obj.BIMObjectProperties props = obj.PsetProperties - add_qto.Usecase( + ifcopenshell.api.run( + "pset.add_qto", self.file, - { + **{ "product": self.file.by_id(oprops.ifc_definition_id), "Name": props.qto_name, }, - ).execute() - Data.load(oprops.ifc_definition_id) + ) + Data.load(IfcStore.get_file(), oprops.ifc_definition_id) return {"FINISHED"} diff --git a/src/ifcblenderexport/blenderbim/bim/module/pset/prop.py b/src/blenderbim/blenderbim/bim/module/pset/prop.py similarity index 97% rename from src/ifcblenderexport/blenderbim/bim/module/pset/prop.py rename to src/blenderbim/blenderbim/bim/module/pset/prop.py index 5e78835483..42c2904e8a 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/pset/prop.py +++ b/src/blenderbim/blenderbim/bim/module/pset/prop.py @@ -1,6 +1,6 @@ import bpy from blenderbim.bim.prop import Attribute -from blenderbim.bim.module.pset.data import Data +from ifcopenshell.api.pset.data import Data import blenderbim.bim.schema from bpy.types import PropertyGroup from bpy.props import ( diff --git a/src/ifcblenderexport/blenderbim/bim/module/pset/qto_calculator.py b/src/blenderbim/blenderbim/bim/module/pset/qto_calculator.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/pset/qto_calculator.py rename to src/blenderbim/blenderbim/bim/module/pset/qto_calculator.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/pset/ui.py b/src/blenderbim/blenderbim/bim/module/pset/ui.py similarity index 94% rename from src/ifcblenderexport/blenderbim/bim/module/pset/ui.py rename to src/blenderbim/blenderbim/bim/module/pset/ui.py index d086b4f22d..d6f5110a74 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/pset/ui.py +++ b/src/blenderbim/blenderbim/bim/module/pset/ui.py @@ -1,5 +1,5 @@ from bpy.types import Panel -from blenderbim.bim.module.pset.data import Data +from ifcopenshell.api.pset.data import Data from blenderbim.bim.ifc import IfcStore @@ -100,7 +100,7 @@ class BIM_PT_object_psets(Panel): if not props.ifc_definition_id: return False if props.ifc_definition_id not in Data.products: - Data.load(props.ifc_definition_id) + Data.load(IfcStore.get_file(), props.ifc_definition_id) if not Data.products[props.ifc_definition_id]: return False return True @@ -111,7 +111,7 @@ class BIM_PT_object_psets(Panel): if not oprops.ifc_definition_id: return if oprops.ifc_definition_id not in Data.products: - Data.load(oprops.ifc_definition_id) + Data.load(IfcStore.get_file(), oprops.ifc_definition_id) row = self.layout.row(align=True) row.prop(props, "pset_name", text="") op = row.operator("bim.add_pset", icon="ADD", text="") @@ -143,7 +143,7 @@ class BIM_PT_object_qtos(Panel): if not props.ifc_definition_id: return False if props.ifc_definition_id not in Data.products: - Data.load(props.ifc_definition_id) + Data.load(IfcStore.get_file(), props.ifc_definition_id) if not Data.products[props.ifc_definition_id]: return False return True @@ -154,7 +154,7 @@ class BIM_PT_object_qtos(Panel): if not oprops.ifc_definition_id: return if oprops.ifc_definition_id not in Data.products: - Data.load(oprops.ifc_definition_id) + Data.load(IfcStore.get_file(), oprops.ifc_definition_id) row = self.layout.row(align=True) row.prop(props, "qto_name", text="") row.operator("bim.add_qto", icon="ADD", text="") @@ -183,7 +183,7 @@ class BIM_PT_material_psets(Panel): if IfcStore.get_file().schema == "IFC2X3": return False # We don't support material psets in IFC2X3 because they suck if props.ifc_definition_id not in Data.products: - Data.load(props.ifc_definition_id) + Data.load(IfcStore.get_file(), props.ifc_definition_id) if not Data.products[props.ifc_definition_id]: return False return True @@ -194,7 +194,7 @@ class BIM_PT_material_psets(Panel): if not oprops.ifc_definition_id: return if oprops.ifc_definition_id not in Data.products: - Data.load(oprops.ifc_definition_id) + Data.load(IfcStore.get_file(), oprops.ifc_definition_id) row = self.layout.row(align=True) row.prop(props, "material_pset_name", text="") op = row.operator("bim.add_pset", icon="ADD", text="") diff --git a/src/ifcblenderexport/blenderbim/bim/module/pset_template/__init__.py b/src/blenderbim/blenderbim/bim/module/pset_template/__init__.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/pset_template/__init__.py rename to src/blenderbim/blenderbim/bim/module/pset_template/__init__.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/pset_template/operator.py b/src/blenderbim/blenderbim/bim/module/pset_template/operator.py similarity index 82% rename from src/ifcblenderexport/blenderbim/bim/module/pset_template/operator.py rename to src/blenderbim/blenderbim/bim/module/pset_template/operator.py index 6193be7a68..d83737be2e 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/pset_template/operator.py +++ b/src/blenderbim/blenderbim/bim/module/pset_template/operator.py @@ -1,13 +1,8 @@ import bpy import ifcopenshell -import blenderbim.bim.module.pset_template.add_pset_template as add_pset_template -import blenderbim.bim.module.pset_template.edit_pset_template as edit_pset_template -import blenderbim.bim.module.pset_template.remove_pset_template as remove_pset_template -import blenderbim.bim.module.pset_template.add_prop_template as add_prop_template -import blenderbim.bim.module.pset_template.edit_prop_template as edit_prop_template -import blenderbim.bim.module.pset_template.remove_prop_template as remove_prop_template +import ifcopenshell.api from blenderbim.bim.module.pset_template.prop import updatePsetTemplateFiles, updatePsetTemplates -from blenderbim.bim.module.pset_template.data import Data +from ifcopenshell.api.pset_template.data import Data from blenderbim.bim.ifc import IfcStore @@ -17,8 +12,8 @@ class AddPsetTemplate(bpy.types.Operator): def execute(self, context): props = context.scene.BIMPsetTemplateProperties - add_pset_template.Usecase(IfcStore.pset_template_file).execute() - Data.load() + ifcopenshell.api.run("pset_template.add_pset_template", IfcStore.pset_template_file) + Data.load(IfcStore.pset_template_file) updatePsetTemplates(self, context) return {"FINISHED"} @@ -31,10 +26,10 @@ class RemovePsetTemplate(bpy.types.Operator): props = context.scene.BIMPsetTemplateProperties if props.active_pset_template_id == int(props.pset_templates): bpy.ops.bim.disable_editing_pset_template() - remove_pset_template.Usecase(IfcStore.pset_template_file, { + ifcopenshell.api.run("pset_template.remove_pset_template", IfcStore.pset_template_file, **{ "pset_template": IfcStore.pset_template_file.by_id(int(props.pset_templates)) - }).execute() - Data.load() + }) + Data.load(IfcStore.pset_template_file) updatePsetTemplates(self, context) return {"FINISHED"} @@ -96,7 +91,7 @@ class EditPsetTemplate(bpy.types.Operator): def execute(self, context): props = context.scene.BIMPsetTemplateProperties - edit_pset_template.Usecase(IfcStore.pset_template_file, { + ifcopenshell.api.run("pset_template.edit_pset_template", IfcStore.pset_template_file, **{ "pset_template": IfcStore.pset_template_file.by_id(props.active_pset_template_id), "attributes": { "Name": props.active_pset_template.name, @@ -104,8 +99,8 @@ class EditPsetTemplate(bpy.types.Operator): "TemplateType": props.active_pset_template.template_type, "ApplicableEntity": props.active_pset_template.applicable_entity, } - }).execute() - Data.load() + }) + Data.load(IfcStore.pset_template_file) updatePsetTemplates(self, context) bpy.ops.bim.disable_editing_pset_template() return {"FINISHED"} @@ -127,10 +122,10 @@ class AddPropTemplate(bpy.types.Operator): def execute(self, context): props = context.scene.BIMPsetTemplateProperties pset_template_id = props.active_pset_template_id or int(props.pset_templates) - add_prop_template.Usecase(IfcStore.pset_template_file, { + ifcopenshell.api.run("pset_template.add_prop_template", IfcStore.pset_template_file, **{ "pset_template": IfcStore.pset_template_file.by_id(pset_template_id) - }).execute() - Data.load() + }) + Data.load(IfcStore.pset_template_file) return {"FINISHED"} @@ -141,10 +136,10 @@ class RemovePropTemplate(bpy.types.Operator): def execute(self, context): props = context.scene.BIMPsetTemplateProperties - remove_prop_template.Usecase(IfcStore.pset_template_file, { + ifcopenshell.api.run("pset_template.remove_prop_template", IfcStore.pset_template_file, **{ "prop_template": IfcStore.pset_template_file.by_id(self.prop_template) - }).execute() - Data.load() + }) + Data.load(IfcStore.pset_template_file) return {"FINISHED"} @@ -154,14 +149,14 @@ class EditPropTemplate(bpy.types.Operator): def execute(self, context): props = context.scene.BIMPsetTemplateProperties - edit_prop_template.Usecase(IfcStore.pset_template_file, { + ifcopenshell.api.run("pset_template.edit_prop_template", IfcStore.pset_template_file, **{ "prop_template": IfcStore.pset_template_file.by_id(props.active_prop_template_id), "attributes": { "Name": props.active_prop_template.name, "Description": props.active_prop_template.description, "PrimaryMeasureType": props.active_prop_template.primary_measure_type, } - }).execute() - Data.load() + }) + Data.load(IfcStore.pset_template_file) bpy.ops.bim.disable_editing_prop_template() return {"FINISHED"} diff --git a/src/ifcblenderexport/blenderbim/bim/module/pset_template/prop.py b/src/blenderbim/blenderbim/bim/module/pset_template/prop.py similarity index 99% rename from src/ifcblenderexport/blenderbim/bim/module/pset_template/prop.py rename to src/blenderbim/blenderbim/bim/module/pset_template/prop.py index e5f812f6a7..9a570bf5a0 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/pset_template/prop.py +++ b/src/blenderbim/blenderbim/bim/module/pset_template/prop.py @@ -14,7 +14,7 @@ from bpy.props import ( FloatVectorProperty, CollectionProperty, ) -from blenderbim.bim.module.pset_template.data import Data +from ifcopenshell.api.pset_template.data import Data psettemplatefiles_enum = [] @@ -58,7 +58,7 @@ def getPsetTemplates(self, context): IfcStore.pset_template_file = ifcopenshell.open(IfcStore.pset_template_path) templates = IfcStore.pset_template_file.by_type("IfcPropertySetTemplate") psettemplates_enum.extend([(str(t.id()), t.Name, "") for t in templates]) - Data.load() + Data.load(IfcStore.get_file()) return psettemplates_enum diff --git a/src/ifcblenderexport/blenderbim/bim/module/pset_template/ui.py b/src/blenderbim/blenderbim/bim/module/pset_template/ui.py similarity index 96% rename from src/ifcblenderexport/blenderbim/bim/module/pset_template/ui.py rename to src/blenderbim/blenderbim/bim/module/pset_template/ui.py index 609761bab2..49813c0c96 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/pset_template/ui.py +++ b/src/blenderbim/blenderbim/bim/module/pset_template/ui.py @@ -1,6 +1,7 @@ import bpy from bpy.types import Panel -from blenderbim.bim.module.pset_template.data import Data +from blenderbim.bim.ifc import IfcStore +from ifcopenshell.api.pset_template.data import Data class BIM_PT_pset_template(Panel): @@ -37,7 +38,7 @@ class BIM_PT_pset_template(Panel): # row.operator("bim.save_pset_template", text="", icon="EXPORT") if not Data.is_loaded and props.pset_template_files: - Data.load() + Data.load(IfcStore.get_file()) if not Data.pset_templates: return diff --git a/src/ifcblenderexport/blenderbim/bim/module/qto/__init__.py b/src/blenderbim/blenderbim/bim/module/qto/__init__.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/qto/__init__.py rename to src/blenderbim/blenderbim/bim/module/qto/__init__.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/qto/operator.py b/src/blenderbim/blenderbim/bim/module/qto/operator.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/qto/operator.py rename to src/blenderbim/blenderbim/bim/module/qto/operator.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/qto/prop.py b/src/blenderbim/blenderbim/bim/module/qto/prop.py similarity index 88% rename from src/ifcblenderexport/blenderbim/bim/module/qto/prop.py rename to src/blenderbim/blenderbim/bim/module/qto/prop.py index ef3b6f0369..205d3e39ef 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/qto/prop.py +++ b/src/blenderbim/blenderbim/bim/module/qto/prop.py @@ -1,6 +1,5 @@ import bpy from blenderbim.bim.prop import StrProperty, Attribute -from blenderbim.bim.module.owner.data import Data from bpy.types import PropertyGroup from bpy.props import ( PointerProperty, diff --git a/src/ifcblenderexport/blenderbim/bim/module/qto/ui.py b/src/blenderbim/blenderbim/bim/module/qto/ui.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/qto/ui.py rename to src/blenderbim/blenderbim/bim/module/qto/ui.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/root/__init__.py b/src/blenderbim/blenderbim/bim/module/root/__init__.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/root/__init__.py rename to src/blenderbim/blenderbim/bim/module/root/__init__.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/root/operator.py b/src/blenderbim/blenderbim/bim/module/root/operator.py similarity index 89% rename from src/ifcblenderexport/blenderbim/bim/module/root/operator.py rename to src/blenderbim/blenderbim/bim/module/root/operator.py index 804941a595..0af5b8bddb 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/root/operator.py +++ b/src/blenderbim/blenderbim/bim/module/root/operator.py @@ -1,13 +1,10 @@ import bpy import numpy as np import ifcopenshell +import ifcopenshell.api import ifcopenshell.util.schema import ifcopenshell.util.element -import blenderbim.bim.module.root.create_product as create_product -import blenderbim.bim.module.root.remove_product as remove_product -import blenderbim.bim.module.root.reassign_class as reassign_class -import blenderbim.bim.module.root.copy_class as copy_class -from blenderbim.bim.module.geometry.data import Data as GeometryData +from ifcopenshell.api.geometry.data import Data as GeometryData from blenderbim.bim.ifc import IfcStore @@ -61,14 +58,15 @@ class ReassignClass(bpy.types.Operator): if predefined_type == "USERDEFINED": predefined_type = bpy.context.scene.BIMRootProperties.ifc_userdefined_type for obj in objects: - product = reassign_class.Usecase( + product = ifcopenshell.api.run( + "root.reassign_class", self.file, - { + **{ "product": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id), "ifc_class": bpy.context.scene.BIMRootProperties.ifc_class, "predefined_type": predefined_type, }, - ).execute() + ) obj.name = "{}/{}".format(product.is_a(), "/".join(obj.name.split("/")[1:])) IfcStore.link_element(product, obj) obj.BIMObjectProperties.is_reassigning_class = False @@ -103,14 +101,15 @@ class AssignClass(bpy.types.Operator): def assign_class(self, context, obj): if obj.BIMObjectProperties.ifc_definition_id: return - product = create_product.Usecase( + product = ifcopenshell.api.run( + "root.create_entity", self.file, - { + **{ "ifc_class": self.ifc_class, "predefined_type": self.predefined_type, "name": obj.name, }, - ).execute() + ) obj.name = "{}/{}".format(product.is_a(), obj.name) IfcStore.link_element(product, obj) @@ -184,21 +183,14 @@ class UnassignClass(bpy.types.Operator): if not obj.BIMObjectProperties.ifc_definition_id: continue product = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id) - self.remove_representations(obj, product) IfcStore.unlink_element(product, obj) - remove_product.Usecase(self.file, {"product": product}).execute() - # TODO: remove object placement + ifcopenshell.api.run("root.remove_product", self.file, **{"product": product}) if "/" in obj.name and obj.name[0:3] == "Ifc": obj.name = "/".join(obj.name.split("/")[1:]) if obj.data and obj.data.name == "Void": bpy.data.objects.remove(obj) return {"FINISHED"} - def remove_representations(self, obj, product): - GeometryData.load(product.id()) - for representation_id in GeometryData.products[product.id()]: - bpy.ops.bim.remove_representation(obj=obj.name, representation_id=representation_id) - class UnlinkObject(bpy.types.Operator): bl_idname = "bim.unlink_object" @@ -233,9 +225,9 @@ class CopyClass(bpy.types.Operator): for obj in objects: if not obj.BIMObjectProperties.ifc_definition_id: continue - result = copy_class.Usecase( - self.file, {"product": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)} - ).execute() + result = ifcopenshell.api.run( + "root.copy_class", self.file, **{"product": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)} + ) IfcStore.link_element(result, obj) relating_type = ifcopenshell.util.element.get_type(result) if relating_type and relating_type.RepresentationMaps: diff --git a/src/ifcblenderexport/blenderbim/bim/module/root/prop.py b/src/blenderbim/blenderbim/bim/module/root/prop.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/root/prop.py rename to src/blenderbim/blenderbim/bim/module/root/prop.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/root/ui.py b/src/blenderbim/blenderbim/bim/module/root/ui.py similarity index 96% rename from src/ifcblenderexport/blenderbim/bim/module/root/ui.py rename to src/blenderbim/blenderbim/bim/module/root/ui.py index b973cfa1f0..d30a7ffe40 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/root/ui.py +++ b/src/blenderbim/blenderbim/bim/module/root/ui.py @@ -1,6 +1,6 @@ import bpy from bpy.types import Panel -from blenderbim.bim.module.root.data import Data +from ifcopenshell.api.root.data import Data from blenderbim.bim.ifc import IfcStore @@ -20,7 +20,7 @@ class BIM_PT_class(Panel): if props.ifc_definition_id: if props.ifc_definition_id not in Data.products: try: - Data.load(props.ifc_definition_id) + Data.load(IfcStore.get_file(), props.ifc_definition_id) except: row = self.layout.row(align=True) row.label(text="IFC Element Not Found") diff --git a/src/ifcblenderexport/blenderbim/bim/module/search/__init__.py b/src/blenderbim/blenderbim/bim/module/search/__init__.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/search/__init__.py rename to src/blenderbim/blenderbim/bim/module/search/__init__.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/search/operator.py b/src/blenderbim/blenderbim/bim/module/search/operator.py similarity index 98% rename from src/ifcblenderexport/blenderbim/bim/module/search/operator.py rename to src/blenderbim/blenderbim/bim/module/search/operator.py index 80788ae87d..500fd42cc3 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/search/operator.py +++ b/src/blenderbim/blenderbim/bim/module/search/operator.py @@ -41,15 +41,17 @@ def does_keyword_exist(pattern, string): class SelectGlobalId(bpy.types.Operator): bl_idname = "bim.select_global_id" bl_label = "Select GlobalId" + global_id: bpy.props.StringProperty() def execute(self, context): self.file = IfcStore.get_file() props = context.scene.BIMSearchProperties + global_id = self.global_id or props.global_id for obj in context.visible_objects: if not obj.BIMObjectProperties.ifc_definition_id: continue element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id) - if element.GlobalId == props.global_id: + if element.GlobalId == global_id: obj.select_set(True) break return {"FINISHED"} diff --git a/src/ifcblenderexport/blenderbim/bim/module/search/prop.py b/src/blenderbim/blenderbim/bim/module/search/prop.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/search/prop.py rename to src/blenderbim/blenderbim/bim/module/search/prop.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/search/ui.py b/src/blenderbim/blenderbim/bim/module/search/ui.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/search/ui.py rename to src/blenderbim/blenderbim/bim/module/search/ui.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/sequence/__init__.py b/src/blenderbim/blenderbim/bim/module/sequence/__init__.py similarity index 82% rename from src/ifcblenderexport/blenderbim/bim/module/sequence/__init__.py rename to src/blenderbim/blenderbim/bim/module/sequence/__init__.py index 15641355a0..26a02991c2 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/sequence/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/sequence/__init__.py @@ -4,8 +4,11 @@ from . import ui, prop, operator classes = ( operator.LoadTasks, operator.DisableTaskEditingUI, + operator.AddWorkPlan, + operator.RemoveWorkPlan, prop.Task, prop.BIMTaskProperties, + ui.BIM_PT_work_plans, ui.BIM_PT_tasks, ui.BIM_UL_tasks, ) diff --git a/src/ifcblenderexport/blenderbim/bim/module/sequence/operator.py b/src/blenderbim/blenderbim/bim/module/sequence/operator.py similarity index 52% rename from src/ifcblenderexport/blenderbim/bim/module/sequence/operator.py rename to src/blenderbim/blenderbim/bim/module/sequence/operator.py index 97cb506169..8fb1570267 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/sequence/operator.py +++ b/src/blenderbim/blenderbim/bim/module/sequence/operator.py @@ -1,6 +1,30 @@ import bpy +import ifcopenshell.api from blenderbim.bim.ifc import IfcStore -from blenderbim.bim.module.sequence.data import Data +from ifcopenshell.api.sequence.data import Data + + +class AddWorkPlan(bpy.types.Operator): + bl_idname = "bim.add_work_plan" + bl_label = "Add Work Plan" + + def execute(self, context): + ifcopenshell.api.run("sequence.add_work_plan", IfcStore.get_file()) + Data.load(IfcStore.get_file()) + return {"FINISHED"} + + +class RemoveWorkPlan(bpy.types.Operator): + bl_idname = "bim.remove_work_plan" + bl_label = "Remove Work Plan" + work_plan: bpy.props.IntProperty() + + def execute(self, context): + ifcopenshell.api.run( + "sequence.remove_work_plan", IfcStore.get_file(), work_plan=IfcStore.get_file().by_id(self.work_plan) + ) + Data.load(IfcStore.get_file()) + return {"FINISHED"} class LoadTasks(bpy.types.Operator): diff --git a/src/ifcblenderexport/blenderbim/bim/module/sequence/prop.py b/src/blenderbim/blenderbim/bim/module/sequence/prop.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/sequence/prop.py rename to src/blenderbim/blenderbim/bim/module/sequence/prop.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/sequence/ui.py b/src/blenderbim/blenderbim/bim/module/sequence/ui.py similarity index 61% rename from src/ifcblenderexport/blenderbim/bim/module/sequence/ui.py rename to src/blenderbim/blenderbim/bim/module/sequence/ui.py index 7334c7d788..f38abf8161 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/sequence/ui.py +++ b/src/blenderbim/blenderbim/bim/module/sequence/ui.py @@ -1,6 +1,32 @@ from bpy.types import Panel, UIList from blenderbim.bim.ifc import IfcStore -from blenderbim.bim.module.sequence.data import Data +from ifcopenshell.api.sequence.data import Data + + +class BIM_PT_work_plans(Panel): + bl_label = "IFC Work Plans" + bl_idname = "BIM_PT_work_plans" + bl_options = {"DEFAULT_CLOSED"} + bl_space_type = "PROPERTIES" + bl_region_type = "WINDOW" + bl_context = "scene" + + @classmethod + def poll(cls, context): + return IfcStore.get_file() + + def draw(self, context): + if not Data.is_loaded: + Data.load(IfcStore.get_file()) + + row = self.layout.row() + row.operator("bim.add_work_plan", icon="ADD") + + for work_plan_id, work_plan in Data.work_plans.items(): + row = self.layout.row(align=True) + row.label(text=work_plan["Name"] or "Unnamed", icon="TEXT") + row.operator("bim.add_work_plan", text="", icon="GREASEPENCIL") + row.operator("bim.remove_work_plan", text="", icon="X").work_plan = work_plan_id class BIM_PT_tasks(Panel): @@ -17,7 +43,7 @@ class BIM_PT_tasks(Panel): def draw(self, context): if not Data.is_loaded: - Data.load() + Data.load(IfcStore.get_file()) self.props = context.scene.BIMTaskProperties row = self.layout.row(align=True) diff --git a/src/ifcblenderexport/blenderbim/bim/module/spatial/__init__.py b/src/blenderbim/blenderbim/bim/module/spatial/__init__.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/spatial/__init__.py rename to src/blenderbim/blenderbim/bim/module/spatial/__init__.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/spatial/operator.py b/src/blenderbim/blenderbim/bim/module/spatial/operator.py similarity index 90% rename from src/ifcblenderexport/blenderbim/bim/module/spatial/operator.py rename to src/blenderbim/blenderbim/bim/module/spatial/operator.py index 8a0c83a9bd..a51948d3d9 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/spatial/operator.py +++ b/src/blenderbim/blenderbim/bim/module/spatial/operator.py @@ -1,8 +1,7 @@ import bpy -import blenderbim.bim.module.spatial.assign_container as assign_container -import blenderbim.bim.module.spatial.remove_container as remove_container +import ifcopenshell.api from blenderbim.bim.ifc import IfcStore -from blenderbim.bim.module.spatial.data import Data +from ifcopenshell.api.spatial.data import Data from blenderbim.bim.module.spatial.prop import getSpatialContainers @@ -24,15 +23,16 @@ class AssignContainer(bpy.types.Operator): self.relating_structure or sprops.spatial_elements[sprops.active_spatial_element_index].ifc_definition_id ) - assign_container.Usecase( + ifcopenshell.api.run( + "spatial.assign_container", self.file, - { + **{ "product": self.file.by_id(oprops.ifc_definition_id), "relating_structure": self.file.by_id(relating_structure), }, - ).execute() + ) bpy.ops.bim.edit_object_placement(obj=related_element.name) - Data.load(oprops.ifc_definition_id) + Data.load(IfcStore.get_file(), oprops.ifc_definition_id) bpy.ops.bim.disable_editing_container(obj=related_element.name) aggregate_collection = bpy.data.collections.get(related_element.name) @@ -100,8 +100,10 @@ class RemoveContainer(bpy.types.Operator): obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object oprops = obj.BIMObjectProperties self.file = IfcStore.get_file() - remove_container.Usecase(self.file, {"product": self.file.by_id(oprops.ifc_definition_id)}).execute() - Data.load(oprops.ifc_definition_id) + ifcopenshell.api.run( + "spatial.remove_container", self.file, **{"product": self.file.by_id(oprops.ifc_definition_id)} + ) + Data.load(IfcStore.get_file(), oprops.ifc_definition_id) aggregate_collection = bpy.data.collections.get(obj.name) if aggregate_collection: diff --git a/src/ifcblenderexport/blenderbim/bim/module/spatial/prop.py b/src/blenderbim/blenderbim/bim/module/spatial/prop.py similarity index 96% rename from src/ifcblenderexport/blenderbim/bim/module/spatial/prop.py rename to src/blenderbim/blenderbim/bim/module/spatial/prop.py index b64228df37..4f14eacf29 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/spatial/prop.py +++ b/src/blenderbim/blenderbim/bim/module/spatial/prop.py @@ -1,6 +1,6 @@ import bpy from blenderbim.bim.prop import StrProperty, Attribute -from blenderbim.bim.module.spatial.data import Data +from ifcopenshell.api.spatial.data import Data from blenderbim.bim.ifc import IfcStore from bpy.types import PropertyGroup from bpy.props import ( @@ -16,7 +16,7 @@ from bpy.props import ( def getSpatialContainers(self, context, parent_id=None): - Data.load() + Data.load(IfcStore.get_file()) self.file = IfcStore.get_file() props = context.scene.BIMSpatialProperties while len(props.spatial_elements) > 0: diff --git a/src/ifcblenderexport/blenderbim/bim/module/spatial/ui.py b/src/blenderbim/blenderbim/bim/module/spatial/ui.py similarity index 91% rename from src/ifcblenderexport/blenderbim/bim/module/spatial/ui.py rename to src/blenderbim/blenderbim/bim/module/spatial/ui.py index be8dab598a..b54ce3606e 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/spatial/ui.py +++ b/src/blenderbim/blenderbim/bim/module/spatial/ui.py @@ -1,5 +1,6 @@ from bpy.types import Panel, UIList -from blenderbim.bim.module.spatial.data import Data +from blenderbim.bim.ifc import IfcStore +from ifcopenshell.api.spatial.data import Data class BIM_PT_spatial(Panel): @@ -17,7 +18,7 @@ class BIM_PT_spatial(Panel): if not oprops.ifc_definition_id: return False if oprops.ifc_definition_id not in Data.products: - Data.load(oprops.ifc_definition_id) + Data.load(IfcStore.get_file(), oprops.ifc_definition_id) if not Data.products[oprops.ifc_definition_id]: return False return True @@ -29,7 +30,7 @@ class BIM_PT_spatial(Panel): if not oprops.ifc_definition_id: return if oprops.ifc_definition_id not in Data.products: - Data.load(oprops.ifc_definition_id) + Data.load(IfcStore.get_file(), oprops.ifc_definition_id) if props.is_editing: row = self.layout.row(align=True) diff --git a/src/ifcblenderexport/blenderbim/bim/module/structural/__init__.py b/src/blenderbim/blenderbim/bim/module/structural/__init__.py similarity index 86% rename from src/ifcblenderexport/blenderbim/bim/module/structural/__init__.py rename to src/blenderbim/blenderbim/bim/module/structural/__init__.py index eaac7afdc2..816b5b374e 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/structural/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/structural/__init__.py @@ -16,6 +16,10 @@ classes = ( operator.RemoveStructuralBoundaryCondition, operator.EnableEditingStructuralBoundaryCondition, operator.DisableEditingStructuralBoundaryCondition, + operator.AddStructuralMemberConnection, + operator.EnableEditingStructuralConnectionCondition, + operator.DisableEditingStructuralConnectionCondition, + operator.RemoveStructuralConnectionCondition, prop.StructuralAnalysisModel, prop.BIMStructuralProperties, prop.BIMObjectStructuralProperties, diff --git a/src/ifcblenderexport/blenderbim/bim/module/structural/operator.py b/src/blenderbim/blenderbim/bim/module/structural/operator.py similarity index 57% rename from src/ifcblenderexport/blenderbim/bim/module/structural/operator.py rename to src/blenderbim/blenderbim/bim/module/structural/operator.py index cf72861d87..a997d2e91f 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/structural/operator.py +++ b/src/blenderbim/blenderbim/bim/module/structural/operator.py @@ -1,55 +1,120 @@ import bpy import json -import blenderbim.bim.module.structural.add_structural_boundary_condition as add_structural_boundary_condition -import blenderbim.bim.module.structural.edit_structural_boundary_condition as edit_structural_boundary_condition -import blenderbim.bim.module.structural.remove_structural_boundary_condition as remove_structural_boundary_condition -import blenderbim.bim.module.structural.add_structural_analysis_model as add_structural_analysis_model -import blenderbim.bim.module.structural.edit_structural_analysis_model as edit_structural_analysis_model -import blenderbim.bim.module.structural.remove_structural_analysis_model as remove_structural_analysis_model -import blenderbim.bim.module.structural.assign_structural_analysis_model as assign_structural_analysis_model -import blenderbim.bim.module.structural.unassign_structural_analysis_model as unassign_structural_analysis_model +import ifcopenshell +import ifcopenshell.api from blenderbim.bim.ifc import IfcStore -from blenderbim.bim.module.structural.data import Data +from ifcopenshell.api.structural.data import Data +from ifcopenshell.api.context.data import Data as ContextData + + +class AddStructuralMemberConnection(bpy.types.Operator): + bl_idname = "bim.add_structural_member_connection" + bl_label = "Add Structural Member Connection" + + def execute(self, context): + obj = bpy.context.active_object + oprops = obj.BIMObjectProperties + props = obj.BIMStructuralProperties + file = IfcStore.get_file() + related_structural_connection = file.by_id(oprops.ifc_definition_id) + relating_structural_member = file.by_id(props.relating_structural_member.BIMObjectProperties.ifc_definition_id) + if not relating_structural_member.is_a("IfcStructuralMember"): + return {"FINISHED"} + ifcopenshell.api.run( + "structural.add_structural_member_connection", + file, + relating_structural_member=relating_structural_member, + related_structural_connection=related_structural_connection, + ) + props.relating_structural_member = None + Data.load(IfcStore.get_file(), related_structural_connection.id()) + return {"FINISHED"} + + +class EnableEditingStructuralConnectionCondition(bpy.types.Operator): + bl_idname = "bim.enable_editing_structural_connection_condition" + bl_label = "Enable Editing Structural Connection Condition" + connects_structural_member: bpy.props.IntProperty() + + def execute(self, context): + obj = bpy.context.active_object + oprops = obj.BIMObjectProperties + props = obj.BIMStructuralProperties + applied_condition_id = Data.connects_structural_members[self.connects_structural_member]["AppliedCondition"] + props.active_connects_structural_member = self.connects_structural_member + return {"FINISHED"} + + +class DisableEditingStructuralConnectionCondition(bpy.types.Operator): + bl_idname = "bim.disable_editing_structural_connection_condition" + bl_label = "Disable Editing Structural Connection Condition" + + def execute(self, context): + obj = bpy.context.active_object + props = obj.BIMStructuralProperties + props.active_connects_structural_member = 0 + return {"FINISHED"} + + +class RemoveStructuralConnectionCondition(bpy.types.Operator): + bl_idname = "bim.remove_structural_connection_condition" + bl_label = "Remove Structural Connection Condition" + connects_structural_member: bpy.props.IntProperty() + + def execute(self, context): + file = IfcStore.get_file() + relation = file.by_id(self.connects_structural_member) + connection = relation.RelatedStructuralConnection + ifcopenshell.api.run("structural.remove_structural_connection_condition", file, **{"relation": relation}) + + Data.load(IfcStore.get_file(), connection.id()) + return {"FINISHED"} class AddStructuralBoundaryCondition(bpy.types.Operator): bl_idname = "bim.add_structural_boundary_condition" bl_label = "Add Structural Boundary Condition" + connection: bpy.props.IntProperty() def execute(self, context): - obj = context.active_object file = IfcStore.get_file() - connection = file.by_id(obj.BIMObjectProperties.ifc_definition_id) - add_structural_boundary_condition.Usecase(file, {"connection": connection}).execute() - Data.load(connection.id()) + connection = file.by_id(self.connection) + ifcopenshell.api.run("structural.add_structural_boundary_condition", file, **{"connection": connection}) + if connection.is_a("IfcRelConnectsStructuralMember"): + Data.load(IfcStore.get_file(), connection.RelatedStructuralConnection.id()) + else: + Data.load(IfcStore.get_file(), connection.id()) return {"FINISHED"} class RemoveStructuralBoundaryCondition(bpy.types.Operator): bl_idname = "bim.remove_structural_boundary_condition" - bl_label = "Enable Editing Structural Boundary Condition" + bl_label = "Remove Structural Boundary Condition" + connection: bpy.props.IntProperty() def execute(self, context): - obj = context.active_object file = IfcStore.get_file() - connection = file.by_id(obj.BIMObjectProperties.ifc_definition_id) - remove_structural_boundary_condition.Usecase(file, {"connection": connection}).execute() - Data.load(connection.id()) + connection = file.by_id(self.connection) + ifcopenshell.api.run("structural.remove_structural_boundary_condition", file, **{"connection": connection}) + if connection.is_a("IfcRelConnectsStructuralMember"): + Data.load(IfcStore.get_file(), connection.RelatedStructuralConnection.id()) + else: + Data.load(IfcStore.get_file(), connection.id()) return {"FINISHED"} class EnableEditingStructuralBoundaryCondition(bpy.types.Operator): bl_idname = "bim.enable_editing_structural_boundary_condition" bl_label = "Enable Editing Structural Boundary Condition" + boundary_condition: bpy.props.IntProperty() def execute(self, context): obj = context.active_object - oprops = obj.BIMObjectProperties props = obj.BIMStructuralProperties while len(props.boundary_condition_attributes) > 0: props.boundary_condition_attributes.remove(0) - data = Data.boundary_conditions[oprops.ifc_definition_id] + data = Data.boundary_conditions[self.boundary_condition] for attribute in IfcStore.get_schema().declaration_by_name(data["type"]).all_attributes(): value = data[attribute.name()] @@ -59,7 +124,7 @@ class EnableEditingStructuralBoundaryCondition(bpy.types.Operator): new.is_null = value is None new.is_optional = attribute.optional() if data_type == "select": - enum_items = [s.name() for s in ifcopenshell.get_select_items(attribute)] + enum_items = [s.name() for s in ifcopenshell.util.attribute.get_select_items(attribute)] new.enum_items = json.dumps(enum_items) if isinstance(value, bool): new.bool_value = False if new.is_null else data[attribute.name()] @@ -71,22 +136,23 @@ class EnableEditingStructuralBoundaryCondition(bpy.types.Operator): new.enum_value = [i for i in enum_items if i != "IfcBoolean"][0] elif data_type == "string": new.string_value = "" if new.is_null else data[attribute.name()] + new.data_type = "string" - props.is_editing_boundary_condition = True + props.active_boundary_condition = self.boundary_condition return {"FINISHED"} class EditStructuralBoundaryCondition(bpy.types.Operator): bl_idname = "bim.edit_structural_boundary_condition" bl_label = "Edit Structural Boundary Condition" + connection: bpy.props.IntProperty() def execute(self, context): obj = context.active_object - oprops = obj.BIMObjectProperties props = obj.BIMStructuralProperties file = IfcStore.get_file() - connection = file.by_id(obj.BIMObjectProperties.ifc_definition_id) + connection = file.by_id(self.connection) condition = connection.AppliedCondition attributes = {} @@ -100,8 +166,13 @@ class EditStructuralBoundaryCondition(bpy.types.Operator): else: attributes[attribute.name] = {"value": attribute.float_value, "type": attribute.enum_value} - edit_structural_boundary_condition.Usecase(file, {"condition": condition, "attributes": attributes}).execute() - Data.load(connection.id()) + ifcopenshell.api.run( + "structural.edit_structural_boundary_condition", file, **{"condition": condition, "attributes": attributes} + ) + if connection.is_a("IfcRelConnectsStructuralMember"): + Data.load(IfcStore.get_file(), connection.RelatedStructuralConnection.id()) + else: + Data.load(IfcStore.get_file(), connection.id()) bpy.ops.bim.disable_editing_structural_boundary_condition() return {"FINISHED"} @@ -111,7 +182,7 @@ class DisableEditingStructuralBoundaryCondition(bpy.types.Operator): bl_label = "Disable Editing Structural Boundary Condition" def execute(self, context): - context.active_object.BIMStructuralProperties.is_editing_boundary_condition = False + context.active_object.BIMStructuralProperties.active_boundary_condition = 0 return {"FINISHED"} @@ -126,7 +197,7 @@ class LoadStructuralAnalysisModels(bpy.types.Operator): for ifc_definition_id, structural_analysis_model in Data.structural_analysis_models.items(): new = props.structural_analysis_models.add() new.ifc_definition_id = ifc_definition_id - new.name = structural_analysis_model["Name"] + new.name = structural_analysis_model["Name"] or "Unnamed" props.is_editing = True bpy.ops.bim.disable_editing_structural_analysis_model() return {"FINISHED"} @@ -146,8 +217,19 @@ class AddStructuralAnalysisModel(bpy.types.Operator): bl_label = "Add Structural Analysis Model" def execute(self, context): - result = add_structural_analysis_model.Usecase(IfcStore.get_file()).execute() - Data.load() + result = ifcopenshell.api.run("structural.add_structural_analysis_model", IfcStore.get_file()) + + has_context = False + ContextData.load(IfcStore.get_file()) + for context in ContextData.contexts.values(): + if context["ContextType"] == "Model": + for subcontext in context["HasSubContexts"].values(): + if subcontext["ContextIdentifier"] == "Reference" and subcontext["TargetView"] == "GRAPH_VIEW": + has_context = True + if not has_context: + bpy.ops.bim.add_subcontext(context="Model", subcontext="Reference", target_view="GRAPH_VIEW") + + Data.load(IfcStore.get_file()) bpy.ops.bim.load_structural_analysis_models() bpy.ops.bim.enable_editing_structural_analysis_model(structural_analysis_model=result.id()) return {"FINISHED"} @@ -169,10 +251,15 @@ class EditStructuralAnalysisModel(bpy.types.Operator): elif attribute.data_type == "enum": attributes[attribute.name] = attribute.enum_value self.file = IfcStore.get_file() - edit_structural_analysis_model.Usecase( - self.file, {"structural_analysis_model": self.file.by_id(props.active_structural_analysis_model_id), "attributes": attributes} - ).execute() - Data.load() + ifcopenshell.api.run( + "structural.edit_structural_analysis_model", + self.file, + **{ + "structural_analysis_model": self.file.by_id(props.active_structural_analysis_model_id), + "attributes": attributes, + } + ) + Data.load(IfcStore.get_file()) bpy.ops.bim.load_structural_analysis_models() return {"FINISHED"} @@ -185,8 +272,12 @@ class RemoveStructuralAnalysisModel(bpy.types.Operator): def execute(self, context): props = context.scene.BIMStructuralProperties self.file = IfcStore.get_file() - remove_structural_analysis_model.Usecase(self.file, {"structural_analysis_model": self.file.by_id(self.structural_analysis_model)}).execute() - Data.load() + ifcopenshell.api.run( + "structural.remove_structural_analysis_model", + self.file, + **{"structural_analysis_model": self.file.by_id(self.structural_analysis_model)} + ) + Data.load(IfcStore.get_file()) bpy.ops.bim.load_structural_analysis_models() return {"FINISHED"} @@ -241,11 +332,15 @@ class AssignStructuralAnalysisModel(bpy.types.Operator): def execute(self, context): product = bpy.data.objects.get(self.product) if self.product else context.active_object self.file = IfcStore.get_file() - assign_structural_analysis_model.Usecase(self.file, { - "product": self.file.by_id(product.BIMObjectProperties.ifc_definition_id), - "structural_analysis_model": self.file.by_id(self.structural_analysis_model) - }).execute() - Data.load() + ifcopenshell.api.run( + "structural.assign_structural_analysis_model", + self.file, + **{ + "product": self.file.by_id(product.BIMObjectProperties.ifc_definition_id), + "structural_analysis_model": self.file.by_id(self.structural_analysis_model), + } + ) + Data.load(IfcStore.get_file()) return {"FINISHED"} @@ -258,9 +353,13 @@ class UnassignStructuralAnalysisModel(bpy.types.Operator): def execute(self, context): product = bpy.data.objects.get(self.product) if self.product else context.active_object self.file = IfcStore.get_file() - unassign_structural_analysis_model.Usecase(self.file, { - "product": self.file.by_id(product.BIMObjectProperties.ifc_definition_id), - "structural_analysis_model": self.file.by_id(self.structural_analysis_model) - }).execute() - Data.load() + ifcopenshell.api.run( + "structural.unassign_structural_analysis_model", + self.file, + **{ + "product": self.file.by_id(product.BIMObjectProperties.ifc_definition_id), + "structural_analysis_model": self.file.by_id(self.structural_analysis_model), + } + ) + Data.load(IfcStore.get_file()) return {"FINISHED"} diff --git a/src/ifcblenderexport/blenderbim/bim/module/structural/prop.py b/src/blenderbim/blenderbim/bim/module/structural/prop.py similarity index 80% rename from src/ifcblenderexport/blenderbim/bim/module/structural/prop.py rename to src/blenderbim/blenderbim/bim/module/structural/prop.py index ebd8199615..f8cc972b87 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/structural/prop.py +++ b/src/blenderbim/blenderbim/bim/module/structural/prop.py @@ -30,5 +30,6 @@ class BIMStructuralProperties(PropertyGroup): class BIMObjectStructuralProperties(PropertyGroup): boundary_condition_attributes: CollectionProperty(name="Boundary Condition Attributes", type=Attribute) - is_editing_boundary_condition: BoolProperty(name="Is Editing Boundary Condition", default=False) - connected_structural_members: CollectionProperty(name="Connected Structural Members", type=Attribute) + active_boundary_condition: IntProperty(name="Active Boundary Condition") + active_connects_structural_member: IntProperty(name="Active Connects Structural Member") + relating_structural_member: PointerProperty(name="Relating Structural Member", type=bpy.types.Object) diff --git a/src/ifcblenderexport/blenderbim/bim/module/structural/ui.py b/src/blenderbim/blenderbim/bim/module/structural/ui.py similarity index 53% rename from src/ifcblenderexport/blenderbim/bim/module/structural/ui.py rename to src/blenderbim/blenderbim/bim/module/structural/ui.py index e5cead4f98..87aff9b060 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/structural/ui.py +++ b/src/blenderbim/blenderbim/bim/module/structural/ui.py @@ -1,6 +1,61 @@ from bpy.types import Panel, UIList from blenderbim.bim.ifc import IfcStore -from blenderbim.bim.module.structural.data import Data +from ifcopenshell.api.structural.data import Data + + +def draw_boundary_condition_ui(layout, boundary_condition_id, connection_id, props): + data = Data.boundary_conditions[boundary_condition_id] if boundary_condition_id else {} + row = layout.row(align=True) + if not data: + row.label(text="No Boundary Condition Found", icon="CON_TRACKTO") + row.operator("bim.add_structural_boundary_condition", text="", icon="ADD").connection = connection_id + return + + if props.active_boundary_condition and props.active_boundary_condition == boundary_condition_id: + row.label(text=data["type"], icon="CON_TRACKTO") + row.operator("bim.edit_structural_boundary_condition", text="", icon="CHECKMARK").connection = connection_id + row.operator("bim.disable_editing_structural_boundary_condition", text="", icon="X") + elif props.active_boundary_condition and props.active_boundary_condition != boundary_condition_id: + row.label(text=data["type"], icon="CON_TRACKTO") + row.operator("bim.remove_structural_boundary_condition", text="", icon="X").connection = connection_id + else: + row.label(text=data["type"], icon="CON_TRACKTO") + op = row.operator("bim.enable_editing_structural_boundary_condition", text="", icon="GREASEPENCIL") + op.boundary_condition = data["id"] + row.operator("bim.remove_structural_boundary_condition", text="", icon="X").connection = connection_id + + if props.active_boundary_condition and props.active_boundary_condition == boundary_condition_id: + draw_boundary_condition_editable_ui(layout, props) + else: + draw_boundary_condition_read_only_ui(layout, data) + + +def draw_boundary_condition_editable_ui(layout, props): + for attribute in props.boundary_condition_attributes: + if attribute.data_type == "string": + row = layout.row() + row.prop(attribute, "string_value", text=attribute["name"]) + else: + row = layout.row(align=True) + row.prop(attribute, "enum_value", text=attribute["name"]) + if attribute.enum_value == "IfcBoolean": + row.prop(attribute, "bool_value", text="") + else: + row.prop(attribute, "float_value", text="") + if attribute.is_optional: + row.prop(attribute, "is_null", icon="RADIOBUT_OFF" if attribute.is_null else "RADIOBUT_ON", text="") + +def draw_boundary_condition_read_only_ui(layout, boundary_condition_data): + for key, value in boundary_condition_data.items(): + if key == "id" or key == "type" or value == None: + continue + row = layout.row(align=True) + row.label(text=key) + if isinstance(value, bool): + row.label(text="", icon="CHECKBOX_HLT" if value else "CHECKBOX_DEHLT") + else: + row.label(text=str(value)) + class BIM_PT_structural_boundary_conditions(Panel): @@ -25,54 +80,11 @@ class BIM_PT_structural_boundary_conditions(Panel): def draw(self, context): self.oprops = context.active_object.BIMObjectProperties self.props = context.active_object.BIMStructuralProperties - if self.oprops.ifc_definition_id not in Data.boundary_conditions: - Data.load(self.oprops.ifc_definition_id) + if self.oprops.ifc_definition_id not in Data.connections: + Data.load(IfcStore.get_file(), self.oprops.ifc_definition_id) - self.data = Data.boundary_conditions[self.oprops.ifc_definition_id] - - row = self.layout.row(align=True) - if self.data and self.props.is_editing_boundary_condition: - row.label(text=self.data["type"], icon="CON_TRACKTO") - row.operator("bim.edit_structural_boundary_condition", text="", icon="CHECKMARK") - row.operator("bim.disable_editing_structural_boundary_condition", text="", icon="X") - elif self.data and not self.props.is_editing_boundary_condition: - row.label(text=self.data["type"], icon="CON_TRACKTO") - row.operator("bim.enable_editing_structural_boundary_condition", text="", icon="GREASEPENCIL") - row.operator("bim.remove_structural_boundary_condition", text="", icon="X") - else: - row.label(text="No Boundary Condition Found", icon="CON_TRACKTO") - row.operator("bim.add_structural_boundary_condition", text="", icon="ADD") - - if self.props.is_editing_boundary_condition: - self.draw_editable_ui(context) - else: - self.draw_read_only_ui(context) - - def draw_editable_ui(self, context): - for attribute in self.props.connection_attributes: - if attribute.data_type == "string": - row = self.layout.row() - row.prop(attribute, "string_value", text=attribute["name"]) - else: - row = self.layout.row(align=True) - row.prop(attribute, "enum_value", text=attribute["name"]) - if attribute.enum_value == "IfcBoolean": - row.prop(attribute, "bool_value", text="") - else: - row.prop(attribute, "float_value", text="") - if attribute.is_optional: - row.prop(attribute, "is_null", icon="RADIOBUT_OFF" if attribute.is_null else "RADIOBUT_ON", text="") - - def draw_read_only_ui(self, context): - for key, value in self.data.items(): - if key == "id" or key == "type" or value == None: - continue - row = self.layout.row(align=True) - row.label(text=key) - if isinstance(value, bool): - row.label(text="", icon="CHECKBOX_HLT" if value else "CHECKBOX_DEHLT") - else: - row.label(text=str(value)) + applied_condition_id = Data.connections[self.oprops.ifc_definition_id]["AppliedCondition"] + draw_boundary_condition_ui(self.layout, applied_condition_id, self.oprops.ifc_definition_id, self.props) class BIM_PT_connected_structural_members(Panel): @@ -97,32 +109,36 @@ class BIM_PT_connected_structural_members(Panel): def draw(self, context): self.oprops = context.active_object.BIMObjectProperties self.props = context.active_object.BIMStructuralProperties - if self.oprops.ifc_definition_id not in Data.connected_structural_members: - Data.load(self.oprops.ifc_definition_id) + if self.oprops.ifc_definition_id not in Data.connections: + Data.load(IfcStore.get_file(), self.oprops.ifc_definition_id) - self.data = Data.connected_structural_members[self.oprops.ifc_definition_id] + rel_ids = Data.connections[self.oprops.ifc_definition_id]["ConnectsStructuralMembers"] - for member in self.data: + row = self.layout.row(align=True) + row.prop(self.props, "relating_structural_member", text="", icon="CON_TRACKTO") + row.operator("bim.add_structural_member_connection", text="", icon="ADD") + + for rel_id in rel_ids: + rel = Data.connects_structural_members[rel_id] row = self.layout.row(align=True) - row.label(text=str(member)) + row.label(text=f"To Member #{IfcStore.get_file().by_id(rel['RelatingStructuralMember']).Name}") + if self.props.active_connects_structural_member and self.props.active_connects_structural_member == rel_id: + row.operator("bim.disable_editing_structural_connection_condition", text="", icon="CHECKMARK") + row.enabled = self.props.active_boundary_condition != rel["AppliedCondition"] + self.draw_editable_ui(context, self.layout, rel) + elif self.props.active_connects_structural_member: + op = row.operator("bim.remove_structural_connection_condition", text="", icon="X") + op.connects_structural_member = rel_id + else: + op = row.operator("bim.enable_editing_structural_connection_condition", text="", icon="GREASEPENCIL") + op.connects_structural_member = rel_id + op = row.operator("bim.remove_structural_connection_condition", text="", icon="X") + op.connects_structural_member = rel_id - # row = self.layout.row(align=True) - # if self.data and self.props.is_editing_boundary_condition: - # row.label(text=self.data["type"], icon="CON_TRACKTO") - # row.operator("bim.edit_structural_boundary_condition", text="", icon="CHECKMARK") - # row.operator("bim.disable_editing_structural_boundary_condition", text="", icon="X") - # elif self.data and not self.props.is_editing_boundary_condition: - # row.label(text=self.data["type"], icon="CON_TRACKTO") - # row.operator("bim.enable_editing_structural_boundary_condition", text="", icon="GREASEPENCIL") - # row.operator("bim.remove_structural_boundary_condition", text="", icon="X") - # else: - # row.label(text="No Boundary Condition Found", icon="CON_TRACKTO") - # row.operator("bim.add_structural_boundary_condition", text="", icon="ADD") - - # if self.props.is_editing_boundary_condition: - # self.draw_editable_ui(context) - # else: - # self.draw_read_only_ui(context) + def draw_editable_ui(self, context, layout, data): + box = layout.box() + row = box.row(align=True) + draw_boundary_condition_ui(box, data["AppliedCondition"], data["id"], self.props) class BIM_PT_structural_analysis_models(Panel): @@ -139,7 +155,7 @@ class BIM_PT_structural_analysis_models(Panel): def draw(self, context): if not Data.is_loaded: - Data.load() + Data.load(IfcStore.get_file()) self.props = context.scene.BIMStructuralProperties row = self.layout.row(align=True) diff --git a/src/ifcblenderexport/blenderbim/bim/module/style/__init__.py b/src/blenderbim/blenderbim/bim/module/style/__init__.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/style/__init__.py rename to src/blenderbim/blenderbim/bim/module/style/__init__.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/style/operator.py b/src/blenderbim/blenderbim/bim/module/style/operator.py similarity index 90% rename from src/ifcblenderexport/blenderbim/bim/module/style/operator.py rename to src/blenderbim/blenderbim/bim/module/style/operator.py index 62cce46f0b..c60bd09a9f 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/style/operator.py +++ b/src/blenderbim/blenderbim/bim/module/style/operator.py @@ -1,6 +1,5 @@ import bpy -import blenderbim.bim.module.style.add_style as add_style -import blenderbim.bim.module.style.edit_style as edit_style +import ifcopenshell.api from blenderbim.bim.ifc import IfcStore @@ -28,7 +27,7 @@ class EditStyle(bpy.types.Operator): material = bpy.data.objects.get(self.material) if self.material else bpy.context.active_object.active_material settings = get_colour_settings(material) settings["style"] = self.file.by_id(material.BIMMaterialProperties.ifc_style_id) - edit_style.Usecase(self.file, settings).execute() + ifcopenshell.api.run("style.edit_style", self.file, **settings) return {"FINISHED"} @@ -43,7 +42,7 @@ class AddStyle(bpy.types.Operator): settings = get_colour_settings(material) settings["Name"] = material.name settings["external_definition"] = None # TODO: Implement. See #1222 - style = add_style.Usecase(self.file, settings).execute() + style = ifcopenshell.api.run("style.add_style", self.file, **settings) material.BIMMaterialProperties.ifc_style_id = int(style.id()) return {"FINISHED"} diff --git a/src/ifcblenderexport/blenderbim/bim/module/style/ui.py b/src/blenderbim/blenderbim/bim/module/style/ui.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/style/ui.py rename to src/blenderbim/blenderbim/bim/module/style/ui.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/type/__init__.py b/src/blenderbim/blenderbim/bim/module/type/__init__.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/type/__init__.py rename to src/blenderbim/blenderbim/bim/module/type/__init__.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/type/operator.py b/src/blenderbim/blenderbim/bim/module/type/operator.py similarity index 85% rename from src/ifcblenderexport/blenderbim/bim/module/type/operator.py rename to src/blenderbim/blenderbim/bim/module/type/operator.py index 343d13ee35..fdfd43fa6e 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/type/operator.py +++ b/src/blenderbim/blenderbim/bim/module/type/operator.py @@ -1,11 +1,9 @@ import bpy import ifcopenshell.util.schema import ifcopenshell.util.type -import blenderbim.bim.module.type.assign_type as assign_type -import blenderbim.bim.module.type.unassign_type as unassign_type -import blenderbim.bim.module.type.get_related_objects as get_related_objects +import ifcopenshell.api from blenderbim.bim.ifc import IfcStore -from blenderbim.bim.module.type.data import Data +from ifcopenshell.api.type.data import Data from blenderbim.bim.module.type.prop import getIfcTypes, getAvailableTypes, updateTypeInstanceIfcClass from mathutils import Vector @@ -24,14 +22,15 @@ class AssignType(bpy.types.Operator): ) for related_object in related_objects: oprops = related_object.BIMObjectProperties - assign_type.Usecase( + ifcopenshell.api.run( + "type.assign_type", self.file, - { + **{ "related_object": self.file.by_id(oprops.ifc_definition_id), "relating_type": self.file.by_id(relating_type), }, - ).execute() - Data.load(oprops.ifc_definition_id) + ) + Data.load(IfcStore.get_file(), oprops.ifc_definition_id) if self.file.by_id(relating_type).RepresentationMaps: bpy.ops.bim.map_representations(product_id=oprops.ifc_definition_id, type_product_id=relating_type) @@ -51,13 +50,14 @@ class UnassignType(bpy.types.Operator): ) for related_object in related_objects: oprops = related_object.BIMObjectProperties - unassign_type.Usecase( + ifcopenshell.api.run( + "type.unassign_type", self.file, - { + **{ "related_object": self.file.by_id(oprops.ifc_definition_id), }, - ).execute() - Data.load(oprops.ifc_definition_id) + ) + Data.load(IfcStore.get_file(), oprops.ifc_definition_id) return {"FINISHED"} @@ -93,13 +93,13 @@ class SelectSimilarType(bpy.types.Operator): product = self.file.by_id(oprops.ifc_definition_id) declaration = IfcStore.get_schema().declaration_by_name(product.is_a()) if ifcopenshell.util.schema.is_a(declaration, "IfcElementType"): - related_objects = get_related_objects.Usecase( - self.file, {"relating_type": self.file.by_id(oprops.ifc_definition_id)} - ).execute() + related_objects = ifcopenshell.api.run( + "type.get_related_objects", self.file, **{"relating_type": self.file.by_id(oprops.ifc_definition_id)} + ) else: - related_objects = get_related_objects.Usecase( - self.file, {"related_object": self.file.by_id(oprops.ifc_definition_id)} - ).execute() + related_objects = ifcopenshell.api.run( + "type.get_related_objects", self.file, **{"related_object": self.file.by_id(oprops.ifc_definition_id)} + ) for obj in bpy.context.visible_objects: if obj.BIMObjectProperties.ifc_definition_id in related_objects: obj.select_set(True) diff --git a/src/ifcblenderexport/blenderbim/bim/module/type/prop.py b/src/blenderbim/blenderbim/bim/module/type/prop.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/type/prop.py rename to src/blenderbim/blenderbim/bim/module/type/prop.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/type/ui.py b/src/blenderbim/blenderbim/bim/module/type/ui.py similarity index 90% rename from src/ifcblenderexport/blenderbim/bim/module/type/ui.py rename to src/blenderbim/blenderbim/bim/module/type/ui.py index 3a4a88215f..bdee759124 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/type/ui.py +++ b/src/blenderbim/blenderbim/bim/module/type/ui.py @@ -1,5 +1,6 @@ from bpy.types import Panel -from blenderbim.bim.module.type.data import Data +from blenderbim.bim.ifc import IfcStore +from ifcopenshell.api.type.data import Data class BIM_PT_type(Panel): @@ -15,7 +16,7 @@ class BIM_PT_type(Panel): if not props.ifc_definition_id: return False if props.ifc_definition_id not in Data.products: - Data.load(props.ifc_definition_id) + Data.load(IfcStore.get_file(), props.ifc_definition_id) if not Data.products[props.ifc_definition_id]: return False return True @@ -27,7 +28,7 @@ class BIM_PT_type(Panel): if not oprops.ifc_definition_id: return if oprops.ifc_definition_id not in Data.products: - Data.load(oprops.ifc_definition_id) + Data.load(IfcStore.get_file(), oprops.ifc_definition_id) if props.is_editing_type: row = self.layout.row(align=True) diff --git a/src/ifcblenderexport/blenderbim/bim/module/unit/__init__.py b/src/blenderbim/blenderbim/bim/module/unit/__init__.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/unit/__init__.py rename to src/blenderbim/blenderbim/bim/module/unit/__init__.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/unit/operator.py b/src/blenderbim/blenderbim/bim/module/unit/operator.py similarity index 84% rename from src/ifcblenderexport/blenderbim/bim/module/unit/operator.py rename to src/blenderbim/blenderbim/bim/module/unit/operator.py index 5ec9155c8e..debf4b2e9a 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/unit/operator.py +++ b/src/blenderbim/blenderbim/bim/module/unit/operator.py @@ -1,7 +1,7 @@ import bpy -import blenderbim.bim.module.unit.assign_unit as assign_unit +import ifcopenshell.api from blenderbim.bim.ifc import IfcStore -from blenderbim.bim.module.unit.data import Data +from ifcopenshell.api.unit.data import Data class AssignUnit(bpy.types.Operator): @@ -9,8 +9,8 @@ class AssignUnit(bpy.types.Operator): bl_label = "Assign Unit" def execute(self, context): - assign_unit.Usecase(IfcStore.get_file(), self.get_units()).execute() - Data.load() + ifcopenshell.api.run("unit.assign_unit", IfcStore.get_file(), **self.get_units()) + Data.load(IfcStore.get_file()) return {"FINISHED"} def get_units(self): diff --git a/src/ifcblenderexport/blenderbim/bim/module/unit/ui.py b/src/blenderbim/blenderbim/bim/module/unit/ui.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/unit/ui.py rename to src/blenderbim/blenderbim/bim/module/unit/ui.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/void/__init__.py b/src/blenderbim/blenderbim/bim/module/void/__init__.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/void/__init__.py rename to src/blenderbim/blenderbim/bim/module/void/__init__.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/void/operator.py b/src/blenderbim/blenderbim/bim/module/void/operator.py similarity index 79% rename from src/ifcblenderexport/blenderbim/bim/module/void/operator.py rename to src/blenderbim/blenderbim/bim/module/void/operator.py index cd1f9956e5..31785ad2dc 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/void/operator.py +++ b/src/blenderbim/blenderbim/bim/module/void/operator.py @@ -1,11 +1,8 @@ import bpy -import blenderbim.bim.module.void.add_opening as add_opening -import blenderbim.bim.module.void.remove_opening as remove_opening -import blenderbim.bim.module.void.add_filling as add_filling -import blenderbim.bim.module.void.remove_filling as remove_filling +import ifcopenshell.api from blenderbim.bim.ifc import IfcStore -from blenderbim.bim.module.void.data import Data -from blenderbim.bim.module.context.data import Data as ContextData +from ifcopenshell.api.void.data import Data +from ifcopenshell.api.context.data import Data as ContextData class AddOpening(bpy.types.Operator): @@ -21,7 +18,7 @@ class AddOpening(bpy.types.Operator): if not opening.BIMObjectProperties.ifc_definition_id: body_context_id = None if not ContextData.is_loaded: - ContextData.load() + ContextData.load(IfcStore.get_file()) for context in ContextData.contexts.values(): for subcontext_id, subcontext in context["HasSubContexts"].items(): if subcontext["ContextType"] == "Model" and subcontext["ContextIdentifier"] == "Body": @@ -33,14 +30,15 @@ class AddOpening(bpy.types.Operator): self.file = IfcStore.get_file() element_id = obj.BIMObjectProperties.ifc_definition_id - add_opening.Usecase( + ifcopenshell.api.run( + "void.add_opening", self.file, - { + **{ "opening": self.file.by_id(opening.BIMObjectProperties.ifc_definition_id), "element": self.file.by_id(element_id), }, - ).execute() - Data.load(element_id) + ) + Data.load(IfcStore.get_file(), element_id) has_modifier = False @@ -75,8 +73,8 @@ class RemoveOpening(bpy.types.Operator): obj.modifiers.remove(modifier) break - remove_opening.Usecase(self.file, {"opening": self.file.by_id(self.opening_id)}).execute() - Data.load(obj.BIMObjectProperties.ifc_definition_id) + ifcopenshell.api.run("void.remove_opening", self.file, **{"opening": self.file.by_id(self.opening_id)}) + Data.load(IfcStore.get_file(), obj.BIMObjectProperties.ifc_definition_id) return {"FINISHED"} @@ -91,14 +89,15 @@ class AddFilling(bpy.types.Operator): opening = bpy.data.objects.get(self.opening) if self.opening else context.scene.VoidProperties.desired_opening self.file = IfcStore.get_file() element_id = obj.BIMObjectProperties.ifc_definition_id - add_filling.Usecase( + ifcopenshell.api.run( + "void.add_filling", self.file, - { + **{ "opening": self.file.by_id(opening.BIMObjectProperties.ifc_definition_id), "element": self.file.by_id(element_id), }, - ).execute() - Data.load(element_id) + ) + Data.load(IfcStore.get_file(), element_id) return {"FINISHED"} @@ -110,8 +109,8 @@ class RemoveFilling(bpy.types.Operator): def execute(self, context): obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object self.file = IfcStore.get_file() - remove_filling.Usecase( - self.file, {"element": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)} - ).execute() - Data.load(obj.BIMObjectProperties.ifc_definition_id) + ifcopenshell.api.run( + "void.remove_filling", self.file, **{"element": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)} + ) + Data.load(IfcStore.get_file(), obj.BIMObjectProperties.ifc_definition_id) return {"FINISHED"} diff --git a/src/ifcblenderexport/blenderbim/bim/module/void/prop.py b/src/blenderbim/blenderbim/bim/module/void/prop.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/module/void/prop.py rename to src/blenderbim/blenderbim/bim/module/void/prop.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/void/ui.py b/src/blenderbim/blenderbim/bim/module/void/ui.py similarity index 96% rename from src/ifcblenderexport/blenderbim/bim/module/void/ui.py rename to src/blenderbim/blenderbim/bim/module/void/ui.py index c878d8ccea..548ff2f096 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/void/ui.py +++ b/src/blenderbim/blenderbim/bim/module/void/ui.py @@ -1,6 +1,6 @@ import bpy from bpy.types import Panel -from blenderbim.bim.module.void.data import Data +from ifcopenshell.api.void.data import Data from blenderbim.bim.ifc import IfcStore @@ -19,7 +19,7 @@ class BIM_PT_voids(Panel): def draw(self, context): props = context.active_object.BIMObjectProperties if props.ifc_definition_id not in Data.products: - Data.load(props.ifc_definition_id) + Data.load(IfcStore.get_file(), props.ifc_definition_id) row = self.layout.row(align=True) if len(context.selected_objects) == 2: diff --git a/src/ifcblenderexport/blenderbim/bim/operator.py b/src/blenderbim/blenderbim/bim/operator.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/operator.py rename to src/blenderbim/blenderbim/bim/operator.py diff --git a/src/ifcblenderexport/blenderbim/bim/prop.py b/src/blenderbim/blenderbim/bim/prop.py similarity index 98% rename from src/ifcblenderexport/blenderbim/bim/prop.py rename to src/blenderbim/blenderbim/bim/prop.py index 4ee0227dea..4c5b493919 100644 --- a/src/ifcblenderexport/blenderbim/bim/prop.py +++ b/src/blenderbim/blenderbim/bim/prop.py @@ -9,6 +9,7 @@ from . import ifc from . import annotation from . import decoration import bpy +from blenderbim.bim.handler import purge_module_data from blenderbim.bim.ifc import IfcStore from bpy.types import PropertyGroup from bpy.props import ( @@ -38,16 +39,7 @@ def updateIfcFile(self, context): if context.scene.BIMProperties.ifc_file: IfcStore.file = None IfcStore.schema = None - # Purge data cache - from blenderbim.bim import modules - - for module in modules.values(): - if not module: - continue - try: - getattr(getattr(module, "data"), "Data").purge() - except AttributeError: - pass + purge_module_data() def getDiagramScales(self, context): @@ -163,10 +155,10 @@ def getMaterialPsetNames(self, context): def getContexts(self, context): - from blenderbim.bim.module.context.data import Data + from ifcopenshell.api.context.data import Data if not Data.is_loaded: - Data.load() + Data.load(IfcStore.get_file()) results = [] for ifc_id, context in Data.contexts.items(): results.append((str(ifc_id), context["ContextType"], "")) diff --git a/src/ifcblenderexport/blenderbim/bim/scheduler.py b/src/blenderbim/blenderbim/bim/scheduler.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/scheduler.py rename to src/blenderbim/blenderbim/bim/scheduler.py diff --git a/src/ifcblenderexport/blenderbim/bim/schema.py b/src/blenderbim/blenderbim/bim/schema.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/schema.py rename to src/blenderbim/blenderbim/bim/schema.py diff --git a/src/ifcblenderexport/blenderbim/bim/schema/IfcAnnotation_IFC4.json b/src/blenderbim/blenderbim/bim/schema/IfcAnnotation_IFC4.json similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/schema/IfcAnnotation_IFC4.json rename to src/blenderbim/blenderbim/bim/schema/IfcAnnotation_IFC4.json diff --git a/src/ifcblenderexport/blenderbim/bim/schema/IfcBoundaryCondition_IFC4.json b/src/blenderbim/blenderbim/bim/schema/IfcBoundaryCondition_IFC4.json similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/schema/IfcBoundaryCondition_IFC4.json rename to src/blenderbim/blenderbim/bim/schema/IfcBoundaryCondition_IFC4.json diff --git a/src/ifcblenderexport/blenderbim/bim/schema/IfcElementType_IFC4.json b/src/blenderbim/blenderbim/bim/schema/IfcElementType_IFC4.json similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/schema/IfcElementType_IFC4.json rename to src/blenderbim/blenderbim/bim/schema/IfcElementType_IFC4.json diff --git a/src/ifcblenderexport/blenderbim/bim/schema/IfcElement_IFC4.json b/src/blenderbim/blenderbim/bim/schema/IfcElement_IFC4.json similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/schema/IfcElement_IFC4.json rename to src/blenderbim/blenderbim/bim/schema/IfcElement_IFC4.json diff --git a/src/ifcblenderexport/blenderbim/bim/schema/IfcGroup_IFC4.json b/src/blenderbim/blenderbim/bim/schema/IfcGroup_IFC4.json similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/schema/IfcGroup_IFC4.json rename to src/blenderbim/blenderbim/bim/schema/IfcGroup_IFC4.json diff --git a/src/ifcblenderexport/blenderbim/bim/schema/IfcMaterialDefinition_IFC4.json b/src/blenderbim/blenderbim/bim/schema/IfcMaterialDefinition_IFC4.json similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/schema/IfcMaterialDefinition_IFC4.json rename to src/blenderbim/blenderbim/bim/schema/IfcMaterialDefinition_IFC4.json diff --git a/src/ifcblenderexport/blenderbim/bim/schema/IfcParameterizedProfileDef_IFC4.json b/src/blenderbim/blenderbim/bim/schema/IfcParameterizedProfileDef_IFC4.json similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/schema/IfcParameterizedProfileDef_IFC4.json rename to src/blenderbim/blenderbim/bim/schema/IfcParameterizedProfileDef_IFC4.json diff --git a/src/ifcblenderexport/blenderbim/bim/schema/IfcPositioningElement_IFC4.json b/src/blenderbim/blenderbim/bim/schema/IfcPositioningElement_IFC4.json similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/schema/IfcPositioningElement_IFC4.json rename to src/blenderbim/blenderbim/bim/schema/IfcPositioningElement_IFC4.json diff --git a/src/ifcblenderexport/blenderbim/bim/schema/IfcSpatialElement_IFC4.json b/src/blenderbim/blenderbim/bim/schema/IfcSpatialElement_IFC4.json similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/schema/IfcSpatialElement_IFC4.json rename to src/blenderbim/blenderbim/bim/schema/IfcSpatialElement_IFC4.json diff --git a/src/ifcblenderexport/blenderbim/bim/schema/IfcStructural_IFC4.json b/src/blenderbim/blenderbim/bim/schema/IfcStructural_IFC4.json similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/schema/IfcStructural_IFC4.json rename to src/blenderbim/blenderbim/bim/schema/IfcStructural_IFC4.json diff --git a/src/ifcblenderexport/blenderbim/bim/schema/classifications/Omniclass_OCCS.ifc b/src/blenderbim/blenderbim/bim/schema/classifications/Omniclass_OCCS.ifc similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/schema/classifications/Omniclass_OCCS.ifc rename to src/blenderbim/blenderbim/bim/schema/classifications/Omniclass_OCCS.ifc diff --git a/src/ifcblenderexport/blenderbim/bim/schema/classifications/Uniclass2015_Jan2020.ifc b/src/blenderbim/blenderbim/bim/schema/classifications/Uniclass2015_Jan2020.ifc similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/schema/classifications/Uniclass2015_Jan2020.ifc rename to src/blenderbim/blenderbim/bim/schema/classifications/Uniclass2015_Jan2020.ifc diff --git a/src/ifcblenderexport/blenderbim/bim/schema/entity_descriptions.json b/src/blenderbim/blenderbim/bim/schema/entity_descriptions.json similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/schema/entity_descriptions.json rename to src/blenderbim/blenderbim/bim/schema/entity_descriptions.json diff --git a/src/ifcblenderexport/blenderbim/bim/schema/enum_descriptions.json b/src/blenderbim/blenderbim/bim/schema/enum_descriptions.json similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/schema/enum_descriptions.json rename to src/blenderbim/blenderbim/bim/schema/enum_descriptions.json diff --git a/src/ifcblenderexport/blenderbim/bim/schema/ifc_types_IFC4.json b/src/blenderbim/blenderbim/bim/schema/ifc_types_IFC4.json similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/schema/ifc_types_IFC4.json rename to src/blenderbim/blenderbim/bim/schema/ifc_types_IFC4.json diff --git a/src/ifcblenderexport/blenderbim/bim/shaders.py b/src/blenderbim/blenderbim/bim/shaders.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/shaders.py rename to src/blenderbim/blenderbim/bim/shaders.py diff --git a/src/ifcblenderexport/blenderbim/bim/sheeter.py b/src/blenderbim/blenderbim/bim/sheeter.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/sheeter.py rename to src/blenderbim/blenderbim/bim/sheeter.py diff --git a/src/ifcblenderexport/blenderbim/bim/svgwriter.py b/src/blenderbim/blenderbim/bim/svgwriter.py similarity index 98% rename from src/ifcblenderexport/blenderbim/bim/svgwriter.py rename to src/blenderbim/blenderbim/bim/svgwriter.py index 7c8b58873b..8275c6439f 100644 --- a/src/ifcblenderexport/blenderbim/bim/svgwriter.py +++ b/src/blenderbim/blenderbim/bim/svgwriter.py @@ -12,10 +12,13 @@ from mathutils import Vector from mathutils import geometry from blenderbim.bim.ifc import IfcStore -try: - from OCC.Core import BRep, BRepTools, TopExp, TopAbs -except ImportError: - from OCC import BRep, BRepTools, TopExp, TopAbs + +def load_occ(): + # Don't import until we really need to, as a temporary step before we can purge OCC + try: + from OCC.Core import BRep, BRepTools, TopExp, TopAbs + except ImportError: + from OCC import BRep, BRepTools, TopExp, TopAbs class External(svgwrite.container.Group): @@ -599,6 +602,7 @@ class SvgWriter: self.draw_polygon(polygon, "cut") def draw_polyline(self, element, position): + load_occ() classes = self.get_classes(element["raw"], position) exp = BRepTools.BRepTools_WireExplorer(element["geometry"]) points = [] @@ -609,6 +613,7 @@ class SvgWriter: self.svg.add(self.svg.polyline(points=points, class_=" ".join(classes))) def draw_line(self, element, position): + load_occ() classes = self.get_classes(element["raw"], position) exp = TopExp.TopExp_Explorer(element["geometry"], TopAbs.TopAbs_VERTEX) points = [] diff --git a/src/ifcblenderexport/blenderbim/bim/ui.py b/src/blenderbim/blenderbim/bim/ui.py similarity index 100% rename from src/ifcblenderexport/blenderbim/bim/ui.py rename to src/blenderbim/blenderbim/bim/ui.py diff --git a/src/ifcblenderexport/blenderbim/libs/site/packages/OCC.pth b/src/blenderbim/blenderbim/libs/site/packages/OCC.pth similarity index 100% rename from src/ifcblenderexport/blenderbim/libs/site/packages/OCC.pth rename to src/blenderbim/blenderbim/libs/site/packages/OCC.pth diff --git a/src/ifcblenderexport/blenderbim/libs/site/packages/ifcopenshell.pth b/src/blenderbim/blenderbim/libs/site/packages/ifcopenshell.pth similarity index 100% rename from src/ifcblenderexport/blenderbim/libs/site/packages/ifcopenshell.pth rename to src/blenderbim/blenderbim/libs/site/packages/ifcopenshell.pth diff --git a/src/ifcblenderexport/blenderbim/libs/site/packages/svgwrite.pth b/src/blenderbim/blenderbim/libs/site/packages/svgwrite.pth similarity index 100% rename from src/ifcblenderexport/blenderbim/libs/site/packages/svgwrite.pth rename to src/blenderbim/blenderbim/libs/site/packages/svgwrite.pth diff --git a/src/ifcblenderexport/docs/Makefile b/src/blenderbim/docs/Makefile similarity index 100% rename from src/ifcblenderexport/docs/Makefile rename to src/blenderbim/docs/Makefile diff --git a/src/ifcblenderexport/docs/bimserver-plugin.rst b/src/blenderbim/docs/bimserver-plugin.rst similarity index 100% rename from src/ifcblenderexport/docs/bimserver-plugin.rst rename to src/blenderbim/docs/bimserver-plugin.rst diff --git a/src/ifcblenderexport/docs/bimtester.rst b/src/blenderbim/docs/bimtester.rst similarity index 100% rename from src/ifcblenderexport/docs/bimtester.rst rename to src/blenderbim/docs/bimtester.rst diff --git a/src/ifcblenderexport/docs/blenderbim.rst b/src/blenderbim/docs/blenderbim.rst similarity index 100% rename from src/ifcblenderexport/docs/blenderbim.rst rename to src/blenderbim/docs/blenderbim.rst diff --git a/src/ifcblenderexport/docs/blenderbim/installation.rst b/src/blenderbim/docs/blenderbim/installation.rst similarity index 97% rename from src/ifcblenderexport/docs/blenderbim/installation.rst rename to src/blenderbim/docs/blenderbim/installation.rst index 7c4df4ff3c..f1d8e5101e 100644 --- a/src/ifcblenderexport/docs/blenderbim/installation.rst +++ b/src/blenderbim/docs/blenderbim/installation.rst @@ -73,7 +73,7 @@ how to use Git, you can also stay up to date like so: $ git checkout v0.6.0 Then, just copy the files from the source code's -``src/ifcblenderexport/blenderbim/`` folder and replace the files in your +``src/blenderbim/blenderbim/`` folder and replace the files in your Blender add-on's ``blenderbim/`` folder. Restart Blender for the changes to take effect. In ``Edit > Preferences > diff --git a/src/ifcblenderexport/docs/blenderbim/scene.rst b/src/blenderbim/docs/blenderbim/scene.rst similarity index 100% rename from src/ifcblenderexport/docs/blenderbim/scene.rst rename to src/blenderbim/docs/blenderbim/scene.rst diff --git a/src/ifcblenderexport/docs/conf.py b/src/blenderbim/docs/conf.py similarity index 100% rename from src/ifcblenderexport/docs/conf.py rename to src/blenderbim/docs/conf.py diff --git a/src/ifcblenderexport/docs/ifcclash.rst b/src/blenderbim/docs/ifcclash.rst similarity index 100% rename from src/ifcblenderexport/docs/ifcclash.rst rename to src/blenderbim/docs/ifcclash.rst diff --git a/src/ifcblenderexport/docs/ifccobie.rst b/src/blenderbim/docs/ifccobie.rst similarity index 100% rename from src/ifcblenderexport/docs/ifccobie.rst rename to src/blenderbim/docs/ifccobie.rst diff --git a/src/ifcblenderexport/docs/ifcconvert.rst b/src/blenderbim/docs/ifcconvert.rst similarity index 100% rename from src/ifcblenderexport/docs/ifcconvert.rst rename to src/blenderbim/docs/ifcconvert.rst diff --git a/src/ifcblenderexport/docs/ifcdiff.rst b/src/blenderbim/docs/ifcdiff.rst similarity index 100% rename from src/ifcblenderexport/docs/ifcdiff.rst rename to src/blenderbim/docs/ifcdiff.rst diff --git a/src/ifcblenderexport/docs/ifcmax.rst b/src/blenderbim/docs/ifcmax.rst similarity index 100% rename from src/ifcblenderexport/docs/ifcmax.rst rename to src/blenderbim/docs/ifcmax.rst diff --git a/src/ifcblenderexport/docs/ifcopenshell-python.rst b/src/blenderbim/docs/ifcopenshell-python.rst similarity index 100% rename from src/ifcblenderexport/docs/ifcopenshell-python.rst rename to src/blenderbim/docs/ifcopenshell-python.rst diff --git a/src/ifcblenderexport/docs/ifcopenshell-python/api-documentation.rst b/src/blenderbim/docs/ifcopenshell-python/api-documentation.rst similarity index 100% rename from src/ifcblenderexport/docs/ifcopenshell-python/api-documentation.rst rename to src/blenderbim/docs/ifcopenshell-python/api-documentation.rst diff --git a/src/ifcblenderexport/docs/ifcopenshell-python/quickstart.rst b/src/blenderbim/docs/ifcopenshell-python/quickstart.rst similarity index 100% rename from src/ifcblenderexport/docs/ifcopenshell-python/quickstart.rst rename to src/blenderbim/docs/ifcopenshell-python/quickstart.rst diff --git a/src/ifcblenderexport/docs/ifcopenshell.rst b/src/blenderbim/docs/ifcopenshell.rst similarity index 100% rename from src/ifcblenderexport/docs/ifcopenshell.rst rename to src/blenderbim/docs/ifcopenshell.rst diff --git a/src/ifcblenderexport/docs/index.rst b/src/blenderbim/docs/index.rst similarity index 100% rename from src/ifcblenderexport/docs/index.rst rename to src/blenderbim/docs/index.rst diff --git a/src/ifcblenderexport/docs/make.bat b/src/blenderbim/docs/make.bat similarity index 100% rename from src/ifcblenderexport/docs/make.bat rename to src/blenderbim/docs/make.bat diff --git a/src/ifcblenderexport/dxf2ifc.py b/src/blenderbim/dxf2ifc.py similarity index 100% rename from src/ifcblenderexport/dxf2ifc.py rename to src/blenderbim/dxf2ifc.py diff --git a/src/ifcblenderexport/extract.py b/src/blenderbim/extract.py similarity index 100% rename from src/ifcblenderexport/extract.py rename to src/blenderbim/extract.py diff --git a/src/ifcblenderexport/gbxml.py b/src/blenderbim/gbxml.py similarity index 100% rename from src/ifcblenderexport/gbxml.py rename to src/blenderbim/gbxml.py diff --git a/src/ifcblenderexport/generate_util_type_json.py b/src/blenderbim/generate_util_type_json.py similarity index 94% rename from src/ifcblenderexport/generate_util_type_json.py rename to src/blenderbim/generate_util_type_json.py index 35a0cba617..bd5313b9dc 100644 --- a/src/ifcblenderexport/generate_util_type_json.py +++ b/src/blenderbim/generate_util_type_json.py @@ -24,6 +24,10 @@ with open(filepath) as fp: is_in_where_rule = True elif entity and is_in_where_rule and "IN TYPEOF" in line and "RelatingType" in line: type_class = line.split("'")[1].split(".")[1] + if type_class == "IFCTRANFORMERTYPE": + # Fix typo in schema + type_class = "IFCTRANSFORMERTYPE" + type_class = schema4.declaration_by_name(type_class).name() entity_to_type_map.setdefault(entity, []).append(type_class) line = fp.readline() diff --git a/src/ifcblenderexport/getIfcElements.py b/src/blenderbim/getIfcElements.py similarity index 100% rename from src/ifcblenderexport/getIfcElements.py rename to src/blenderbim/getIfcElements.py diff --git a/src/ifcblenderexport/get_description.py b/src/blenderbim/get_description.py similarity index 96% rename from src/ifcblenderexport/get_description.py rename to src/blenderbim/get_description.py index 2c60f47468..09846d8fae 100644 --- a/src/ifcblenderexport/get_description.py +++ b/src/blenderbim/get_description.py @@ -37,7 +37,7 @@ class Describer: f.write(json.dumps(self.enum_descriptions, indent=4)) def get_html_sources(self): - html_dir = "/home/dion/Projects/IfcOpenShell/src/ifcblenderexport/descriptions/IFC4_3/RC1/HTML" + html_dir = "/home/dion/Projects/IfcOpenShell/src/blenderbim/descriptions/IFC4_3/RC1/HTML" for filename in Path(html_dir).rglob("*.htm"): if "lexical" not in str(filename): continue diff --git a/src/ifcblenderexport/get_volume_by_material.py b/src/blenderbim/get_volume_by_material.py similarity index 100% rename from src/ifcblenderexport/get_volume_by_material.py rename to src/blenderbim/get_volume_by_material.py diff --git a/src/ifcblenderexport/ifc_to_gantt.py b/src/blenderbim/ifc_to_gantt.py similarity index 100% rename from src/ifcblenderexport/ifc_to_gantt.py rename to src/blenderbim/ifc_to_gantt.py diff --git a/src/ifcblenderexport/ifcopenshell-screenshot.png b/src/blenderbim/ifcopenshell-screenshot.png similarity index 100% rename from src/ifcblenderexport/ifcopenshell-screenshot.png rename to src/blenderbim/ifcopenshell-screenshot.png diff --git a/src/ifcblenderexport/occ_utils.py b/src/blenderbim/occ_utils.py old mode 100755 new mode 100644 similarity index 100% rename from src/ifcblenderexport/occ_utils.py rename to src/blenderbim/occ_utils.py diff --git a/src/ifcblenderexport/p6_to_ifc.py b/src/blenderbim/p6_to_ifc.py similarity index 100% rename from src/ifcblenderexport/p6_to_ifc.py rename to src/blenderbim/p6_to_ifc.py diff --git a/src/ifcblenderexport/runpytest.py b/src/blenderbim/runpytest.py similarity index 100% rename from src/ifcblenderexport/runpytest.py rename to src/blenderbim/runpytest.py diff --git a/src/ifcblenderexport/tests/test_segment_clipping.py b/src/blenderbim/tests/test_segment_clipping.py similarity index 100% rename from src/ifcblenderexport/tests/test_segment_clipping.py rename to src/blenderbim/tests/test_segment_clipping.py diff --git a/src/ifcbimtester/patch/model_core.patch b/src/ifcbimtester/patch/model_core.patch index 9452fd4985..77f0badc9a 100644 --- a/src/ifcbimtester/patch/model_core.patch +++ b/src/ifcbimtester/patch/model_core.patch @@ -1,5 +1,5 @@ --- behave/model_core.py 2018-02-26 02:53:03.000000000 +1100 -+++ /home/dion/Projects/IfcOpenShell/src/ifcblenderexport/patch-behave-model_core.py 2021-03-21 11:57:27.625195794 +1100 ++++ /home/dion/Projects/IfcOpenShell/src/blenderbim/patch-behave-model_core.py 2021-03-21 11:57:27.625195794 +1100 @@ -269,7 +269,10 @@ class BasicStatement(object): def __init__(self, filename, line, keyword, name): diff --git a/src/ifcbimtester/patch/runner_util.patch b/src/ifcbimtester/patch/runner_util.patch index d6a5ba7729..2362da317c 100644 --- a/src/ifcbimtester/patch/runner_util.patch +++ b/src/ifcbimtester/patch/runner_util.patch @@ -1,5 +1,5 @@ --- behave/runner_util.py 2018-02-26 02:53:03.000000000 +1100 -+++ /home/dion/Projects/IfcOpenShell/src/ifcblenderexport/patch-behave-runner_util.py 2021-03-21 11:58:29.777638958 +1100 ++++ /home/dion/Projects/IfcOpenShell/src/blenderbim/patch-behave-runner_util.py 2021-03-21 11:58:29.777638958 +1100 @@ -381,7 +381,10 @@ locals_["__file__"] = filename with open(filename, "rb") as f: diff --git a/src/ifcblenderexport/blenderbim/bim/data/cache/shapes/.gitignore b/src/ifcblenderexport/blenderbim/bim/data/cache/shapes/.gitignore deleted file mode 100644 index d6b7ef32c8..0000000000 --- a/src/ifcblenderexport/blenderbim/bim/data/cache/shapes/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore diff --git a/src/ifcblenderexport/blenderbim/bim/data/diagrams/.gitkeep b/src/ifcblenderexport/blenderbim/bim/data/diagrams/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/ifcblenderexport/blenderbim/bim/data/fonts/OpenGost Type B TT.ttf b/src/ifcblenderexport/blenderbim/bim/data/fonts/OpenGost Type B TT.ttf deleted file mode 100644 index f4d86985cff7024c482ba0510da0b34fced8d494..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 54076 zcmeFa34C04buWJJtkP&SnoY}$w%N2;vLtK9mMvR$9LJWO*l`v+vEu}=Ejx*flNiSY zncxsY3#m(-Ko(P48va1ivJ~zek4Xqy+6G!^0yGK!P#Q`|d2K_1Mz4JYh&_7W@A=(3 zizGW?d4=~rf6LO`ZSFn4^EkUuzx$gaA^IOE7sgQcE?6dbN?64$7#{K%Kyg8h$bnq&FIEr${{1>XajR`Wd0w_SVSx*N6>hW-rur*VGob-Qjpfa5_; ztJ{Omn(Ou-zP9oGkNpVy`!(&psq6Rd+T*n=AN#8{%~{xg)5NaAAO9on_YuISKX=2fsRIt59@n&ozKQD-H}1M&ukoMn z{15EEq-os;4%~F}q1*rRKR>8xPwoWFmmD~__rTW^pL$-?o;Gm(JKwT*_qF@Kcljwz zduB2AJ@_T|v?o`7_#6EEJNJfF{QUaq_Seao0Crlm1pYd(uWLWTuS@pSH~DS;`n0Xu zZq2oJeA8AfK5_Wqey#hugL~hoW%utobfdOPzN5{|$hG|bt8MFV+~nG+5ZM24&7-{9-k<+-=0lj)_^H)CfS+3J zQT+I{$MECRzM}mN{yvEx7oISsT~b9MvgQFLX@oSP{@F*>9_hp*XGv}LKXrAD?DB67 zo?DB*q(q;!t&Z?0&(?qfxWy~%ANhL4A0MD=0$zxf+klPRfd%5=PK^C-jQM>S>-#ar zM=>^z>`57oPurwzuHrcv;W>lCbC!_;F)K6pbM7r(=5prrdoW^`JLi5sD7RC6I!|eP z9U&shZQ<#5&GBbJE%OS$#DAAwyKay6xK`hF+H<^k91G;QK8eHfMCV4=No*%dc;-FY z)J*7$fm>p{O>^lj_*|o{#`8HN^}xZ0w2x>HX&=)*p?yj#XrFU@#qk}-b1vQGb6w`z z;d+DXy$N3;nusSl5~)OYVkogZ@rJ}Flc}!LGG5*zfqQ%y_xN+%<1Z@ifuXwmt}U)> zT=yijL@?2kXtVAyT5%73=6}un^UPn({N>E!Ghdwf!p!Gq9+@%E{MniN&fI(Y!0DS# z-+20l)B8`4J^%IRzxw=Fp8xXmfA##Ao`2-|Pd$J1`BmTh>UUmJW5if~t$#YWl1-F4 zF~i@=e>mxMxjo*RT3?;NKF|;hg(K0%rskGdytS>pqcf3Ar88aKJ-rM1`WFri4lNqa z<`yp*S-Na=`HHcXtIk_}{+bJ*A*|nU;YAxaUA*~{OE0^8%hoHd+_wFy9amrTy4Sy9 z=dQ}9on?DskM;vi+jrf+zwuh@ioJ8Myng@x*eyq&`|kH&_^0p5<`4h%-}w3bKg(X# zpBrw%?v3^#p(C!1!`dy{VaL_ltyn8pXlvaeLtAKQk&VWtOSc;r-Ex(orO#_IJpJ2O zUM0tlT$Om%&?AE_1BSjZ@g2k8KVUc(ZoGW^y7X1a0mHd)vL#`xzI1!iSbf!i;abSA zCez8cZvSrUQ&+X(y6tCLe|%MII%&B3w;SWPTqP&2x(fGmFRZ_2$AIBkXr}Z#@$|%< z*Id(TXt<4cp_!3Gt4oJ!7KTHK(V+pOc46WOAMyn5pD>(V7p4=2tNS8DyL9`}y+?N? zxUsA?nY^m?sO(*?_V_@bf-cw^OyVJR3lmSvaQq7sLx#8in(c|i`t*49d_KjOwlZJlP_M;fkh3TW|#L)|nrgsq%4u^jUPmt3P z#x#UD0B(e54FG_q$J4v^?W`OLzZzMHK^%QI(RR_E^ii*oxODqi>*F{RU3fxUt*>6Q zM&I~oP@B-?FE73VkSC5_zCFDg(5Kh5;zLib0p?dPm)^YaNMVMt^_tdiNE-_{3V*Q@FnaykFC%!7sg#kvT07 zq0?_VoiFC=9a_I`M2C#pQ-+o`gYFj%SJrg9Uo;!_e$A|RhQda8bkXq0;*o4q)RS^7 z33012gzc$xE?xScOQmvY{nD7TA(lzUPfy3v^4u}!M*RgmH>9PtKhW|XJkDsz6&hTc z-_>s`;C$KW2@?3+N3r1`&@=&FkmpYL9FIP(J>qcI`J;{P9fQ_C{iGbQ_KnqX-E4P+!e+R2bW~e399evxzDmzw9MJ|n zpr=#aOXnOJ(^tAv(O6m^bEg_(>FMfS=bb*+bfh&MpYKEA+xY~>y+S)rdzY3U0ltla zTt3M0H|O$oI`AK9&E-sw^F=ecDw{1VcaGH6_nYZ499-^t(OfW`1$I^s8Ou(YE`K&_ z<}fMYv1~TKEa&S#v3i+a+i%olja<-Nr1zWAmAIrIm&8-Jq<;}F>F>cM9a-~yOy#2C z@Zymb`Vx$lpVlnq>`zW^zupLx@RPIKy(E;jKT}<~CF!Yjd}@l5%XyzpXVZsc>2&O{ z`itFZ9G;5lzUgWGJ?a8|fR`7au|KVgiqG(i`hfj;cp9Vvil3Uf)49<-06q6SZCv|P z%@`RH8Xa+RFeAelOy`gp2i3+qc_iLg3))>jWcY=4mw|Sd1r^Xelg#i zUX4v-Flb%?EcN1=wye1Uo6GzlZTF~=3mKkK^MXO_rACe3kdYk43L62jcvp{(8l9m> zYW$hrWn&kNXPQTic-Ty@9L0iIx_Bg)ZEk7~^$hAu7O!$FUBY$It~WI|d83|ms;9dr z)ZC#rMgtCSBhk51@9yc2M4LMGP(TOuEm=II1Ev1J!M!JkF6uo0)-6EK9Y<4oI;M_Y z*ikxmcqp}J`|I?9?XSCR52nB~uJnurdShvvDV}#*^6gvt zF5R@G7H3lNm7Wy==QWEiZywk8`8S;Yfd9g!JC}{q>H$yi92cI@pml0JurVIg@;#)~ z_MF)dG&@PHjXATy^e)OlsI&iSHlEE+QOQ)VsDS{pR$fmW~%!yPn} z*j#|k1wnHFn_VExVSLuthQcSE9X-&BW3LXJcV}!aWu2dT@cR!w`2FtfN49T2 z@<%?$)8S++U3+GLAC3nq&N)Y(fAGQQAJi}Ah1*YS;h<{_YdhTV$`h^Wx2bcRZ`;28 zw(W{epTpYz2ViU%*4Tb6-vONEyU0?BwOU}!T;T$8Rt_23DWSREpy{dWH?zPSjBzc#aeV!giZk0#%H=gN%}$Bs>0JASBm zWMfl09u4okJrs(iTX%PkjX!(;#IbG5^}B8#cZ_v)zGZJ}@$mZfkZ0igB5y+4Rf_9d zEMGUmL#75U@5mNv-C8q*KwZ|1oSp5v!1o;|$luA@b<>GY^7DDQ_$;11i%CcvzTbwL5bku?LJ7Y%Qg;?E33zy)gkA~HrC5sT6s!HBiQ59_xD7R1u7 zLx^UvPr32L3?6vo2%euA^VjJa$D?{$o>%+eO%AM92ad{j;z&af{4iunY!Lzh}UQ#NMNu}&Gb?1*Q*7$LJ?dp zOFFVdrX?oIL`SHWfHu>qv2<+R3STCc42_R-o%vR*BY(oNbSxRhu|zDxW6qD~(%XWe zSf+K~K3Qtp(z(>OU^teJ;{ebZ4sIjfv?+|>8Ld^jTr=WBMhI}bFkRVvT%Jhh>CApL$X+P8p=()0D*Rr zz@NlMAx5cIu?xvoP;)yr)1XZQ(vY@IGa7~p9#L+7la${4YTC(3pL;qIPg&Xs@up8Y zp3z^>>cH6zALJ-B3jFGZUuN6%*1Sk|t<-{Cl3X>NOig8C`U@O!u|tN7amyS)cf|O- z@I#d~M_Yx|jT(^w)EW6(D|fZ^MN3B%?NF_Q2Iodk2XtKxlwHNVr(BL54Slh+^UOnm zzF6j@zt;0WFBVhn&-e90nS>5I^PJ-u@ZCDCSz8HeCc|w2!*!A2Hga$+!f^eVd4JFh zVI_G1Pz;|T2>TPRTAveKl$@ii#C9*GtbkSv2H7}eykg-0;eGe-!+*Wj@sT5japcVF z_;=&JeH$Gg**LlHB93DWe;&rVifAKR9xk~4ycabNN}mphRLlozL33I_1I>v- z?G9sQHDG0tlgo0lbSy7agt72+xCJUxE`2ndO*`*w!G1da$`hOs=O>PasZy)?5Il5i z7i#$ovCs}IG!qLo#6r)I;XY-?frUgi@8;Tou!r&#%9_2H9J4(G7#yQUP3VNPJ`@+h zvXqknDUnWjJzlk%myTHL-K*R5(LGhGKOWn6(S-|PXmn8#S+()N5u>koi#}zMO=c|A z;P|ip;f<4>ZL39@X?T7A6646_>(A_kg<#PW;6JGiXgjt1Lc&i=q@D1$K+_2M7q&yw z2yrNbus%;2Q2>t7Bw_CKax~snj7H0zSnb8KHit03yCJxS~_YquS=%7w>qai3D`Q$f7Ig`q8dMDt9U$?(FeRf z=f(*5vbXk(ZZW{D%?Zo&$T4rR=#ldo;e5t1pRN8(1oPR-`NU8gL|JdeP+Nnh7ju`u zW>c2qGg})V_?!^9hBsuo>XhK6xl*1&+MhPR3Sl6#rcNfz;$b^Za@|%;T3r9Wtghm5 z(Xle|U|NnNJfNY_%>TgoMv1RW6&5sDXeFP}LR{a|t*`QpBYtHJrs~ zJe{zVoqBWe<5(IlO{_&v?JG}2;^~;j=X_}lOoBYjsci)>e;K^I8GeC&_@Nc%+kkm0 zDP}+DrYF_p1Lk{(`Gq24V!*sNaVkV}!iWXUPBjHaBxv|~SPYIK6Z~Hp9b^iwQDZ^q z5np3dZEG^shUqcBcQdO5G)*g_J>Wsm$u!A1H6xB9X%aj5U}ZjUQePY z4mCTwbi~oqo$@*?6XObfS98abmHD5UV@o=kckaBV_^qp(^;Jv1vJ5VUWnW$vzy1T) zUH5?p^*8Nli45Ga>0O_F?Dsd_F%W6lQ@nf68{VKlRQ!+gmoGnG53U&<)t^3b!wn~H z0Di<@BRrmTxmigVGX(62tV;kpjjetcu+vB*tcor%y(0EVmn~2vF<7H5bi(EIM=j!1 z;|fI`UfN8U$5r}LxuuPwSe#AVyZ({)r&)FcvSp3vii;t{zrDJ^!LZKV? z>6eROwERqt9ncjTz~4*S0@Na|Cfx{fBH^|WJJGK^O%T*rGq%RyAlB#gE;-zm8Ug%> z&V}cM5Y@XtGh#yu6VMPNrwnJ-YzBqYW(|#GL3(HtS|#Y?*^+oE1qc3e-_R7!uL0ro?x_=ozNQ&58%iXHmx8$;8cbgV1<*ylw2(s4qZ zPeVsOE_zX~()Os@57BO?PDJ${Rt9xGBb=o^Bo8gI(G*Z_v(zdT5VEhV4o0(SI4JZ> z#pj3TmUVL(Yj~(oTOO+iPlP)$04m~_ethW@8rZRAR z=r5#F#g2d<`d?S*bB~3(;nSE7$*`-|1-ZucTE3tBx(Dlm+LzhpdNJST2BXv3lC}IR z;uX9DG?4)`po!kB5eSM(SOcyYtKr2lidT9mXzv+Kqed)b)-{7bYQlz3*g2O7m^e*t z4+RdrIn>`oVS>JdG1%lX)x6~QUVp^6aeF@qW&8H?_g!@9j#MZb%g{ZR&bfBBMfwuP zkz-eHNH15y^uR?MmTcQN8Evgkzw(?SB+O~?xcg!7$K~2O#OLy1j&l{pNp^20u^|F# z0R|kSD{&1b9Nw~FF0pZ8`U4p3Kv2xd71&%6G*@GU9oXy$ip-(|Vm%J6UJ(jE;&Jyb z2oI0s$R9gGMsU=~gpB~W4f=rI$bEeE-Nk=DVvN7uIHIqcIF^o`c{rBYw^47r_mz9@ zdF9^Xzu)_d_kvolH-CB)^>+P>>$4yq@(l=|JE5Poz@miaPI+(C=Y)I;;aHO!EH%tk z(>5eFq8V<2l<;Yzqoz9s476hGqAJ4}x0Y&mk2C2Mi5N*b$6WgLfrWh`{W@2wHInpP zS=_wMlZ><`|CheoTv1o!TG_Ygm9N&+wWOQFx~q6P+?>|m>4*|G_&@Q7G0g~IOC!*b zM`#p|U7PEt!S&l(L*)7(ba9-+yA;KYwq=cI&}_kE)?+V0o(JltGu>=S0BR7i*&4-0 zJw*X_jda+k;ZW>3i$V#8q=O0Ay%dv24S9+6N$Eat#5i#2HP7A;k8S4gG`&I7)5Poa zm}@MSF^=4Q^`ejNy8qeq6?cF67>y^6M~7!jbNmg))5?fLjAIGgW2sX(rhBXb>#%{^ ziPivHo=y>EoYO{w;wS!SkPE1)wAa1=TlcHALr~P#{om3-Cii~}tL)fBv18&G)YoST zhsY$sYXesLA}wD}NP;#bF+u{d0Z1792nNk4&<2MlMFts`jUrOIg&taq{kkCL{%5PO zBKUarfntXsW4Hdo#4&{nTW4$6)@%9Js(A%23jRnd=haVOIs_QbE4&<0!Aumk05Ef6 zbuM*<55+)wqNfYpwIZI8M^YIq@SLF3sLK_+O>vIETV4oMSv*;z zStyVy5>|$_7D$8;KM3%tPa<;(_5`VTCLS!(x!6&{XS{f|{t$sx?gK}M!mMRKh;Oz| zODZpl07cgjR{>on{8io|`^ol`%J-N1$~p&66(3_nTWCot+JAMB$l_u3o}%Qb$JCO8Q+W62-ZCnu!>ui$NJH_1`o5Zudc?qr zAG^0a>Y~Syj_5&L6D+>%%rTy?>2O^7;o^Z3-3reO5*H$@y%wj@p$=O3g<1?;toGIc z7va*9kqH(-2{yBzvpQ?R#!qW%sakkod@+SAoqV#AwtT>YG6*bTPku&HqCwC>6&NN_ zG-P;3jRqweT#)Uix6#HCL|d)6rrPZ|pc6O(mYfPnaOyVcIX%||hc2LeIh5A*RP<%R z(P*qEUDWlNbWgM6mA@gsaqceeNv8D=oc>cHsA>*l+6E=#7!jpmV-R-5iyJYAjmkej zuQ=8BMg_YWpjj7!NOOe)FEy$Kb!d&e3=O zx1N3A%qhwfG8#u8{}Nwi`4xoLvQ~qzv^g`qWp$wj@)0qv6lbRUGnAzVl(7UV0%Xf( zi(sp!ge{1SAe>%;q)4T#CkRwlEkUnD8elE%0EQe(A>siOar7u~)C4OJ5gvgFY7AJi zEm&c~i~kNRg`5p+jUFCy7CP*DnnU5d(}l?sUr%iqR+t$li}u4151Blm{Ir5UZzgc`1_R>5j~N}>se_J33YT6@;NR|OOPz*mLmb!#q>=)~r?5#Q@~ zA}o=veO)p+AKv3wWmj92+M+1cOab+cN*Sv#!Qp8!TC+xzxF+DrBlcE4-+hx{Agy7ADFB@2oVEWM_G%RSdjYD-XJFPX^reqG8f6eF(=gZn~~G2d|y6m;TR2If+~=K z#bS7arXT30r;&jSKbW7{*d#uSQWQf4FhoO$dJ^4?xq#RyMX_x4bl&knh zp}zix;`?2$x6;lzeUtOOuyb1KYG3)OcP1?qswzssF^E?W=$6v-SPM{{PT9{MP8{_d8q*7MwZlygu5RZmIFS^5x+L zj{Y;>S}^Qd;g&hr09w2cxadKyx5RUd4ojyAVj6mf%mt#!AZlaQC)I*lT1zJiUCc^W z&(ddV1;XwPb^4a#Cw;AfXfmWP)t817(Lk%O_(^?BU0Wd987_Xc_|N?_>kCkW)L#S z&_>N#7d{#7rezP^3uF%ANI)#JD%HI+;7AwYluE}Pkb*U5zODZkpGmL7SY500J6Lh) zcp!ATvt&zIc?ON-FN_b0?Mt25bkj-GL|w2DbTj4-W5wDsn~5LlIpP>>hPrPXy^M88 zkP6FN86acyrpJJbF*p4t+4L(Lp)oV;FZ`txXO(3OZ-q)r(rJbD1sqqqAV~Te&OGdL z!{qAy`M#QZe0UyUDmlJ?81U~yo`k^fB>eP4*ijLIU;MZh;8pO`vFW1Utcl=P+f>l; z52s@#&^eSVvS}A0?5R}z7f1{vZ*Yw{I^2_57&^33H-wA@x={mkqedioq)@AJ6`68=NRR9#aokwQ3Jz-IWU3aH|FGf#jm zk78Qh)vbN7&%#Jq0Ys*6^}P& z+9SCxg&O%_Xd38|i2=NHydZOj)ZP^y6aVg*heV#53Sd%_hhaxh58OZVZ_e|OSJMPu zjmS?)-2&A^Fi?EZ71%+@l_6y5U5p68p^>kZU}9|m>kzh)*+%k@jvBQgWOzdPLVCAZ z54FqeU<|c()Nm>FgknY(1Y9u6k0<^A|vGG!(#l?z(GF@tL;d;pyDE@vL%LF)I;AkMFrFb>(RpO)x zI3f2^^Bb$ii9(3s&Ptf0jFVD|r}AT{;EqhzU3;jPB-)Bk@44$R5CXIaD9~BNUC^4m zYfo<6arJo4hQ~P}RceUtN__{vcyb3W8{V#Kis}x2Fz+phF6qanM!X z3&-4O(<8H(DE&?xdzcB~&35{ng|o;Y?`pCoy8+o zzU`h^W@>l?(05GVx|P%={0nIj4iE5{Ms1GD&#NKtMMNa;1n5R2XQtpYkEsOYgk%gc zCLPY^TN4ylt<7+0!2y?OUFj}qoPztqjEHjAi$%+%%^dTr)K{dOtNWHAwc@r5jY8eCh718kFp+ZubC=>wDaMie>o6e06c09 z3vrS{<`5XLcrSk4yg4#yJB0;#bB%hEoVoZtJ99-(D#na;3Lf_i@Id*7_?yIHMCKC~ zhRTwf>91CQG6l3?%G4<3Sj1NRppr1 z2j=k99l%c`c`7wL1qs7dK_>QSK{$;q^MM@92&uGty7_=6i+-txNNP@*n<9-3X>0U? zGMiO6+P;ghigHQ@k)K1q6gpW%KT$i^P%j?a+s?=KW?;yEiT@^#gcIdPmu@Z z6UanF^w@R^K|}6_pNIx8Sc2t7+P{2o{PxdmjOgiHxbK~B7;X*(+w}3_^Nv5T;e$(X zG#&~}P8M1c#mD+b9mhwmYU$b(f#ToSQr8@BZw^1z`TFHI-LhmTl1tZa+TYpP_*Cn5 z;=$G(TIrvr#*?S+p!9~i96g-yul@>|#ukUS47rlSh{^&cW|o$qw6WqdRZ7AvJ|fzf z@Ka2T5m5Fw_=x2{JtQ`*P(r&O=`Bd=H~lK#1ExKk&9Lz;8>bmw6zbNHp*b?jN zRxTlN5y^o{7m+gsiuH9`6pL}m@D?>!`H7eipd3ZW59r>IYK0Rzb zv^C`@puDWF;cagV^hZ-$1W9s-caMFd&4-y+iy-vQCBtX|;x2mszh>s)R2dT4kyT`c@oe=bzS)0bDKVkWi zB6ewkOp!H7w(u86SNGPs?|i2&6Yq$8=?kGwU5|CC{bcA1Uy5|Zx>kl8^bPv@hHy() zy!e9N-rC)a=-Fe%&jzB+-EDeX@t<2!8Y6In*Ang|t-S!@jpmGmr6;A3Ack2((oi#q zi1ukS4f`6h2vj4OA<G(inbKs&My6EQkEQl4P`Cpz^UaF z5ZzsBLicS1*T|&@;MRw3ihQ1Q&T&4s^oOtw5ro+Ey2XpvN{|8x)fX|)sm7;GV|>(8 z=8r}=9U#+uSX6~DSfS+q*%^OJ;mc+MD}aG_3>At<_6Io8OP;@M;OzsUY&vr3 z^Op{+K5rn}#PW~Gri=UgLuvWc`|13J{x-7_Hiib?GejR0l>B}po--FfCPuUQ^a5fp zjrftMErvg5F2ora)vkp+IPAEt3p9{ABr`hmz#AF)UKA(---9(3Z+I8 zSIgG6&>@OesTa?(X{YYqO_@5YLKUe6hu06UTsgcR4i9WoxQP}15SAGHZSY1On}F22 zn%QEOO(Ai!hgAiyluRwi=A9!%xN{MP8RqJfyu&b$wZUspsHq*|4#Q&J?83it7uy5{*i=Sj1`&SBmXI4n@65P^s9P;vIq|F}z-lpWYU! zZ72{Og`~cDcs&j%(~ zD!5adD|Gj#P)Lf9zu67!v}X&sK{|}9^L>F?hVXGi2rGbLNCL8Osq=yO4?D}YNlXrwA z_Rtwi`-|TbgiNEp07W7oE#)kczbA{|n;nyQJ21j!ZkIS)yZSqVTtlugsflNfG;AOV zxcPEi${-QhRcS$zD{U9lqO6M9eU|Ikb`W63g|jGT_;ox6DW)pkDBD<{tgC*`{btZ{ z9Xu67+Mg)zNTI>0^}AGxS0N(Xg@JA#e0hZdwb#-qdo8kORr(g{J^YqYFG)&;wCv^6 zQPO_853_*icUnrX3SK!URljMv86p8tYAAFP*%1w{u;~7s-AFx!;P%%CLso%rFq}!a z!a;{Ck#PiJ&EwYzIzF3Yb?TFPmwvV0{fSQ$zf*ju_>bH4b^6!zb;ZvWM;6^Td0QwR z58XCCF)^;TChyb#qT=fBeBu+1M~frH&&ij@&kX37P2Lwv#U{p!pB|sU#(mUV=vz`X zh}3(BnAL4`OGE;R-6-YJjXo((XouR;k4Zw-OgQguM4|cYRct^OPC;bH|SZV(UKHz5@tf0TIH#kitG4$k9L1Yxirh~H&0A8%U zQth8ceaQ}Dm9y{4#eKLQWf~RqF$jwM#@Q)k!I03z0!2I6!|GcwfO+rA7FtHC=mm>d zKQ)V9`V{pHWsN>5)GxHD1F0-sGVl%BRKp7CXg#PVzygiF5WGhC%!N2c1=xi~v* z#X`?a-goU~rY9C^@qgugAeF5jBbj~dT=aE%hvVf??7qn>-_>0F7hioS7SUG~{~;8E zsGWGv1m!*mNw_c=!ZHfh`W zgz(NNW4lcHFZcyV;^0$ODC^46Ttsp-OgCd$rFu)kDs#>7Af)6}WD4=Y!;B9`Hg9I_ zrAuqUKK{2rNxb;taGLAi>S02DysGW;@PL+mJK$H1 zqqCJt(?tQSs{PU$nJwHHG{TYy4t20bbdwr!*R;yS76K}QiqIgK6xt|Y%HVggYu2b7 zif-6F)wW{wy5%inEnqn5_|l`+X2!K68Sd>1>k;s(R1jNXKM0Gw5-|bP_qHQ1?21>* zbVhZj<@KCD)0xg$`1}gpDr$On%GM$(=azEW&YF^XG+6_s;2+W*s17h?$|}Py z#MA^-k_Al@K(<7wvE)9foJBr=b^p()8| zr4&Y?@ertwF>+{K%>r|C2ViENeKQk{RJ_l2H;bl>>K{v-Rs}2fKl^}9T@%ObExVqj zSe+v-5=~g3 zh}G3f_RqJg6>q!A5V5Ike(5~U(w+&IGTJQ>4 zMOVsSw<@6f#ZO~Wgdyqq)-m$+|Gr#$2Ysus3r-3zyHjQEBVs5aXG!#FW_oc~nB~v1 z!cn{pZ!21)w4iGVDxjHO%p7yrt*9wugr8~V;9m5-uKd_f{z3U(RSPed+2Z`U+h~5= z$y)Umrr*IKDdokQ*@dh-Gl0YZm4k)+Laeez+N(jS!a(Rv6&-h3iOL(C`T#1{xzwhu z5}foC#qW7Kp%y!y!SX_d(wN8R8bjqVyiLr5WbWlFXp$jCN|p|!p~mhcxLL2Z%c=$I z0K107lx%cXX|yuC0lJY`XS7Wh2-jc`5dm!#M`W!=QrL)*3`*4%LLnyNAjtG(YCVgL z%K=uqhNEI|iVfOhBZH8Fj%lWZ(}I+;j?%Cc-Pq+F_Ta1nk1Lp-t>m!u*+`=E3!)e; z^wU&UN@Qgis#3yem)R@yDK3o;FlHZp+^z65{E`(Eb67dYa+ZpUc^G^AoaGgB`Mu~H zGR_!mvn#F0DlRQL(uRp4{oVDn|VDUpV)}i(vKj*n0ZC$@DBuL-K%} z=YeOXVR0hAULrm0OCW?9$Q6=4NxNZI$l#EwkymatEB1pLF*tb{{>gWW_ScDq0Ah@H zQv1yG3F|6n5Zm4&3~yGV2-sW6`eqOwD+{BOz6!_|*|-l>3O!2sMPksDt)6ca#}G!s zC{Lpa1CsmpZ9Ms`;{&2nC_R1#`H8}NK%K0IGs0M77+|ZHHYKxf>_uo-#91S={bNv+ zYAlvhE{Nki*$a##Df~QBBAQ0Ca5W0->=B1ZxzSo`sr6l?u|%@`MJ&FchaMY1kz; zW!HsPXlFL-wQE9c?W}lQ7_Q<)|L@hcij4#OOO02#8b@TLs_~M-fsz(nQR7uYE4{K6 zn8doWkteFH$fp+cL!7{KI#7QCFRE0~B6--X??gjGcd*c|EMNHDCASSFDR$)-d;i3P zW&#t;iePx_nxVWf7HlQYpZ9^EspcQe)iYzr(@elc5Y_hJMF#{fR&XE!B!E^pB9I6a=z@1!dT_}_qDEPn(4@F@Bp=a+D73@6qup%qul`k+2C7KF?4 z?R`AfoktW~HQMN1&De131tFU1s_>?$>~=ng4XD)NDTT*~gv>bOm;qG^ z`kK_9N{wJ1(97Du*$3fP-UUT}SpS0S-_@F4=Ag7oLSY(0A!P`Kl_3;ThLAFUEFLR?I~YE6RKng_80;6% zLN@(Z#qatDT2r)dMsl_uN#kZ9BkP&?WNmPQwZY7VEY+Q}zE=5ZtSm^oHkig+8%bhL zZEz>`;B(dn_nf^lxa-_?!Ei>G3xie6kUHV-R=qsyE`FElfy;Pmgl(Yck-4Pg(Lr)! zDJ`;d1MS?_a&Dj!;EK4E;R!v2RZWy675xL0dE(N_`iQ+we|PGTe^+{ph~MV7T2ET` zds;b*(#3ABwP?4EIj5Oec6`#FQf$ocMwTub zU5YmfZJjhT!IY*Da!ie6=!70p~A>$?Bpr#%yRtK2};hGAgM{JPZP8m1a2?Q1*LBVtSd?1%1;BT~$u6 z4f8zHEGb5WU9~AXefX^K&zf@wbGM!UhH+TF5ve$#Z-hxUW)!}Wn)U|vv6n`YRC@9K7ISEBmA@-9S3u*!?Q2;8#6L=D;sW>SqPoZoEYt)8d%l@nqvy`JE(} zSL(ne7RcOj=`$R&DIrjsiUF(A*%h%sRB0jLig-re+d)cTry@j!(544@XI3nb33f=G zTd7-B;;2I)Xe!Bu;t_l3Tfwp%wo2m`nvr3PJ=E+t1-lxtIt56^U)3y3;ShQz-z(4x zDS+;8>=>mQ|8-i9-@Ko&cY%t%O<})H5t0NiaZFWW2c4b~2}{H0ix?P|K}x)tM9b3? zNQkI|{Hs`zIh6`%dA3y&jMb=5bps`^s=`OiJ@&@N{}NgJ1Cs$&lWhGmsm=Qrmit)E zvK`t^tV!16vyaLiD;5E3T6`ynjTag_T9~tJ_fbKnB(lIQ@L{vEx{>xZo2axg53*&H zW~&oMiDovUzY}Ws*|g9J@ve#v;Ae?Q`_@WbR~b@atL$;7@ASd@tf*}^{f**3!>^LT z3lOHKC&q$7{l4UvZbdIS%SW$2TwKwfcK+d)@77-ct^dDPhb?tKm>+T=_><{NU@4ZG zATcR~=`iV?#e-p(UN!Dv@^}bOb_BzA37z6PH6F-1u{tVT3Xu0 zx7NVz#wPLLdREd9{J&l|OSPJjTE3LI<_xoTwTj`&m2M8|%8 zQw{0}B121Vp`0nxYFfLjf>x#0*9RA+6z(Nhs-f~b$`s2=2xy!64#`&SV6iDXWRiHz zCYHvinPhP{#EexeT}`P{E)DLzepp3{CXQLtS?YCg*iM(etW^70>OBg5RO;*a#@GLw zYU#Ive}4!yF|&Q&B)(t9_l;U3Nf>Olm1_HqD$Yn#Gx&n-M_LkMo1N~hfnu?qiG!gc zRKa2h;Y2xtasP4+>qfr z1^vKWh}G4b&HJRl!H15+=3-FQLZ2)l6fYs%YAmG0;);rejb7#OE;qy~(Hd093U4=E z;&66bxv6Llk_%_fAG>ht#mg3PD2tYEzIfTda6HnE&N!FeIeFhzSAF>A`zFFj;}3Ur zY+SzdVo2?aZ@L&k8K5G#|GvpXn=U?ttX0-=STPsOsnjF?x7HDgt|)w(@&>)lOHXg3 zc7rars&<6sj7r(HtRcIckrIb~b~8qc9`8#+zHc~eBq~*!DxU>awAnuEap@@lT46g0 zYVAPjbZq|8N9W&H#I3Q0S-;%QE(78VW{o{)#b6oa+zNZwuUTQQIu8_$`77*IzR+>N z(`45Ri*K5=3+-Ds;G1qZMQ?Pz!3Q#4-M}VHaG2ml82}85lX#pX65&^}3zn^{zA@KJ zfqq8ybLl_$LH)wk3Zb87mQ-(BIrC85mYX z(hfmT?6M}2{${KU^rEx^5UzGiY*kN3t9I1VPNjfUwo$aw+4QrYA<2TC%P)k+Ltg-_ zQrO&4{HT6SM+wyC;>+#rdhMAPab+d#SNoYchsgM8@=9OUCVEnpYk(PoRhsoL(U+Ak z3c-JAv}<*dkk{dX+N7I={T4jn(UNW8Nx%I%{aO4$qD%jM{R)1!dITsR^KZ8=kn;Ke zPWQL4`Z}c9p;Yp2E9%nuE&?Pk*(%v<@I9A0vNWANF^RUQV&heCiq-zXzHhs@;P?;6XKZ2c&_XH@`g+hO5kw!muSqHk>B}p@A27%WJAfwDO zPsR6)bc`zBGYtsx2>PC(Q?eeyaxW{7rn0b?gj6Hb5XwT)|AlXbN$-620q`<E)TOD!cgONp3El?rMYPEoo*ETpD=_D=ZnbYA|p$p9QH7Wv9 z=_6YpR%Q!NSe4~ zhnjTsQe*d_lGM1{lDj3IP>D0KfdZ11ayC>^5VK3i*-@p8T8LVzPin2PR+gTtbo>k& z+m{wvsZYdYb-xJAsf+J{?4?f`??IF~HN$cEl)GhCyOBsDvuY|}Rc`Ivd9{FLN>c_? zjH*z{t}S~uD=?X};GS=)ZTPM1q=(KmhRSJ&Y=)}ico}1v<5#At1s4NeU@U%RDJuUp z{mKgE3^Ca4f8kd~v9jICF0nH9b+qYPmz!ogG3c<*-1WD2rQ%S@9vZ)Po#Js4s|CFC z`;|$u@GG}?#jlJu(zdES$1lqlW4;EzvI-2^DS~tS%52C}KnK35+&G$u+1=_(3K7A- z5}+6HrpFSIa~zhfV2uNkrR-P65USw+75vHy&oo zIloUCAm{yry9*TD_CA9UtsNO$ETNX`9Zf2_P$-nfePO|M+c(y>5!9LoOAMcQiZk19OBBczUb-M{CHe#&|jxPQ?-qcEySWAtp!;59&w?F=3c z@g+~AVZ4KyD1dbidO4d@*c@Re=atHz^~*VjXV;0mc4u)_)yQl096LW;T`5@B<7U+f zl6~;4k4+6yCn&t|HP#7o0WsbrQU!H_P(V}#LR0Bzw{(M}geyLsTc;Ge@vPm~w6Y_t z#mP}5co*ehrT_nTy*FErYVrS?db6F>Ut4pw8#+{THqi(EoBMoP^@E5jsrtdoRi&J2 z+tH*7!}vm1kdAnaYUGtxC)^D+)fI%ucd4u(Y+wap9bbD&>mh^Y7FR9ehxKKkc_VzW_do*G>2{B4XLF8u?(!LPiy$0{EC{0miVb|gX zSkkmQ3cn?*?dUgTESMQ;W*dTZjQyrVW<8pVC}C~6GG+DAaNCX**dH;AgzJv1EN*Q$Vz%PXq zR^1v^lBH)iaC@W3snXv%$`D0$xcX8JNh7Hoo&>bG8MzBFhJEL z&DNGUBFnCqCW}?A2j*JR?6~OsVU>o2G0?|`Ibuy9@7pviNDS5Cua1#4w}cIsFu z$RfTVE5>q;+Ca77?2wD)Gx&9C1I1M@%~4@uS=4o=!lR-3V@aPnESP8Teu9b~t(*a5 zO5|O9)rF?ooK@vvyTQ1aTu_;ZZM%WsVX-3``a|UKX!nK>$*+-;7HA483tRc+kE3j= z;@Q+$?z060@p7z!nU?fBlzJHdQhkL0>;L)dk#hNh#7pG84KBR5fda%oWWBu( z)LBx#>@0V_v;)oU7?zG^6m%pq(KK7yTdi| zOHMR+XpYo+UX(W!HmKYS?1PW^CG!A~W}EExG~McL5Ye=I3~%X(rd=y_z7L``GVQKa zAJhrU&qakWEA|TwrRR!|*O6r}oMyDCLMbpasZf`{s_vytmE|Z%ANjcpFaCC%z#HWK zEcioRK0fW&exs$2^}3%1Rf0e3eaOx`eXi*Uip2jNk8SKxSn&MDp=y3L zs0!6UK?fnF$Q((8LVB(>=GZ(46D1vwl$u{PSIi2+`}xckOklDlj0tST1XA~4&z#v4 zCT}A<*A$`_{2ViCO>Aj?t6}~FHN$vIk~PWbxGb6y`a-qWX!YoK1h~#N!IXbQZ})Q}ik`Qe_h@5#2j`yu^pkSH+9w^D?G8xxFy5jl1D{P1OJ8j^ruCKRbsJ0T zWA0QVUJzeRG8X071cY(VG+;%Ne$v{zNkK+3XAu!P=>K*`J(uEs*-=-MnY z8&9IQrx(4g(3u4JXMBT<^`RRz(ooGUuM8@v5A>HJE!wui6!g^fyY)ljN~7Iq^(#V! zEqhlr^Q{tIY7KO^Ga1(Oh2e~sL-Mi$^nuq;&FVPF>S4CB!W$XoePHD`wcE`H?N8FgMXSLEPTKlvJ+QMVettfus~bT{d5 z-i~^6o9E5xl}CJ3J{#{An(v+Eg@8O?9$NX@@_E{w&FyS9w~ra0nVEUc^_R%&y+C`H zmS08u=iuMVt)i-sTZ#}!i0Xqh5#`I~v^MnbDy(s?3ZV*SLC)m6y@#@e`WiXVl{4#c zpcCt0EuETXFOoZYrJrao8u6W2-78&1dx<@(tEjmS)7J}8V+PK*?adWB^7kxn^N7Z- z>ME#*3?vu2gNhf!6K%G(nq2I<3;~6NB&23(J!!t;8ve-#a9FONe1`>L+L zC(;&6*T3npy~RSW)3vX0?vO|9xYo55JUoJ|Enreo`dd13xk6al z5gM=-!%mJnJPfL-M;ucb}Ckb7H%$GstaZd;@0XI^78M<0|O2Mdj`3s{TY=EZ_CYs%n5E3SbblKh+ z59ybo>tE>YXd8H2NPj*aYN|6$e-n@cW(!OG8^vM$7ok}A z<(I?pV9_JTZuxvT{Q2ThY?H?DPvWOepDou;8rGYRF0C!-Osh(1%fI z!>^n^X?=gwlaJSrFL*=4*#FWxYj{KL>!;gaXMgf-C!XWz?51fom<#m}&-EO~TTpOl z=FXWJ&v6Bbb(SALcKk?N%ey%~hTo_0s7Z9w?BF}T&{yxTwJC1{`=Np(3}|Ee_wk8e z#}3hLpqrIGvwk1JKHw4f zj#}5iKX1c{@9dZF@j8D0UTr7tJ;v|wo~{D6|54i@_s2PoL+%Lu z#Gj1uUvZrK1>Eb~_}!po`E=lwM*6$)>sG(oU*mHW3u~L2*U~*O4&p}E6W0`e zx!&wwp-Vi6-^DSmrzzgo-3UBBDKyP>yU_Z%Ui*Q5n`6ZBv~!QsaQ?{E>$=nR9e2ik zk^6xAnEP2z*mKbHymyE9(VB40p;}k%&f5EGpZCRmSNiU$bJZDjMgO(_kNbaAzpDQC z>i;E>4eSWq6L`KM+HkPpuY$hd*5Fq{eW60=zrxGHhr+*zTpsywuyu3moo(T^ z8`~al547Lb{-KUw$EEoBO6Q)=|C#7Zd@Y$uE>9Lyi&OWczLt)rcc#CY*_`=M=4V}Z zbbY*A>mKR;Oi!lg{k^W|fsh#KP#pw=VqJKx*K&fv*jQ z2R9GCfAG1XwxL5qrx$Hq^zfpe4378yrEz5Q+%P%XAt{uH&^lQug%dc6UUy)kzwiVwTYZ|+D?8%jxm3OXudR6bL z`&RwzyxUgStS+4IKmVTdzqTf|X5X5xUodvTC)Wnn-m&)Sb-{I;&+>Eay4%)0uVFaU%;^&$J93T80@KShZfM^WoiUqi{Z(yI*Jq$F-GmOChqZ&K<+x6}9&bIM=XC;|z7o&? z79k&f7~V>?l?A;fkWDYD7 zA?;dR!)y7;d-EwbV{Z^g_u}{hyc_QTwr&J9+=Mg4?^fWO#}e8a+1sjJj=k&fMxgzG z=b$|IY|megZ@iW}CT87}-9$Nx0r*eK^ZBdX=}N$Q5F?qCku#z`2peNARQ4#>V7y!L z%<3`zpP{?nUzze2fVO=VG(c!?mXY3qzoZXR180RRV3*L-+%Z?r?I7;>o1$or?A$cH z0Q11-Z3Tr+0`^LXw*dBQ0sC8ozDRlMiv9SU!1!*Iv2v7e#`Yc=cLLXQRkM!fLS&tn zM_YO4O;vXwf0#`l!+?vwm5^0G*M^2%-~jHY@Vy(K`*Gwg!gY2DT=tb*`#0lU0^_*_ zzvLpju-eHHDpxW&)VOv&s+f4?A*=!4to3^{#!udN0B3Iol%#8NB(<7{u-3*gcH-3s z8vbqk_$u&!DZC4tWlWdgb1SwsVQwyvqg(LzY}ii#a<2Xn`R-m|>L6yCyymbRUxZb> z^tU)dA3DZf4*1X4E(TBBge^raoXzVn7izu}*t!-+Y`V0$*V*Zj{94T* z_#UOvJ{+CE`J08JZ7AN1vy@v0ai%=B@^?v}N=_+`>%-o)a&LZv>s&#y3-{h7(B1$D zCUD$dGhA&qihSX!Cwx4sWG=@~SZ^+DH{@XM&0v(Tzd%jS5k>j zH~@Ic()=cjjeLwUtIQ$!Bt;o~24|3*hS1p5Rn4Oai#;dmDsmqM@tg5I!bIE=zi-C2 z;$l2<1MbZIYprAUn0(e4)trzA?Z!84ZN$d#e!_x;@j1en^L$Z-pI> ziZnvrtZ=j!IN`ZH__2?j8ykuWhA^swxNmuM#0H^PGr@0> z+A5{J4|h{EOgzuVu07v2c3%xAWlUGokWJh3eV>@5tRhwJl^HuI^rdiX&$GfXp(l1p z6~t$?6t^)`UI)a0t$`}uQBCV*c-5@D2{Sk;IHDGT z5`g(8e2ciYN45*A_y9(A7+6qz$Q}o;oxpv|u#`EZJ$g!UMYr~9u7p!TuFh~=d_MU@ zHC5Z(VlAZ6IHc@m{BFfBCGQqMm8#GPw*aO}s!QRX#KX06-!i|jq2WA{{uK7f890Bu zZth%GuHeKx_K^?O9BQ?5486DuW!-DTyG?;y?W7;dKCTDO-$B?`3ZIJG+>CpYciYsV zW>WEPpWxf(8H$VFgzFFD8{8|8ko<)lfg>iRR_kACMe_LUSytSJ{7>=ll-LuMYqnAg zur>6v&4W!#m8<+_&>Q7*HK*pB*dr%&oMqzK=BYk>gR-yMf~FK8#9Rq##i)6)VZQ`- zpuJ5hrSzGtx19}cn|^GqL+KN?C8nrp9Pp?$I-4qOnNMwl@{(6^e4JnEIrB@RSED~x z6V0YSdz=^JOttK*whqoVPJ4dlTbGJDdB*0y)Oz?7d&S=*oRU|Ns;SxV4Ed=oKi&)) zRGJW_wS5J(Wa`Pho;n-XfLf)TZ*`P93`fhStE+8T74|Dq@3e;NR zdgQv}a}>o;15o^ztIyT}38R`TTbnFnMA>oYq70kIQu6JE%t_$yjgUL!j~s(d$M(#g zFL)y^4uTWT&+Tl?a3;u+>51Xm;kbBrH5%%X>X?$$*I|#cmrqp3xsHed>Zz1}`!SPm z!8vNJYAvdHt(0(F%hdP?yV5+VuW{Xw>iOMDZA*>bp1ZT-NsXRX*yXTPE`%JQZA^)f z(7N$^fo!jxB`GcySg4iXEO<~bDgLQ6Q(9!4XEk<0XzN9`9%#!7MG4B&L_FH_rnH~x zQPclLK14cDwBW;@!U8##ea}}Pclk+5_u;;+=^nQ962%31M$H_3VcaWgd+MCc5%|5c zYkjfvUh~fCePnpve;}q+nD0& zvuy@@l_}aHA0j{D9N#Sd1|Pg1l*pTb37%6kZp)8KsWlr8r44ai+bc=&58j1*n@{HR zlx;?Po;V^LvpEkj&8uni%;q_2?YtVNR+_z%_T)3RjIXpZ6kMDu`akJ0$;!xo^=F=K z&ghe>o--vCNYnFM9cQOBQkbHmU&X#4t(?okpjO2-TV8caW8fNBE0Z&6)0OffDDQ!y z-DPIb+vA#ci-njW zCD2wQU6Kb--YV%#9FyXdT$*13R?9qFhq0-FtKcAh2%FNTY)x-|&w8aUI*2E4Ev*f8 z4<-BQg)3{#H(GOJ+nlz%sMZP;HIlY%3Q@WQxwOKLq7bUNej!7OzZp8@7{)$;*yr14y z(h%b{Wz1JbZ)WQ{N|&|yGVe@IOYgKj*Gj%CxM^c;fxWc}P+tg+L5qw~Z@?CHYCAr* z1zY1dz75wg!jzEjB_!T-31XEOqLV4vITacqtC zyv_I)pUW5@txe7qA>E4O<)>Cdbs?@%&l?963NII63<~D+ac{5>uKYfqx>1fQ$cPipGGQs-g|eQ{R&XS6{z~h9 zw6iudB|5FeWa3tND{b%39DQb#y$QV;3-0tIeo}r*g0D47*YFzwYHGb{YVqa%}?_3;0-OGM9DYra!;*+>k z5OS6kHeUU{gOCD;@MC8VReQeAmU*xZ9B?|O9EJA#L zIkwqDRK@yL-qvC}mw4t*XzKI*`!TZ69J&*kVJ_sXc~Hqvqtyccb(&wR*8-?(2%=IX zjI8h|s^XeZ<U++^)k4Z2fgT5u=Jo`1z(bxe@^f9GXLM3?)0Q8={LPmvspJu zyV5)L3A$O|;j>kL3EQs!L+q4YlGB;nqY>}Z*sR9nil>qKy4N7oeMnuhUw5?}(EV5k zb)Qyc-g>H^*JAa_a7=SZ`*fuHbxtd5^^ATN&gx8@)0KTepROgjC_^$VBXUVD>-(=q z(I`)3PF~4Nc_y!Q59d>PA#dcj{FOh*Ad4m}K{J+O8J26B)e5v=CG>P{v|<%jV-40~ z9oAz5Hlhui(2fptqH=uB7Hq{fY{w4lgr=rqx8{)S#XcBVIB?-14<7+SMCihPX!e%o za~;GXbmK63^xdfi6mbMcaSX@NhZE?>Nu0uIoWTIjLJzgTd0fCCO1Ow23}XbBa2Z!H zimSMWF^ppZlbAvo*Kq^WxQSc1jXSuj`_SLZC;2QtN$+gp|V3|hsrLMT`Id&b~yqr87>(v8JcO5 zjH642ONK{=M}|j+M}|j6eOx>;^nAO7;gR8y;WH|qSNOcb=M_G$2pCnsSOUfpFqVMI z0hI$P2UHHI98x*t{f1mb+{1Hqo`Vd7?ZyJ2O5udT*-M

W*Uu-PQ&fKmR^2Hwc zf`z#lFQhMSIz2cKye!QZGr7UexTVw=w+^WDxYQPBa>IiXH*^%@hFovl*irZ@4UHqR zNDmFp^&(!JG-N6bi!r1P^9{uZ+BI9Pd9+ZkY3eAv%VyIKrMNYxUswabrvHij2OfTR AZvX%Q diff --git a/src/ifcblenderexport/blenderbim/bim/data/mpass/Material.mpass b/src/ifcblenderexport/blenderbim/bim/data/mpass/Material.mpass deleted file mode 100644 index dce28bad6b..0000000000 --- a/src/ifcblenderexport/blenderbim/bim/data/mpass/Material.mpass +++ /dev/null @@ -1,8 +0,0 @@ -{ - "eevee": { - "uri": "mpass/shader.blend" - }, - "cycles": { - "uri": "mpass/shader.blend" - } -} diff --git a/src/ifcblenderexport/blenderbim/bim/data/mpass/shader.blend b/src/ifcblenderexport/blenderbim/bim/data/mpass/shader.blend deleted file mode 100644 index 35ebd98cf2c6d850e97eee183aa8342c54f31ed7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 563560 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�ogbav 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

t1W@ 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�J(%b zf);%Q7`*kZZ_QqP_0_5`^z`&(FTM2AY*SNHwymvA$pOljF)ES=z#2Gy?Q37lf)5y5 zz)y^Kz#Z=P?b~y*01UqW{qHLt{L8=mi|Pv)Bf*2dzP{|MUiGT%s#UA97hKShJ?^;U zg#V{zPd)Y2$nqgyY%lOc*;7+fYP_47nNfU!3%LXakOPbj}6?CNmpMVnK~(w3hvlQ4;D@(-@cfs*{H5Xn z;%~qG_FO;QvSo|vH^2`vxPJY5H7{apfc&BTC|~+wB>o@y$VaAGKJfq5uYRR4248;j zo8M%A{p(*V-a{_Y$5H-mx80T-i;xC$6J%xc=FMtcf=qhbFaF5#WegvO?6D5u!F~7L zr{s=2KwZ!mF&1F%ML8G?F$bf3$cq>Mb?eq;WlYWSU&eyS{wIB<1!FGC2hMO=7sv## z#n^;?2f2sbf$!iI`Hyjj^4HnfnQd-vR%0OKA9Fzz?->saP&R%j4_HGkF&3fS=>MoA zaA5zV{9`Wi_CK^8I>E}7E3-?NE-l#iSUxbon1c2N%f|SJxgj|Ia0~{oG5=#O?(Xi+ zUUbn#YWxHK((jA5opreEvdhMSH|l_~7~?O>hRkvNW#4Dt1MfNhLiW-3+S}XJ5B>hY z0}pIr{>9wJ#>N(zJI8@9#$n()Jw2`FIq4(0vDZ8HL2fYzW6p`kGgWOX_G5>=P824q~iR^E|GQ+|$hmW)G zW8B3Ug#4j{K<9)G1inM>!gvjQFb=L+vj$`Scvzn0#>pJoBDjtN1IRw~jazTMHG9Ji zH>k3JJNiF#gm=ID-RNgkwK=MO;7KeN8<%-zTFRS7|3H~i{xp8`vG$0ni;bTf1TMJ9 zaqiep&M*9^wj-P(*}^U`HdWZJaKS}u;=?$%8iR#FFNlL+56czEH9TjjU%b} z2B)z%mWeryeTh_Bq6TB~cg)%3TRe zIe*v2xcYp2<497@rIlA-`%}r$5od!O#UQ^koy?|@xRW03R&L*5tlt@q4aF~iG4hIS zkk3x2>I}-!f*CpVaS$GSxJw`Z*fkRCU5cU_C5J>NKGcz^b5-JN#s^c0{!!ao&GvF4Qb{cbqI3w;?#88*ZUyQ2AIry=DDSJ4+G0`g! zCb~_VO7PG@4$P6y$>gnXa_Y*W}RTY9GCg*epwavf|Oi3u)Xa!lSp?!{e402`5v(0C~e z2Q#T?0m2*Hc=?&Ha|ZAS?19@efOr3UyE2KPxYS~31d)PDPeytAlLSCy>ixFZ`@S)%qF?tJtDvO)fq^YZqz954*T*+GLsCy4 zQ}IC&t_^}tG7}$+4>_ZP@CGHdS}IXeDp!&mDl+CY#(D)=5ewvsMCnZG^5v45@+Yp2 z>y|r>D6O$Cl^jCuAO<>TIz2!V1<8pD5SU?+o<5vcA`OJZH)>(-Ne+#G(~1#kXBdQO zNB?bw)bX>`u8hV_V zI)*2m6bKZEXm7InDv?bmh7bP9EA(Bu*|}h@t!@m47nk0&yf?M6t0$QnmaZa#fPjXbwCg(Nhcl9Rwzy|3E$v(ltk^YG| z2fuC^P=;i*N;7?5BBQ(P*)jmjcpXnVsnKC2Mvdv7xJYJSN=DYluhUh{Iqj z!l>fYq9CS?zY76LoX*IIk3?>Ssvg>?CKJ`azzal}in}AAWRE#dS0tSgf$CLlI12;0 z2(ZA4znj!wH3}i9GKNPnTHWix_j522#nK~V__N7TQE4eF-X#K>NeuU=wQzPR@mIs* z3K<~;8dMgLv9Y0 z3FRu0F8RAj{kc&0Em*nD=VO-r5uc8D+uXHZB()lvN7?q(RL)So9kDu`M$cN@seS2kUM8x{U@Oru? zN|d1f0mRApZ}RR>#Wu*8ipar4pUM;9BP`RAs#0GfKB!ug*(e{I${H#!3|;3m6eghYlWETt;FFYSz^H|alJs&{v3nE*XHy9r`~kB@Z;#;HWNOwLMS zQ?ssCA7!MK@1YvMR(O($w4}xaH>|w6PilW+xNmS2(~!B>9ZM%T(@O`}L<+@`xTrIF zWX-kH6Q@TJC}=&&ZYakF7-$$Kb5#YIUAjjHrE4jbSEf7>AQ^bmF}a~NRwX+9iZ}Qp z`j&{3N;}lw)#1n=`BvWOa4dz{RYJ+0jA+3!aEezCwBqZJiJpTYy(>19l)>2+ zRzy9b0IP)oJZfE_W1xPi81V>8bvvC{AGD>hRD2{Zs?8?jiZ&-=Dq5vF8%Ir5!!en2 z)ey5xsrSP&yeQtw5H0g3^bk=c&A0@|olQkE(-C8E6u(qA(1M9L9TfQS!73e4ZBfHs zdZ2eBG{oMG{pxSG`YXNEk-0C`ze(XPqm0Z&N~;o&%EA$$U4}oR%_ZZ~X@vX2dhHh# z&G{FKJco0v`?2JqXq)9wn-bAQ8h*smQ3QRu&DU4 zE*TPprP_-s=6su6@71!}8TJh1%Ym}+Nib1E%0O%|DKpTB%o$x0tqvYSCwMXFdSW7J z(6(b^N|bUDQsv|@78#`I6S7>OM~Nyrg_L3vnt*CG@1$i)7LXXs$h5Iu4LBIuyU=R{ zWu3lJ&vaNxijuCBQCUQ!p(%<6o?IXAO7(ZgP-hXq!CYV{F_!b2wV$RInU-adqSand z8bOiaxi=w=GpOZ)W*C&Emh|M|u6|jvDW2sBRJT+r2y;-X8Db2yCQF8L2^it(xVae7 zD=mmV5q9}2!Y+TiF-^)UDwUF+fe5ExzC8Aj*j+qJz4ZSGKk2c zZ4_%SX}3Vuw?YlE$OkzJ*Q8xtqS}uPXVRnU?*^$elFKUw3?isI$Th zEXcG^#-QY|o^BhtZe9v4U1>sEnzc7QluTkBD~Ej!_QXcgW?F|SM6@AC@>VSp)O&?Y z@?C~MXPS0mIbqtWydrGFqmKMlwg;GG`UaC5rElPiwphlh9)(pGdZZu?xmQzIdO*(e zcl7wZQDD;w&*&hG4Wokt+A20COR!DyLn>V%S+>iifo?aRM#VpjNxRMLS#eU-68%&CA zBX>_s3Y$b{NRCLurGIvBU|(uX4+sS7H;O??S3;H~vOpJoFgYwq5~5m(I+qxRC20su zktwoqNM+YJq{`6FsB{4pMrUsv5)=iEAt>n>R!mUUS8zZ@8+%PiB@iUUydwY^Jd}5X zLPeYQ`jme}{T)<)1rL>xxGH;bP5s2DDk!e1A%;vvqB{phQy`NY9}UXJk)dCIb5srP zO5iYXrQ{RN!oLm4vG}0YxP39PURj&Ua$iP!6R-M*;vzQwiKsut@nb`Sv*pM+`YDWD%Z*^$XcZ&xOQ7#+Ec9kbdEk7dnkHl*%g2 zLA7P&Dds?=msLQI=%KPCz}gHxa6=rhRrFKjVjP(ip{7e`li@|w_4vlY4TI9I{y1Fe zU~u&44r2>h8^vBM^R_k<3-}3HE{a)Bne%DG zVYINqsC6<^jnG0ixQ4P*w<RYOY88Ht?#iSqS?g@KFHYp*{ z$`VSH&zwuH%7OxgRMytg&)_p0983%uA9)Hb!oy-n5%e`Zn~D8GxR)4~RfotN{IbLo zzu0m_L6v?0$W3uZWfn;LQzI_-#NaoCrDCI+vmmIVhG3MI!Bd7Ye277$S&O@#p6~zy zcBG`3IF~Jzo+Nf(HwuO=xv30X;>x54XvNeBN9;>+vAK$Pqq1T#k@ku$F}-O>6tvW) zE(N7V$JA5Wixrq^w#Ht(0-9PJ8iN)xl-v~8r64eWlVc`NStX~`Tntfxtwpj@1`E|l zFi{y&bc@xXt_D11mehv7cA1MsmL=DIu_5D`lYUB)7*->cgi*d4y;K*ISy%=M-P>f6 zz{oCYYi8h;-P-sjD-Rj(QcwT^HvP&3VpO-0j8fr*Vjz}Csm=+HS~uYN1q$;-#MCO* zjS!LYQ}l?zUn!4`qNd5nBU7<@?W$46gE1Ls_}K^eESdedh#1x%GW#Q`&mf<((|{7Zjlv{RTSXs+rleLW@(i_WqgeT*U0Bt^D;l#| zsOz9RV5_@oz!ig8a)hGLmy8X`q$Gk41*md{lhOxQ0pC^EepvN>Fl73RJaw zHWsDNgftTLCUUUMri%SjsbZ(LF1^_QDlOXSrG$o8hne%Gojp; zfF7tGYVvksz4ACYH_M9x=?UQhue41)@W#_&2?b|56)7W1mr|YN@$|50aH81=sYlPz zA@$57DeFt#&Mj(k5mb9};CRaGim8dh8`I4gPwTp3f#!B~%Vayoxm^r1(v3v!$It-` z+HO$eh1uBL7e&Z)JsGmJ@hfM3ljmi_8^ns(sGi}->?lvCVLO*GTs962i`76YWmuki zreje~V2u>3u(F>F_sf<9<3|}7GZRp2r2}>M#*EX|tt zBL8B<(T`#EXelhjG8h9UhFB9+)l_+z2@-ljmn^yAY*6!WJf$=(VVR6kU1@o?-K|VT zsUE%hH8*-?%uzSQqi(1fONsG_h`L5z1`c_e)T_siQRzPD+kNu1Rr`di7+F*z^|%l- zopdAPho0l8rK^h2UZr2?NUhKSa(M*eQ^f=$838m*YJs30=jkV%UGiu|>`ok{%u)s; zkHHUGfUvU^4G^P4kR(a-{~0?EI6bQ}?VovPVuB!|B4RcG zC7D!7NX&!~M17r}A=8+WOk%^fVqGk|qHDq3RnfJuYgzl+Mc0CB!;Zc8#`f=jUH3W9 z^SqOR-$%ITJ?%OD+~;oR95Ck`0@oSIl7csv2+TQUEeRp)!m^LP37kC1}VcHapjXILI%X9EiPehffb4 z(6F)&m|@mbdl-dd!aD`oTA?1*=`7VL2v9ZHlQu{QMdX2zoEw3x$P3RoG<{-}9H7M6 znJ2Q6XbS}_p(gkE#}%7=YaIFR0tk4C=0dF>=wUk-9%s2MlLKheL}>WN8eDI7x`` z2rEjaW7%UvkzQ7u*ceoT^bdwsb|l&}oCXdtF(x(1LY9PKg7%PE$)EdTidyDoP#C8aTF*q*!pIF`MxrQs|f$ctA9L465 zlgsm;V%=ebh(*GFfv5@NAvTy2hD{aIl~Oc?JY{Nc5b;)ckI<=FxLTt8XoRd#b0ai9 zv*Wpm){HsWE~H0l+j{LT_0*7E6-wJ#3~FI-Ltuxu3(R43!i`9Q+f^zf046PqD*l{A>5GrbLl2~_k1 z;RuM9jz=>tNXll2+pl(?dkK=SiRs|~sY~Vw2??pNL`qs-CQL^y_cYIIBLpo0q(36L zJd!eTu$@EfqemfF)2M_QA=ep23?=@YX#&SighV`}?V0Jr>pkL&J^tz;n)&w)R;|o(nnf}4LL`GF6^26nwE)>ajvP-aK$#RjU zXhK64S2epR?ZYK&WdPbF2Z9+XJ4=VpqS{FqguHcWQ-&Okj>jDgxr~h?0S!bvCfXMZ zQw8&z119G%x4HcBo|&Pd8&%A<+yU*@rYMd`$tmD2i|b&7I{qYFom93*(!DG~1~iAM^%Z zZ-#)3kxa2S?z0HE@;Z6t+gvOqG^qsC|{E@v7YcfqK{@rEAbos>fTPbS>RHiQkSglv@t=p$Y zRh4S5#lOLpu%iRBTV(a-Sd+Q5OTv?JSks}IxxI)bqnolvJ%#g8*+Lm|T^0l0x%$g? z)C}AcW^7Coi)1V z8#fS@=f&ae62lh1;737KX>CVeg5;v~_r7T8x0ENsj6C!A&;e zbhH534VE9yBxWC26$1@T4<>wju-X=~NC=)5aYq&sj*d>wjEsq|m4Iayw1q6g1<1|k z#U18UIopLrdX{q$h!^y%~l z0v=4l#uvRGhy-_jRIQeP3``A-O&poQ_(bcO{g5$bL1yoyLrJZZ1!dP}?#|}%#KvI+ zIgzu?ZtQv)+U&t>kNq@z#s(&_#JY55U8I*IW`*{Y>@_JB75#gA>MdMRX)%x@fEEKHNvarXwE@29o8wMvy$jwF(+K=PgKrX zGKb27ypZsS&=-rih=wm6(VzTf+idaJzyc%@+cI15)4GXIX$^+Mma)x@59M=9EGj4w|7GM+U_niWZ@~oXIS+z#937LK zj&n%RyqsvL+;bzB2@@QO$t|BY?Aqrlsz)9uUI+>o9(VLeTXF~n@0b98&BUq_W?4ub zfCQ92Ky)vefKJLVxOJ>HPw8)#3o3crZmzO|-1(xhfGR;3FvaLnR*qkNTJ zn$(u^SF=Ez2{<;!+aUwf?QEei#Kr@yIzNp-AnUG>c6xsHIxx<9)J_xq99^4$ zyOz?`{7kM3!C*0Yba1KZ0maxB5t$&5SWL}d`IHa|rrRbBWP_B;-a!9mBrDfnK91xN=szy<Q1*CDC z9T8oQ1C5AWmg##;?2^z?XB8LXvCALb0k&0X$jb2lQ}^|cP(<#f5c=&H4hg|VZB{G1a& zdr<3`f|YQGiQ_FSw%K2hhSV|=eMGfLft-(7#QD92DK=gSR1tlu8#&I2m9Z)k+!RMO zWnHWQbHKAKPfd%;lZ`g)M?xZu0mBAfgR+wPjo;OWg3Zu@7hb7cR}Ew+-a(l=`@kYnf(rVQcf*GN$R`$dvS)Crg-~i%#dHl zgqPkl(1*~Es2Ni*SaM_N9O^A&p2qM;B}5$->r^4F9BRYUK&72QBDqTu8F9slz&xhv zVkp?Lkb+e{l~Q|jB%&C#y8;bgM_j>HTIn4AbK1%sC>C=cWiHOy3Ln%bfxUVU=ih}x zS?(??=LpLx`&a>CoMAQmzyfnzXE9T(qafSDB9Enw`4gKnCis#LV+vJ%8#pMZ$h4XA z8%K4^ZZaj3sHhGC=@#E14!K#~UBw?-w=_gscV`-jL?Z--K}&!sRAp2JRXtnfU01ek z$x*3ABRuz)jKXaT!MCPzW-%TV7emp}k7e_d9(RTT0v{DMe`J^E8_di+t2~R#i^oWt zP*aRCk!_m9-Yp75R@YJ#9U%}T^krwN zQ7`yF=*%yS$HgRKK_5hYux%J2$I!&w29eBW8yAr#FoZNP237j^IFw0{&U}Mr0#oF8 z=ToN&DiJi^5e;RAI6ULmWn-4vEtX9eha*aUO9~HMwL$@5di+Zz&Sf&v8n*K-QE|)dtcI6FR*^!8cK~>D71vNU4Vbb2_pmrGR z$saL|0L)nq=+I84CtOV*U4*cd&>aNEp+zWsHd-o#?3UFx2gN9SC$_pHP-ktXP@HL! zG!qwuDQZ>=vOO@6MRanh42ht|#>sVbRHTNKO|o$yXlP;3D)k2GOeh^(bX}bhoRJX; zC5FGYuHXY7m^qToj_?OBS{;~g6cl8d<}HDZ?CS9O0Zwye5rEtwZLETLO{T+rsma2| z9yd2PTNNy~#UIr%9);BSQNCaap${O$l5QrcH4) z0!urN3GxX0xTi+55gk(|?6(@hd8U;7#^#%o#J)`5*o}JC7ZnVGe|6d!yBqa*cxz&i ziz%S)OkHSdhIeT+3M9UCN{LM}(`$bwX>v9;Ih({#6iG=iPk9hK!h)eHGru68SO=Pn znHtXl`OKYb&kYe;O`+dtxY?yprbvA*VgpWk3R$C4)-6HB20<0nZ0hA)ifluL7|rK% z$Y_qGEBai#6cPdXuzNrs53g3COrOm-8wtuNmTFRzhq#Wl7H-~|^MZ|& zUEO)e3gC0>3`NtG|Hx89OG|jqcWHmjQv(BGae%(#M$txw5(>wqQtFV?;2uJ67 z#TZN+V%}t&72*ny()3o2`p?6B$o>n`R?D&ShW4}ef{tV#tu!+I zRb$)}#i)Xoan4MCu};rNB=H?(vCE1^EklFszxr0pqQ5uSNG8Krk#aVKU~h7Vg_=$9 zSfhryEFYD!CL$k)>9&N-5!jUtI|{2Nq|CrifgjY1Rq)6H@?? z8fH$UGQ%yr(TvVvR^OLUt+-cOUtE8i8IWm;g z((Oro7#}#y);!GsFQ8@sI8O3a6yiCz82+ zrHO5Jvs0DCb|}aJgcNZMSj@U-sFZ{ldF!w4=;6owr;xHXCd9&E1O4%sh_KK#aD*c# z6NNRh==4lbs2}~+s(}(`&d7$F&2DPUvonWq+B0QrC_d1sopp|vn_y15K#*wSivI%t zWc66)OvFY~h%6%Da75r2bN!rvRqp1wN~W#G4sbbyx=1&ZaQ9g-;*t(z%27)B?8H!@ zEH^J}DR@=b6c^TDot`{sc`8IX=6|9coU)??&AoLJd?WtDxEEa$<6t6fz4WV08h_$S zmYlpX8q-O$6CCS<*~91o6iW~0XdA7AiPgRaHekIh^~d7OeIP@sNSp(ri#-}SMDp7p zHI^jSMd_wCWQf6`S#pdjj0Oj4)UsA~&}IDPk{d~&RItv$Dvj7ji+R%U ze4A6%w%x--K^|H@BIBW~%&KHr-r#}{&^C(xgd@bF=#2DGwJuQ8a_D|2&Uq97PV%i@NC>$W`aymtml{GYvyw!Bafxxz!XotDmLgpN>7a{b*FkU;Q(xv%DF61$` z!ZirW*ChZx+l=AB!~)toUFCxD6@!_lA;dkxh~f_+s_2o0Nf@~}^w=Jr;XJ?QdvJew z{6bYg&+2MO#o7UzAagf@xJ-%r6T-=vNyK81=U98OKPfuw1czlhsi_$PcCsFynGfR* z-zXUYsNJK!vg9HG=5#35ARcVYLxEzo-1!ahkHw76%EsMVD?Un!bP{}R6K(aNQJ?;x z<*ic7@3qay+UQ$^CN^!lMUhTq_W*(GQbR@&@-!^K#E>efT zGmVf3gcx@U)EU)booTgUa@lH~Fb9-WD5aUJ7*nz)lt{B(zfdI@Z-o0WgTWFV(>hLvRbWK2gAoJ0guaro-hQoz7qgbVqGYi0qvQgyh~ zE8G=qcpG(~e#r78P8XN>n^@1`X320y1G5yzaCiXIkg5qY<7hRif`i0~$=M#69OOzP z^^j{2OTZ$|ra!g_;Ur96n)42dEt9ss!?$s@+oG9u@;y=)*>e@LNkk1Rs7h2WP9`4nRO zWfTi7uAR%a|908(|A0=?xL3rR=?f7qwi$%{l3%QO`8A;-4;T-MUM@+S9TKupIn5!; z5!{cen_OT-wS56aBLO5pt6(5s{ z^A5%5lnmLD)C#G-Fj+}}X%%G{Qhtn+Mx1~4N}=0`l}@waHBaC4OZ{sFQS6U76BWE9 zUj;46+tusL->D$)JyjZ+S8GP)uodMVhmEK{9L^yT~RSDAs`LjK-^4bN zYn1nl`ddw`vn9)B2gNuMOEljEtmGxcHhP@_=(8FLY{b(H$Sh?eNnK!Grj|P79RjJa zE`6IG6zd74hXU951AGxe$0_XkC9+1eAyPW{K96!Z zjPST~w!YO0_@dG(aF%>o$8N6CDe zx!$qzQmnV6j)2A_ToNu#ud1#a?22-Gy~jdWP$KQnCAfYLkxR%e;^h-gsC{VQ8b0xT z4R4WN7tAldmR%By9QUNX1Eci1^0lvO{*qKxc$GXha@G(>=J^`b-<;l+cS&5eaI;{i zVhD;K*@|wJ)Xv~ag{Trf*umO4mkCzM%LK|dHw&D+R-QK#U5~X4bj+cu1U%fX zgcM62>6+a5SmIdS$iUjt7)4j1H31yCW|LQ?5k1d$bqZu5Q1e;{aHr0Nlbl$|1pOdJ zu(46wJ0<$RqC_23I@70nlnGpMn;Yo{$jdZ!<@X`#DuqtCH$1W@$QnU^AZpAZn&2f} zSw>1BcQelF^pY^^)-zv>hCDBm!bvs)d_{`BlK?GDv^#yB3AjIFDmTm@WPfKO#Z;L% znHGK(Vhi+6U-f-xxrBm|3+j;wrE3PpDp#m_Kyvg!cXRQTlGtT}1e-@uFb~0xSPvV) zG%vXdG!?eISb$+WpbLr9JYAX)sb3~)3m4UufjXza=Y?I9UI&Qjr?BpQUCF>9}=NZTx=JG6AN=V#^me=wlFJ_-#u%siT-{kH3OHL+!79$0& z;SwEKLb%4FDIS}i$)E7pM>9N!n)3_1VJV}`2}l+du-kVBhAQ6F-&s2RE9snjSf;!A zZ0q5HiG#;Di~7e*OTL)xQtserXSXiIwJDZpSSj5@2O(o@3AUqyie*FAJj-$`OZ>

$Ch*CL3maos(1nae9O8J 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

4|l45X2M(6)~% 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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/ifcblenderexport/blenderbim/bim/data/templates/patterns.svg b/src/ifcblenderexport/blenderbim/bim/data/templates/patterns.svg deleted file mode 100644 index 3a9ea5c53c..0000000000 --- a/src/ifcblenderexport/blenderbim/bim/data/templates/patterns.svg +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/ifcblenderexport/blenderbim/bim/data/templates/symbols.svg b/src/ifcblenderexport/blenderbim/bim/data/templates/symbols.svg deleted file mode 100644 index b3209968e5..0000000000 --- a/src/ifcblenderexport/blenderbim/bim/data/templates/symbols.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/src/ifcblenderexport/blenderbim/bim/data/templates/titleblocks/A1.svg b/src/ifcblenderexport/blenderbim/bim/data/templates/titleblocks/A1.svg deleted file mode 100644 index 9b8b8be18b..0000000000 --- a/src/ifcblenderexport/blenderbim/bim/data/templates/titleblocks/A1.svg +++ /dev/null @@ -1,208 +0,0 @@ - - - - - - - image/svg+xml - - - - - - /home/dion/Projects/IfcOpenShell/src/ifcblenderexport/titleblock.dxf - scale = 1.000000, origin = (0.000000, 0.000000), method = manual - - - - REV. NO. - - - - - - - - - - - - - - - - DESCRIPTION - AUTHOR - DATE - DRAWING NUMBER - REV - {{revision}} - {{number}} - - - - - - - diff --git a/src/ifcblenderexport/blenderbim/bim/data/templates/titleblocks/A2.svg b/src/ifcblenderexport/blenderbim/bim/data/templates/titleblocks/A2.svg deleted file mode 100644 index f450a15cfb..0000000000 --- a/src/ifcblenderexport/blenderbim/bim/data/templates/titleblocks/A2.svg +++ /dev/null @@ -1,203 +0,0 @@ - - - - - - - image/svg+xml - - - - - - /home/dion/Projects/IfcOpenShell/src/ifcblenderexport/titleblock.dxf - scale = 1.000000, origin = (0.000000, 0.000000), method = manual - - - REV. NO. - - - - - - - - - - - - - DESCRIPTION - AUTHOR - DATE - - - - DRAWING NUMBER - REV - {{revision}} - {{number}} - - - - - - diff --git a/src/ifcblenderexport/blenderbim/bim/data/templates/titleblocks/A3.svg b/src/ifcblenderexport/blenderbim/bim/data/templates/titleblocks/A3.svg deleted file mode 100644 index 0f570cc865..0000000000 --- a/src/ifcblenderexport/blenderbim/bim/data/templates/titleblocks/A3.svg +++ /dev/null @@ -1,207 +0,0 @@ - - - - - - - image/svg+xml - - - - - - /home/dion/Projects/IfcOpenShell/src/ifcblenderexport/titleblock.dxf - scale = 1.000000, origin = (0.000000, 0.000000), method = manual - - - REV. NO. - - - - - - - - - - - - - DESCRIPTION - AUTHOR - DATE - - - - - DRAWING NUMBER - REV - {{revision}} - {{number}} - - - - - - - diff --git a/src/ifcblenderexport/blenderbim/bim/data/templates/view-title.svg b/src/ifcblenderexport/blenderbim/bim/data/templates/view-title.svg deleted file mode 100644 index 302826ec61..0000000000 --- a/src/ifcblenderexport/blenderbim/bim/data/templates/view-title.svg +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - - - {{no}} - {{name}} - {{scale}} - - diff --git a/src/ifcblenderexport/blenderbim/bim/data/window/typical/IfcWindowLiningProperties.csv b/src/ifcblenderexport/blenderbim/bim/data/window/typical/IfcWindowLiningProperties.csv deleted file mode 100644 index 2c7207fe62..0000000000 --- a/src/ifcblenderexport/blenderbim/bim/data/window/typical/IfcWindowLiningProperties.csv +++ /dev/null @@ -1,2 +0,0 @@ -Name,foo -TransomThickness,500 diff --git a/src/ifcblenderexport/blenderbim/bim/module/owner/add_organisation.py b/src/ifcblenderexport/blenderbim/bim/module/owner/add_organisation.py deleted file mode 100644 index d9c8cd2a65..0000000000 --- a/src/ifcblenderexport/blenderbim/bim/module/owner/add_organisation.py +++ /dev/null @@ -1,6 +0,0 @@ -class Usecase: - def __init__(self, file): - self.file = file - - def execute(self): - self.file.createIfcOrganization("APTR", "Aperture Science") diff --git a/src/ifcblenderexport/blenderbim/bim/module/owner/add_person.py b/src/ifcblenderexport/blenderbim/bim/module/owner/add_person.py deleted file mode 100644 index 0772105757..0000000000 --- a/src/ifcblenderexport/blenderbim/bim/module/owner/add_person.py +++ /dev/null @@ -1,6 +0,0 @@ -class Usecase: - def __init__(self, file): - self.file = file - - def execute(self): - self.file.createIfcPerson("HSeldon", "Seldon", "Hari") diff --git a/src/ifcblenderexport/blenderbim/bim/module/owner/api.py b/src/ifcblenderexport/blenderbim/bim/module/owner/api.py deleted file mode 100644 index b95d928b46..0000000000 --- a/src/ifcblenderexport/blenderbim/bim/module/owner/api.py +++ /dev/null @@ -1,62 +0,0 @@ -import bpy -import time -import addon_utils -import blenderbim.bim.module.owner.create_owner_history as create_owner_history_usecase -import blenderbim.bim.module.owner.update_owner_history as update_owner_history_usecase -from blenderbim.bim.ifc import IfcStore - - -def update_owner_history(element, change_action=None): - if not element.OwnerHistory: - element.OwnerHistory = create_owner_history() - return - file = IfcStore.get_file() - return update_owner_history_usecase.Usecase( - file, - { - "element": element, - "person": file.by_id(int(bpy.context.scene.BIMOwnerProperties.user_person)), - "organisation": file.by_id(int(bpy.context.scene.BIMOwnerProperties.user_organisation)), - "ApplicationIdentifier": "BlenderBIM", - "ApplicationFullName": "BlenderBIM Add-on", - "Version": get_application_version(), - "ChangeAction": change_action or "MODIFIED", - }, - ).execute() - - -def create_owner_history(change_action=None): - file = IfcStore.get_file() - - if ( - not bpy.context.scene.BIMOwnerProperties.user_person - or not bpy.context.scene.BIMOwnerProperties.user_organisation - ): - if file.schema == "IFC2X3": - assert False, "A person and organisation is required in IFC2X3." - return None - - return create_owner_history_usecase.Usecase( - file, - { - "person": file.by_id(int(bpy.context.scene.BIMOwnerProperties.user_person)), - "organisation": file.by_id(int(bpy.context.scene.BIMOwnerProperties.user_organisation)), - "ApplicationIdentifier": "BlenderBIM", - "ApplicationFullName": "BlenderBIM Add-on", - "Version": get_application_version(), - "ChangeAction": change_action or "ADDED", - }, - ).execute() - - -def get_application_version(): - return ".".join( - [ - str(x) - for x in [ - addon.bl_info.get("version", (-1, -1, -1)) - for addon in addon_utils.modules() - if addon.bl_info["name"] == "BlenderBIM" - ][0] - ] - ) diff --git a/src/ifcblenderexport/blenderbim/bim/module/owner/create_owner_history.py b/src/ifcblenderexport/blenderbim/bim/module/owner/create_owner_history.py deleted file mode 100644 index f91b275375..0000000000 --- a/src/ifcblenderexport/blenderbim/bim/module/owner/create_owner_history.py +++ /dev/null @@ -1,101 +0,0 @@ -import time -import ifcopenshell - - -class Usecase: - def __init__(self, file, settings=None): - self.file = file - self.settings = { - "person": None, - "organisation": None, - "ApplicationIdentifier": "", - "ApplicationFullName": "", - "Version": "", - "ChangeAction": "NOTDEFINED", - } - for key, value in settings.items(): - self.settings[key] = value - - def execute(self): - user = self.get_user() - application = self.get_application() - return self.file.create_entity( - "IfcOwnerHistory", - **{ - "OwningUser": user, - "OwningApplication": application, - "State": "READWRITE", - "ChangeAction": self.settings["ChangeAction"], - "LastModifiedDate": int(time.time()), - "LastModifyingUser": user, - "LastModifyingApplication": application, - "CreationDate": int(time.time()), - }, - ) - - def get_user(self): - for element in self.file.by_type("IfcPersonAndOrganization"): - if ( - element.ThePerson == self.settings["person"] - and element.TheOrganization == self.settings["organisation"] - ): - return element - return self.file.create_entity( - "IfcPersonAndOrganization", - **{"ThePerson": self.settings["person"], "TheOrganization": self.settings["organisation"]}, - ) - - def get_application(self): - for element in self.file.by_type("IfcApplication"): - if element.ApplicationIdentifier == self.settings["ApplicationIdentifier"]: - return element - return self.file.create_entity( - "IfcApplication", - **{ - "ApplicationDeveloper": self.get_application_organisation(), - "Version": self.settings["Version"], - "ApplicationFullName": self.settings["ApplicationFullName"], - "ApplicationIdentifier": self.settings["ApplicationIdentifier"], - }, - ) - - def get_application_organisation(self): - return self.file.create_entity( - "IfcOrganization", - **{ - "Name": "IfcOpenShell", - "Description": "IfcOpenShell is an open source (LGPL) software library that helps users and software developers to work with the IFC file format.", - "Roles": [ - self.file.create_entity("IfcActorRole", **{"Role": "USERDEFINED", "UserDefinedRole": "CONTRIBUTOR"}) - ], - "Addresses": [ - self.file.create_entity( - "IfcTelecomAddress", - **{ - "Purpose": "USERDEFINED", - "UserDefinedPurpose": "WEBPAGE", - "Description": "The main webpage of the software collection.", - "WWWHomePageURL": "https://ifcopenshell.org", - }, - ), - self.file.create_entity( - "IfcTelecomAddress", - **{ - "Purpose": "USERDEFINED", - "UserDefinedPurpose": "WEBPAGE", - "Description": "The BlenderBIM Add-on webpage of the software collection.", - "WWWHomePageURL": "https://blenderbim.org", - }, - ), - self.file.create_entity( - "IfcTelecomAddress", - **{ - "Purpose": "USERDEFINED", - "UserDefinedPurpose": "REPOSITORY", - "Description": "The source code repository of the software collection.", - "WWWHomePageURL": "https://github.com/IfcOpenShell/IfcOpenShell.git", - }, - ), - ], - }, - ) diff --git a/src/ifcblenderexport/blenderbim/bim/module/owner/update_owner_history.py b/src/ifcblenderexport/blenderbim/bim/module/owner/update_owner_history.py deleted file mode 100644 index 7456e4c19b..0000000000 --- a/src/ifcblenderexport/blenderbim/bim/module/owner/update_owner_history.py +++ /dev/null @@ -1,99 +0,0 @@ -import time -import ifcopenshell - - -class Usecase: - def __init__(self, file, settings=None): - self.file = file - self.settings = { - "OwnerHistory": None, - "person": None, - "organisation": None, - "ApplicationIdentifier": "", - "ApplicationFullName": "", - "Version": "", - "ChangeAction": "NOTDEFINED", - } - for key, value in settings.items(): - self.settings[key] = value - - def execute(self): - if len(self.file.get_inverse(self.settings["element"].OwnerHistory)) > 1: - old_history = self.settings["element"].OwnerHistory - self.settings["element"].OwnerHistory = self.file.create_entity("IfcOwnerHistory") - for i, attribute in enumerate(old_history): - self.settings["element"].OwnerHistory[i] = attribute - user = self.get_user() - application = self.get_application() - self.settings["element"].OwnerHistory.ChangeAction = self.settings["ChangeAction"] - self.settings["element"].OwnerHistory.LastModifiedDate = int(time.time()) - self.settings["element"].OwnerHistory.LastModifyingUser = user - self.settings["element"].OwnerHistory.LastModifyingApplication = application - return self.settings["OwnerHistory"] - - def get_user(self): - for element in self.file.by_type("IfcPersonAndOrganization"): - if ( - element.ThePerson == self.settings["person"] - and element.TheOrganization == self.settings["organisation"] - ): - return element - return self.file.create_entity( - "IfcPersonAndOrganization", - **{"ThePerson": self.settings["person"], "TheOrganization": self.settings["organisation"]}, - ) - - def get_application(self): - for element in self.file.by_type("IfcApplication"): - if element.ApplicationIdentifier == self.settings["ApplicationIdentifier"]: - return element - return self.file.create_entity( - "IfcApplication", - **{ - "ApplicationDeveloper": self.get_application_organisation(), - "Version": self.settings["Version"], - "ApplicationFullName": self.settings["ApplicationFullName"], - "ApplicationIdentifier": self.settings["ApplicationIdentifier"], - }, - ) - - def get_application_organisation(self): - return self.file.create_entity( - "IfcOrganization", - **{ - "Name": "IfcOpenShell", - "Description": "IfcOpenShell is an open source (LGPL) software library that helps users and software developers to work with the IFC file format.", - "Roles": [ - self.file.create_entity("IfcActorRole", **{"Role": "USERDEFINED", "UserDefinedRole": "CONTRIBUTOR"}) - ], - "Addresses": [ - self.file.create_entity( - "IfcTelecomAddress", - **{ - "Purpose": "USERDEFINED", - "UserDefinedPurpose": "WEBPAGE", - "Description": "The main webpage of the software collection.", - "WWWHomePageURL": "https://ifcopenshell.org", - }, - ), - self.file.create_entity( - "IfcTelecomAddress", - **{ - "Purpose": "USERDEFINED", - "UserDefinedPurpose": "WEBPAGE", - "Description": "The BlenderBIM Add-on webpage of the software collection.", - "WWWHomePageURL": "https://blenderbim.org", - }, - ), - self.file.create_entity( - "IfcTelecomAddress", - **{ - "Purpose": "USERDEFINED", - "UserDefinedPurpose": "REPOSITORY", - "Description": "The source code repository of the software collection.", - "WWWHomePageURL": "https://github.com/IfcOpenShell/IfcOpenShell.git", - }, - ), - ], - }, - ) diff --git a/src/ifcblenderexport/blenderbim/bim/module/root/remove_product.py b/src/ifcblenderexport/blenderbim/bim/module/root/remove_product.py deleted file mode 100644 index 31ca4be404..0000000000 --- a/src/ifcblenderexport/blenderbim/bim/module/root/remove_product.py +++ /dev/null @@ -1,11 +0,0 @@ -class Usecase: - def __init__(self, file, settings=None): - self.file = file - self.settings = { - "product": None - } - for key, value in settings.items(): - self.settings[key] = value - - def execute(self): - self.file.remove(self.settings["product"]) diff --git a/src/ifcblenderexport/blenderbim/bim/module/sequence/data.py b/src/ifcblenderexport/blenderbim/bim/module/sequence/data.py deleted file mode 100644 index dd7dc98e98..0000000000 --- a/src/ifcblenderexport/blenderbim/bim/module/sequence/data.py +++ /dev/null @@ -1,18 +0,0 @@ -from blenderbim.bim.ifc import IfcStore - - -class Data: - is_loaded = False - tasks = {} - - @classmethod - def purge(cls): - cls.is_loaded = False - cls.tasks = {} - - @classmethod - def load(cls): - cls.tasks = {} - for task in IfcStore.get_file().by_type("IfcTask"): - cls.tasks[task.id()] = {"Name": task.Name, "Identification": task.Identification or ""} - cls.is_loaded=True diff --git a/src/ifcblenderexport/blenderbim/bim/module/structural/add_structural_analysis_model.py b/src/ifcblenderexport/blenderbim/bim/module/structural/add_structural_analysis_model.py deleted file mode 100644 index f7539c02ed..0000000000 --- a/src/ifcblenderexport/blenderbim/bim/module/structural/add_structural_analysis_model.py +++ /dev/null @@ -1,18 +0,0 @@ -import ifcopenshell -from blenderbim.bim.module.owner.api import create_owner_history - - -class Usecase: - def __init__(self, file, settings={}): - self.file = file - self.settings = {} - for key, value in settings.items(): - self.settings[key] = value - - def execute(self): - return self.file.create_entity("IfcStructuralAnalysisModel", **{ - "GlobalId": ifcopenshell.guid.new(), - "OwnerHistory": create_owner_history(), - "Name": "Unnamed", - "PredefinedType": "LOADING_3D" - }) diff --git a/src/ifcblenderexport/blenderbim/bim/module/structural/add_structural_boundary_condition.py b/src/ifcblenderexport/blenderbim/bim/module/structural/add_structural_boundary_condition.py deleted file mode 100644 index 4a3e8412c1..0000000000 --- a/src/ifcblenderexport/blenderbim/bim/module/structural/add_structural_boundary_condition.py +++ /dev/null @@ -1,15 +0,0 @@ -class Usecase: - def __init__(self, file, settings={}): - self.file = file - self.settings = {"connection": None} - for key, value in settings.items(): - self.settings[key] = value - - def execute(self): - if self.settings["connection"].is_a("IfcStructuralPointConnection"): - boundary_class = "IfcBoundaryNodeCondition" - elif self.settings["connection"].is_a("IfcStructuralCurveConnection"): - boundary_class = "IfcBoundaryEdgeCondition" - elif self.settings["connection"].is_a("IfcStructuralSurfaceConnection"): - boundary_class = "IfcBoundaryFaceCondition" - self.settings["connection"].AppliedCondition = self.file.create_entity(boundary_class) diff --git a/src/ifcblenderexport/blenderbim/bim/module/structural/data.py b/src/ifcblenderexport/blenderbim/bim/module/structural/data.py deleted file mode 100644 index dfe1265db4..0000000000 --- a/src/ifcblenderexport/blenderbim/bim/module/structural/data.py +++ /dev/null @@ -1,68 +0,0 @@ -from blenderbim.bim.ifc import IfcStore - - -class Data: - is_loaded = False - products = {} - boundary_conditions = {} - structural_analysis_models = {} - - @classmethod - def purge(cls): - cls.is_loaded = False - cls.products = {} - cls.boundary_conditions = {} - cls.connected_structural_members = {} - cls.structural_analysis_models = {} - - @classmethod - def load(cls, product_id=None): - if product_id: - cls.boundary_conditions = {} - return cls.load_structural_connection(product_id) - cls.products = {} - cls.structural_analysis_models = {} - cls.load_structural_analysis_models() - cls.is_loaded = True - - @classmethod - def load_structural_analysis_models(cls): - for model in IfcStore.get_file().by_type("IfcStructuralAnalysisModel"): - if model.IsGroupedBy: - for rel in model.IsGroupedBy: - for product in rel.RelatedObjects: - cls.products.setdefault(product.id(), []).append(model.id()) - data = model.get_info() - del data["OwnerHistory"] - del data["OrientationOf2DPlane"] - - loaded_by = [] - for load_group in model.LoadedBy or []: - loaded_by.append(load_group.id()) - data["LoadedBy"] = loaded_by - - has_results = [] - for result_group in model.HasResults or []: - has_results.append(result_group.id()) - data["HasResults"] = has_results - - cls.structural_analysis_models[model.id()] = data - - @classmethod - def load_structural_connection(cls, product_id): - connection = IfcStore.get_file().by_id(product_id) - if connection.AppliedCondition: - data = connection.AppliedCondition.get_info() - for key, value in data.items(): - if not value or key in ["Name", "type", "id"]: - continue - data[key] = value.wrappedValue - else: - data = {} - cls.boundary_conditions[connection.id()] = data - - cls.connected_structural_members[connection.id()] = [ - rel.RelatingStructuralMember.id() - for rel in connection.ConnectsStructuralMembers or [] - ] - diff --git a/src/ifccobie/get_maintainable_assets.py b/src/ifccobie/get_maintainable_assets.py index b4a599e0cd..1e71ac50d5 100644 --- a/src/ifccobie/get_maintainable_assets.py +++ b/src/ifccobie/get_maintainable_assets.py @@ -2,9 +2,9 @@ import json import ifcopenshell import ifcopenshell.util.selector -with open("../ifcblenderexport/blenderbim/bim/schema/entity_descriptions.json") as f: +with open("../blenderbim/blenderbim/bim/schema/entity_descriptions.json") as f: entity_descriptions = json.load(f) -with open("../ifcblenderexport/blenderbim/bim/schema/enum_descriptions.json") as f: +with open("../blenderbim/blenderbim/bim/schema/enum_descriptions.json") as f: enum_descriptions = json.load(f) print('{|class="wikitable"') diff --git a/src/ifcconvert/IfcConvert.cpp b/src/ifcconvert/IfcConvert.cpp index 977b418cdf..3359ce5052 100644 --- a/src/ifcconvert/IfcConvert.cpp +++ b/src/ifcconvert/IfcConvert.cpp @@ -386,6 +386,8 @@ int main(int argc, char** argv) { ("draw-storey-heights", po::value(&storey_height_display)->default_value("none")->implicit_value("full"), "Draws a horizontal line at the height of building storeys in vertical drawings") + ("storey-height-line-length", po::value(), + "Length of the line when --draw-storey-heights=left") ("svg-xmlns", "Stores name and guid in a separate namespace as opposed to data-name, data-guid") ("svg-poly", @@ -426,6 +428,8 @@ int main(int argc, char** argv) { " and any other value means that 6 or 7 decimals are used.") ("print-space-names", "Prints IfcSpace LongName and Name in the geometry output. Applicable for SVG output") ("print-space-areas", "Prints calculated IfcSpace areas in square meters. Applicable for SVG output") + ("space-name-transform", po::value(), + "Additional transform to the space labels in SVG") ("edge-arrows", "Adds arrow heads to edge segments to signify edge direction") ; @@ -1010,6 +1014,16 @@ int main(int argc, char** argv) { if (relative_center_x && relative_center_y) { static_cast(serializer.get())->setDrawingCenter(*relative_center_x, *relative_center_y); } + if (vmap.count("storey-height-line-length")) { + static_cast(serializer.get())->setStoreyHeightLineLength( + vmap["storey-height-line-length"].as() + ); + } + if (vmap.count("space-name-transform")) { + static_cast(serializer.get())->setSpaceNameTransform( + vmap["space-name-transform"].as() + ); + } } if (convert_back_units) { diff --git a/src/ifcopenshell-python/ifcopenshell/api/__init__.py b/src/ifcopenshell-python/ifcopenshell/api/__init__.py new file mode 100644 index 0000000000..0468132d86 --- /dev/null +++ b/src/ifcopenshell-python/ifcopenshell/api/__init__.py @@ -0,0 +1,11 @@ +import importlib +import ifcopenshell.api + + +def run(usecase_path, ifc_file=None, **settings): + importlib.import_module(f"ifcopenshell.api.{usecase_path}") + module, usecase = usecase_path.split(".") + usecase_class = getattr(getattr(getattr(ifcopenshell.api, module), usecase), "Usecase") + if ifc_file: + return usecase_class(ifc_file, **settings).execute() + return usecase_class(**settings).execute() diff --git a/src/ifcblenderexport/blenderbim/bim/module/aggregate/assign_object.py b/src/ifcopenshell-python/ifcopenshell/api/aggregate/assign_object.py similarity index 80% rename from src/ifcblenderexport/blenderbim/bim/module/aggregate/assign_object.py rename to src/ifcopenshell-python/ifcopenshell/api/aggregate/assign_object.py index 6a3dd1b946..805de997cc 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/aggregate/assign_object.py +++ b/src/ifcopenshell-python/ifcopenshell/api/aggregate/assign_object.py @@ -1,10 +1,9 @@ import ifcopenshell -from blenderbim.bim.module.owner.api import create_owner_history -from blenderbim.bim.module.owner.api import update_owner_history +import ifcopenshell.api class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = { "product": None, @@ -32,7 +31,7 @@ class Usecase: related_objects.remove(self.settings["product"]) if related_objects: decomposes.RelatedObjects = related_objects - update_owner_history(decomposes) + ifcopenshell.api.run("owner.update_owner_history", self.file, **{"element": decomposes}) else: self.file.remove(decomposes) @@ -40,13 +39,13 @@ class Usecase: related_objects = list(is_decomposed_by.RelatedObjects) related_objects.append(self.settings["product"]) is_decomposed_by.RelatedObjects = related_objects - update_owner_history(is_decomposed_by) + ifcopenshell.api.run("owner.update_owner_history", self.file, **{"element": is_decomposed_by}) else: is_decomposed_by = self.file.create_entity( "IfcRelAggregates", **{ "GlobalId": ifcopenshell.guid.new(), - "OwnerHistory": create_owner_history(), + "OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", self.file), "RelatedObjects": [self.settings["product"]], "RelatingObject": self.settings["relating_object"], } diff --git a/src/ifcblenderexport/blenderbim/bim/module/aggregate/data.py b/src/ifcopenshell-python/ifcopenshell/api/aggregate/data.py similarity index 82% rename from src/ifcblenderexport/blenderbim/bim/module/aggregate/data.py rename to src/ifcopenshell-python/ifcopenshell/api/aggregate/data.py index 67ff085df2..88d783f1f6 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/aggregate/data.py +++ b/src/ifcopenshell-python/ifcopenshell/api/aggregate/data.py @@ -1,6 +1,3 @@ -from blenderbim.bim.ifc import IfcStore - - class Data: products = {} @@ -9,8 +6,7 @@ class Data: cls.products = {} @classmethod - def load(cls, product_id): - file = IfcStore.get_file() + def load(cls, file, product_id): if not file: return product = file.by_id(product_id) diff --git a/src/ifcblenderexport/blenderbim/bim/module/attribute/data.py b/src/ifcopenshell-python/ifcopenshell/api/attribute/data.py similarity index 88% rename from src/ifcblenderexport/blenderbim/bim/module/attribute/data.py rename to src/ifcopenshell-python/ifcopenshell/api/attribute/data.py index 2458759c89..a6750c18fd 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/attribute/data.py +++ b/src/ifcopenshell-python/ifcopenshell/api/attribute/data.py @@ -1,6 +1,5 @@ import ifcopenshell import ifcopenshell.util.attribute -from blenderbim.bim.ifc import IfcStore class Data: @@ -11,13 +10,13 @@ class Data: cls.products = {} @classmethod - def load(cls, product_id): - file = IfcStore.get_file() + def load(cls, file, product_id): if not file: return product = file.by_id(product_id) + schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(file.schema) cls.products[product_id] = [] - declaration = IfcStore.get_schema().declaration_by_name(product.is_a()) + declaration = schema.declaration_by_name(product.is_a()) for attribute in declaration.all_attributes(): data_type = ifcopenshell.util.attribute.get_primitive_type(attribute) value = getattr(product, attribute.name()) diff --git a/src/ifcblenderexport/blenderbim/bim/module/attribute/edit_attributes.py b/src/ifcopenshell-python/ifcopenshell/api/attribute/edit_attributes.py similarity index 53% rename from src/ifcblenderexport/blenderbim/bim/module/attribute/edit_attributes.py rename to src/ifcopenshell-python/ifcopenshell/api/attribute/edit_attributes.py index 4e45c6b61b..9a68bd8f09 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/attribute/edit_attributes.py +++ b/src/ifcopenshell-python/ifcopenshell/api/attribute/edit_attributes.py @@ -1,13 +1,10 @@ -from blenderbim.bim.module.owner.api import update_owner_history +import ifcopenshell.api -class Usecase(): - def __init__(self, file, settings=None): +class Usecase: + def __init__(self, file, **settings): self.file = file - self.settings = { - "product": None, - "attributes": {} - } + self.settings = {"product": None, "attributes": {}} for key, value in settings.items(): self.settings[key] = value @@ -15,4 +12,4 @@ class Usecase(): for name, value in self.settings["attributes"].items(): setattr(self.settings["product"], name, value) if hasattr(self.settings["product"], "OwnerHistory"): - update_owner_history(self.settings["product"]) + ifcopenshell.api.run("owner.update_owner_history", self.file, **{"element": self.settings["product"]}) diff --git a/src/ifcblenderexport/blenderbim/bim/module/classification/add_classification.py b/src/ifcopenshell-python/ifcopenshell/api/classification/add_classification.py similarity index 97% rename from src/ifcblenderexport/blenderbim/bim/module/classification/add_classification.py rename to src/ifcopenshell-python/ifcopenshell/api/classification/add_classification.py index 7c16292e9f..f66135c23d 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/classification/add_classification.py +++ b/src/ifcopenshell-python/ifcopenshell/api/classification/add_classification.py @@ -3,7 +3,7 @@ import ifcopenshell.util.schema import ifcopenshell.util.date class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = { "classification": None, diff --git a/src/ifcblenderexport/blenderbim/bim/module/classification/add_reference.py b/src/ifcopenshell-python/ifcopenshell/api/classification/add_reference.py similarity index 98% rename from src/ifcblenderexport/blenderbim/bim/module/classification/add_reference.py rename to src/ifcopenshell-python/ifcopenshell/api/classification/add_reference.py index 5c880510eb..921ad3d79f 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/classification/add_reference.py +++ b/src/ifcopenshell-python/ifcopenshell/api/classification/add_reference.py @@ -3,7 +3,7 @@ import ifcopenshell.util.schema class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = { "product": None, diff --git a/src/ifcblenderexport/blenderbim/bim/module/classification/data.py b/src/ifcopenshell-python/ifcopenshell/api/classification/data.py similarity index 95% rename from src/ifcblenderexport/blenderbim/bim/module/classification/data.py rename to src/ifcopenshell-python/ifcopenshell/api/classification/data.py index 0a5f8c367a..00b39ab610 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/classification/data.py +++ b/src/ifcopenshell-python/ifcopenshell/api/classification/data.py @@ -1,6 +1,5 @@ import ifcopenshell import ifcopenshell.util.date -from blenderbim.bim.ifc import IfcStore class Data: @@ -23,8 +22,8 @@ class Data: cls.library_references = {} @classmethod - def load(cls, product_id=None): - cls._file = IfcStore.get_file() + def load(cls, file, product_id=None): + cls._file = file if not cls._file: return if product_id: diff --git a/src/ifcblenderexport/blenderbim/bim/module/classification/edit_classification.py b/src/ifcopenshell-python/ifcopenshell/api/classification/edit_classification.py similarity index 89% rename from src/ifcblenderexport/blenderbim/bim/module/classification/edit_classification.py rename to src/ifcopenshell-python/ifcopenshell/api/classification/edit_classification.py index 58fd59ea9a..12c60626f7 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/classification/edit_classification.py +++ b/src/ifcopenshell-python/ifcopenshell/api/classification/edit_classification.py @@ -1,5 +1,5 @@ class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = { "classification": None, diff --git a/src/ifcblenderexport/blenderbim/bim/module/document/edit_reference.py b/src/ifcopenshell-python/ifcopenshell/api/classification/edit_reference.py similarity index 89% rename from src/ifcblenderexport/blenderbim/bim/module/document/edit_reference.py rename to src/ifcopenshell-python/ifcopenshell/api/classification/edit_reference.py index b538bafb46..a37391d11b 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/document/edit_reference.py +++ b/src/ifcopenshell-python/ifcopenshell/api/classification/edit_reference.py @@ -1,5 +1,5 @@ class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = { "reference": None, diff --git a/src/ifcblenderexport/blenderbim/bim/module/classification/remove_classification.py b/src/ifcopenshell-python/ifcopenshell/api/classification/remove_classification.py similarity index 95% rename from src/ifcblenderexport/blenderbim/bim/module/classification/remove_classification.py rename to src/ifcopenshell-python/ifcopenshell/api/classification/remove_classification.py index a6708c871c..cae293c6ae 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/classification/remove_classification.py +++ b/src/ifcopenshell-python/ifcopenshell/api/classification/remove_classification.py @@ -1,5 +1,5 @@ class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = {"classification": None} for key, value in settings.items(): diff --git a/src/ifcblenderexport/blenderbim/bim/module/classification/remove_reference.py b/src/ifcopenshell-python/ifcopenshell/api/classification/remove_reference.py similarity index 96% rename from src/ifcblenderexport/blenderbim/bim/module/classification/remove_reference.py rename to src/ifcopenshell-python/ifcopenshell/api/classification/remove_reference.py index 5ca45a19cf..d9172b675e 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/classification/remove_reference.py +++ b/src/ifcopenshell-python/ifcopenshell/api/classification/remove_reference.py @@ -2,7 +2,7 @@ import ifcopenshell.util.schema class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = {"reference": None, "product": None} for key, value in settings.items(): diff --git a/src/ifcblenderexport/blenderbim/bim/module/constraint/add_objective.py b/src/ifcopenshell-python/ifcopenshell/api/constraint/add_objective.py similarity index 90% rename from src/ifcblenderexport/blenderbim/bim/module/constraint/add_objective.py rename to src/ifcopenshell-python/ifcopenshell/api/constraint/add_objective.py index 5891bfb49d..a6dc8e2108 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/constraint/add_objective.py +++ b/src/ifcopenshell-python/ifcopenshell/api/constraint/add_objective.py @@ -1,7 +1,7 @@ import ifcopenshell class Usecase: - def __init__(self, file, settings={}): + def __init__(self, file, **settings): self.file = file self.settings = {} for key, value in settings.items(): diff --git a/src/ifcblenderexport/blenderbim/bim/module/constraint/assign_constraint.py b/src/ifcopenshell-python/ifcopenshell/api/constraint/assign_constraint.py similarity index 95% rename from src/ifcblenderexport/blenderbim/bim/module/constraint/assign_constraint.py rename to src/ifcopenshell-python/ifcopenshell/api/constraint/assign_constraint.py index 6a8a8755ae..7dc946e911 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/constraint/assign_constraint.py +++ b/src/ifcopenshell-python/ifcopenshell/api/constraint/assign_constraint.py @@ -2,7 +2,7 @@ import ifcopenshell class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = { "product": None, diff --git a/src/ifcblenderexport/blenderbim/bim/module/constraint/data.py b/src/ifcopenshell-python/ifcopenshell/api/constraint/data.py similarity index 92% rename from src/ifcblenderexport/blenderbim/bim/module/constraint/data.py rename to src/ifcopenshell-python/ifcopenshell/api/constraint/data.py index 165a40902d..aaae145eaf 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/constraint/data.py +++ b/src/ifcopenshell-python/ifcopenshell/api/constraint/data.py @@ -1,6 +1,5 @@ import ifcopenshell import ifcopenshell.util.date -from blenderbim.bim.ifc import IfcStore from datetime import datetime @@ -16,8 +15,8 @@ class Data: cls.objectives = {} @classmethod - def load(cls, product_id=None): - cls._file = IfcStore.get_file() + def load(cls, file, product_id=None): + cls._file = file if not cls._file: return if product_id: diff --git a/src/ifcblenderexport/blenderbim/bim/module/constraint/edit_objective.py b/src/ifcopenshell-python/ifcopenshell/api/constraint/edit_objective.py similarity index 89% rename from src/ifcblenderexport/blenderbim/bim/module/constraint/edit_objective.py rename to src/ifcopenshell-python/ifcopenshell/api/constraint/edit_objective.py index 9a1003ba70..4b569581ee 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/constraint/edit_objective.py +++ b/src/ifcopenshell-python/ifcopenshell/api/constraint/edit_objective.py @@ -1,5 +1,5 @@ class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = { "objective": None, diff --git a/src/ifcblenderexport/blenderbim/bim/module/constraint/remove_constraint.py b/src/ifcopenshell-python/ifcopenshell/api/constraint/remove_constraint.py similarity index 89% rename from src/ifcblenderexport/blenderbim/bim/module/constraint/remove_constraint.py rename to src/ifcopenshell-python/ifcopenshell/api/constraint/remove_constraint.py index 27b0938322..09476c0b3f 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/constraint/remove_constraint.py +++ b/src/ifcopenshell-python/ifcopenshell/api/constraint/remove_constraint.py @@ -1,5 +1,5 @@ class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = {"constraint": None} for key, value in settings.items(): diff --git a/src/ifcblenderexport/blenderbim/bim/module/constraint/unassign_constraint.py b/src/ifcopenshell-python/ifcopenshell/api/constraint/unassign_constraint.py similarity index 91% rename from src/ifcblenderexport/blenderbim/bim/module/constraint/unassign_constraint.py rename to src/ifcopenshell-python/ifcopenshell/api/constraint/unassign_constraint.py index 0c47723a59..63b7d17a2b 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/constraint/unassign_constraint.py +++ b/src/ifcopenshell-python/ifcopenshell/api/constraint/unassign_constraint.py @@ -2,7 +2,7 @@ import ifcopenshell class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = { "product": None, diff --git a/src/ifcblenderexport/blenderbim/bim/module/context/add_context.py b/src/ifcopenshell-python/ifcopenshell/api/context/add_context.py similarity index 97% rename from src/ifcblenderexport/blenderbim/bim/module/context/add_context.py rename to src/ifcopenshell-python/ifcopenshell/api/context/add_context.py index 2d478b6173..4c4d310834 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/context/add_context.py +++ b/src/ifcopenshell-python/ifcopenshell/api/context/add_context.py @@ -1,5 +1,5 @@ class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = { "context": None, diff --git a/src/ifcblenderexport/blenderbim/bim/module/context/data.py b/src/ifcopenshell-python/ifcopenshell/api/context/data.py similarity index 89% rename from src/ifcblenderexport/blenderbim/bim/module/context/data.py rename to src/ifcopenshell-python/ifcopenshell/api/context/data.py index 08fe2c1fe9..cd2380bbcf 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/context/data.py +++ b/src/ifcopenshell-python/ifcopenshell/api/context/data.py @@ -1,6 +1,3 @@ -from blenderbim.bim.ifc import IfcStore - - class Data: is_loaded = False contexts = {} @@ -11,8 +8,7 @@ class Data: cls.contexts = {} @classmethod - def load(cls): - file = IfcStore.get_file() + def load(cls, file): if not file: return cls.contexts = {} diff --git a/src/ifcblenderexport/blenderbim/bim/module/context/remove_context.py b/src/ifcopenshell-python/ifcopenshell/api/context/remove_context.py similarity index 89% rename from src/ifcblenderexport/blenderbim/bim/module/context/remove_context.py rename to src/ifcopenshell-python/ifcopenshell/api/context/remove_context.py index ce17b0ef2d..1315d0b01a 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/context/remove_context.py +++ b/src/ifcopenshell-python/ifcopenshell/api/context/remove_context.py @@ -1,5 +1,5 @@ class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = {"context": None} for key, value in settings.items(): diff --git a/src/ifcblenderexport/blenderbim/bim/module/document/add_information.py b/src/ifcopenshell-python/ifcopenshell/api/document/add_information.py similarity index 91% rename from src/ifcblenderexport/blenderbim/bim/module/document/add_information.py rename to src/ifcopenshell-python/ifcopenshell/api/document/add_information.py index fc1b639695..bb3013e0b9 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/document/add_information.py +++ b/src/ifcopenshell-python/ifcopenshell/api/document/add_information.py @@ -1,7 +1,7 @@ import ifcopenshell class Usecase: - def __init__(self, file, settings={}): + def __init__(self, file, **settings): self.file = file self.settings = {} for key, value in settings.items(): diff --git a/src/ifcblenderexport/blenderbim/bim/module/document/add_reference.py b/src/ifcopenshell-python/ifcopenshell/api/document/add_reference.py similarity index 90% rename from src/ifcblenderexport/blenderbim/bim/module/document/add_reference.py rename to src/ifcopenshell-python/ifcopenshell/api/document/add_reference.py index 7030f4fc32..0e631fefa9 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/document/add_reference.py +++ b/src/ifcopenshell-python/ifcopenshell/api/document/add_reference.py @@ -1,7 +1,7 @@ import ifcopenshell class Usecase: - def __init__(self, file, settings={}): + def __init__(self, file, **settings): self.file = file self.settings = {} for key, value in settings.items(): diff --git a/src/ifcblenderexport/blenderbim/bim/module/document/assign_document.py b/src/ifcopenshell-python/ifcopenshell/api/document/assign_document.py similarity index 97% rename from src/ifcblenderexport/blenderbim/bim/module/document/assign_document.py rename to src/ifcopenshell-python/ifcopenshell/api/document/assign_document.py index b7295a3905..c056b988b0 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/document/assign_document.py +++ b/src/ifcopenshell-python/ifcopenshell/api/document/assign_document.py @@ -2,7 +2,7 @@ import ifcopenshell class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = { "product": None, diff --git a/src/ifcblenderexport/blenderbim/bim/module/document/data.py b/src/ifcopenshell-python/ifcopenshell/api/document/data.py similarity index 95% rename from src/ifcblenderexport/blenderbim/bim/module/document/data.py rename to src/ifcopenshell-python/ifcopenshell/api/document/data.py index 1e3eb3184c..ec67429ecd 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/document/data.py +++ b/src/ifcopenshell-python/ifcopenshell/api/document/data.py @@ -1,6 +1,5 @@ import ifcopenshell import ifcopenshell.util.date -from blenderbim.bim.ifc import IfcStore from datetime import datetime @@ -18,8 +17,8 @@ class Data: cls.information = {} @classmethod - def load(cls, product_id=None): - cls._file = IfcStore.get_file() + def load(cls, file, product_id=None): + cls._file = file if not cls._file: return if product_id: diff --git a/src/ifcblenderexport/blenderbim/bim/module/document/edit_information.py b/src/ifcopenshell-python/ifcopenshell/api/document/edit_information.py similarity index 89% rename from src/ifcblenderexport/blenderbim/bim/module/document/edit_information.py rename to src/ifcopenshell-python/ifcopenshell/api/document/edit_information.py index 6071bf5d95..1a86df4186 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/document/edit_information.py +++ b/src/ifcopenshell-python/ifcopenshell/api/document/edit_information.py @@ -1,5 +1,5 @@ class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = { "information": None, diff --git a/src/ifcblenderexport/blenderbim/bim/module/classification/edit_reference.py b/src/ifcopenshell-python/ifcopenshell/api/document/edit_reference.py similarity index 89% rename from src/ifcblenderexport/blenderbim/bim/module/classification/edit_reference.py rename to src/ifcopenshell-python/ifcopenshell/api/document/edit_reference.py index b538bafb46..a37391d11b 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/classification/edit_reference.py +++ b/src/ifcopenshell-python/ifcopenshell/api/document/edit_reference.py @@ -1,5 +1,5 @@ class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = { "reference": None, diff --git a/src/ifcblenderexport/blenderbim/bim/module/document/remove_document.py b/src/ifcopenshell-python/ifcopenshell/api/document/remove_document.py similarity index 89% rename from src/ifcblenderexport/blenderbim/bim/module/document/remove_document.py rename to src/ifcopenshell-python/ifcopenshell/api/document/remove_document.py index 4f3137bf9d..0ebc89e101 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/document/remove_document.py +++ b/src/ifcopenshell-python/ifcopenshell/api/document/remove_document.py @@ -1,5 +1,5 @@ class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = {"document": None} for key, value in settings.items(): diff --git a/src/ifcblenderexport/blenderbim/bim/module/document/unassign_document.py b/src/ifcopenshell-python/ifcopenshell/api/document/unassign_document.py similarity index 91% rename from src/ifcblenderexport/blenderbim/bim/module/document/unassign_document.py rename to src/ifcopenshell-python/ifcopenshell/api/document/unassign_document.py index a1bdf6c158..ef90f03c67 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/document/unassign_document.py +++ b/src/ifcopenshell-python/ifcopenshell/api/document/unassign_document.py @@ -2,7 +2,7 @@ import ifcopenshell class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = { "product": None, diff --git a/src/ifcblenderexport/blenderbim/bim/module/geometry/add_representation.py b/src/ifcopenshell-python/ifcopenshell/api/geometry/add_representation.py similarity index 99% rename from src/ifcblenderexport/blenderbim/bim/module/geometry/add_representation.py rename to src/ifcopenshell-python/ifcopenshell/api/geometry/add_representation.py index ad0e32225c..6868b91fe2 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/geometry/add_representation.py +++ b/src/ifcopenshell-python/ifcopenshell/api/geometry/add_representation.py @@ -6,7 +6,7 @@ from blenderbim.bim.module.geometry.helper import Helper class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): # TODO: This usecase currently depends on Blender's data model self.file = file self.settings = { @@ -424,12 +424,12 @@ class Usecase: ) def create_structural_reference_representation(self): - if self.settings["blender_object"].type == "EMPTY": + if len(self.settings["geometry"].vertices) == 1: return self.file.createIfcTopologyRepresentation( self.settings["context"], self.settings["context"].ContextIdentifier, "Vertex", - [self.create_vertex_point(Vector((0, 0, 0)))], + [self.create_vertex_point(self.settings["geometry"].vertices[0].co)], ) return self.file.createIfcTopologyRepresentation( self.settings["context"], diff --git a/src/ifcblenderexport/blenderbim/bim/module/geometry/assign_representation.py b/src/ifcopenshell-python/ifcopenshell/api/geometry/assign_representation.py similarity index 90% rename from src/ifcblenderexport/blenderbim/bim/module/geometry/assign_representation.py rename to src/ifcopenshell-python/ifcopenshell/api/geometry/assign_representation.py index 482fce9451..1835bfbe39 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/geometry/assign_representation.py +++ b/src/ifcopenshell-python/ifcopenshell/api/geometry/assign_representation.py @@ -1,5 +1,8 @@ +import ifcopenshell.api + + class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = {"product": None, "representation": None} for key, value in settings.items(): @@ -32,3 +35,4 @@ class Usecase: ) ) self.settings["product"].RepresentationMaps = maps + ifcopenshell.api.run("owner.update_owner_history", self.file, **{"element": self.settings["product"]}) diff --git a/src/ifcblenderexport/blenderbim/bim/module/geometry/assign_styles.py b/src/ifcopenshell-python/ifcopenshell/api/geometry/assign_styles.py similarity index 96% rename from src/ifcblenderexport/blenderbim/bim/module/geometry/assign_styles.py rename to src/ifcopenshell-python/ifcopenshell/api/geometry/assign_styles.py index e4ad0a1e36..2fbc699a6c 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/geometry/assign_styles.py +++ b/src/ifcopenshell-python/ifcopenshell/api/geometry/assign_styles.py @@ -1,5 +1,5 @@ class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = { "shape_representation": None, diff --git a/src/ifcblenderexport/blenderbim/bim/module/geometry/data.py b/src/ifcopenshell-python/ifcopenshell/api/geometry/data.py similarity index 92% rename from src/ifcblenderexport/blenderbim/bim/module/geometry/data.py rename to src/ifcopenshell-python/ifcopenshell/api/geometry/data.py index 63fd96fbdf..c72cc104cf 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/geometry/data.py +++ b/src/ifcopenshell-python/ifcopenshell/api/geometry/data.py @@ -1,6 +1,3 @@ -from blenderbim.bim.ifc import IfcStore - - class Data: products = {} representations = {} @@ -11,8 +8,7 @@ class Data: cls.representations = {} @classmethod - def load(cls, product_id): - file = IfcStore.get_file() + def load(cls, file, product_id): if not file: return cls.products[product_id] = [] diff --git a/src/ifcblenderexport/blenderbim/bim/module/geometry/edit_object_placement.py b/src/ifcopenshell-python/ifcopenshell/api/geometry/edit_object_placement.py similarity index 95% rename from src/ifcblenderexport/blenderbim/bim/module/geometry/edit_object_placement.py rename to src/ifcopenshell-python/ifcopenshell/api/geometry/edit_object_placement.py index 97070ec8ad..1a5f205956 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/geometry/edit_object_placement.py +++ b/src/ifcopenshell-python/ifcopenshell/api/geometry/edit_object_placement.py @@ -1,10 +1,11 @@ import numpy as np +import ifcopenshell.api import ifcopenshell.util.element import ifcopenshell.util.placement class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = {"product": None, "matrix": np.eye(4)} for key, value in settings.items(): @@ -46,6 +47,8 @@ class Usecase: ifcopenshell.util.element.remove_deep(self.file, old) self.settings["product"].ObjectPlacement = placement + ifcopenshell.api.run("owner.update_owner_history", self.file, **{"element": self.settings["product"]}) + for settings in dependent_objects: self.settings = settings self.execute() diff --git a/src/ifcblenderexport/blenderbim/bim/module/geometry/map_representation.py b/src/ifcopenshell-python/ifcopenshell/api/geometry/map_representation.py similarity index 96% rename from src/ifcblenderexport/blenderbim/bim/module/geometry/map_representation.py rename to src/ifcopenshell-python/ifcopenshell/api/geometry/map_representation.py index 58b3218c99..933f0f1ee4 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/geometry/map_representation.py +++ b/src/ifcopenshell-python/ifcopenshell/api/geometry/map_representation.py @@ -1,5 +1,5 @@ class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = {"representation": None} self.ifc_vertices = [] diff --git a/src/ifcblenderexport/blenderbim/bim/module/geometry/remove_representation.py b/src/ifcopenshell-python/ifcopenshell/api/geometry/remove_representation.py similarity index 97% rename from src/ifcblenderexport/blenderbim/bim/module/geometry/remove_representation.py rename to src/ifcopenshell-python/ifcopenshell/api/geometry/remove_representation.py index 2d8e95ef33..cad9044db3 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/geometry/remove_representation.py +++ b/src/ifcopenshell-python/ifcopenshell/api/geometry/remove_representation.py @@ -2,7 +2,7 @@ import ifcopenshell.util.element class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = {"representation": None} for key, value in settings.items(): diff --git a/src/ifcblenderexport/blenderbim/bim/module/geometry/unassign_representation.py b/src/ifcopenshell-python/ifcopenshell/api/geometry/unassign_representation.py similarity index 92% rename from src/ifcblenderexport/blenderbim/bim/module/geometry/unassign_representation.py rename to src/ifcopenshell-python/ifcopenshell/api/geometry/unassign_representation.py index ec99e71772..579b0c0a7c 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/geometry/unassign_representation.py +++ b/src/ifcopenshell-python/ifcopenshell/api/geometry/unassign_representation.py @@ -1,9 +1,9 @@ -import blenderbim.bim.module.geometry.remove_representation as remove_representation +import ifcopenshell.api import ifcopenshell.util.element class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = {"product": None, "representation": None} for key, value in settings.items(): @@ -53,4 +53,4 @@ class Usecase: for item in mapped_representations: self.unassign_product_representation(item["product"], item["representation"]) for representation in just_representations: - remove_representation.Usecase(self.file, {"representation": representation}).execute() + ifcopenshell.api.run("owner.remove_representation", self.file, **{"representation": representation}) diff --git a/src/ifcblenderexport/blenderbim/bim/module/georeference/add_georeferencing.py b/src/ifcopenshell-python/ifcopenshell/api/georeference/add_georeferencing.py similarity index 93% rename from src/ifcblenderexport/blenderbim/bim/module/georeference/add_georeferencing.py rename to src/ifcopenshell-python/ifcopenshell/api/georeference/add_georeferencing.py index 6979fdca09..4d31164426 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/georeference/add_georeferencing.py +++ b/src/ifcopenshell-python/ifcopenshell/api/georeference/add_georeferencing.py @@ -1,5 +1,5 @@ class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file def execute(self): diff --git a/src/ifcblenderexport/blenderbim/bim/module/georeference/data.py b/src/ifcopenshell-python/ifcopenshell/api/georeference/data.py similarity index 91% rename from src/ifcblenderexport/blenderbim/bim/module/georeference/data.py rename to src/ifcopenshell-python/ifcopenshell/api/georeference/data.py index b6efe005db..b8d029b2be 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/georeference/data.py +++ b/src/ifcopenshell-python/ifcopenshell/api/georeference/data.py @@ -1,6 +1,3 @@ -from blenderbim.bim.ifc import IfcStore - - class Data: is_loaded = False map_conversion = {} @@ -13,8 +10,7 @@ class Data: cls.projected_crs = {} @classmethod - def load(cls): - file = IfcStore.get_file() + def load(cls, file): if not file: return cls.map_conversion = {} diff --git a/src/ifcblenderexport/blenderbim/bim/module/georeference/edit_georeferencing.py b/src/ifcopenshell-python/ifcopenshell/api/georeference/edit_georeferencing.py similarity index 97% rename from src/ifcblenderexport/blenderbim/bim/module/georeference/edit_georeferencing.py rename to src/ifcopenshell-python/ifcopenshell/api/georeference/edit_georeferencing.py index 8e21d061f5..aafe61dd83 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/georeference/edit_georeferencing.py +++ b/src/ifcopenshell-python/ifcopenshell/api/georeference/edit_georeferencing.py @@ -2,7 +2,7 @@ import ifcopenshell.util.unit class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = { "map_conversion": {}, diff --git a/src/ifcblenderexport/blenderbim/bim/module/georeference/remove_georeferencing.py b/src/ifcopenshell-python/ifcopenshell/api/georeference/remove_georeferencing.py similarity index 91% rename from src/ifcblenderexport/blenderbim/bim/module/georeference/remove_georeferencing.py rename to src/ifcopenshell-python/ifcopenshell/api/georeference/remove_georeferencing.py index 4b57823afb..d06df550db 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/georeference/remove_georeferencing.py +++ b/src/ifcopenshell-python/ifcopenshell/api/georeference/remove_georeferencing.py @@ -1,5 +1,5 @@ class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file def execute(self): diff --git a/src/ifcblenderexport/blenderbim/bim/module/grid/create_axis_curve.py b/src/ifcopenshell-python/ifcopenshell/api/grid/create_axis_curve.py similarity index 97% rename from src/ifcblenderexport/blenderbim/bim/module/grid/create_axis_curve.py rename to src/ifcopenshell-python/ifcopenshell/api/grid/create_axis_curve.py index 009e405f6e..9de1815b3e 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/grid/create_axis_curve.py +++ b/src/ifcopenshell-python/ifcopenshell/api/grid/create_axis_curve.py @@ -5,7 +5,7 @@ from mathutils import Matrix # For now, we depend on Blender class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = { "AxisCurve": None, # A Blender object diff --git a/src/ifcblenderexport/blenderbim/bim/module/grid/create_grid_axis.py b/src/ifcopenshell-python/ifcopenshell/api/grid/create_grid_axis.py similarity index 93% rename from src/ifcblenderexport/blenderbim/bim/module/grid/create_grid_axis.py rename to src/ifcopenshell-python/ifcopenshell/api/grid/create_grid_axis.py index 979ededc75..6a98a6fc59 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/grid/create_grid_axis.py +++ b/src/ifcopenshell-python/ifcopenshell/api/grid/create_grid_axis.py @@ -1,5 +1,5 @@ class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = { "AxisTag": "A", diff --git a/src/ifcblenderexport/blenderbim/bim/module/group/add_group.py b/src/ifcopenshell-python/ifcopenshell/api/group/add_group.py similarity index 68% rename from src/ifcblenderexport/blenderbim/bim/module/group/add_group.py rename to src/ifcopenshell-python/ifcopenshell/api/group/add_group.py index 7a7559bd91..1a35093ff0 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/group/add_group.py +++ b/src/ifcopenshell-python/ifcopenshell/api/group/add_group.py @@ -1,9 +1,9 @@ import ifcopenshell -from blenderbim.bim.module.owner.api import create_owner_history +import ifcopenshell.api class Usecase: - def __init__(self, file, settings={}): + def __init__(self, file, **settings): self.file = file self.settings = {} for key, value in settings.items(): @@ -12,6 +12,6 @@ class Usecase: def execute(self): return self.file.create_entity("IfcGroup", **{ "GlobalId": ifcopenshell.guid.new(), - "OwnerHistory": create_owner_history(), + "OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", self.file), "Name": "Unnamed" }) diff --git a/src/ifcblenderexport/blenderbim/bim/module/group/assign_group.py b/src/ifcopenshell-python/ifcopenshell/api/group/assign_group.py similarity index 74% rename from src/ifcblenderexport/blenderbim/bim/module/group/assign_group.py rename to src/ifcopenshell-python/ifcopenshell/api/group/assign_group.py index 99b4e8308a..34bf010531 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/group/assign_group.py +++ b/src/ifcopenshell-python/ifcopenshell/api/group/assign_group.py @@ -1,10 +1,9 @@ import ifcopenshell -from blenderbim.bim.module.owner.api import create_owner_history -from blenderbim.bim.module.owner.api import update_owner_history +import ifcopenshell.api class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = { "product": None, @@ -17,7 +16,7 @@ class Usecase: if not self.settings["group"].IsGroupedBy: return self.file.create_entity("IfcRelAssignsToGroup", **{ "GlobalId": ifcopenshell.guid.new(), - "OwnerHistory": create_owner_history(), + "OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", self.file), "RelatedObjects": [self.settings["product"]], "RelatingGroup": self.settings["group"] }) @@ -25,4 +24,4 @@ class Usecase: related_objects = set(rel.RelatedObjects) or set() related_objects.add(self.settings["product"]) rel.RelatedObjects = list(related_objects) - update_owner_history(rel) + ifcopenshell.api.run("owner.update_owner_history", self.file, **{"element": rel}) diff --git a/src/ifcblenderexport/blenderbim/bim/module/group/data.py b/src/ifcopenshell-python/ifcopenshell/api/group/data.py similarity index 80% rename from src/ifcblenderexport/blenderbim/bim/module/group/data.py rename to src/ifcopenshell-python/ifcopenshell/api/group/data.py index 0524bb3501..bcfffbe5b2 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/group/data.py +++ b/src/ifcopenshell-python/ifcopenshell/api/group/data.py @@ -1,6 +1,3 @@ -from blenderbim.bim.ifc import IfcStore - - class Data: is_loaded = False products = {} @@ -13,10 +10,10 @@ class Data: cls.groups = {} @classmethod - def load(cls): + def load(cls, file): cls.products = {} cls.groups = {} - for group in IfcStore.get_file().by_type("IfcGroup", include_subtypes=False): + for group in file.by_type("IfcGroup", include_subtypes=False): if group.IsGroupedBy: for rel in group.IsGroupedBy: for product in rel.RelatedObjects: diff --git a/src/ifcblenderexport/blenderbim/bim/module/group/edit_group.py b/src/ifcopenshell-python/ifcopenshell/api/group/edit_group.py similarity index 88% rename from src/ifcblenderexport/blenderbim/bim/module/group/edit_group.py rename to src/ifcopenshell-python/ifcopenshell/api/group/edit_group.py index 584fb7f091..1111ce7f35 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/group/edit_group.py +++ b/src/ifcopenshell-python/ifcopenshell/api/group/edit_group.py @@ -1,5 +1,5 @@ class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = { "group": None, diff --git a/src/ifcblenderexport/blenderbim/bim/module/group/remove_group.py b/src/ifcopenshell-python/ifcopenshell/api/group/remove_group.py similarity index 88% rename from src/ifcblenderexport/blenderbim/bim/module/group/remove_group.py rename to src/ifcopenshell-python/ifcopenshell/api/group/remove_group.py index 6acddf7b10..9ead307c68 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/group/remove_group.py +++ b/src/ifcopenshell-python/ifcopenshell/api/group/remove_group.py @@ -1,5 +1,5 @@ class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = {"group": None} for key, value in settings.items(): diff --git a/src/ifcblenderexport/blenderbim/bim/module/group/unassign_group.py b/src/ifcopenshell-python/ifcopenshell/api/group/unassign_group.py similarity index 79% rename from src/ifcblenderexport/blenderbim/bim/module/group/unassign_group.py rename to src/ifcopenshell-python/ifcopenshell/api/group/unassign_group.py index 84ffbcec39..7ec1b74c41 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/group/unassign_group.py +++ b/src/ifcopenshell-python/ifcopenshell/api/group/unassign_group.py @@ -1,9 +1,9 @@ import ifcopenshell -from blenderbim.bim.module.owner.api import update_owner_history +import ifcopenshell.api class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = { "product": None, @@ -20,6 +20,6 @@ class Usecase: related_objects.remove(self.settings["product"]) if len(related_objects): rel.RelatedObjects = list(related_objects) - update_owner_history(rel) + ifcopenshell.api.run("owner.update_owner_history", self.file, **{"element": rel}) else: self.file.remove(rel) diff --git a/src/ifcblenderexport/blenderbim/bim/module/layer/add_layer.py b/src/ifcopenshell-python/ifcopenshell/api/layer/add_layer.py similarity index 87% rename from src/ifcblenderexport/blenderbim/bim/module/layer/add_layer.py rename to src/ifcopenshell-python/ifcopenshell/api/layer/add_layer.py index 03a16945ee..edfe94275a 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/layer/add_layer.py +++ b/src/ifcopenshell-python/ifcopenshell/api/layer/add_layer.py @@ -1,5 +1,5 @@ class Usecase: - def __init__(self, file, settings={}): + def __init__(self, file, **settings): self.file = file self.settings = {} for key, value in settings.items(): diff --git a/src/ifcblenderexport/blenderbim/bim/module/layer/assign_layer.py b/src/ifcopenshell-python/ifcopenshell/api/layer/assign_layer.py similarity index 90% rename from src/ifcblenderexport/blenderbim/bim/module/layer/assign_layer.py rename to src/ifcopenshell-python/ifcopenshell/api/layer/assign_layer.py index e433de6715..66fb65a748 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/layer/assign_layer.py +++ b/src/ifcopenshell-python/ifcopenshell/api/layer/assign_layer.py @@ -2,7 +2,7 @@ import ifcopenshell class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = { "item": None, diff --git a/src/ifcblenderexport/blenderbim/bim/module/layer/data.py b/src/ifcopenshell-python/ifcopenshell/api/layer/data.py similarity index 89% rename from src/ifcblenderexport/blenderbim/bim/module/layer/data.py rename to src/ifcopenshell-python/ifcopenshell/api/layer/data.py index c77a91dcad..6bb53498e2 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/layer/data.py +++ b/src/ifcopenshell-python/ifcopenshell/api/layer/data.py @@ -1,6 +1,5 @@ import ifcopenshell import ifcopenshell.util.date -from blenderbim.bim.ifc import IfcStore from datetime import datetime @@ -16,8 +15,8 @@ class Data: cls.layers = {} @classmethod - def load(cls): - cls._file = IfcStore.get_file() + def load(cls, file): + cls._file = file if not cls._file: return cls.load_layers() diff --git a/src/ifcblenderexport/blenderbim/bim/module/layer/edit_layer.py b/src/ifcopenshell-python/ifcopenshell/api/layer/edit_layer.py similarity index 88% rename from src/ifcblenderexport/blenderbim/bim/module/layer/edit_layer.py rename to src/ifcopenshell-python/ifcopenshell/api/layer/edit_layer.py index a07d90cd0f..0c2da2e637 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/layer/edit_layer.py +++ b/src/ifcopenshell-python/ifcopenshell/api/layer/edit_layer.py @@ -1,5 +1,5 @@ class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = { "layer": None, diff --git a/src/ifcblenderexport/blenderbim/bim/module/layer/remove_layer.py b/src/ifcopenshell-python/ifcopenshell/api/layer/remove_layer.py similarity index 83% rename from src/ifcblenderexport/blenderbim/bim/module/layer/remove_layer.py rename to src/ifcopenshell-python/ifcopenshell/api/layer/remove_layer.py index 005ff1fec6..88bd925292 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/layer/remove_layer.py +++ b/src/ifcopenshell-python/ifcopenshell/api/layer/remove_layer.py @@ -1,5 +1,5 @@ class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = {"layer": None} for key, value in settings.items(): diff --git a/src/ifcblenderexport/blenderbim/bim/module/layer/unassign_layer.py b/src/ifcopenshell-python/ifcopenshell/api/layer/unassign_layer.py similarity index 91% rename from src/ifcblenderexport/blenderbim/bim/module/layer/unassign_layer.py rename to src/ifcopenshell-python/ifcopenshell/api/layer/unassign_layer.py index 33584f7ccc..9803ea2a13 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/layer/unassign_layer.py +++ b/src/ifcopenshell-python/ifcopenshell/api/layer/unassign_layer.py @@ -2,7 +2,7 @@ import ifcopenshell class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = { "item": None, diff --git a/src/ifcblenderexport/blenderbim/bim/module/material/add_constituent.py b/src/ifcopenshell-python/ifcopenshell/api/material/add_constituent.py similarity index 92% rename from src/ifcblenderexport/blenderbim/bim/module/material/add_constituent.py rename to src/ifcopenshell-python/ifcopenshell/api/material/add_constituent.py index e22431aa63..f91dda0980 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/material/add_constituent.py +++ b/src/ifcopenshell-python/ifcopenshell/api/material/add_constituent.py @@ -2,7 +2,7 @@ import ifcopenshell class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = {"constituent_set": None, "material": None} for key, value in settings.items(): diff --git a/src/ifcblenderexport/blenderbim/bim/module/material/add_layer.py b/src/ifcopenshell-python/ifcopenshell/api/material/add_layer.py similarity index 92% rename from src/ifcblenderexport/blenderbim/bim/module/material/add_layer.py rename to src/ifcopenshell-python/ifcopenshell/api/material/add_layer.py index 19b0da8ee2..b5cb426eb9 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/material/add_layer.py +++ b/src/ifcopenshell-python/ifcopenshell/api/material/add_layer.py @@ -2,7 +2,7 @@ import ifcopenshell class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = {"layer_set": None, "material": None} for key, value in settings.items(): diff --git a/src/ifcblenderexport/blenderbim/bim/module/material/add_list_item.py b/src/ifcopenshell-python/ifcopenshell/api/material/add_list_item.py similarity index 90% rename from src/ifcblenderexport/blenderbim/bim/module/material/add_list_item.py rename to src/ifcopenshell-python/ifcopenshell/api/material/add_list_item.py index db020647c9..9c52d74fc7 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/material/add_list_item.py +++ b/src/ifcopenshell-python/ifcopenshell/api/material/add_list_item.py @@ -2,7 +2,7 @@ import ifcopenshell class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = {"material_list": None, "material": None} for key, value in settings.items(): diff --git a/src/ifcblenderexport/blenderbim/bim/module/material/add_material.py b/src/ifcopenshell-python/ifcopenshell/api/material/add_material.py similarity index 87% rename from src/ifcblenderexport/blenderbim/bim/module/material/add_material.py rename to src/ifcopenshell-python/ifcopenshell/api/material/add_material.py index 94184b3d8e..48ee7b4511 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/material/add_material.py +++ b/src/ifcopenshell-python/ifcopenshell/api/material/add_material.py @@ -2,7 +2,7 @@ import ifcopenshell class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = {"Name": "Unnamed"} for key, value in settings.items(): diff --git a/src/ifcblenderexport/blenderbim/bim/module/material/assign_material.py b/src/ifcopenshell-python/ifcopenshell/api/material/assign_material.py similarity index 98% rename from src/ifcblenderexport/blenderbim/bim/module/material/assign_material.py rename to src/ifcopenshell-python/ifcopenshell/api/material/assign_material.py index 766f690774..f7fc4be564 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/material/assign_material.py +++ b/src/ifcopenshell-python/ifcopenshell/api/material/assign_material.py @@ -2,7 +2,7 @@ import ifcopenshell class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = {"product": None, "type": "IfcMaterial", "material": None} for key, value in settings.items(): diff --git a/src/ifcblenderexport/blenderbim/bim/module/material/data.py b/src/ifcopenshell-python/ifcopenshell/api/material/data.py similarity index 96% rename from src/ifcblenderexport/blenderbim/bim/module/material/data.py rename to src/ifcopenshell-python/ifcopenshell/api/material/data.py index 26321ee2a3..1c39d5b20f 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/material/data.py +++ b/src/ifcopenshell-python/ifcopenshell/api/material/data.py @@ -1,5 +1,4 @@ import ifcopenshell -from blenderbim.bim.ifc import IfcStore class Data: @@ -31,8 +30,8 @@ class Data: cls._file = None @classmethod - def load(cls, product_id=None): - cls._file = IfcStore.get_file() + def load(cls, file, product_id=None): + cls._file = file if not cls._file: return if product_id: diff --git a/src/ifcblenderexport/blenderbim/bim/module/material/edit_assigned_material.py b/src/ifcopenshell-python/ifcopenshell/api/material/edit_assigned_material.py similarity index 89% rename from src/ifcblenderexport/blenderbim/bim/module/material/edit_assigned_material.py rename to src/ifcopenshell-python/ifcopenshell/api/material/edit_assigned_material.py index f74956736d..f8dca15b0e 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/material/edit_assigned_material.py +++ b/src/ifcopenshell-python/ifcopenshell/api/material/edit_assigned_material.py @@ -1,5 +1,5 @@ class Usecase(): - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = { "element": None, diff --git a/src/ifcblenderexport/blenderbim/bim/module/material/edit_constituent.py b/src/ifcopenshell-python/ifcopenshell/api/material/edit_constituent.py similarity index 91% rename from src/ifcblenderexport/blenderbim/bim/module/material/edit_constituent.py rename to src/ifcopenshell-python/ifcopenshell/api/material/edit_constituent.py index c6c2d24749..3ba02305d1 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/material/edit_constituent.py +++ b/src/ifcopenshell-python/ifcopenshell/api/material/edit_constituent.py @@ -1,5 +1,5 @@ class Usecase(): - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = { "constituent": None, diff --git a/src/ifcblenderexport/blenderbim/bim/module/material/edit_layer.py b/src/ifcopenshell-python/ifcopenshell/api/material/edit_layer.py similarity index 91% rename from src/ifcblenderexport/blenderbim/bim/module/material/edit_layer.py rename to src/ifcopenshell-python/ifcopenshell/api/material/edit_layer.py index 440e5e9fa4..fa4fdffca2 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/material/edit_layer.py +++ b/src/ifcopenshell-python/ifcopenshell/api/material/edit_layer.py @@ -1,5 +1,5 @@ class Usecase(): - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = { "layer": None, diff --git a/src/ifcblenderexport/blenderbim/bim/module/material/edit_profile.py b/src/ifcopenshell-python/ifcopenshell/api/material/edit_profile.py similarity index 91% rename from src/ifcblenderexport/blenderbim/bim/module/material/edit_profile.py rename to src/ifcopenshell-python/ifcopenshell/api/material/edit_profile.py index c41a5152f7..f833922d30 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/material/edit_profile.py +++ b/src/ifcopenshell-python/ifcopenshell/api/material/edit_profile.py @@ -1,5 +1,5 @@ class Usecase(): - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = { "profile": None, diff --git a/src/ifcblenderexport/blenderbim/bim/module/material/remove_constituent.py b/src/ifcopenshell-python/ifcopenshell/api/material/remove_constituent.py similarity index 85% rename from src/ifcblenderexport/blenderbim/bim/module/material/remove_constituent.py rename to src/ifcopenshell-python/ifcopenshell/api/material/remove_constituent.py index 84d930bb52..9c66ae6afc 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/material/remove_constituent.py +++ b/src/ifcopenshell-python/ifcopenshell/api/material/remove_constituent.py @@ -2,7 +2,7 @@ import ifcopenshell class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = {"constituent": None} for key, value in settings.items(): diff --git a/src/ifcblenderexport/blenderbim/bim/module/material/remove_layer.py b/src/ifcopenshell-python/ifcopenshell/api/material/remove_layer.py similarity index 85% rename from src/ifcblenderexport/blenderbim/bim/module/material/remove_layer.py rename to src/ifcopenshell-python/ifcopenshell/api/material/remove_layer.py index 09740f8eb8..d953c56a25 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/material/remove_layer.py +++ b/src/ifcopenshell-python/ifcopenshell/api/material/remove_layer.py @@ -2,7 +2,7 @@ import ifcopenshell class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = {"layer": None} for key, value in settings.items(): diff --git a/src/ifcblenderexport/blenderbim/bim/module/material/remove_list_item.py b/src/ifcopenshell-python/ifcopenshell/api/material/remove_list_item.py similarity index 89% rename from src/ifcblenderexport/blenderbim/bim/module/material/remove_list_item.py rename to src/ifcopenshell-python/ifcopenshell/api/material/remove_list_item.py index 741cf44149..6cafec8420 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/material/remove_list_item.py +++ b/src/ifcopenshell-python/ifcopenshell/api/material/remove_list_item.py @@ -2,7 +2,7 @@ import ifcopenshell class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = {"material_list": None, "material": None} for key, value in settings.items(): diff --git a/src/ifcblenderexport/blenderbim/bim/module/material/remove_material.py b/src/ifcopenshell-python/ifcopenshell/api/material/remove_material.py similarity index 94% rename from src/ifcblenderexport/blenderbim/bim/module/material/remove_material.py rename to src/ifcopenshell-python/ifcopenshell/api/material/remove_material.py index 0cbcf804e8..39ed5c0a68 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/material/remove_material.py +++ b/src/ifcopenshell-python/ifcopenshell/api/material/remove_material.py @@ -2,7 +2,7 @@ import ifcopenshell class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = {"material": None} for key, value in settings.items(): diff --git a/src/ifcblenderexport/blenderbim/bim/module/material/reorder_set_item.py b/src/ifcopenshell-python/ifcopenshell/api/material/reorder_set_item.py similarity index 95% rename from src/ifcblenderexport/blenderbim/bim/module/material/reorder_set_item.py rename to src/ifcopenshell-python/ifcopenshell/api/material/reorder_set_item.py index c4f15373fc..a4b722c6a5 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/material/reorder_set_item.py +++ b/src/ifcopenshell-python/ifcopenshell/api/material/reorder_set_item.py @@ -1,5 +1,5 @@ class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = {"material_set": None, "old_index": 0, "new_index": 0} for key, value in settings.items(): diff --git a/src/ifcblenderexport/blenderbim/bim/module/material/unassign_material.py b/src/ifcopenshell-python/ifcopenshell/api/material/unassign_material.py similarity index 89% rename from src/ifcblenderexport/blenderbim/bim/module/material/unassign_material.py rename to src/ifcopenshell-python/ifcopenshell/api/material/unassign_material.py index a02c548502..8a6fad3b53 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/material/unassign_material.py +++ b/src/ifcopenshell-python/ifcopenshell/api/material/unassign_material.py @@ -2,7 +2,7 @@ import ifcopenshell class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = {"product": None} for key, value in settings.items(): diff --git a/src/ifcblenderexport/blenderbim/bim/module/owner/add_address.py b/src/ifcopenshell-python/ifcopenshell/api/owner/add_address.py similarity index 91% rename from src/ifcblenderexport/blenderbim/bim/module/owner/add_address.py rename to src/ifcopenshell-python/ifcopenshell/api/owner/add_address.py index 26beaeb9cb..14d2a48fac 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/owner/add_address.py +++ b/src/ifcopenshell-python/ifcopenshell/api/owner/add_address.py @@ -1,5 +1,5 @@ class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = {"assigned_object": None, "ifc_class": "IfcPostalAddress"} for key, value in settings.items(): diff --git a/src/ifcopenshell-python/ifcopenshell/api/owner/add_organisation.py b/src/ifcopenshell-python/ifcopenshell/api/owner/add_organisation.py new file mode 100644 index 0000000000..6635fdcb8a --- /dev/null +++ b/src/ifcopenshell-python/ifcopenshell/api/owner/add_organisation.py @@ -0,0 +1,12 @@ +class Usecase: + def __init__(self, file, **settings): + self.file = file + self.settings = { + "Identification": "APTR", + "Name": "Aperture Science", + } + for key, value in settings.items(): + self.settings[key] = value + + def execute(self): + return self.file.create_entity("IfcOrganization", **self.settings) diff --git a/src/ifcopenshell-python/ifcopenshell/api/owner/add_person.py b/src/ifcopenshell-python/ifcopenshell/api/owner/add_person.py new file mode 100644 index 0000000000..f136af8d16 --- /dev/null +++ b/src/ifcopenshell-python/ifcopenshell/api/owner/add_person.py @@ -0,0 +1,13 @@ +class Usecase: + def __init__(self, file, **settings): + self.file = file + self.settings = { + "Identification": "HSeldon", + "FamilyName": "Seldon", + "GivenName": "Hari", + } + for key, value in settings.items(): + self.settings[key] = value + + def execute(self): + return self.file.create_entity("IfcPerson", **self.settings) diff --git a/src/ifcblenderexport/blenderbim/bim/module/owner/add_role.py b/src/ifcopenshell-python/ifcopenshell/api/owner/add_role.py similarity index 90% rename from src/ifcblenderexport/blenderbim/bim/module/owner/add_role.py rename to src/ifcopenshell-python/ifcopenshell/api/owner/add_role.py index dfbe523db9..a934f927bb 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/owner/add_role.py +++ b/src/ifcopenshell-python/ifcopenshell/api/owner/add_role.py @@ -1,5 +1,5 @@ class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = {"assigned_object": None} for key, value in settings.items(): diff --git a/src/ifcopenshell-python/ifcopenshell/api/owner/create_owner_history.py b/src/ifcopenshell-python/ifcopenshell/api/owner/create_owner_history.py new file mode 100644 index 0000000000..fb5561390a --- /dev/null +++ b/src/ifcopenshell-python/ifcopenshell/api/owner/create_owner_history.py @@ -0,0 +1,45 @@ +import time +import ifcopenshell +import ifcopenshell.api.owner.settings + + +class Usecase: + def __init__(self, file, **settings): + self.file = file + self.settings = {} + for key, value in settings.items(): + self.settings[key] = value + + def execute(self): + self.settings["person"] = ifcopenshell.api.owner.settings.get_person(self.file) + self.settings["organisation"] = ifcopenshell.api.owner.settings.get_organisation(self.file) + if self.file.schema != "IFC2X3": + if not self.settings["person"] or not self.settings["organisation"]: + return + user = self.get_user() + application = ifcopenshell.api.owner.settings.get_application(self.file) + return self.file.create_entity( + "IfcOwnerHistory", + **{ + "OwningUser": user, + "OwningApplication": application, + "State": "READWRITE", + "ChangeAction": "ADDED", + "LastModifiedDate": int(time.time()), + "LastModifyingUser": user, + "LastModifyingApplication": application, + "CreationDate": int(time.time()), + }, + ) + + def get_user(self): + for element in self.file.by_type("IfcPersonAndOrganization"): + if ( + element.ThePerson == self.settings["person"] + and element.TheOrganization == self.settings["organisation"] + ): + return element + return self.file.create_entity( + "IfcPersonAndOrganization", + **{"ThePerson": self.settings["person"], "TheOrganization": self.settings["organisation"]}, + ) diff --git a/src/ifcblenderexport/blenderbim/bim/module/owner/data.py b/src/ifcopenshell-python/ifcopenshell/api/owner/data.py similarity index 95% rename from src/ifcblenderexport/blenderbim/bim/module/owner/data.py rename to src/ifcopenshell-python/ifcopenshell/api/owner/data.py index 290becd1dd..d4aa5a3b4d 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/owner/data.py +++ b/src/ifcopenshell-python/ifcopenshell/api/owner/data.py @@ -1,6 +1,3 @@ -from blenderbim.bim.ifc import IfcStore - - class Data: is_loaded = False people = {} @@ -17,8 +14,7 @@ class Data: cls.roles = {} @classmethod - def load(cls): - file = IfcStore.get_file() + def load(cls, file): if not file: return cls.people = {} diff --git a/src/ifcblenderexport/blenderbim/bim/module/owner/edit_address.py b/src/ifcopenshell-python/ifcopenshell/api/owner/edit_address.py similarity index 88% rename from src/ifcblenderexport/blenderbim/bim/module/owner/edit_address.py rename to src/ifcopenshell-python/ifcopenshell/api/owner/edit_address.py index fcc14d455f..4abb9d5542 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/owner/edit_address.py +++ b/src/ifcopenshell-python/ifcopenshell/api/owner/edit_address.py @@ -1,5 +1,5 @@ class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = { "address": None, diff --git a/src/ifcblenderexport/blenderbim/bim/module/owner/edit_organisation.py b/src/ifcopenshell-python/ifcopenshell/api/owner/edit_organisation.py similarity index 89% rename from src/ifcblenderexport/blenderbim/bim/module/owner/edit_organisation.py rename to src/ifcopenshell-python/ifcopenshell/api/owner/edit_organisation.py index 661c29c022..c9705ac7cb 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/owner/edit_organisation.py +++ b/src/ifcopenshell-python/ifcopenshell/api/owner/edit_organisation.py @@ -1,5 +1,5 @@ class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = { "organisation": None, diff --git a/src/ifcblenderexport/blenderbim/bim/module/owner/edit_person.py b/src/ifcopenshell-python/ifcopenshell/api/owner/edit_person.py similarity index 88% rename from src/ifcblenderexport/blenderbim/bim/module/owner/edit_person.py rename to src/ifcopenshell-python/ifcopenshell/api/owner/edit_person.py index afeaa9b429..f8f96afe94 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/owner/edit_person.py +++ b/src/ifcopenshell-python/ifcopenshell/api/owner/edit_person.py @@ -1,5 +1,5 @@ class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = { "person": None, diff --git a/src/ifcblenderexport/blenderbim/bim/module/owner/edit_role.py b/src/ifcopenshell-python/ifcopenshell/api/owner/edit_role.py similarity index 88% rename from src/ifcblenderexport/blenderbim/bim/module/owner/edit_role.py rename to src/ifcopenshell-python/ifcopenshell/api/owner/edit_role.py index f081a850f7..fda91bee32 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/owner/edit_role.py +++ b/src/ifcopenshell-python/ifcopenshell/api/owner/edit_role.py @@ -1,5 +1,5 @@ class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = { "role": None, diff --git a/src/ifcblenderexport/blenderbim/bim/module/owner/remove_address.py b/src/ifcopenshell-python/ifcopenshell/api/owner/remove_address.py similarity index 84% rename from src/ifcblenderexport/blenderbim/bim/module/owner/remove_address.py rename to src/ifcopenshell-python/ifcopenshell/api/owner/remove_address.py index 9891d04062..2362f4a24d 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/owner/remove_address.py +++ b/src/ifcopenshell-python/ifcopenshell/api/owner/remove_address.py @@ -1,5 +1,5 @@ class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = {"address": None} for key, value in settings.items(): diff --git a/src/ifcblenderexport/blenderbim/bim/module/owner/remove_organisation.py b/src/ifcopenshell-python/ifcopenshell/api/owner/remove_organisation.py similarity index 84% rename from src/ifcblenderexport/blenderbim/bim/module/owner/remove_organisation.py rename to src/ifcopenshell-python/ifcopenshell/api/owner/remove_organisation.py index 567ea52d99..0287a9c5e5 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/owner/remove_organisation.py +++ b/src/ifcopenshell-python/ifcopenshell/api/owner/remove_organisation.py @@ -1,5 +1,5 @@ class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = {"organisation": None} for key, value in settings.items(): diff --git a/src/ifcblenderexport/blenderbim/bim/module/owner/remove_person.py b/src/ifcopenshell-python/ifcopenshell/api/owner/remove_person.py similarity index 84% rename from src/ifcblenderexport/blenderbim/bim/module/owner/remove_person.py rename to src/ifcopenshell-python/ifcopenshell/api/owner/remove_person.py index f9e4a6e9fe..66a88d783f 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/owner/remove_person.py +++ b/src/ifcopenshell-python/ifcopenshell/api/owner/remove_person.py @@ -1,5 +1,5 @@ class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = {"person": None} for key, value in settings.items(): diff --git a/src/ifcblenderexport/blenderbim/bim/module/owner/remove_role.py b/src/ifcopenshell-python/ifcopenshell/api/owner/remove_role.py similarity index 83% rename from src/ifcblenderexport/blenderbim/bim/module/owner/remove_role.py rename to src/ifcopenshell-python/ifcopenshell/api/owner/remove_role.py index 446d0e7a39..2218616a44 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/owner/remove_role.py +++ b/src/ifcopenshell-python/ifcopenshell/api/owner/remove_role.py @@ -1,5 +1,5 @@ class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = {"role": None} for key, value in settings.items(): diff --git a/src/ifcopenshell-python/ifcopenshell/api/owner/settings.py b/src/ifcopenshell-python/ifcopenshell/api/owner/settings.py new file mode 100644 index 0000000000..f87f34a3aa --- /dev/null +++ b/src/ifcopenshell-python/ifcopenshell/api/owner/settings.py @@ -0,0 +1,10 @@ +def get_person(ifc): + pass + + +def get_organisation(ifc): + pass + + +def get_application(ifc): + pass diff --git a/src/ifcopenshell-python/ifcopenshell/api/owner/update_owner_history.py b/src/ifcopenshell-python/ifcopenshell/api/owner/update_owner_history.py new file mode 100644 index 0000000000..79e9283947 --- /dev/null +++ b/src/ifcopenshell-python/ifcopenshell/api/owner/update_owner_history.py @@ -0,0 +1,44 @@ +import time +import ifcopenshell +import ifcopenshell.api + + +class Usecase: + def __init__(self, file, **settings): + self.file = file + self.settings = {} + for key, value in settings.items(): + self.settings[key] = value + + def execute(self): + self.settings["person"] = ifcopenshell.api.owner.settings.get_person(self.file) + self.settings["organisation"] = ifcopenshell.api.owner.settings.get_organisation(self.file) + if not self.settings["element"].OwnerHistory: + self.settings["element"].OwnerHistory = ifcopenshell.api.run( + "owner.create_owner_history", self.file, **self.settings + ) + return self.settings["element"].OwnerHistory + if len(self.file.get_inverse(self.settings["element"].OwnerHistory)) > 1: + old_history = self.settings["element"].OwnerHistory + self.settings["element"].OwnerHistory = self.file.create_entity("IfcOwnerHistory") + for i, attribute in enumerate(old_history): + self.settings["element"].OwnerHistory[i] = attribute + user = self.get_user() + application = ifcopenshell.api.owner.settings.get_application(self.file) + self.settings["element"].OwnerHistory.ChangeAction = "MODIFIED" + self.settings["element"].OwnerHistory.LastModifiedDate = int(time.time()) + self.settings["element"].OwnerHistory.LastModifyingUser = user + self.settings["element"].OwnerHistory.LastModifyingApplication = application + return self.settings["element"].OwnerHistory + + def get_user(self): + for element in self.file.by_type("IfcPersonAndOrganization"): + if ( + element.ThePerson == self.settings["person"] + and element.TheOrganization == self.settings["organisation"] + ): + return element + return self.file.create_entity( + "IfcPersonAndOrganization", + **{"ThePerson": self.settings["person"], "TheOrganization": self.settings["organisation"]}, + ) diff --git a/src/ifcblenderexport/blenderbim/bim/module/project/create_file.py b/src/ifcopenshell-python/ifcopenshell/api/project/create_file.py similarity index 96% rename from src/ifcblenderexport/blenderbim/bim/module/project/create_file.py rename to src/ifcopenshell-python/ifcopenshell/api/project/create_file.py index e4e442f75c..9e4fd31796 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/project/create_file.py +++ b/src/ifcopenshell-python/ifcopenshell/api/project/create_file.py @@ -3,7 +3,7 @@ import ifcopenshell class Usecase: - def __init__(self, settings=None): + def __init__(self, **settings): self.settings = {"version": "IFC4"} for key, value in settings.items(): self.settings[key] = value diff --git a/src/ifcblenderexport/blenderbim/bim/module/pset/add_pset.py b/src/ifcopenshell-python/ifcopenshell/api/pset/add_pset.py similarity index 97% rename from src/ifcblenderexport/blenderbim/bim/module/pset/add_pset.py rename to src/ifcopenshell-python/ifcopenshell/api/pset/add_pset.py index 17d2612ddf..37062d3845 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/pset/add_pset.py +++ b/src/ifcopenshell-python/ifcopenshell/api/pset/add_pset.py @@ -3,7 +3,7 @@ import blenderbim.bim.schema # TODO: refactor class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = {"product": None, "Name": None} for key, value in settings.items(): diff --git a/src/ifcblenderexport/blenderbim/bim/module/pset/add_qto.py b/src/ifcopenshell-python/ifcopenshell/api/pset/add_qto.py similarity index 94% rename from src/ifcblenderexport/blenderbim/bim/module/pset/add_qto.py rename to src/ifcopenshell-python/ifcopenshell/api/pset/add_qto.py index 5df089d98e..b55522da08 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/pset/add_qto.py +++ b/src/ifcopenshell-python/ifcopenshell/api/pset/add_qto.py @@ -3,7 +3,7 @@ import blenderbim.bim.schema # TODO: refactor class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = {"product": None, "Name": None} for key, value in settings.items(): diff --git a/src/ifcblenderexport/blenderbim/bim/module/pset/data.py b/src/ifcopenshell-python/ifcopenshell/api/pset/data.py similarity index 96% rename from src/ifcblenderexport/blenderbim/bim/module/pset/data.py rename to src/ifcopenshell-python/ifcopenshell/api/pset/data.py index 4632a085be..9b1410fe77 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/pset/data.py +++ b/src/ifcopenshell-python/ifcopenshell/api/pset/data.py @@ -1,7 +1,6 @@ import ifcopenshell import ifcopenshell.util.attribute import blenderbim.bim.schema # TODO: refactor elsewhere -from blenderbim.bim.ifc import IfcStore class Data: @@ -16,8 +15,9 @@ class Data: cls.qtos = {} @classmethod - def load(cls, product_id): - file = IfcStore.get_file() + def load(cls, file, product_id): + cls._file = file + cls._schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(file.schema) if not file: return product = file.by_id(product_id) @@ -162,7 +162,7 @@ class Data: if prop_template.TemplateType == "P_SINGLEVALUE": try: data_type = ifcopenshell.util.attribute.get_primitive_type( - IfcStore.get_schema().declaration_by_name(prop_template.PrimaryMeasureType or "IfcLabel") + cls._schema.declaration_by_name(prop_template.PrimaryMeasureType or "IfcLabel") ) except: # TODO: Occurs if the data type is something that exists in IFC4 and not in IFC2X3. To fully fix diff --git a/src/ifcblenderexport/blenderbim/bim/module/pset/edit_pset.py b/src/ifcopenshell-python/ifcopenshell/api/pset/edit_pset.py similarity index 98% rename from src/ifcblenderexport/blenderbim/bim/module/pset/edit_pset.py rename to src/ifcopenshell-python/ifcopenshell/api/pset/edit_pset.py index 0fc34751b1..dd76185234 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/pset/edit_pset.py +++ b/src/ifcopenshell-python/ifcopenshell/api/pset/edit_pset.py @@ -2,7 +2,7 @@ import blenderbim.bim.schema # TODO: refactor class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = {"pset": None, "Name": None, "Properties": {}} for key, value in settings.items(): diff --git a/src/ifcblenderexport/blenderbim/bim/module/pset/edit_qto.py b/src/ifcopenshell-python/ifcopenshell/api/pset/edit_qto.py similarity index 98% rename from src/ifcblenderexport/blenderbim/bim/module/pset/edit_qto.py rename to src/ifcopenshell-python/ifcopenshell/api/pset/edit_qto.py index 95a672b850..bd43f646af 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/pset/edit_qto.py +++ b/src/ifcopenshell-python/ifcopenshell/api/pset/edit_qto.py @@ -2,7 +2,7 @@ import blenderbim.bim.schema # TODO: refactor class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = {"qto": None, "Name": None, "Properties": {}} for key, value in settings.items(): diff --git a/src/ifcblenderexport/blenderbim/bim/module/pset/remove_pset.py b/src/ifcopenshell-python/ifcopenshell/api/pset/remove_pset.py similarity index 95% rename from src/ifcblenderexport/blenderbim/bim/module/pset/remove_pset.py rename to src/ifcopenshell-python/ifcopenshell/api/pset/remove_pset.py index 3ccdf6d0ef..2c742a65cb 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/pset/remove_pset.py +++ b/src/ifcopenshell-python/ifcopenshell/api/pset/remove_pset.py @@ -2,7 +2,7 @@ import blenderbim.bim.schema # TODO: refactor class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = {"product": None, "pset": None} for key, value in settings.items(): diff --git a/src/ifcblenderexport/blenderbim/bim/module/pset_template/add_prop_template.py b/src/ifcopenshell-python/ifcopenshell/api/pset_template/add_prop_template.py similarity index 94% rename from src/ifcblenderexport/blenderbim/bim/module/pset_template/add_prop_template.py rename to src/ifcopenshell-python/ifcopenshell/api/pset_template/add_prop_template.py index 7093d3fbd8..b57b36cf82 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/pset_template/add_prop_template.py +++ b/src/ifcopenshell-python/ifcopenshell/api/pset_template/add_prop_template.py @@ -2,7 +2,7 @@ import ifcopenshell class Usecase: - def __init__(self, file, settings={}): + def __init__(self, file, **settings): self.file = file self.settings = {"pset_template": None} for key, value in settings.items(): diff --git a/src/ifcblenderexport/blenderbim/bim/module/pset_template/add_pset_template.py b/src/ifcopenshell-python/ifcopenshell/api/pset_template/add_pset_template.py similarity index 91% rename from src/ifcblenderexport/blenderbim/bim/module/pset_template/add_pset_template.py rename to src/ifcopenshell-python/ifcopenshell/api/pset_template/add_pset_template.py index 613298aa96..341790790b 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/pset_template/add_pset_template.py +++ b/src/ifcopenshell-python/ifcopenshell/api/pset_template/add_pset_template.py @@ -2,7 +2,7 @@ import ifcopenshell class Usecase: - def __init__(self, file, settings={}): + def __init__(self, file, **settings): self.file = file self.settings = {} for key, value in settings.items(): diff --git a/src/ifcblenderexport/blenderbim/bim/module/pset_template/data.py b/src/ifcopenshell-python/ifcopenshell/api/pset_template/data.py similarity index 90% rename from src/ifcblenderexport/blenderbim/bim/module/pset_template/data.py rename to src/ifcopenshell-python/ifcopenshell/api/pset_template/data.py index 6ff8bd6ba1..d3c9ccb040 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/pset_template/data.py +++ b/src/ifcopenshell-python/ifcopenshell/api/pset_template/data.py @@ -1,6 +1,3 @@ -from blenderbim.bim.ifc import IfcStore - - class Data: is_loaded = False pset_templates = {} @@ -13,8 +10,8 @@ class Data: cls.prop_templates = {} @classmethod - def load(cls): - cls._file = IfcStore.pset_template_file + def load(cls, file): + cls._file = file cls.pset_templates = {} cls.prop_templates = {} diff --git a/src/ifcblenderexport/blenderbim/bim/module/pset_template/edit_prop_template.py b/src/ifcopenshell-python/ifcopenshell/api/pset_template/edit_prop_template.py similarity index 88% rename from src/ifcblenderexport/blenderbim/bim/module/pset_template/edit_prop_template.py rename to src/ifcopenshell-python/ifcopenshell/api/pset_template/edit_prop_template.py index 5e7ed302ae..5ad617f698 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/pset_template/edit_prop_template.py +++ b/src/ifcopenshell-python/ifcopenshell/api/pset_template/edit_prop_template.py @@ -1,5 +1,5 @@ class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = {"prop_template": None, "attributes": {}} for key, value in settings.items(): diff --git a/src/ifcblenderexport/blenderbim/bim/module/pset_template/edit_pset_template.py b/src/ifcopenshell-python/ifcopenshell/api/pset_template/edit_pset_template.py similarity index 88% rename from src/ifcblenderexport/blenderbim/bim/module/pset_template/edit_pset_template.py rename to src/ifcopenshell-python/ifcopenshell/api/pset_template/edit_pset_template.py index 3d5f1caa8b..8d039b9e32 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/pset_template/edit_pset_template.py +++ b/src/ifcopenshell-python/ifcopenshell/api/pset_template/edit_pset_template.py @@ -1,5 +1,5 @@ class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = {"pset_template": None, "attributes": {}} for key, value in settings.items(): diff --git a/src/ifcblenderexport/blenderbim/bim/module/pset_template/remove_prop_template.py b/src/ifcopenshell-python/ifcopenshell/api/pset_template/remove_prop_template.py similarity index 94% rename from src/ifcblenderexport/blenderbim/bim/module/pset_template/remove_prop_template.py rename to src/ifcopenshell-python/ifcopenshell/api/pset_template/remove_prop_template.py index 68e20e6135..0221852eea 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/pset_template/remove_prop_template.py +++ b/src/ifcopenshell-python/ifcopenshell/api/pset_template/remove_prop_template.py @@ -2,7 +2,7 @@ import ifcopenshell.util.element class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = { "prop_template": None diff --git a/src/ifcblenderexport/blenderbim/bim/module/pset_template/remove_pset_template.py b/src/ifcopenshell-python/ifcopenshell/api/pset_template/remove_pset_template.py similarity index 88% rename from src/ifcblenderexport/blenderbim/bim/module/pset_template/remove_pset_template.py rename to src/ifcopenshell-python/ifcopenshell/api/pset_template/remove_pset_template.py index b58e21284f..16f0246782 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/pset_template/remove_pset_template.py +++ b/src/ifcopenshell-python/ifcopenshell/api/pset_template/remove_pset_template.py @@ -2,7 +2,7 @@ import ifcopenshell.util.element class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = { "pset_template": None diff --git a/src/ifcblenderexport/blenderbim/bim/module/root/copy_class.py b/src/ifcopenshell-python/ifcopenshell/api/root/copy_class.py similarity index 97% rename from src/ifcblenderexport/blenderbim/bim/module/root/copy_class.py rename to src/ifcopenshell-python/ifcopenshell/api/root/copy_class.py index 04ba418578..9300ebd0e6 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/root/copy_class.py +++ b/src/ifcopenshell-python/ifcopenshell/api/root/copy_class.py @@ -2,7 +2,7 @@ import ifcopenshell class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = {"product": None} for key, value in settings.items(): diff --git a/src/ifcblenderexport/blenderbim/bim/module/root/create_product.py b/src/ifcopenshell-python/ifcopenshell/api/root/create_entity.py similarity index 86% rename from src/ifcblenderexport/blenderbim/bim/module/root/create_product.py rename to src/ifcopenshell-python/ifcopenshell/api/root/create_entity.py index 2a460df11b..1f40d77108 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/root/create_product.py +++ b/src/ifcopenshell-python/ifcopenshell/api/root/create_entity.py @@ -1,9 +1,9 @@ import ifcopenshell -from blenderbim.bim.module.owner.api import create_owner_history +import ifcopenshell.api class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = { "ifc_class": "IfcBuildingElementProxy", @@ -16,7 +16,7 @@ class Usecase: def execute(self): element = self.file.create_entity(self.settings["ifc_class"], **{ "GlobalId": ifcopenshell.guid.new(), - "OwnerHistory": create_owner_history() + "OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", self.file) }) element.Name = self.settings["name"] or None if self.settings["predefined_type"]: diff --git a/src/ifcblenderexport/blenderbim/bim/module/root/data.py b/src/ifcopenshell-python/ifcopenshell/api/root/data.py similarity index 81% rename from src/ifcblenderexport/blenderbim/bim/module/root/data.py rename to src/ifcopenshell-python/ifcopenshell/api/root/data.py index 445ece8e37..2fe987f5dc 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/root/data.py +++ b/src/ifcopenshell-python/ifcopenshell/api/root/data.py @@ -1,6 +1,3 @@ -from blenderbim.bim.ifc import IfcStore - - class Data: products = {} @@ -9,8 +6,7 @@ class Data: cls.products = {} @classmethod - def load(cls, product_id): - file = IfcStore.get_file() + def load(cls, file, product_id): if not file: return product = file.by_id(product_id) diff --git a/src/ifcblenderexport/blenderbim/bim/module/root/reassign_class.py b/src/ifcopenshell-python/ifcopenshell/api/root/reassign_class.py similarity index 94% rename from src/ifcblenderexport/blenderbim/bim/module/root/reassign_class.py rename to src/ifcopenshell-python/ifcopenshell/api/root/reassign_class.py index 2179e3f0fa..bebb563e76 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/root/reassign_class.py +++ b/src/ifcopenshell-python/ifcopenshell/api/root/reassign_class.py @@ -3,7 +3,7 @@ import ifcopenshell.util.schema class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = { "product": None, diff --git a/src/ifcopenshell-python/ifcopenshell/api/root/remove_product.py b/src/ifcopenshell-python/ifcopenshell/api/root/remove_product.py new file mode 100644 index 0000000000..80c9e16004 --- /dev/null +++ b/src/ifcopenshell-python/ifcopenshell/api/root/remove_product.py @@ -0,0 +1,26 @@ +import ifcopenshell.api + + +class Usecase: + def __init__(self, file, **settings): + self.file = file + self.settings = {"product": None} + for key, value in settings.items(): + self.settings[key] = value + + def execute(self): + representations = [] + if self.settings["product"].is_a("IfcProduct"): + if self.settings["product"].Representation: + representations = self.settings["product"].Representation.Representations or [] + else: + representations = [] + elif self.settings["product"].is_a("IfcTypeProduct"): + representations = [rm.MappedRepresentation for rm in self.settings["product"].RepresentationMaps or []] + for representation in representations: + ifcopenshell.api.run("owner.unassign_representation", + self.file, **{"product": self.settings["product"], "representation": representation} + ) + ifcopenshell.api.run("owner.remove_representation", self.file, **{"representation": representation}) + # TODO: remove object placement and other relationships + self.file.remove(self.settings["product"]) diff --git a/src/ifcopenshell-python/ifcopenshell/api/sequence/add_work_plan.py b/src/ifcopenshell-python/ifcopenshell/api/sequence/add_work_plan.py new file mode 100644 index 0000000000..f885077333 --- /dev/null +++ b/src/ifcopenshell-python/ifcopenshell/api/sequence/add_work_plan.py @@ -0,0 +1,42 @@ +import ifcopenshell.api +import ifcopenshell.util.date +from datetime import datetime + + +class Usecase: + def __init__(self, file, **settings): + self.file = file + self.settings = {"name": None, "predefined_type": "NOTDEFINED", "start_time": datetime.now()} + for key, value in settings.items(): + self.settings[key] = value + + def execute(self): + work_plan = ifcopenshell.api.run( + "root.create_entity", + self.file, + ifc_class="IfcWorkPlan", + predefined_type=self.settings["predefined_type"], + name=self.settings["name"], + ) + work_plan.CreationDate = ifcopenshell.util.date.datetime2ifc(datetime.now(), "IfcDateTime") + person = ifcopenshell.api.owner.settings.get_person(self.file) + if person: + work_plan.Creators = [person] + work_plan.StartTime = ifcopenshell.util.date.datetime2ifc(self.settings["start_time"], "IfcDateTime") + + context = self.file.by_type("IfcContext")[0] + if context.Declares: + rel_declares = context.Declares[0] + ifcopenshell.api.run("owner.update_owner_history", self.file, element=rel_declares) + else: + rel_declares = self.file.create_entity("IfcRelDeclares", **{ + "GlobalId": ifcopenshell.guid.new(), + "OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", self.file), + "RelatingContext": context + }) + + related_definitions = list(rel_declares.RelatedDefinitions or []) + related_definitions.append(work_plan) + rel_declares.RelatedDefinitions = related_definitions + + return work_plan diff --git a/src/ifcopenshell-python/ifcopenshell/api/sequence/data.py b/src/ifcopenshell-python/ifcopenshell/api/sequence/data.py new file mode 100644 index 0000000000..894a942a40 --- /dev/null +++ b/src/ifcopenshell-python/ifcopenshell/api/sequence/data.py @@ -0,0 +1,31 @@ +import ifcopenshell.util.date + + +class Data: + is_loaded = False + work_plans = {} + tasks = {} + + @classmethod + def purge(cls): + cls.is_loaded = False + cls.work_plans = {} + cls.tasks = {} + + @classmethod + def load(cls, file): + cls.work_plans = {} + cls.tasks = {} + for work_plan in file.by_type("IfcWorkPlan"): + data = work_plan.get_info() + del data["OwnerHistory"] + if data["Creators"]: + data["Creators"] = [p.id() for p in data["Creators"]] + data["CreationDate"] = ifcopenshell.util.date.ifc2datetime(data["CreationDate"]) + data["StartTime"] = ifcopenshell.util.date.ifc2datetime(data["StartTime"]) + if data["FinishTime"]: + data["FinishTime"] = ifcopenshell.util.date.ifc2datetime(data["FinishTime"]) + cls.work_plans[work_plan.id()] = data + for task in file.by_type("IfcTask"): + cls.tasks[task.id()] = {"Name": task.Name, "Identification": task.Identification or ""} + cls.is_loaded=True diff --git a/src/ifcopenshell-python/ifcopenshell/api/sequence/remove_work_plan.py b/src/ifcopenshell-python/ifcopenshell/api/sequence/remove_work_plan.py new file mode 100644 index 0000000000..941000f7ff --- /dev/null +++ b/src/ifcopenshell-python/ifcopenshell/api/sequence/remove_work_plan.py @@ -0,0 +1,14 @@ +class Usecase: + def __init__(self, file, **settings): + self.file = file + self.settings = {"work_plan": None} + for key, value in settings.items(): + self.settings[key] = value + + def execute(self): + # TODO: do a deep purge + if self.settings["work_plan"].HasContext: + rel_declares = self.settings["work_plan"].HasContext[0] + if len(rel_declares.RelatedDefinitions) == 1: + self.file.remove(rel_declares) + self.file.remove(self.settings["work_plan"]) diff --git a/src/ifcblenderexport/blenderbim/bim/module/spatial/assign_container.py b/src/ifcopenshell-python/ifcopenshell/api/spatial/assign_container.py similarity index 79% rename from src/ifcblenderexport/blenderbim/bim/module/spatial/assign_container.py rename to src/ifcopenshell-python/ifcopenshell/api/spatial/assign_container.py index afbe536700..0312748c45 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/spatial/assign_container.py +++ b/src/ifcopenshell-python/ifcopenshell/api/spatial/assign_container.py @@ -1,8 +1,9 @@ import ifcopenshell +import ifcopenshell.api class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = { "product": None, @@ -23,6 +24,7 @@ class Usecase: related_elements.remove(self.settings["product"]) if related_elements: contained_in_structure[0].RelatedElements = related_elements + ifcopenshell.api.run("owner.update_owner_history", self.file, **{"element": contained_in_structure[0]}) else: self.file.remove(contained_in_structure[0]) @@ -30,12 +32,13 @@ class Usecase: related_elements = list(contains_elements[0].RelatedElements) related_elements.append(self.settings["product"]) contains_elements[0].RelatedElements = related_elements + ifcopenshell.api.run("owner.update_owner_history", self.file, **{"element": contains_elements[0]}) else: contains_elements = self.file.create_entity( "IfcRelContainedInSpatialStructure", **{ "GlobalId": ifcopenshell.guid.new(), - # TODO "OwnerHistory": None + "OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", self.file), "RelatedElements": [self.settings["product"]], "RelatingStructure": self.settings["relating_structure"], } diff --git a/src/ifcblenderexport/blenderbim/bim/module/spatial/data.py b/src/ifcopenshell-python/ifcopenshell/api/spatial/data.py similarity index 83% rename from src/ifcblenderexport/blenderbim/bim/module/spatial/data.py rename to src/ifcopenshell-python/ifcopenshell/api/spatial/data.py index 027edea27f..03118e0ab0 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/spatial/data.py +++ b/src/ifcopenshell-python/ifcopenshell/api/spatial/data.py @@ -1,6 +1,3 @@ -from blenderbim.bim.ifc import IfcStore - - class Data: products = {} spatial_elements = {} @@ -11,14 +8,13 @@ class Data: cls.spatial_elements = {} @classmethod - def load(cls, product_id=None): + def load(cls, file, product_id=None): if product_id: - return cls.load_product(product_id) - cls.load_spatial_elements() + return cls.load_product(file, product_id) + cls.load_spatial_elements(file) @classmethod - def load_product(cls, product_id): - file = IfcStore.get_file() + def load_product(cls, file, product_id): if not file: return product = file.by_id(product_id) @@ -31,8 +27,7 @@ class Data: cls.products[product_id] = {"type": None, "Name": None, "id": None} @classmethod - def load_spatial_elements(cls): - file = IfcStore.get_file() + def load_spatial_elements(cls, file): if not file: return cls.spatial_elements = {} diff --git a/src/ifcblenderexport/blenderbim/bim/module/spatial/remove_container.py b/src/ifcopenshell-python/ifcopenshell/api/spatial/remove_container.py similarity index 77% rename from src/ifcblenderexport/blenderbim/bim/module/spatial/remove_container.py rename to src/ifcopenshell-python/ifcopenshell/api/spatial/remove_container.py index 57b9a75af3..57a5399980 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/spatial/remove_container.py +++ b/src/ifcopenshell-python/ifcopenshell/api/spatial/remove_container.py @@ -1,8 +1,9 @@ import ifcopenshell +import ifcopenshell.api class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = {"product": None} for key, value in settings.items(): @@ -16,5 +17,6 @@ class Usecase: related_elements.remove(self.settings["product"]) if related_elements: contained_in_structure[0].RelatedElements = related_elements + ifcopenshell.api.run("owner.update_owner_history", self.file, **{"element": contained_in_structure[0]}) else: self.file.remove(contained_in_structure) diff --git a/src/ifcopenshell-python/ifcopenshell/api/structural/add_structural_analysis_model.py b/src/ifcopenshell-python/ifcopenshell/api/structural/add_structural_analysis_model.py new file mode 100644 index 0000000000..1e58a3a87c --- /dev/null +++ b/src/ifcopenshell-python/ifcopenshell/api/structural/add_structural_analysis_model.py @@ -0,0 +1,15 @@ +import ifcopenshell +import ifcopenshell.api + + +class Usecase: + def __init__(self, file, **settings): + self.file = file + self.settings = {} + for key, value in settings.items(): + self.settings[key] = value + + def execute(self): + return ifcopenshell.api.run( + "root.create_entity", self.file, ifc_class="IfcStructuralAnalysisModel", predefined_type="LOADING_3D" + ) diff --git a/src/ifcopenshell-python/ifcopenshell/api/structural/add_structural_boundary_condition.py b/src/ifcopenshell-python/ifcopenshell/api/structural/add_structural_boundary_condition.py new file mode 100644 index 0000000000..9cb49ec47a --- /dev/null +++ b/src/ifcopenshell-python/ifcopenshell/api/structural/add_structural_boundary_condition.py @@ -0,0 +1,21 @@ +class Usecase: + def __init__(self, file, **settings): + self.file = file + self.settings = {"connection": None} + for key, value in settings.items(): + self.settings[key] = value + + def execute(self): + if self.settings["connection"].is_a("IfcRelConnectsStructuralMember"): + related_connection = self.settings["connection"].RelatedStructuralConnection + else: + related_connection = self.settings["connection"] + + if related_connection.is_a("IfcStructuralPointConnection"): + boundary_class = "IfcBoundaryNodeCondition" + elif related_connection.is_a("IfcStructuralCurveConnection"): + boundary_class = "IfcBoundaryEdgeCondition" + elif related_connection.is_a("IfcStructuralSurfaceConnection"): + boundary_class = "IfcBoundaryFaceCondition" + + self.settings["connection"].AppliedCondition = self.file.create_entity(boundary_class) diff --git a/src/ifcopenshell-python/ifcopenshell/api/structural/add_structural_member_connection.py b/src/ifcopenshell-python/ifcopenshell/api/structural/add_structural_member_connection.py new file mode 100644 index 0000000000..e184725bb6 --- /dev/null +++ b/src/ifcopenshell-python/ifcopenshell/api/structural/add_structural_member_connection.py @@ -0,0 +1,19 @@ +import ifcopenshell +import ifcopenshell.api + + +class Usecase: + def __init__(self, file, **settings): + self.file = file + self.settings = {"relating_structural_member": None, "related_structural_connection": None} + for key, value in settings.items(): + self.settings[key] = value + + def execute(self): + for connection in self.settings["related_structural_connection"].ConnectsStructuralMembers or []: + if connection.RelatingStructuralMember == self.settings["relating_structural_member"]: + return + rel = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcRelConnectsStructuralMember") + rel.RelatingStructuralMember = self.settings["relating_structural_member"] + rel.RelatedStructuralConnection = self.settings["related_structural_connection"] + return rel diff --git a/src/ifcblenderexport/blenderbim/bim/module/structural/assign_structural_analysis_model.py b/src/ifcopenshell-python/ifcopenshell/api/structural/assign_structural_analysis_model.py similarity index 76% rename from src/ifcblenderexport/blenderbim/bim/module/structural/assign_structural_analysis_model.py rename to src/ifcopenshell-python/ifcopenshell/api/structural/assign_structural_analysis_model.py index ff486b3fbf..a2925e7981 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/structural/assign_structural_analysis_model.py +++ b/src/ifcopenshell-python/ifcopenshell/api/structural/assign_structural_analysis_model.py @@ -1,10 +1,9 @@ import ifcopenshell -from blenderbim.bim.module.owner.api import create_owner_history -from blenderbim.bim.module.owner.api import update_owner_history +import ifcopenshell.api class Usecase: - def __init__(self, file, settings={}): + def __init__(self, file, **settings): self.file = file self.settings = { "product": None, @@ -17,7 +16,7 @@ class Usecase: if not self.settings["structural_analysis_model"].IsGroupedBy: return self.file.create_entity("IfcRelAssignsToGroup", **{ "GlobalId": ifcopenshell.guid.new(), - "OwnerHistory": create_owner_history(), + "OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", self.file), "RelatedObjects": [self.settings["product"]], "RelatingGroup": self.settings["structural_analysis_model"] }) @@ -25,4 +24,4 @@ class Usecase: related_objects = set(rel.RelatedObjects) or set() related_objects.add(self.settings["product"]) rel.RelatedObjects = list(related_objects) - update_owner_history(rel) + ifcopenshell.api.run("owner.update_owner_history", self.file, **{"element": rel}) diff --git a/src/ifcopenshell-python/ifcopenshell/api/structural/data.py b/src/ifcopenshell-python/ifcopenshell/api/structural/data.py new file mode 100644 index 0000000000..0165ab64f9 --- /dev/null +++ b/src/ifcopenshell-python/ifcopenshell/api/structural/data.py @@ -0,0 +1,99 @@ +class Data: + is_loaded = False + products = {} + structural_analysis_models = {} + connections = {} + boundary_conditions = {} + connects_structural_members = {} + + @classmethod + def purge(cls): + cls.is_loaded = False + cls.products = {} + cls.structural_analysis_models = {} + cls.connections = {} + cls.boundary_conditions = {} + cls.connects_structural_members = {} + + @classmethod + def load(cls, file, product_id=None): + cls._file = file + if not cls._file: + return + if product_id: + return cls.load_structural_connection(product_id) + cls.load_structural_analysis_models() + cls.is_loaded = True + + @classmethod + def load_structural_analysis_models(cls): + cls.products = {} + cls.structural_analysis_models = {} + + for model in cls._file.by_type("IfcStructuralAnalysisModel"): + if model.IsGroupedBy: + for rel in model.IsGroupedBy: + for product in rel.RelatedObjects: + cls.products.setdefault(product.id(), []).append(model.id()) + data = model.get_info() + del data["OwnerHistory"] + del data["OrientationOf2DPlane"] + + loaded_by = [] + for load_group in model.LoadedBy or []: + loaded_by.append(load_group.id()) + data["LoadedBy"] = loaded_by + + has_results = [] + for result_group in model.HasResults or []: + has_results.append(result_group.id()) + data["HasResults"] = has_results + + data["SharedPlacement"] = model.SharedPlacement.id() if model.SharedPlacement else None + + cls.structural_analysis_models[model.id()] = data + + @classmethod + def load_structural_connection(cls, product_id): + cls.connections = {} + cls.boundary_conditions = {} + cls.connects_structural_members = {} + + connection = cls._file.by_id(product_id) + connection_data = {"AppliedCondition": None, "ConnectsStructuralMembers": []} + + if connection.AppliedCondition: + cls.load_boundary_condition(connection.AppliedCondition) + connection_data["AppliedCondition"] = connection.AppliedCondition.id() + + for rel in connection.ConnectsStructuralMembers or []: + cls.load_connects_structural_member(rel) + connection_data["ConnectsStructuralMembers"].append(rel.id()) + + cls.connections[connection.id()] = connection_data + + @classmethod + def load_boundary_condition(cls, boundary_condition): + data = boundary_condition.get_info() + for key, value in data.items(): + if not value or key in ["Name", "type", "id"]: + continue + data[key] = value.wrappedValue + cls.boundary_conditions[boundary_condition.id()] = data + + @classmethod + def load_connects_structural_member(cls, rel): + rel_data = rel.get_info() + del rel_data["OwnerHistory"] + rel_data["RelatingStructuralMember"] = rel.RelatingStructuralMember.id() + rel_data["RelatedStructuralConnection"] = rel.RelatedStructuralConnection.id() + del rel_data["ConditionCoordinateSystem"] # TODO: consider orientation + + if rel.is_a("IfcRelConnectsWithEccentricity"): + rel_data["ConnectionConstraint"] = rel.ConnectionConstraint # TODO + + if rel.AppliedCondition: + cls.load_boundary_condition(rel.AppliedCondition) + rel_data["AppliedCondition"] = rel.AppliedCondition.id() + + cls.connects_structural_members[rel.id()] = rel_data diff --git a/src/ifcblenderexport/blenderbim/bim/module/structural/edit_structural_analysis_model.py b/src/ifcopenshell-python/ifcopenshell/api/structural/edit_structural_analysis_model.py similarity index 90% rename from src/ifcblenderexport/blenderbim/bim/module/structural/edit_structural_analysis_model.py rename to src/ifcopenshell-python/ifcopenshell/api/structural/edit_structural_analysis_model.py index 3e003870b9..9fe0dfd108 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/structural/edit_structural_analysis_model.py +++ b/src/ifcopenshell-python/ifcopenshell/api/structural/edit_structural_analysis_model.py @@ -1,5 +1,5 @@ class Usecase: - def __init__(self, file, settings={}): + def __init__(self, file, **settings): self.file = file self.settings = { "structural_analysis_model": None, diff --git a/src/ifcblenderexport/blenderbim/bim/module/structural/edit_structural_boundary_condition.py b/src/ifcopenshell-python/ifcopenshell/api/structural/edit_structural_boundary_condition.py similarity index 94% rename from src/ifcblenderexport/blenderbim/bim/module/structural/edit_structural_boundary_condition.py rename to src/ifcopenshell-python/ifcopenshell/api/structural/edit_structural_boundary_condition.py index 5b1e3d75e3..0862310e6f 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/structural/edit_structural_boundary_condition.py +++ b/src/ifcopenshell-python/ifcopenshell/api/structural/edit_structural_boundary_condition.py @@ -1,5 +1,5 @@ class Usecase: - def __init__(self, file, settings={}): + def __init__(self, file, **settings): self.file = file self.settings = { "condition": None, diff --git a/src/ifcblenderexport/blenderbim/bim/module/structural/remove_structural_analysis_model.py b/src/ifcopenshell-python/ifcopenshell/api/structural/remove_structural_analysis_model.py similarity index 90% rename from src/ifcblenderexport/blenderbim/bim/module/structural/remove_structural_analysis_model.py rename to src/ifcopenshell-python/ifcopenshell/api/structural/remove_structural_analysis_model.py index b191fb588c..89c214ed3d 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/structural/remove_structural_analysis_model.py +++ b/src/ifcopenshell-python/ifcopenshell/api/structural/remove_structural_analysis_model.py @@ -1,5 +1,5 @@ class Usecase: - def __init__(self, file, settings={}): + def __init__(self, file, **settings): self.file = file self.settings = {"structural_analysis_model": None} for key, value in settings.items(): diff --git a/src/ifcblenderexport/blenderbim/bim/module/structural/remove_structural_boundary_condition.py b/src/ifcopenshell-python/ifcopenshell/api/structural/remove_structural_boundary_condition.py similarity index 73% rename from src/ifcblenderexport/blenderbim/bim/module/structural/remove_structural_boundary_condition.py rename to src/ifcopenshell-python/ifcopenshell/api/structural/remove_structural_boundary_condition.py index 67626af084..48ca3354df 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/structural/remove_structural_boundary_condition.py +++ b/src/ifcopenshell-python/ifcopenshell/api/structural/remove_structural_boundary_condition.py @@ -1,5 +1,5 @@ class Usecase: - def __init__(self, file, settings={}): + def __init__(self, file, **settings): self.file = file self.settings = {"connection": None} for key, value in settings.items(): @@ -8,7 +8,6 @@ class Usecase: def execute(self): if not self.settings["connection"].AppliedCondition: return - if len(self.file.get_inverse(self.settings["connection"].AppliedCondition)) > 1: - self.settings["connection"].AppliedCondition = None - else: + if len(self.file.get_inverse(self.settings["connection"].AppliedCondition)) == 1: self.file.remove(self.settings["connection"].AppliedCondition) + self.settings["connection"].AppliedCondition = None diff --git a/src/ifcopenshell-python/ifcopenshell/api/structural/remove_structural_connection_condition.py b/src/ifcopenshell-python/ifcopenshell/api/structural/remove_structural_connection_condition.py new file mode 100644 index 0000000000..0b376f9895 --- /dev/null +++ b/src/ifcopenshell-python/ifcopenshell/api/structural/remove_structural_connection_condition.py @@ -0,0 +1,19 @@ +import ifcopenshell.api + + +class Usecase: + def __init__(self, file, **settings): + self.file = file + self.settings = {"relation": None} + for key, value in settings.items(): + self.settings[key] = value + + def execute(self): + if self.settings["relation"].AppliedCondition: + ifcopenshell.api.run( + "structural.remove_structural_boundary_condition", + self.file, + **{"connection": self.settings["relation"].RelatedStructuralConnection} + ) + self.file.remove(self.settings["relation"]) + diff --git a/src/ifcblenderexport/blenderbim/bim/module/structural/unassign_structural_analysis_model.py b/src/ifcopenshell-python/ifcopenshell/api/structural/unassign_structural_analysis_model.py similarity index 81% rename from src/ifcblenderexport/blenderbim/bim/module/structural/unassign_structural_analysis_model.py rename to src/ifcopenshell-python/ifcopenshell/api/structural/unassign_structural_analysis_model.py index 0f1b49290e..8c8a18d57b 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/structural/unassign_structural_analysis_model.py +++ b/src/ifcopenshell-python/ifcopenshell/api/structural/unassign_structural_analysis_model.py @@ -1,9 +1,9 @@ import ifcopenshell -from blenderbim.bim.module.owner.api import update_owner_history +import ifcopenshell.api class Usecase: - def __init__(self, file, settings={}): + def __init__(self, file, **settings): self.file = file self.settings = { "product": None, @@ -20,6 +20,6 @@ class Usecase: related_objects.remove(self.settings["product"]) if len(related_objects): rel.RelatedObjects = list(related_objects) - update_owner_history(rel) + ifcopenshell.api.run("owner.update_owner_history", self.file, **{"element": rel}) else: self.file.remove(rel) diff --git a/src/ifcblenderexport/blenderbim/bim/module/style/add_style.py b/src/ifcopenshell-python/ifcopenshell/api/style/add_style.py similarity index 97% rename from src/ifcblenderexport/blenderbim/bim/module/style/add_style.py rename to src/ifcopenshell-python/ifcopenshell/api/style/add_style.py index f4cef0abe7..6221a33674 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/style/add_style.py +++ b/src/ifcopenshell-python/ifcopenshell/api/style/add_style.py @@ -1,5 +1,5 @@ class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = { "Name": "Name", diff --git a/src/ifcblenderexport/blenderbim/bim/module/style/edit_style.py b/src/ifcopenshell-python/ifcopenshell/api/style/edit_style.py similarity index 98% rename from src/ifcblenderexport/blenderbim/bim/module/style/edit_style.py rename to src/ifcopenshell-python/ifcopenshell/api/style/edit_style.py index e83397eece..61cd9311d0 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/style/edit_style.py +++ b/src/ifcopenshell-python/ifcopenshell/api/style/edit_style.py @@ -1,5 +1,5 @@ class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = { "style": None, diff --git a/src/ifcblenderexport/blenderbim/bim/module/type/assign_type.py b/src/ifcopenshell-python/ifcopenshell/api/type/assign_type.py similarity index 82% rename from src/ifcblenderexport/blenderbim/bim/module/type/assign_type.py rename to src/ifcopenshell-python/ifcopenshell/api/type/assign_type.py index fe936f02d2..a162a373de 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/type/assign_type.py +++ b/src/ifcopenshell-python/ifcopenshell/api/type/assign_type.py @@ -1,8 +1,9 @@ import ifcopenshell +import ifcopenshell.api class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = { "related_object": None, @@ -32,6 +33,7 @@ class Usecase: related_objects.remove(self.settings["related_object"]) if related_objects: is_typed_by[0].RelatedObjects = related_objects + ifcopenshell.api.run("owner.update_owner_history", self.file, **{"element": is_typed_by[0]}) else: self.file.remove(is_typed_by[0]) @@ -39,12 +41,13 @@ class Usecase: related_objects = list(types[0].RelatedObjects) related_objects.append(self.settings["related_object"]) types[0].RelatedObjects = related_objects + ifcopenshell.api.run("owner.update_owner_history", self.file, **{"element": types[0]}) else: types = self.file.create_entity( "IfcRelDefinesByType", **{ "GlobalId": ifcopenshell.guid.new(), - # TODO "OwnerHistory": None + "OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", self.file), "RelatedObjects": [self.settings["related_object"]], "RelatingType": self.settings["relating_type"], } diff --git a/src/ifcblenderexport/blenderbim/bim/module/type/data.py b/src/ifcopenshell-python/ifcopenshell/api/type/data.py similarity index 91% rename from src/ifcblenderexport/blenderbim/bim/module/type/data.py rename to src/ifcopenshell-python/ifcopenshell/api/type/data.py index 696db35582..ac8cd509aa 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/type/data.py +++ b/src/ifcopenshell-python/ifcopenshell/api/type/data.py @@ -1,6 +1,3 @@ -from blenderbim.bim.ifc import IfcStore - - class Data: products = {} @@ -9,8 +6,7 @@ class Data: cls.products = {} @classmethod - def load(cls, product_id): - file = IfcStore.get_file() + def load(cls, file, product_id): if not file: return product = file.by_id(product_id) diff --git a/src/ifcblenderexport/blenderbim/bim/module/type/get_related_objects.py b/src/ifcopenshell-python/ifcopenshell/api/type/get_related_objects.py similarity index 96% rename from src/ifcblenderexport/blenderbim/bim/module/type/get_related_objects.py rename to src/ifcopenshell-python/ifcopenshell/api/type/get_related_objects.py index 9226799575..63380a8412 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/type/get_related_objects.py +++ b/src/ifcopenshell-python/ifcopenshell/api/type/get_related_objects.py @@ -2,7 +2,7 @@ import ifcopenshell class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = { "related_object": None, diff --git a/src/ifcblenderexport/blenderbim/bim/module/type/unassign_type.py b/src/ifcopenshell-python/ifcopenshell/api/type/unassign_type.py similarity index 85% rename from src/ifcblenderexport/blenderbim/bim/module/type/unassign_type.py rename to src/ifcopenshell-python/ifcopenshell/api/type/unassign_type.py index e20ba75a2d..3bb7d06d7f 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/type/unassign_type.py +++ b/src/ifcopenshell-python/ifcopenshell/api/type/unassign_type.py @@ -1,8 +1,9 @@ import ifcopenshell +import ifcopenshell.api class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = { "related_object": None @@ -27,5 +28,6 @@ class Usecase: related_objects.remove(self.settings["related_object"]) if related_objects: is_typed_by.RelatedObjects = related_objects + ifcopenshell.api.run("owner.update_owner_history", self.file, **{"element": is_typed_by}) else: self.file.remove(is_typed_by) diff --git a/src/ifcblenderexport/blenderbim/bim/module/unit/assign_unit.py b/src/ifcopenshell-python/ifcopenshell/api/unit/assign_unit.py similarity index 98% rename from src/ifcblenderexport/blenderbim/bim/module/unit/assign_unit.py rename to src/ifcopenshell-python/ifcopenshell/api/unit/assign_unit.py index 3872a50829..f99e41220b 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/unit/assign_unit.py +++ b/src/ifcopenshell-python/ifcopenshell/api/unit/assign_unit.py @@ -2,7 +2,7 @@ import ifcopenshell.util.unit class Usecase(): - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = { "length": { diff --git a/src/ifcblenderexport/blenderbim/bim/module/unit/data.py b/src/ifcopenshell-python/ifcopenshell/api/unit/data.py similarity index 82% rename from src/ifcblenderexport/blenderbim/bim/module/unit/data.py rename to src/ifcopenshell-python/ifcopenshell/api/unit/data.py index 08e1198d55..8b71dad1b4 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/unit/data.py +++ b/src/ifcopenshell-python/ifcopenshell/api/unit/data.py @@ -1,6 +1,3 @@ -from blenderbim.bim.ifc import IfcStore - - class Data: is_loaded = False units = {} @@ -11,8 +8,7 @@ class Data: cls.units = {} @classmethod - def load(cls): - file = IfcStore.get_file() + def load(cls, file): if not file: return unit_assignment = file.by_type("IfcUnitAssignment") diff --git a/src/ifcblenderexport/blenderbim/bim/module/void/add_filling.py b/src/ifcopenshell-python/ifcopenshell/api/void/add_filling.py similarity index 91% rename from src/ifcblenderexport/blenderbim/bim/module/void/add_filling.py rename to src/ifcopenshell-python/ifcopenshell/api/void/add_filling.py index 0acb8b6c48..48393d1874 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/void/add_filling.py +++ b/src/ifcopenshell-python/ifcopenshell/api/void/add_filling.py @@ -2,7 +2,7 @@ import ifcopenshell class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = {"opening": None, "element": None} for key, value in settings.items(): diff --git a/src/ifcblenderexport/blenderbim/bim/module/void/add_opening.py b/src/ifcopenshell-python/ifcopenshell/api/void/add_opening.py similarity index 75% rename from src/ifcblenderexport/blenderbim/bim/module/void/add_opening.py rename to src/ifcopenshell-python/ifcopenshell/api/void/add_opening.py index 5e813b405c..541a35d1f3 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/void/add_opening.py +++ b/src/ifcopenshell-python/ifcopenshell/api/void/add_opening.py @@ -1,8 +1,9 @@ import ifcopenshell +import ifcopenshell.api class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = {"opening": None, "element": None} for key, value in settings.items(): @@ -11,6 +12,7 @@ class Usecase: def execute(self): self.file.create_entity("IfcRelVoidsElement", **{ "GlobalId": ifcopenshell.guid.new(), + "OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", self.file), "RelatingBuildingElement": self.settings["element"], "RelatedOpeningElement": self.settings["opening"] }) diff --git a/src/ifcblenderexport/blenderbim/bim/module/void/data.py b/src/ifcopenshell-python/ifcopenshell/api/void/data.py similarity index 95% rename from src/ifcblenderexport/blenderbim/bim/module/void/data.py rename to src/ifcopenshell-python/ifcopenshell/api/void/data.py index 84c80f3fb0..1f8da638ee 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/void/data.py +++ b/src/ifcopenshell-python/ifcopenshell/api/void/data.py @@ -1,6 +1,3 @@ -from blenderbim.bim.ifc import IfcStore - - class Data: products = {} openings = {} @@ -13,8 +10,7 @@ class Data: cls.fillings = {} @classmethod - def load(cls, product_id): - file = IfcStore.get_file() + def load(cls, file, product_id): if not file: return cls.products[product_id] = set() diff --git a/src/ifcblenderexport/blenderbim/bim/module/void/remove_filling.py b/src/ifcopenshell-python/ifcopenshell/api/void/remove_filling.py similarity index 89% rename from src/ifcblenderexport/blenderbim/bim/module/void/remove_filling.py rename to src/ifcopenshell-python/ifcopenshell/api/void/remove_filling.py index 105acb9160..a805d44b41 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/void/remove_filling.py +++ b/src/ifcopenshell-python/ifcopenshell/api/void/remove_filling.py @@ -1,5 +1,5 @@ class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = {"element": None} for key, value in settings.items(): diff --git a/src/ifcblenderexport/blenderbim/bim/module/void/remove_opening.py b/src/ifcopenshell-python/ifcopenshell/api/void/remove_opening.py similarity index 94% rename from src/ifcblenderexport/blenderbim/bim/module/void/remove_opening.py rename to src/ifcopenshell-python/ifcopenshell/api/void/remove_opening.py index cc84466790..d89d44c2e0 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/void/remove_opening.py +++ b/src/ifcopenshell-python/ifcopenshell/api/void/remove_opening.py @@ -1,5 +1,5 @@ class Usecase: - def __init__(self, file, settings=None): + def __init__(self, file, **settings): self.file = file self.settings = {"opening": None} for key, value in settings.items(): diff --git a/src/ifcopenshell-python/ifcopenshell/util/attribute.py b/src/ifcopenshell-python/ifcopenshell/util/attribute.py index 35d61c7b0a..5e56c62f2f 100644 --- a/src/ifcopenshell-python/ifcopenshell/util/attribute.py +++ b/src/ifcopenshell-python/ifcopenshell/util/attribute.py @@ -3,7 +3,9 @@ def get_primitive_type(attribute_or_data_type): data_type = str(attribute_or_data_type.type_of_attribute()) else: data_type = str(attribute_or_data_type) - if " +#include #include "SvgSerializer.h" @@ -88,7 +89,7 @@ bool SvgSerializer::ready() { return true; } -void SvgSerializer::write(path_object& p, const TopoDS_Wire& wire) { +void SvgSerializer::write(path_object& p, const TopoDS_Wire& wire, boost::optional> dash_array) { /* ShapeFix_Wire fix; Handle(ShapeExtend_WireData) data = new ShapeExtend_WireData; for (TopExp_Explorer edges(result, TopAbs_EDGE); edges.More(); edges.Next()) { @@ -301,7 +302,22 @@ void SvgSerializer::write(path_object& p, const TopoDS_Wire& wire) { first = false; } - path.add("\"/>\n"); + path.add("\""); + + if (dash_array) { + path.add(" stroke-dasharray=\""); + bool first = true; + for (auto& d : *dash_array) { + if (!first) { + path.add(" "); + } + first = false; + radii.push_back(path.add(d)); + } + path.add("\""); + } + + path.add("/>\n"); p.second.push_back(path); } @@ -422,6 +438,68 @@ namespace { return box_t{ {{x0, y0, z0}}, {{x1, y1, z1}} }; } + + struct string_property { + std::string pset_name, prop_name, value; + }; + + template + void enumerate_string_properties(IfcUtil::IfcBaseEntity* product, It output_it) { + auto rels = product->get_inverse("IsDefinedBy"); + for (auto& rel : *rels) { + if (rel->declaration().is("IfcRelDefinesByProperties")) { + auto pset = (IfcUtil::IfcBaseEntity*) (IfcUtil::IfcBaseClass*) *((IfcUtil::IfcBaseEntity*) rel)->get("RelatingPropertyDefinition"); + std::string pset_name; + if (!pset->get("Name")->isNull()) { + pset_name = (std::string) *pset->get("Name"); + } + IfcEntityList::ptr props = *pset->get("HasProperties"); + for (auto& prop : *props) { + if (prop->declaration().is("IfcPropertySingleValue")) { + std::string name = *((IfcUtil::IfcBaseEntity*) prop)->get("Name"); + IfcUtil::IfcBaseClass* v = *((IfcUtil::IfcBaseEntity*) prop)->get("NominalValue"); + auto value = v->data().getArgument(0); + if (value->type() == IfcUtil::Argument_STRING) { + std::string v_str = *value; + *output_it++ = string_property{ pset_name, name, v_str }; + } + } + } + } + } + } +} + +namespace { + boost::optional get_curve_style_name(IfcUtil::IfcBaseEntity* item) { + auto refs = item->get_inverse("StyledByItem"); + for (auto& ref : *refs) { + if (ref->declaration().is("IfcStyledItem")) { + IfcEntityList::ptr styles = *((IfcUtil::IfcBaseEntity*)ref)->get("Styles"); + for (auto& s_ : *styles) { + auto s = (IfcUtil::IfcBaseEntity*) s_; + std::vector pss; + if (s->declaration().is("IfcPresentationStyleAssignment")) { + IfcEntityList::ptr pstyles = *s->get("Styles"); + for (auto& ssss : *pstyles) { + pss.push_back((IfcUtil::IfcBaseEntity*) ssss); + } + } else { + pss.push_back(s); + } + for (auto& ps : pss) { + if (ps->declaration().is("IfcCurveStyle")) { + auto arg = ps->get("Name"); + if (!arg->isNull()) { + return (std::string) *arg; + } + } + } + } + } + } + return boost::none; + } } void SvgSerializer::write(const IfcGeom::BRepElement* brep_obj) { @@ -431,7 +509,36 @@ void SvgSerializer::write(const IfcGeom::BRepElement* brep_obj) { object_type = static_cast(*brep_obj->product()->get("ObjectType")); } + std::vector>> dash_arrays; + TopoDS_Shape compound_local = brep_obj->geometry().as_compound(); + for (auto& x : brep_obj->geometry()) { + dash_arrays.emplace_back(); + + auto item = (IfcUtil::IfcBaseEntity*) this->file->instance_by_id(x.ItemId()); + auto curve_style_name = get_curve_style_name(item); + + if (curve_style_name && + (boost::starts_with(*curve_style_name, "LINE_") || + boost::starts_with(*curve_style_name, "DASH_"))) + { + std::vector tokens; + boost::split(tokens, *curve_style_name, boost::is_any_of("_")); + if (tokens.size() > 1) { + dash_arrays.back().emplace(); + for (auto& tok : tokens) { + double d; + try { + d = boost::lexical_cast(tok); + } catch (boost::bad_lexical_cast&) { + continue; + } + dash_arrays.back()->push_back(d / 1000.); + } + } + } + } + const gp_Trsf& trsf = brep_obj->transformation().data(); const bool is_section = (section_ref_ && object_type && *section_ref_ == *object_type); @@ -443,6 +550,9 @@ void SvgSerializer::write(const IfcGeom::BRepElement* brep_obj) { // (When determinant < 0, copy is implied and the input is not mutated.) auto compound_unmirrored = make_transform_global.Shape(); + boost::optional scale; + boost::optional> size; + auto e = edge_from_compound(compound_unmirrored); boost::optional pln; if (e) { @@ -457,8 +567,39 @@ void SvgSerializer::write(const IfcGeom::BRepElement* brep_obj) { pln = gp_Pln(gp_Ax3(P, N, V)); } } - else if (box_from_compound(compound_local)) { + else if (boost::optional b = box_from_compound(compound_local)) { pln = gp_Pln().Transformed(trsf); + size = std::make_pair( + b->second[0] - b->first[0], + b->second[1] - b->first[1] + ); + } + + std::vector props; + enumerate_string_properties(brep_obj->product(), std::back_inserter(props)); + std::map prop_map; + for (auto& p : props) { + prop_map[p.pset_name + "." + p.prop_name] = p.value; + } + auto pit = prop_map.find("EPset_Drawing.Scale"); + if (pit != prop_map.end()) { + typedef boost::tokenizer> tokenizer; + tokenizer tok{ pit->second }; + auto tokit = tok.begin(); + std::string num, denum; + if (tokit != tok.end()) { + num = *tokit++; + } + tokit++; + if (tokit != tok.end()) { + denum = *tokit++; + } + if (num.size() && denum.size()) { + try { + scale = (float) boost::lexical_cast(num) / boost::lexical_cast(denum); + } + catch (boost::bad_lexical_cast&) {} + } } if (pln) { @@ -477,10 +618,10 @@ void SvgSerializer::write(const IfcGeom::BRepElement* brep_obj) { name = boost::lexical_cast(brep_obj->id()); } if (is_section) { - deferred_section_data_->push_back(vertical_section{ *pln , "Section " + name, false }); + deferred_section_data_->push_back(vertical_section{ *pln , "Section " + name, false, scale, size }); } if (is_elevation) { - deferred_section_data_->push_back(vertical_section{ *pln , "Elevation " + name, true }); + deferred_section_data_->push_back(vertical_section{ *pln , "Elevation " + name, true, scale, size }); } } @@ -491,7 +632,7 @@ void SvgSerializer::write(const IfcGeom::BRepElement* brep_obj) { IfcUtil::IfcBaseEntity* storey = p ? p->first : nullptr; double elev = p ? p->second : std::numeric_limits::quiet_NaN(); // @todo is it correct to call nameElement() here with a single storey (what if this element spans multiple?) - geometry_data data{ compound_local, trsf, brep_obj->product(), storey, elev, brep_obj->name(), nameElement(storey, brep_obj) }; + geometry_data data{ compound_local, dash_arrays, trsf, brep_obj->product(), storey, elev, brep_obj->name(), nameElement(storey, brep_obj) }; if (auto_section_ || auto_elevation_ || section_ref_ || elevation_ref_) { element_buffer_.push_back(data); @@ -819,13 +960,14 @@ void SvgSerializer::write(const geometry_data& data) { } TopoDS_Iterator it(compound_to_use); + auto dash_it = data.dash_arrays.begin(); TopoDS_Face largest_closed_wire_face; double largest_closed_wire_area = 0.; path_object* po = nullptr; // Iterate over components of compound to have better chance of matching section edges to closed wires - for (; it.More(); it.Next()) { + for (; it.More(); it.Next(), ++dash_it) { const TopoDS_Shape& subshape = it.Value(); @@ -965,7 +1107,7 @@ void SvgSerializer::write(const geometry_data& data) { TopExp_Explorer exp(subshape, TopAbs_WIRE, TopAbs_FACE); for (; exp.More(); exp.Next()) { const auto& W = TopoDS::Wire(exp.Current()); - write(*po, W); + write(*po, W, *dash_it); } } @@ -1094,7 +1236,8 @@ void SvgSerializer::write(const geometry_data& data) { auto d = (p1.XYZ() - p0.XYZ()); d.Normalize(); - d *= 3; + const double shll = storey_height_line_length_.get_value_or(2.); + d *= shll; gp_Pnt p1x(p0.XYZ() + d); wire = BRepBuilderAPI_MakePolygon(p0, p1x).Wire(); @@ -1202,7 +1345,11 @@ void SvgSerializer::write(const geometry_data& data) { xcoords.push_back(path.add(center_point->X())); path.add("\" y=\""); ycoords.push_back(path.add(center_point->Y())); - path.add("\">"); + path.add("\""); + if (space_name_transform_) { + path.add(" transform=\"" + *space_name_transform_ + "\""); + } + path.add(">"); for (auto lit = labels.begin(); lit != labels.end(); ++lit) { const auto& l = *lit; double dy = labels.begin() == lit @@ -1233,16 +1380,14 @@ void SvgSerializer::write(const geometry_data& data) { } void SvgSerializer::setBoundingRectangle(double width, double height) { - this->width = width; - this->height = height; - this->rescale = true; + size_ = std::make_pair(width, height); } std::array, 3> SvgSerializer::resize() { // identity matrix; std::array, 3> m = {{ {{1,0,0}},{{0,1,0}},{{0,0,1}} }}; - if (rescale) { + if (size_) { // Scale the resulting image to a bounding rectangle specified by command line arguments const double dx = xmax - xmin; const double dy = ymax - ymin; @@ -1250,19 +1395,19 @@ std::array, 3> SvgSerializer::resize() { double sc, cx, cy; if (scale_) { sc = (*scale_) * 1000; - cx = (xmax + xmin) / 2. * sc - width * center_x_.get_value_or(0.5); - cy = (ymax + ymin) / 2. * sc - height * center_y_.get_value_or(0.5); + cx = (xmax + xmin) / 2. * sc - size_->first * center_x_.get_value_or(0.5); + cy = (ymax + ymin) / 2. * sc - size_->second * center_y_.get_value_or(0.5); } else { if (calculated_scale_) { sc = *calculated_scale_; } else { - if (dx / width > dy / height) { - sc = width / dx; + if (dx / size_->first > dy / size_->second) { + sc = size_->first / dx; } else { - sc = height / dy; + sc = size_->second / dy; } calculated_scale_ = sc; } @@ -1541,7 +1686,9 @@ void SvgSerializer::finalize() { double x0, y0, z0, x1, y1, z1; bnd_.Get(x0, y0, z0, x1, y1, z1); - BRepBuilderAPI_MakeFace mf(elev_pln, x0 - 1., x1 + 1., y0 - 1., y1 + 1.); + const double shll = storey_height_line_length_.get_value_or(2.); + + BRepBuilderAPI_MakeFace mf(elev_pln, x0 - shll, x1 + shll, y0 - shll, y1 + shll); gp_Trsf trsf; TopoDS_Compound C; BRep_Builder B; @@ -1553,7 +1700,7 @@ void SvgSerializer::finalize() { name = (std::string) *a2; } write(geometry_data{ - C,trsf,storey,storey,elev,name,nameElement(storey) + C,{boost::none},trsf,storey,storey,elev,name,nameElement(storey) }); } } @@ -1609,11 +1756,11 @@ void SvgSerializer::writeHeader() { if (use_namespace_) { svg_file << " xmlns:ifc=\"http://www.ifcopenshell.org/ns\""; } - if (scale_) { + if (scale_ && size_) { svg_file << - " width=\"" << width << "mm\"" - " height=\"" << height << "mm\"" << - " viewBox=\"0 0 " << width << " " << height << "\""; + " width=\"" << size_->first << "mm\"" + " height=\"" << size_->second << "mm\"" << + " viewBox=\"0 0 " << size_->first << " " << size_->second << "\""; } svg_file << ">\n" diff --git a/src/serializers/SvgSerializer.h b/src/serializers/SvgSerializer.h index 7b19e0434e..0772e03bdb 100644 --- a/src/serializers/SvgSerializer.h +++ b/src/serializers/SvgSerializer.h @@ -97,12 +97,15 @@ struct vertical_section { gp_Pln plane; std::string name; bool with_projection; + boost::optional scale; + boost::optional> size; }; typedef boost::variant section_data; struct geometry_data { TopoDS_Shape compound_local; + std::vector>> dash_arrays; gp_Trsf trsf; IfcUtil::IfcBaseEntity* product; IfcUtil::IfcBaseEntity* storey; @@ -130,12 +133,15 @@ public: }; protected: std::ofstream svg_file; - double xmin, ymin, xmax, ymax, width, height; + double xmin, ymin, xmax, ymax; boost::optional> section_data_; boost::optional> deferred_section_data_; - boost::optional scale_, calculated_scale_, center_x_, center_y_; + boost::optional scale_, calculated_scale_, center_x_, center_y_, scale_backup_; + boost::optional storey_height_line_length_; + boost::optional> size_, size_backup_; + boost::optional space_name_transform_; - bool with_section_heights_from_storey_, rescale, print_space_names_, print_space_areas_; + bool with_section_heights_from_storey_, print_space_names_, print_space_areas_; storey_height_display_types storey_height_display_; bool draw_door_arcs_, is_floor_plan_; bool auto_section_, auto_elevation_; @@ -173,7 +179,6 @@ public: , xmax(-std::numeric_limits::infinity()) , ymax(-std::numeric_limits::infinity()) , with_section_heights_from_storey_(false) - , rescale(false) , print_space_names_(false) , print_space_areas_(false) , draw_door_arcs_(false) @@ -198,7 +203,7 @@ public: bool ready(); void write(const IfcGeom::TriangulationElement* /*o*/) {} void write(const IfcGeom::BRepElement* o); - void write(path_object& p, const TopoDS_Wire& wire); + void write(path_object& p, const TopoDS_Wire& wire, boost::optional> dash_array=boost::none); void write(const geometry_data& data); path_object& start_path(const gp_Pln& p, IfcUtil::IfcBaseEntity* storey, const std::string& id); path_object& start_path(const gp_Pln& p, const std::string& drawing_name, const std::string& id); @@ -213,6 +218,8 @@ public: void setPrintSpaceAreas(bool b) { print_space_areas_ = b; } void setDrawStoreyHeights(storey_height_display_types sh) { storey_height_display_ = sh; } void setDrawDoorArcs(bool b) { draw_door_arcs_ = b; } + void setStoreyHeightLineLength(double d) { storey_height_line_length_ = d; } + void setSpaceNameTransform(const std::string& v) { space_name_transform_ = v; } std::array, 3> resize(); void resetScale();