mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-13 02:47:48 +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:
|
||||
import bpy
|
||||
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.bcf as module_bcf
|
||||
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_aggregate.classes)
|
||||
classes.extend(module_attribute.classes)
|
||||
classes.extend(module_bcf.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.SCENE_PT_unit.append(ui.ifc_units)
|
||||
module_root.register()
|
||||
module_aggregate.register()
|
||||
module_attribute.register()
|
||||
module_bcf.register()
|
||||
module_context.register()
|
||||
@@ -384,5 +387,6 @@ if bpy is not None:
|
||||
module_context.unregister()
|
||||
module_bcf.unregister()
|
||||
module_attribute.register()
|
||||
module_aggregate.register()
|
||||
module_root.unregister()
|
||||
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"])
|
||||
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="")
|
||||
|
||||
@@ -3957,14 +3957,10 @@ class InspectFromObject(bpy.types.Operator):
|
||||
bl_label = "Inspect From Object"
|
||||
|
||||
def execute(self, context):
|
||||
global_id = bpy.context.active_object.BIMObjectProperties.attributes.get("GlobalId")
|
||||
if not global_id:
|
||||
ifc_definition_id = bpy.context.active_object.BIMObjectProperties.ifc_definition_id
|
||||
if not ifc_definition_id:
|
||||
return {"FINISHED"}
|
||||
global_id = global_id.string_value
|
||||
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())
|
||||
bpy.ops.bim.inspect_from_step_id(step_id=ifc_definition_id)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
|
||||
@@ -1461,6 +1461,8 @@ class BIMObjectProperties(PropertyGroup):
|
||||
global_ids: CollectionProperty(name="GlobalIds", type=GlobalId)
|
||||
attributes: CollectionProperty(name="Attributes", type=Attribute)
|
||||
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_structure: PointerProperty(name="Spatial Container", type=bpy.types.Object)
|
||||
psets: CollectionProperty(name="Psets", type=PsetQto)
|
||||
|
||||
Reference in New Issue
Block a user