Fix #5544. Assign / add of objects with styles are now supported.

This commit is contained in:
Dion Moult
2024-10-09 18:27:36 +11:00
parent 11eb1c26f0
commit bba862e3ae
5 changed files with 170 additions and 64 deletions
+2 -16
View File
@@ -210,12 +210,7 @@ class AssignClass(bpy.types.Operator, tool.Ifc.Operator):
ifc_representation_class=self.ifc_representation_class,
)
if self.should_add_representation and obj.data and len(obj.data.vertices):
builder = ifcopenshell.util.shape_builder.ShapeBuilder(tool.Ifc.get())
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
verts = [v.co / unit_scale for v in obj.data.vertices]
faces = [p.vertices[:] for p in obj.data.polygons]
item = builder.mesh(verts, faces)
representation = builder.get_representation(ifc_context, [item])
representation = tool.Geometry.export_mesh_to_tessellation(obj, ifc_context)
ifcopenshell.api.geometry.assign_representation(tool.Ifc.get(), element, representation)
bonsai.core.geometry.switch_representation(
tool.Ifc,
@@ -373,16 +368,7 @@ class AddElement(bpy.types.Operator, tool.Ifc.Operator):
pass
elif representation_template == "OBJ" and props.representation_obj:
obj.matrix_world = props.representation_obj.matrix_world
builder = ifcopenshell.util.shape_builder.ShapeBuilder(tool.Ifc.get())
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
items = []
meshes = tool.Geometry.split_by_loose_parts(props.representation_obj)
for mesh in meshes:
verts = [v.co / unit_scale for v in mesh.vertices]
faces = [p.vertices[:] for p in mesh.polygons]
items.append(builder.mesh(verts, faces))
bpy.data.meshes.remove(mesh)
representation = builder.get_representation(ifc_context, items)
representation = tool.Geometry.export_mesh_to_tessellation(props.representation_obj, ifc_context)
ifcopenshell.api.geometry.assign_representation(tool.Ifc.get(), element, representation)
bonsai.core.geometry.switch_representation(
tool.Ifc,
+32
View File
@@ -27,6 +27,7 @@ import multiprocessing
import ifcopenshell
import ifcopenshell.api
import ifcopenshell.api.grid
import ifcopenshell.api.style
import ifcopenshell.geom
import ifcopenshell.guid
import ifcopenshell.util.element
@@ -1600,3 +1601,34 @@ class Geometry(bonsai.core.tool.Geometry):
@classmethod
def reload_representation_item_ids(cls, representation: ifcopenshell.entity_instance, data: bpy.types.Mesh) -> None:
data["ios_item_ids"] = [i["item"].id() for i in ifcopenshell.util.representation.resolve_items(representation)]
@classmethod
def export_mesh_to_tessellation(cls, obj: bpy.types.Object, ifc_context) -> ifcopenshell.entity_instance:
builder = ifcopenshell.util.shape_builder.ShapeBuilder(tool.Ifc.get())
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
items = []
meshes = cls.split_by_loose_parts(obj)
for mesh in meshes:
verts = [v.co / unit_scale for v in mesh.vertices]
faces = [p.vertices[:] for p in mesh.polygons]
item = builder.mesh(verts, faces)
items.append(item)
material_index = mesh.polygons[0].material_index
if materials := list(mesh.materials):
material = materials[material_index]
if not (style := tool.Style.get_style(material)):
style = ifcopenshell.api.run("style.add_style", tool.Ifc.get(), name=material.name)
if material.use_nodes:
ifc_class = "IfcSurfaceStyleRendering"
attributes = tool.Style.get_surface_rendering_attributes(material)
else:
ifc_class = "IfcSurfaceStyleShading"
attributes = tool.Style.get_surface_shading_attributes(material)
ifcopenshell.api.style.add_surface_style(
tool.Ifc.get(), style=style, ifc_class=ifc_class, attributes=attributes
)
tool.Ifc.link(style, material)
material.use_fake_user = True
ifcopenshell.api.style.assign_item_style(tool.Ifc.get(), item=item, style=style)
bpy.data.meshes.remove(mesh)
return builder.get_representation(ifc_context, items)
+2 -48
View File
@@ -594,55 +594,9 @@ class Style(bonsai.core.tool.Style):
@classmethod
def assign_style_to_representation_item(
cls, representation_item: ifcopenshell.entity_instance, style: Optional[ifcopenshell.entity_instance] = None
cls, item: ifcopenshell.entity_instance, style: Optional[ifcopenshell.entity_instance] = None
) -> None:
"""Assign specified style to a representation item and unassign all previously assigned styles."""
ifc_file = representation_item.file
if not (styled_item := next(iter(representation_item.StyledByItem), None)):
if style is None:
return
if ifc_file.schema == "IFC2X3":
style = ifc_file.create_entity("IfcPresentationStyleAssignment", (style,))
ifc_file.create_entity("IfcStyledItem", representation_item, (style,))
return
styled_item_styles = styled_item.Styles
if style and styled_item_styles == (style,):
return
if ifc_file.schema == "IFC4X3":
if style is None:
ifc_file.remove(styled_item)
return
styled_item.Styles = (style,)
return
# < IFC4X3
# Can't just remove a styled item or assign a style
# since we need to remove/change the possible style assignments.
assignment = None
for style_ in styled_item_styles:
if not style_.is_a("IfcPresentationStyleAssignment"):
continue
# Remove second assignment.
if style is None or assignment:
ifc_file.remove(style_)
else:
assignment = style_
if assignment.Styles != (style,):
assignment.Styles = (style,)
if style is None:
ifc_file.remove(styled_item)
return
if assignment:
if styled_item_styles == (assignment,):
return
styled_item.Styles = (assignment,)
return
styled_item.Styles = (style,)
return ifcopenshell.api.style.assign_item_style(tool.Ifc.get(), item=item, style=style)
@classmethod
def get_representation_item_style(