mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-25 09:32:37 +00:00
WIP create aggregation module to manipulate aggregations. See #1222.
This commit is contained in:
@@ -6,6 +6,7 @@ bpy = sys.modules.get("bpy")
|
|||||||
if bpy is not None:
|
if bpy is not None:
|
||||||
import bpy
|
import bpy
|
||||||
import blenderbim.bim.module.root as module_root
|
import blenderbim.bim.module.root as module_root
|
||||||
|
import blenderbim.bim.module.aggregate as module_aggregate
|
||||||
import blenderbim.bim.module.attribute as module_attribute
|
import blenderbim.bim.module.attribute as module_attribute
|
||||||
import blenderbim.bim.module.bcf as module_bcf
|
import blenderbim.bim.module.bcf as module_bcf
|
||||||
import blenderbim.bim.module.context as module_context
|
import blenderbim.bim.module.context as module_context
|
||||||
@@ -311,6 +312,7 @@ if bpy is not None:
|
|||||||
]
|
]
|
||||||
|
|
||||||
classes.extend(module_root.classes)
|
classes.extend(module_root.classes)
|
||||||
|
classes.extend(module_aggregate.classes)
|
||||||
classes.extend(module_attribute.classes)
|
classes.extend(module_attribute.classes)
|
||||||
classes.extend(module_bcf.classes)
|
classes.extend(module_bcf.classes)
|
||||||
classes.extend(module_context.classes)
|
classes.extend(module_context.classes)
|
||||||
@@ -350,6 +352,7 @@ if bpy is not None:
|
|||||||
bpy.types.TextCurve.BIMTextProperties = bpy.props.PointerProperty(type=prop.BIMTextProperties)
|
bpy.types.TextCurve.BIMTextProperties = bpy.props.PointerProperty(type=prop.BIMTextProperties)
|
||||||
bpy.types.SCENE_PT_unit.append(ui.ifc_units)
|
bpy.types.SCENE_PT_unit.append(ui.ifc_units)
|
||||||
module_root.register()
|
module_root.register()
|
||||||
|
module_aggregate.register()
|
||||||
module_attribute.register()
|
module_attribute.register()
|
||||||
module_bcf.register()
|
module_bcf.register()
|
||||||
module_context.register()
|
module_context.register()
|
||||||
@@ -384,5 +387,6 @@ if bpy is not None:
|
|||||||
module_context.unregister()
|
module_context.unregister()
|
||||||
module_bcf.unregister()
|
module_bcf.unregister()
|
||||||
module_attribute.register()
|
module_attribute.register()
|
||||||
|
module_aggregate.register()
|
||||||
module_root.unregister()
|
module_root.unregister()
|
||||||
bpy.app.handlers.depsgraph_update_pre.remove(operator.depsgraph_update_pre_handler)
|
bpy.app.handlers.depsgraph_update_pre.remove(operator.depsgraph_update_pre_handler)
|
||||||
|
|||||||
@@ -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"])
|
blender_attribute = props.attributes.get(attribute["name"])
|
||||||
if not blender_attribute:
|
if not blender_attribute:
|
||||||
continue
|
continue
|
||||||
if blender_attribute.is_null:
|
if attribute["is_optional"] and blender_attribute.is_null:
|
||||||
attributes[attribute["name"]] = None
|
attributes[attribute["name"]] = None
|
||||||
elif attribute["type"] == "string":
|
elif attribute["type"] == "string":
|
||||||
attributes[attribute["name"]] = blender_attribute.string_value
|
attributes[attribute["name"]] = blender_attribute.string_value
|
||||||
elif attribute["type"] == "list":
|
elif attribute["type"] == "list":
|
||||||
values = blender_attribute.string_value[1:-1].split(", ")
|
values = blender_attribute.string_value[1:-1].split(", ")
|
||||||
print(attribute["name"])
|
|
||||||
print(attribute["list_type"])
|
|
||||||
if attribute["list_type"] == "float":
|
if attribute["list_type"] == "float":
|
||||||
values = [float(v) for v in values]
|
values = [float(v) for v in values]
|
||||||
elif attribute["list_type"] == "integer":
|
elif attribute["list_type"] == "integer":
|
||||||
|
|||||||
@@ -15,10 +15,10 @@ class BIM_PT_class(Panel):
|
|||||||
if props.ifc_definition_id not in Data.products:
|
if props.ifc_definition_id not in Data.products:
|
||||||
Data.load(props.ifc_definition_id)
|
Data.load(props.ifc_definition_id)
|
||||||
if props.is_reassigning_class:
|
if props.is_reassigning_class:
|
||||||
self.draw_class_dropdowns()
|
|
||||||
row = self.layout.row(align=True)
|
row = self.layout.row(align=True)
|
||||||
row.operator("bim.reassign_class", icon="CHECKMARK")
|
row.operator("bim.reassign_class", icon="CHECKMARK")
|
||||||
row.operator("bim.disable_reassign_class", icon="X", text="")
|
row.operator("bim.disable_reassign_class", icon="X", text="")
|
||||||
|
self.draw_class_dropdowns()
|
||||||
else:
|
else:
|
||||||
data = Data.products[props.ifc_definition_id]
|
data = Data.products[props.ifc_definition_id]
|
||||||
name = data["type"]
|
name = data["type"]
|
||||||
|
|||||||
@@ -31,5 +31,7 @@ class BIM_PT_spatial(Panel):
|
|||||||
name = "{}/{}".format(
|
name = "{}/{}".format(
|
||||||
Data.products[props.ifc_definition_id]["type"], Data.products[props.ifc_definition_id]["Name"]
|
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.label(text=name)
|
||||||
row.operator("bim.assign_container", icon="FILE_REFRESH", text="")
|
row.operator("bim.assign_container", icon="FILE_REFRESH", text="")
|
||||||
|
|||||||
@@ -3957,14 +3957,10 @@ class InspectFromObject(bpy.types.Operator):
|
|||||||
bl_label = "Inspect From Object"
|
bl_label = "Inspect From Object"
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
global_id = bpy.context.active_object.BIMObjectProperties.attributes.get("GlobalId")
|
ifc_definition_id = bpy.context.active_object.BIMObjectProperties.ifc_definition_id
|
||||||
if not global_id:
|
if not ifc_definition_id:
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
global_id = global_id.string_value
|
bpy.ops.bim.inspect_from_step_id(step_id=ifc_definition_id)
|
||||||
self.file = ifc.IfcStore.get_file()
|
|
||||||
element = self.file.by_guid(global_id)
|
|
||||||
if element:
|
|
||||||
bpy.ops.bim.inspect_from_step_id(step_id=element.id())
|
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1461,6 +1461,8 @@ class BIMObjectProperties(PropertyGroup):
|
|||||||
global_ids: CollectionProperty(name="GlobalIds", type=GlobalId)
|
global_ids: CollectionProperty(name="GlobalIds", type=GlobalId)
|
||||||
attributes: CollectionProperty(name="Attributes", type=Attribute)
|
attributes: CollectionProperty(name="Attributes", type=Attribute)
|
||||||
is_editing_attributes: BoolProperty(name="Is Editing Attributes")
|
is_editing_attributes: BoolProperty(name="Is Editing Attributes")
|
||||||
|
relating_object: PointerProperty(name="Aggregate", type=bpy.types.Object)
|
||||||
|
is_editing_aggregate: BoolProperty(name="Is Editing Aggregate")
|
||||||
relating_type: PointerProperty(name="Type Product", type=bpy.types.Object)
|
relating_type: PointerProperty(name="Type Product", type=bpy.types.Object)
|
||||||
relating_structure: PointerProperty(name="Spatial Container", type=bpy.types.Object)
|
relating_structure: PointerProperty(name="Spatial Container", type=bpy.types.Object)
|
||||||
psets: CollectionProperty(name="Psets", type=PsetQto)
|
psets: CollectionProperty(name="Psets", type=PsetQto)
|
||||||
|
|||||||
Reference in New Issue
Block a user