mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-24 03:57:56 +00:00
WIP migrate types to partial editing. See #1222.
This commit is contained in:
@@ -29,10 +29,7 @@ class AssignObject(bpy.types.Operator):
|
||||
Data.load(props.ifc_definition_id)
|
||||
bpy.ops.bim.disable_editing_aggregate(obj=related_object.name)
|
||||
|
||||
file = IfcStore.get_file()
|
||||
ifc_schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(file.schema)
|
||||
declaration = ifc_schema.declaration_by_name(product.is_a())
|
||||
|
||||
declaration = IfcStore.get_schema().declaration_by_name(product.is_a())
|
||||
# TODO: we may not need this conditional if aggregates stop using collection instances
|
||||
if ifcopenshell.util.schema.is_a(declaration, "IfcSpatialElement"):
|
||||
related_collection = related_object.users_collection[0]
|
||||
|
||||
@@ -13,8 +13,7 @@ class Data:
|
||||
product = file.by_id(product_id)
|
||||
cls.products[product_id] = []
|
||||
attributes = product.get_info()
|
||||
schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(file.schema)
|
||||
declaration = schema.declaration_by_name(product.is_a())
|
||||
declaration = IfcStore.get_schema().declaration_by_name(product.is_a())
|
||||
for attribute in declaration.all_attributes():
|
||||
data_type = str(attribute.type_of_attribute())
|
||||
value = getattr(product, attribute.name())
|
||||
|
||||
@@ -20,8 +20,6 @@ class EnableReassignClass(bpy.types.Operator):
|
||||
def execute(self, context):
|
||||
obj = bpy.context.active_object
|
||||
ifc_class = obj.name.split("/")[0]
|
||||
file = IfcStore.get_file()
|
||||
ifc_schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(file.schema)
|
||||
bpy.context.active_object.BIMObjectProperties.is_reassigning_class = True
|
||||
ifc_products = [
|
||||
"IfcElement",
|
||||
@@ -34,7 +32,7 @@ class EnableReassignClass(bpy.types.Operator):
|
||||
"IfcAnnotation",
|
||||
]
|
||||
for ifc_product in ifc_products:
|
||||
if ifcopenshell.util.schema.is_a(ifc_schema.declaration_by_name(ifc_class), ifc_product):
|
||||
if ifcopenshell.util.schema.is_a(IfcStore.get_schema().declaration_by_name(ifc_class), ifc_product):
|
||||
bpy.context.scene.BIMProperties.ifc_product = ifc_product
|
||||
bpy.context.scene.BIMProperties.ifc_class = obj.name.split("/")[0]
|
||||
predefined_type = obj.BIMObjectProperties.attributes.get("PredefinedType")
|
||||
@@ -87,8 +85,7 @@ class AssignClass(bpy.types.Operator):
|
||||
def execute(self, context):
|
||||
objects = [bpy.data.objects.get(self.obj)] if self.obj else bpy.context.selected_objects
|
||||
self.file = IfcStore.get_file()
|
||||
ifc_schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(self.file.schema)
|
||||
self.declaration = ifc_schema.declaration_by_name(self.ifc_class)
|
||||
self.declaration = IfcStore.get_schema().declaration_by_name(self.ifc_class)
|
||||
if self.predefined_type == "USERDEFINED":
|
||||
self.predefined_type = self.ifc_userdefined_type
|
||||
elif self.predefined_type == "":
|
||||
|
||||
@@ -15,7 +15,7 @@ class Usecase:
|
||||
contained_in_structure = self.settings["product"].ContainedInStructure
|
||||
contains_elements = self.settings["relating_structure"].ContainsElements
|
||||
|
||||
if contains_elements and contained_in_structure == contains_elements:
|
||||
if contains_elements and contained_in_structure and contained_in_structure[0] == contains_elements[0]:
|
||||
return
|
||||
|
||||
if contained_in_structure:
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import bpy
|
||||
from . import ui, operator
|
||||
|
||||
classes = (
|
||||
operator.AssignType,
|
||||
operator.UnassignType,
|
||||
operator.EnableEditingType,
|
||||
operator.DisableEditingType,
|
||||
operator.SelectSimilarType,
|
||||
ui.BIM_PT_type,
|
||||
)
|
||||
|
||||
|
||||
def register():
|
||||
pass
|
||||
|
||||
|
||||
def unregister():
|
||||
pass
|
||||
@@ -0,0 +1,51 @@
|
||||
import ifcopenshell
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, settings=None):
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"related_object": None,
|
||||
"relating_type": None,
|
||||
}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
if self.file.schema == "IFC2X3":
|
||||
is_typed_by = None
|
||||
is_defined_by = self.settings["related_object"].IsDefinedBy
|
||||
for rel in is_defined_by:
|
||||
if rel.is_a("IfcRelDefinesByType"):
|
||||
is_typed_by = [rel]
|
||||
break
|
||||
types = self.settings["relating_type"].ObjectTypeOf
|
||||
else:
|
||||
is_typed_by = self.settings["related_object"].IsTypedBy
|
||||
types = self.settings["relating_type"].Types
|
||||
|
||||
if types and is_typed_by == types:
|
||||
return
|
||||
|
||||
if is_typed_by:
|
||||
related_objects = list(is_typed_by[0].RelatedObjects)
|
||||
related_objects.remove(self.settings["related_object"])
|
||||
if related_objects:
|
||||
is_typed_by[0].RelatedObjects = related_objects
|
||||
else:
|
||||
self.file.remove(is_typed_by)
|
||||
|
||||
if types:
|
||||
related_objects = list(types[0].RelatedObjects)
|
||||
related_objects.append(self.settings["related_object"])
|
||||
types[0].RelatedObjects = related_objects
|
||||
else:
|
||||
types = self.file.create_entity(
|
||||
"IfcRelDefinesByType",
|
||||
**{
|
||||
"GlobalId": ifcopenshell.guid.new(),
|
||||
# TODO "OwnerHistory": None
|
||||
"RelatedObjects": [self.settings["related_object"]],
|
||||
"RelatingType": self.settings["relating_type"],
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,27 @@
|
||||
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 file.schema == "IFC2X3" and not hasattr(product, "IsDefinedBy"):
|
||||
cls.products[product_id] = None
|
||||
elif file.schema != "IFC2X3" and not hasattr(product, "IsTypedBy"):
|
||||
cls.products[product_id] = None
|
||||
elif hasattr(product, "IsTypedBy") and product.IsTypedBy:
|
||||
type = product.IsTypedBy[0].RelatingType
|
||||
cls.products[product_id] = {"type": type.is_a(), "Name": type.Name, "id": int(type.id())}
|
||||
elif hasattr(product, "IsDefinedBy") and product.IsDefinedBy:
|
||||
cls.products[product_id] = {"type": None, "Name": None}
|
||||
for rel in product.IsDefinedBy:
|
||||
if rel.is_a("IfcRelDefinesByType"):
|
||||
type = rel.RelatingType
|
||||
cls.products[product_id] = {"type": type.is_a(), "Name": type.Name, "id": int(type.id())}
|
||||
else:
|
||||
cls.products[product_id] = {"type": None, "Name": None, "id": None}
|
||||
@@ -0,0 +1,32 @@
|
||||
import ifcopenshell
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, settings=None):
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"related_object": None,
|
||||
"relating_type": None,
|
||||
}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
if self.settings["related_object"]:
|
||||
if self.file.schema == "IFC2X3":
|
||||
is_defined_by = self.settings["related_object"].IsDefinedBy
|
||||
for rel in is_defined_by:
|
||||
if rel.is_a("IfcRelDefinesByType"):
|
||||
return set([int(o.id()) for o in rel.RelatedObjects])
|
||||
else:
|
||||
is_typed_by = self.settings["related_object"].IsTypedBy
|
||||
if is_typed_by:
|
||||
return set([int(o.id()) for o in is_typed_by[0].RelatedObjects])
|
||||
elif self.settings["relating_type"]:
|
||||
if self.file.schema == "IFC2X3":
|
||||
types = self.settings["relating_type"].ObjectTypeOf
|
||||
else:
|
||||
types = self.settings["relating_type"].Types
|
||||
if types:
|
||||
return set([int(o.id()) for o in types[0].RelatedObjects])
|
||||
return set()
|
||||
@@ -0,0 +1,97 @@
|
||||
import bpy
|
||||
import ifcopenshell.util.schema
|
||||
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
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
from blenderbim.bim.module.type.data import Data
|
||||
|
||||
|
||||
class AssignType(bpy.types.Operator):
|
||||
bl_idname = "bim.assign_type"
|
||||
bl_label = "Assign Type"
|
||||
relating_type: bpy.props.StringProperty()
|
||||
related_object: bpy.props.StringProperty()
|
||||
|
||||
def execute(self, context):
|
||||
self.file = IfcStore.get_file()
|
||||
related_object = bpy.data.objects.get(self.related_object) if self.related_object else bpy.context.active_object
|
||||
props = related_object.BIMObjectProperties
|
||||
relating_type = bpy.data.objects.get(self.relating_type) if self.relating_type else props.relating_type
|
||||
if not relating_type or not relating_type.BIMObjectProperties.ifc_definition_id:
|
||||
return {"FINISHED"}
|
||||
assign_type.Usecase(
|
||||
self.file,
|
||||
{
|
||||
"related_object": self.file.by_id(props.ifc_definition_id),
|
||||
"relating_type": self.file.by_id(relating_type.BIMObjectProperties.ifc_definition_id),
|
||||
},
|
||||
).execute()
|
||||
Data.load(props.ifc_definition_id)
|
||||
bpy.ops.bim.disable_editing_type(obj=related_object.name)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class UnassignType(bpy.types.Operator):
|
||||
bl_idname = "bim.unassign_type"
|
||||
bl_label = "Unassign Type"
|
||||
related_object: bpy.props.StringProperty()
|
||||
|
||||
def execute(self, context):
|
||||
self.file = IfcStore.get_file()
|
||||
related_object = bpy.data.objects.get(self.related_object) if self.related_object else bpy.context.active_object
|
||||
props = related_object.BIMObjectProperties
|
||||
unassign_type.Usecase(
|
||||
self.file,
|
||||
{
|
||||
"related_object": self.file.by_id(props.ifc_definition_id),
|
||||
},
|
||||
).execute()
|
||||
Data.load(props.ifc_definition_id)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class EnableEditingType(bpy.types.Operator):
|
||||
bl_idname = "bim.enable_editing_type"
|
||||
bl_label = "Enable Editing Type"
|
||||
|
||||
def execute(self, context):
|
||||
bpy.context.active_object.BIMObjectProperties.relating_type = None
|
||||
bpy.context.active_object.BIMObjectProperties.is_editing_type = True
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class DisableEditingType(bpy.types.Operator):
|
||||
bl_idname = "bim.disable_editing_type"
|
||||
bl_label = "Disable Editing Type"
|
||||
obj: bpy.props.StringProperty()
|
||||
|
||||
def execute(self, context):
|
||||
obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object
|
||||
obj.BIMObjectProperties.is_editing_type = False
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class SelectSimilarType(bpy.types.Operator):
|
||||
bl_idname = "bim.select_similar_type"
|
||||
bl_label = "Select Similar Type"
|
||||
related_object: bpy.props.StringProperty()
|
||||
|
||||
def execute(self, context):
|
||||
self.file = IfcStore.get_file()
|
||||
related_object = bpy.data.objects.get(self.related_object) if self.related_object else bpy.context.active_object
|
||||
props = related_object.BIMObjectProperties
|
||||
product = self.file.by_id(props.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(props.ifc_definition_id)
|
||||
}).execute()
|
||||
else:
|
||||
related_objects = get_related_objects.Usecase(self.file, {
|
||||
"related_object": self.file.by_id(props.ifc_definition_id)
|
||||
}).execute()
|
||||
for obj in bpy.context.visible_objects:
|
||||
if obj.BIMObjectProperties.ifc_definition_id in related_objects:
|
||||
obj.select_set(True)
|
||||
return {"FINISHED"}
|
||||
@@ -0,0 +1,49 @@
|
||||
from bpy.types import Panel
|
||||
from blenderbim.bim.module.type.data import Data
|
||||
|
||||
|
||||
class BIM_PT_type(Panel):
|
||||
bl_label = "IFC Construction Type"
|
||||
bl_idname = "BIM_PT_type"
|
||||
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_type:
|
||||
row = self.layout.row(align=True)
|
||||
row.prop(props, "relating_type", text="")
|
||||
row.operator("bim.assign_type", icon="CHECKMARK", text="")
|
||||
row.operator("bim.disable_editing_type", 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":
|
||||
label = "This object has no type"
|
||||
else:
|
||||
label = name
|
||||
row.label(text=label)
|
||||
row.operator("bim.select_similar_type", icon="RESTRICT_SELECT_OFF", text="")
|
||||
row.operator("bim.enable_editing_type", icon="GREASEPENCIL", text="")
|
||||
if name != "None/None":
|
||||
row.operator("bim.unassign_type", icon="X", text="")
|
||||
@@ -0,0 +1,31 @@
|
||||
import ifcopenshell
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, settings=None):
|
||||
self.file = file
|
||||
self.settings = {
|
||||
"related_object": None
|
||||
}
|
||||
for key, value in settings.items():
|
||||
self.settings[key] = value
|
||||
|
||||
def execute(self):
|
||||
if self.file.schema == "IFC2X3":
|
||||
is_typed_by = None
|
||||
is_defined_by = self.settings["related_object"].IsDefinedBy
|
||||
for rel in is_defined_by:
|
||||
if rel.is_a("IfcRelDefinesByType"):
|
||||
is_typed_by = rel
|
||||
else:
|
||||
is_typed_by = self.settings["related_object"].IsTypedBy
|
||||
if is_typed_by:
|
||||
is_typed_by = is_typed_by[0]
|
||||
|
||||
if is_typed_by:
|
||||
related_objects = list(is_typed_by.RelatedObjects)
|
||||
related_objects.remove(self.settings["related_object"])
|
||||
if related_objects:
|
||||
is_typed_by.RelatedObjects = related_objects
|
||||
else:
|
||||
self.file.remove(is_typed_by)
|
||||
Reference in New Issue
Block a user