mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-30 03:59:55 +00:00
WIP create aggregation module to manipulate aggregations. See #1222.
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
import bpy
|
||||
from . import ui, operator
|
||||
|
||||
classes = (
|
||||
operator.AssignObject,
|
||||
operator.EnableEditingAggregate,
|
||||
operator.DisableEditingAggregate,
|
||||
ui.BIM_PT_aggregate,
|
||||
)
|
||||
|
||||
|
||||
def register():
|
||||
pass
|
||||
|
||||
|
||||
def unregister():
|
||||
pass
|
||||
@@ -0,0 +1,49 @@
|
||||
import ifcopenshell
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, settings=None):
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"product": None,
|
||||
"relating_object": None,
|
||||
}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
decomposes = None
|
||||
if self.settings["product"].Decomposes:
|
||||
decomposes = self.settings["product"].Decomposes[0]
|
||||
|
||||
is_decomposed_by = None
|
||||
for rel in self.settings["relating_object"].IsDecomposedBy:
|
||||
if rel.is_a("IfcRelAggregates"):
|
||||
is_decomposed_by = rel
|
||||
break
|
||||
|
||||
if decomposes and decomposes == is_decomposed_by:
|
||||
return
|
||||
|
||||
if decomposes:
|
||||
related_objects = list(decomposes.RelatedObjects)
|
||||
related_objects.remove(self.settings["product"])
|
||||
if related_objects:
|
||||
decomposes.RelatedObjects = related_objects
|
||||
else:
|
||||
self.file.remove(decomposes)
|
||||
|
||||
if is_decomposed_by:
|
||||
related_objects = list(is_decomposed_by.RelatedObjects)
|
||||
related_objects.append(self.settings["product"])
|
||||
is_decomposed_by.RelatedObjects = related_objects
|
||||
else:
|
||||
is_decomposed_by = self.file.create_entity(
|
||||
"IfcRelAggregates",
|
||||
**{
|
||||
"GlobalId": ifcopenshell.guid.new(),
|
||||
# TODO "OwnerHistory": None
|
||||
"RelatedObjects": [self.settings["product"]],
|
||||
"RelatingObject": self.settings["relating_object"],
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,17 @@
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
|
||||
|
||||
class Data:
|
||||
products = {}
|
||||
|
||||
@classmethod
|
||||
def load(cls, product_id):
|
||||
file = IfcStore.get_file()
|
||||
if not file:
|
||||
return
|
||||
product = file.by_id(product_id)
|
||||
if product.Decomposes and product.Decomposes[0].is_a("IfcRelAggregates"):
|
||||
obj = product.Decomposes[0].RelatingObject
|
||||
cls.products[product_id] = {"type": obj.is_a(), "Name": obj.Name, "id": int(obj.id())}
|
||||
else:
|
||||
cls.products[product_id] = {"type": None, "Name": None, "id": None}
|
||||
@@ -0,0 +1,47 @@
|
||||
import bpy
|
||||
import blenderbim.bim.module.aggregate.assign_object as assign_object
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
from blenderbim.bim.module.aggregate.data import Data
|
||||
|
||||
|
||||
class AssignObject(bpy.types.Operator):
|
||||
bl_idname = "bim.assign_object"
|
||||
bl_label = "Assign Object"
|
||||
|
||||
def execute(self, context):
|
||||
self.file = IfcStore.get_file()
|
||||
obj = bpy.context.active_object
|
||||
props = obj.BIMObjectProperties
|
||||
relating_object = props.relating_object
|
||||
if not relating_object or not relating_object.BIMObjectProperties.ifc_definition_id:
|
||||
return {"FINISHED"}
|
||||
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()
|
||||
Data.load(props.ifc_definition_id)
|
||||
bpy.ops.bim.disable_editing_aggregate()
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class EnableEditingAggregate(bpy.types.Operator):
|
||||
bl_idname = "bim.enable_editing_aggregate"
|
||||
bl_label = "Enable Editing Aggregate"
|
||||
|
||||
def execute(self, context):
|
||||
bpy.context.active_object.BIMObjectProperties.relating_object = None
|
||||
bpy.context.active_object.BIMObjectProperties.is_editing_aggregate = True
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class DisableEditingAggregate(bpy.types.Operator):
|
||||
bl_idname = "bim.disable_editing_aggregate"
|
||||
bl_label = "Disable Editing Aggregate"
|
||||
|
||||
def execute(self, context):
|
||||
bpy.context.active_object.BIMObjectProperties.is_editing_aggregate = False
|
||||
return {"FINISHED"}
|
||||
@@ -0,0 +1,43 @@
|
||||
from bpy.types import Panel
|
||||
from blenderbim.bim.module.aggregate.data import Data
|
||||
|
||||
|
||||
class BIM_PT_aggregate(Panel):
|
||||
bl_label = "IFC Aggregation"
|
||||
bl_idname = "BIM_PT_aggregate"
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "object"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
props = context.active_object.BIMObjectProperties
|
||||
if not props.ifc_definition_id:
|
||||
return False
|
||||
if props.ifc_definition_id not in Data.products:
|
||||
Data.load(props.ifc_definition_id)
|
||||
if not Data.products[props.ifc_definition_id]:
|
||||
return False
|
||||
return True
|
||||
|
||||
def draw(self, context):
|
||||
props = context.active_object.BIMObjectProperties
|
||||
if not props.ifc_definition_id:
|
||||
return
|
||||
if props.ifc_definition_id not in Data.products:
|
||||
Data.load(props.ifc_definition_id)
|
||||
|
||||
if props.is_editing_aggregate:
|
||||
row = self.layout.row(align=True)
|
||||
row.prop(props, "relating_object", text="")
|
||||
row.operator("bim.assign_object", icon="CHECKMARK", text="")
|
||||
row.operator("bim.disable_editing_aggregate", icon="X", text="")
|
||||
else:
|
||||
row = self.layout.row(align=True)
|
||||
name = "{}/{}".format(
|
||||
Data.products[props.ifc_definition_id]["type"], Data.products[props.ifc_definition_id]["Name"]
|
||||
)
|
||||
if name == "None/None":
|
||||
name = "This object is not part of an aggregation"
|
||||
row.label(text=name)
|
||||
row.operator("bim.enable_editing_aggregate", icon="GREASEPENCIL", text="")
|
||||
@@ -59,14 +59,12 @@ class EditAttributes(bpy.types.Operator):
|
||||
blender_attribute = props.attributes.get(attribute["name"])
|
||||
if not blender_attribute:
|
||||
continue
|
||||
if blender_attribute.is_null:
|
||||
if attribute["is_optional"] and blender_attribute.is_null:
|
||||
attributes[attribute["name"]] = None
|
||||
elif attribute["type"] == "string":
|
||||
attributes[attribute["name"]] = blender_attribute.string_value
|
||||
elif attribute["type"] == "list":
|
||||
values = blender_attribute.string_value[1:-1].split(", ")
|
||||
print(attribute["name"])
|
||||
print(attribute["list_type"])
|
||||
if attribute["list_type"] == "float":
|
||||
values = [float(v) for v in values]
|
||||
elif attribute["list_type"] == "integer":
|
||||
|
||||
@@ -15,10 +15,10 @@ class BIM_PT_class(Panel):
|
||||
if props.ifc_definition_id not in Data.products:
|
||||
Data.load(props.ifc_definition_id)
|
||||
if props.is_reassigning_class:
|
||||
self.draw_class_dropdowns()
|
||||
row = self.layout.row(align=True)
|
||||
row.operator("bim.reassign_class", icon="CHECKMARK")
|
||||
row.operator("bim.disable_reassign_class", icon="X", text="")
|
||||
self.draw_class_dropdowns()
|
||||
else:
|
||||
data = Data.products[props.ifc_definition_id]
|
||||
name = data["type"]
|
||||
|
||||
@@ -31,5 +31,7 @@ class BIM_PT_spatial(Panel):
|
||||
name = "{}/{}".format(
|
||||
Data.products[props.ifc_definition_id]["type"], Data.products[props.ifc_definition_id]["Name"]
|
||||
)
|
||||
if name == "None/None":
|
||||
name = "This object is not spatially contained"
|
||||
row.label(text=name)
|
||||
row.operator("bim.assign_container", icon="FILE_REFRESH", text="")
|
||||
|
||||
Reference in New Issue
Block a user