WIP you can now start a fresh project with partial editing support. See #1222.

This commit is contained in:
Dion Moult
2021-01-05 21:15:52 +11:00
parent f76d792a25
commit 113efa1206
16 changed files with 217 additions and 213 deletions
@@ -7,22 +7,23 @@ from blenderbim.bim.module.aggregate.data import Data
class AssignObject(bpy.types.Operator):
bl_idname = "bim.assign_object"
bl_label = "Assign Object"
relating_object: bpy.props.StringProperty()
related_object: bpy.props.StringProperty()
def execute(self, context):
self.file = IfcStore.get_file()
obj = bpy.context.active_object
obj = bpy.data.objects.get(self.related_object) if self.related_object else bpy.context.active_object
props = obj.BIMObjectProperties
relating_object = props.relating_object
relating_object = bpy.data.objects.get(self.relating_object) if self.relating_object else props.relating_object
if not relating_object or not relating_object.BIMObjectProperties.ifc_definition_id:
return {"FINISHED"}
usecase = assign_object.Usecase(
assign_object.Usecase(
self.file,
{
"product": self.file.by_id(props.ifc_definition_id),
"relating_object": self.file.by_id(relating_object.BIMObjectProperties.ifc_definition_id),
},
)
usecase.execute()
).execute()
Data.load(props.ifc_definition_id)
bpy.ops.bim.disable_editing_aggregate()
return {"FINISHED"}
@@ -18,8 +18,17 @@ class Usecase:
if not parent:
self.create_origin()
if self.settings["context"] == "Plan":
return self.file.createIfcGeometricRepresentationContext(None, "Plan", 2, 1.0e-05, self.origin)
return self.file.createIfcGeometricRepresentationContext(None, "Model", 3, 1.0e-05, self.origin)
context = self.file.createIfcGeometricRepresentationContext(None, "Plan", 2, 1.0e-05, self.origin)
else:
context = self.file.createIfcGeometricRepresentationContext(None, "Model", 3, 1.0e-05, self.origin)
project = self.file.by_type("IfcProject")[0]
if project.RepresentationContexts:
contexts = list(project.RepresentationContexts)
else:
contexts = []
contexts.append(context)
project.RepresentationContexts = contexts
return context
parent = parent[0]
return self.file.create_entity("IfcGeometricRepresentationSubContext", **{
"ContextIdentifier": self.settings["subcontext"],
@@ -8,18 +8,20 @@ from blenderbim.bim.module.context.data import Data
class AddSubcontext(bpy.types.Operator):
bl_idname = "bim.add_subcontext"
bl_label = "Add Subcontext"
context: bpy.props.StringProperty()
subcontext: bpy.props.StringProperty()
target_view: bpy.props.StringProperty()
def execute(self, context):
self.file = IfcStore.get_file()
usecase = add_context.Usecase(
add_context.Usecase(
self.file,
{
"context": bpy.context.scene.BIMProperties.available_contexts,
"subcontext": bpy.context.scene.BIMProperties.available_subcontexts,
"target_view": bpy.context.scene.BIMProperties.available_target_views,
"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,
},
)
result = usecase.execute()
).execute()
Data.load()
return {"FINISHED"}
@@ -10,6 +10,8 @@ class Usecase:
self.settings[key] = value
def execute(self):
if not hasattr(self.settings["product"], "ObjectPlacement"):
return
self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(self.file)
if not self.settings["product"].ObjectPlacement:
placement_rel_to = None
@@ -0,0 +1,15 @@
import bpy
from . import ui, operator
classes = (
operator.CreateProject,
ui.BIM_PT_project,
)
def register():
pass
def unregister():
pass
@@ -0,0 +1,25 @@
import datetime
import ifcopenshell
class Usecase:
def __init__(self, settings=None):
self.settings = {"version": "IFC4"}
for key, value in settings.items():
self.settings[key] = value
def execute(self):
self.file = ifcopenshell.file(schema=self.settings["version"])
# TODO: add all metadata, pending bug #747
self.file.wrapped_data.header.file_name.name = "/dev/null" # Hehehe
self.file.wrapped_data.header.file_name.time_stamp = (
datetime.datetime.utcnow()
.replace(tzinfo=datetime.timezone.utc)
.astimezone()
.replace(microsecond=0)
.isoformat()
)
self.file.wrapped_data.header.file_name.preprocessor_version = "IfcOpenShell {}".format(ifcopenshell.version)
self.file.wrapped_data.header.file_name.originating_system = "IfcOpenShell {}".format(ifcopenshell.version)
self.file.wrapped_data.header.file_name.authorization = "Nobody"
return self.file
@@ -0,0 +1,68 @@
import bpy
import ifcopenshell
import blenderbim.bim.module.project.create_file as create_file
import blenderbim.bim.module.context.add_context as add_context
import blenderbim.bim.module.root.create_product as create_product
import blenderbim.bim.module.aggregate.assign_object as assign_object
import bpy
from blenderbim.bim.ifc import IfcStore
# from blenderbim.bim.module.project.data import Data
class CreateProject(bpy.types.Operator):
bl_idname = "bim.create_project"
bl_label = "Create Project"
def execute(self, context):
self.file = IfcStore.get_file()
if self.file:
return {"FINISHED"}
IfcStore.file = create_file.Usecase({"version": bpy.context.scene.BIMProperties.export_schema}).execute()
self.file = IfcStore.get_file()
project = bpy.data.collections.new("My Project")
site = bpy.data.collections.new("My Site")
building = bpy.data.collections.new("My Building")
building_storey = bpy.data.collections.new("Ground Floor")
project_obj = bpy.data.objects.new("My Project", None)
site_obj = bpy.data.objects.new("My Site", None)
building_obj = bpy.data.objects.new("My Building", None)
building_storey_obj = bpy.data.objects.new("Ground Floor", None)
bpy.context.scene.collection.children.link(project)
project.children.link(site)
site.children.link(building)
building.children.link(building_storey)
project.objects.link(project_obj)
site.objects.link(site_obj)
building.objects.link(building_obj)
building_storey.objects.link(building_storey_obj)
bpy.ops.bim.assign_class(obj=project_obj.name, ifc_class="IfcProject")
bpy.ops.bim.assign_unit()
bpy.ops.bim.add_subcontext(context="Model")
bpy.ops.bim.add_subcontext(context="Model", subcontext="Body", target_view="MODEL_VIEW")
bpy.ops.bim.add_subcontext(context="Model", subcontext="Box", target_view="MODEL_VIEW")
bpy.ops.bim.add_subcontext(context="Plan")
bpy.ops.bim.add_subcontext(context="Plan", subcontext="Annotation", target_view="PLAN_VIEW")
bpy.ops.bim.assign_class(obj=site_obj.name, ifc_class="IfcSite")
bpy.ops.bim.assign_class(obj=building_obj.name, ifc_class="IfcBuilding")
bpy.ops.bim.assign_class(obj=building_storey_obj.name, ifc_class="IfcBuildingStorey")
bpy.ops.bim.assign_object(related_object=site_obj.name, relating_object=project_obj.name)
bpy.ops.bim.assign_object(related_object=building_obj.name, relating_object=site_obj.name)
bpy.ops.bim.assign_object(related_object=building_storey_obj.name, relating_object=building_obj.name)
# Data.load()
return {"FINISHED"}
def assign_object(self, product, relating_object):
assign_object.Usecase(
self.file,
{
"product": product,
"relating_object": relating_object,
},
).execute()
@@ -0,0 +1,31 @@
from bpy.types import Panel
from blenderbim.bim.ifc import IfcStore
class BIM_PT_project(Panel):
bl_label = "IFC Project"
bl_idname = "BIM_PT_project"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "scene"
def draw(self, context):
self.layout.use_property_decorate = False
self.layout.use_property_split = True
self.file = IfcStore.get_file()
props = context.scene.BIMProperties
if self.file:
pass
else:
row = self.layout.row()
row.prop(props, "export_schema")
row = self.layout.row()
row.prop(context.scene.unit_settings, "system")
row = self.layout.row()
row.prop(context.scene.unit_settings, "length_unit")
row = self.layout.row()
row.prop(props, "area_unit", text="Area Unit")
row = self.layout.row()
row.prop(props, "volume_unit", text="Volume Unit")
row = self.layout.row()
row.operator("bim.create_project")
@@ -60,15 +60,14 @@ class ReassignClass(bpy.types.Operator):
predefined_type = bpy.context.scene.BIMProperties.ifc_predefined_type
if predefined_type == "USERDEFINED":
predefined_type = bpy.context.scene.BIMProperties.ifc_userdefined_type
usecase = reassign_class.Usecase(
product = reassign_class.Usecase(
self.file,
{
"product": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id),
"ifc_class": bpy.context.scene.BIMProperties.ifc_class,
"predefined_type": predefined_type,
},
)
product = usecase.execute()
).execute()
obj.name = "{}/{}".format(product.is_a(), "/".join(obj.name.split("/")[1:]))
obj.BIMObjectProperties.ifc_definition_id = int(product.id())
bpy.context.active_object.BIMObjectProperties.is_reassigning_class = False
@@ -78,48 +77,51 @@ class ReassignClass(bpy.types.Operator):
class AssignClass(bpy.types.Operator):
bl_idname = "bim.assign_class"
bl_label = "Assign IFC Class"
object_name: bpy.props.StringProperty()
obj: bpy.props.StringProperty()
ifc_class: bpy.props.StringProperty()
predefined_type: bpy.props.StringProperty()
userdefined_type: bpy.props.StringProperty()
def execute(self, context):
objects = [bpy.data.objects.get(self.object_name)] if self.object_name else bpy.context.selected_objects
objects = [bpy.data.objects.get(self.obj)] if self.obj else bpy.context.selected_objects
self.file = IfcStore.get_file()
for obj in objects:
if obj.BIMObjectProperties.ifc_definition_id:
continue
predefined_type = bpy.context.scene.BIMProperties.ifc_predefined_type
if predefined_type == "USERDEFINED":
predefined_type = bpy.context.scene.BIMProperties.ifc_userdefined_type
usecase = create_product.Usecase(
if self.predefined_type == "USERDEFINED":
predefined_type = self.ifc_userdefined_type
elif self.predefined_type == "":
predefined_type = None
else:
predefined_type = self.predefined_type
product = create_product.Usecase(
self.file,
{
"ifc_class": bpy.context.scene.BIMProperties.ifc_class,
"ifc_class": self.ifc_class,
"predefined_type": predefined_type,
"name": obj.name,
},
)
product = usecase.execute()
).execute()
usecase = add_object_placement.Usecase(
add_object_placement.Usecase(
self.file,
{
"product": product,
"matrix": np.array(obj.matrix_world),
},
)
result = usecase.execute()
).execute()
if obj.data:
usecase = add_representation.Usecase(
representation = add_representation.Usecase(
self.file,
{
"context": self.file.by_id(int(bpy.context.scene.BIMProperties.contexts)),
"geometry": obj.data,
"total_items": max(1, len(obj.material_slots)),
},
)
representation = usecase.execute()
).execute()
usecase = assign_styles.Usecase(
assign_styles.Usecase(
self.file,
{
"shape_representation": representation,
@@ -129,13 +131,11 @@ class AssignClass(bpy.types.Operator):
if s.material
],
},
)
usecase.execute()
).execute()
usecase = assign_representation.Usecase(
assign_representation.Usecase(
self.file, {"product": product, "representation": representation}
)
usecase.execute()
).execute()
relating_structure = None
for collection in obj.users_collection:
@@ -146,16 +146,15 @@ class AssignClass(bpy.types.Operator):
break
if relating_structure:
usecase = assign_container.Usecase(
assign_container.Usecase(
self.file,
{
"product": product,
"relating_structure": relating_structure,
},
)
usecase.execute()
).execute()
obj.name = "{}/{}".format(bpy.context.scene.BIMProperties.ifc_class, obj.name)
obj.name = "{}/{}".format(product.is_a(), obj.name)
obj.BIMObjectProperties.ifc_definition_id = int(product.id())
if bpy.context.scene.BIMProperties.ifc_product == "IfcElementType":
self.place_in_types_collection(obj)
@@ -1,6 +1,7 @@
import bpy
from bpy.types import Panel
from blenderbim.bim.module.root.data import Data
from blenderbim.bim.ifc import IfcStore
class BIM_PT_class(Panel):
bl_label = "IFC Class"
@@ -9,6 +10,10 @@ class BIM_PT_class(Panel):
bl_region_type = "WINDOW"
bl_context = "object"
@classmethod
def poll(cls, context):
return IfcStore.get_file()
def draw(self, context):
props = context.active_object.BIMObjectProperties
if props.ifc_definition_id:
@@ -35,7 +40,10 @@ class BIM_PT_class(Panel):
self.draw_class_dropdowns()
row = self.layout.row(align=True)
op = row.operator("bim.assign_class")
op.object_name = context.active_object.name
op.obj = context.active_object.name
op.ifc_class = bpy.context.scene.BIMProperties.ifc_class
op.predefined_type = bpy.context.scene.BIMProperties.ifc_predefined_type
op.userdefined_type = bpy.context.scene.BIMProperties.ifc_userdefined_type
def draw_class_dropdowns(self):
props = bpy.context.scene.BIMProperties