Change currently edited item's profile

Example - https://imgur.com/a/2yiVIW5
This commit is contained in:
Andrej730
2025-01-21 15:46:21 +05:00
parent 992424c748
commit ff337bc849
4 changed files with 70 additions and 1 deletions
@@ -26,6 +26,7 @@ from ifcopenshell.util.doc import get_entity_doc, get_predefined_type_doc
import bonsai.tool as tool import bonsai.tool as tool
from math import degrees from math import degrees
from natsort import natsorted from natsort import natsorted
from typing import Union
def refresh(): def refresh():
@@ -617,6 +618,7 @@ class ItemData:
cls.data = {} cls.data = {}
cls.data["representation_identifier"] = cls.representation_identifier() cls.data["representation_identifier"] = cls.representation_identifier()
cls.data["representation_type"] = cls.representation_type() cls.data["representation_type"] = cls.representation_type()
cls.data["profiles_enum"] = cls.profiles_enum()
@classmethod @classmethod
def representation_identifier(cls): def representation_identifier(cls):
@@ -629,3 +631,25 @@ class ItemData:
props = bpy.context.scene.BIMGeometryProperties props = bpy.context.scene.BIMGeometryProperties
rep = tool.Geometry.get_active_representation(props.representation_obj) rep = tool.Geometry.get_active_representation(props.representation_obj)
return rep.RepresentationType return rep.RepresentationType
@classmethod
def profiles_enum(cls) -> list[Union[tuple[str, str, str], None]]:
ifc_file = tool.Ifc.get()
profiles: list[Union[tuple[str, str, str], None]] = []
profiles.append(
(
"-",
"Use Unnamed Profile",
"If named profile is currently used, replace it with the unnamed version so it can be edited without affecting original profile.",
)
)
profiles.append(None)
named_profiles: list[tuple[str, str, str]] = []
for profile in ifc_file.by_type("IfcProfileDef"):
if (profile_name := profile.ProfileName) is None:
continue
named_profiles.append((str(profile.id()), profile_name, profile.is_a()))
named_profiles.sort(key=lambda x: x[1])
profiles.extend(named_profiles)
return profiles
@@ -282,6 +282,12 @@ class EditItemUI:
return return
obj = context.active_object obj = context.active_object
assert obj assert obj
mesh_props = obj.data.BIMMeshProperties
if cls.get_item_object_class(obj) == "IfcExtrudedAreaSolid":
row = cls.layout.row()
row.prop(mesh_props, "item_profile")
for item_attribute in obj.data.BIMMeshProperties.item_attributes: for item_attribute in obj.data.BIMMeshProperties.item_attributes:
row = cls.layout.row() row = cls.layout.row()
draw_attribute(item_attribute, cls.layout) draw_attribute(item_attribute, cls.layout)
@@ -289,6 +295,10 @@ class EditItemUI:
row = cls.layout.row() row = cls.layout.row()
row.operator("bim.update_item_attributes", icon="FILE_REFRESH", text="") row.operator("bim.update_item_attributes", icon="FILE_REFRESH", text="")
@classmethod
def get_item_object_class(cls, obj: bpy.types.Object) -> str:
return obj.name.split("/")[1]
class BIM_MT_add_representation_item(Menu): class BIM_MT_add_representation_item(Menu):
bl_idname = "BIM_MT_add_representation_item" bl_idname = "BIM_MT_add_representation_item"
+9
View File
@@ -539,6 +539,14 @@ class BIMObjectProperties(PropertyGroup):
rotation_checksum: StringProperty(name="Rotation Checksum") rotation_checksum: StringProperty(name="Rotation Checksum")
def get_profiles(self: "BIMMeshProperties", context: bpy.types.Context):
from bonsai.bim.module.model.data import ItemData
if not ItemData.is_loaded:
ItemData.load()
return ItemData.data["profiles_enum"]
class BIMMeshProperties(PropertyGroup): class BIMMeshProperties(PropertyGroup):
ifc_definition_id: IntProperty(name="IFC Definition ID") ifc_definition_id: IntProperty(name="IFC Definition ID")
ifc_boolean_id: IntProperty(name="IFC Boolean ID") ifc_boolean_id: IntProperty(name="IFC Boolean ID")
@@ -550,6 +558,7 @@ class BIMMeshProperties(PropertyGroup):
subshape_type: EnumProperty(name="Subshape Type", items=[(i, i, "") for i in ("-", "PROFILE", "AXIS")]) subshape_type: EnumProperty(name="Subshape Type", items=[(i, i, "") for i in ("-", "PROFILE", "AXIS")])
ifc_parameters: CollectionProperty(name="IFC Parameters", type=IfcParameter) ifc_parameters: CollectionProperty(name="IFC Parameters", type=IfcParameter)
item_attributes: CollectionProperty(name="Item Attributes", type=Attribute) item_attributes: CollectionProperty(name="Item Attributes", type=Attribute)
item_profile: EnumProperty(name="Item Profile", items=get_profiles)
material_checksum: StringProperty(name="Material Checksum", default="[]") material_checksum: StringProperty(name="Material Checksum", default="[]")
mesh_checksum: StringProperty(name="Mesh Checksum", default="") mesh_checksum: StringProperty(name="Mesh Checksum", default="")
replaced_mesh: PointerProperty(type=bpy.types.Mesh, description="Original mesh to revert section cutaway") replaced_mesh: PointerProperty(type=bpy.types.Mesh, description="Original mesh to revert section cutaway")
+27 -1
View File
@@ -27,6 +27,7 @@ import multiprocessing
import ifcopenshell import ifcopenshell
import ifcopenshell.api import ifcopenshell.api
import ifcopenshell.api.grid import ifcopenshell.api.grid
import ifcopenshell.api.profile
import ifcopenshell.api.style import ifcopenshell.api.style
import ifcopenshell.geom import ifcopenshell.geom
import ifcopenshell.guid import ifcopenshell.guid
@@ -50,7 +51,7 @@ from math import radians, pi
from mathutils import Vector, Matrix from mathutils import Vector, Matrix
from mathutils.bvhtree import BVHTree from mathutils.bvhtree import BVHTree
from bonsai.bim.ifc import IfcStore from bonsai.bim.ifc import IfcStore
from typing import Union, Iterable, Optional, Literal, Iterator, List, TYPE_CHECKING, get_args, Generator from typing import Union, Iterable, Optional, Literal, Iterator, List, TYPE_CHECKING, get_args, Generator, cast
from typing_extensions import TypeIs from typing_extensions import TypeIs
if TYPE_CHECKING: if TYPE_CHECKING:
@@ -1675,13 +1676,38 @@ class Geometry(bonsai.core.tool.Geometry):
bonsai.bim.helper.import_attributes2(item, props.item_attributes, callback=callback) bonsai.bim.helper.import_attributes2(item, props.item_attributes, callback=callback)
profile = None
if item.is_a("IfcExtrudedAreaSolid"):
profile = item.SweptArea
if profile is None or profile.ProfileName is None:
item_profile = "-"
else:
item_profile = str(profile.id())
props.item_profile = item_profile
@classmethod @classmethod
def update_item_attributes(cls, obj: bpy.types.Object) -> None: def update_item_attributes(cls, obj: bpy.types.Object) -> None:
props = obj.data.BIMMeshProperties props = obj.data.BIMMeshProperties
ifc_file = tool.Ifc.get()
item = tool.Ifc.get().by_id(props.ifc_definition_id) item = tool.Ifc.get().by_id(props.ifc_definition_id)
for attribute in props.item_attributes: for attribute in props.item_attributes:
setattr(item, attribute.name, attribute.get_value()) setattr(item, attribute.name, attribute.get_value())
if item.is_a("IfcSweptAreaSolid"):
item_profile = cast(str, props.item_profile)
profile = item.SweptArea
profile_name: Union[str, None] = profile.ProfileName
if item_profile == "-":
if profile_name is not None:
profile = ifcopenshell.util.element.copy_deep(ifc_file, profile)
profile.ProfileName = None
item.SweptArea = profile
else:
if profile_name is None:
ifcopenshell.api.profile.remove_profile(ifc_file, profile)
item.SweptArea = ifc_file.by_id(int(item_profile))
@classmethod @classmethod
def import_item(cls, obj: bpy.types.Object) -> None: def import_item(cls, obj: bpy.types.Object) -> None:
props = bpy.context.scene.BIMGeometryProperties props = bpy.context.scene.BIMGeometryProperties