mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 01:41:57 +00:00
bim.switch_representation to handle representations with the same context
1) If object had multiple representations for the same context, then switch simply wouldn't work as it would always pick up the first representation it could find. Now it prioritizes the one user is selecting in UI. 2) If some object is selected and it also has multiple representations for the same context, then switch representation would switch it to any representation in that context it first finds. As user doesn't provide representation explicitly in that case, now it will stick to the already active representation on selected object if it matches the context, to avoid accident switches. Notcied by working with example from #5824
This commit is contained in:
@@ -338,22 +338,36 @@ class SwitchRepresentation(bpy.types.Operator, tool.Ifc.Operator):
|
||||
return False
|
||||
|
||||
def _execute(self, context):
|
||||
context = tool.Ifc.get().by_id(self.ifc_definition_id).ContextOfItems
|
||||
provided_representation = tool.Ifc.get().by_id(self.ifc_definition_id)
|
||||
ifc_context = provided_representation.ContextOfItems
|
||||
for obj in tool.Blender.get_selected_objects():
|
||||
if (
|
||||
(element := tool.Ifc.get_entity(obj))
|
||||
and obj.mode == "OBJECT"
|
||||
and (representation := ifcopenshell.util.representation.get_representation(element, context))
|
||||
):
|
||||
core.switch_representation(
|
||||
tool.Ifc,
|
||||
tool.Geometry,
|
||||
obj=obj,
|
||||
representation=representation,
|
||||
should_reload=self.should_reload,
|
||||
is_global=self.should_switch_all_meshes,
|
||||
should_sync_changes_first=True,
|
||||
)
|
||||
if not (element := tool.Ifc.get_entity(obj)) or obj.mode != "OBJECT":
|
||||
continue
|
||||
|
||||
# Find representation to switch to.
|
||||
if (active_representation := tool.Geometry.get_active_representation(obj)) is None:
|
||||
# No active representation => probably has no representations.
|
||||
continue
|
||||
elif obj == context.active_object:
|
||||
# Prioritize provided representation.
|
||||
representation = provided_representation
|
||||
elif active_representation.ContextOfItems == ifc_context:
|
||||
# Prioritize already active representation if context matches.
|
||||
representation = active_representation
|
||||
else:
|
||||
representation = ifcopenshell.util.representation.get_representation(element, ifc_context)
|
||||
if not representation:
|
||||
continue
|
||||
|
||||
core.switch_representation(
|
||||
tool.Ifc,
|
||||
tool.Geometry,
|
||||
obj=obj,
|
||||
representation=representation,
|
||||
should_reload=self.should_reload,
|
||||
is_global=self.should_switch_all_meshes,
|
||||
should_sync_changes_first=True,
|
||||
)
|
||||
|
||||
|
||||
class RemoveRepresentation(bpy.types.Operator, tool.Ifc.Operator):
|
||||
|
||||
@@ -678,6 +678,7 @@ class Geometry(bonsai.core.tool.Geometry):
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
assert element
|
||||
|
||||
ifc_file = tool.Ifc.get()
|
||||
elements = set()
|
||||
element_types = set()
|
||||
representation = ifcopenshell.util.representation.resolve_representation(representation)
|
||||
@@ -716,16 +717,26 @@ class Geometry(bonsai.core.tool.Geometry):
|
||||
else:
|
||||
iterator = None # For example, when switching representation of a type with no occurrences
|
||||
meshes = {}
|
||||
base_representation = representation
|
||||
if iterator and iterator.initialize():
|
||||
while True:
|
||||
shape = iterator.get()
|
||||
element = tool.Ifc.get().by_id(shape.id)
|
||||
if obj := tool.Ifc.get_object(element):
|
||||
# It's possible that there will be multiple shapes for the same context,
|
||||
# Unfortunately, iterator still processes them all and
|
||||
# we need to ensure we pick the one that was requested for reimport.
|
||||
representation_id = tool.Loader.get_representation_id_from_shape(shape.geometry)
|
||||
representation = ifc_file.by_id(representation_id)
|
||||
resolved_representation = ifcopenshell.util.representation.resolve_representation(representation)
|
||||
if resolved_representation != base_representation:
|
||||
if not iterator.next():
|
||||
break
|
||||
continue
|
||||
|
||||
mesh_name = tool.Loader.get_mesh_name_from_shape(shape.geometry)
|
||||
mesh = meshes.get(mesh_name)
|
||||
if mesh is None:
|
||||
# Duplicate code
|
||||
representation = tool.Ifc.get().by_id(int(shape.geometry.id.split("-")[0]))
|
||||
if element.is_a("IfcAnnotation") and element.ObjectType == "DRAWING":
|
||||
mesh = tool.Loader.create_camera(element, representation, shape)
|
||||
elif element.is_a("IfcAnnotation") and ifc_importer.is_curve_annotation(element):
|
||||
|
||||
@@ -70,15 +70,20 @@ class Loader(bonsai.core.tool.Loader):
|
||||
cls.settings = settings
|
||||
|
||||
@classmethod
|
||||
def get_mesh_name_from_shape(cls, geometry: ifcopenshell.geom.ShapeType) -> str:
|
||||
representation_id = geometry.id
|
||||
def get_representation_id_from_shape(cls, geometry: ifcopenshell.geom.ShapeType) -> int:
|
||||
representation_id: str = geometry.id
|
||||
if "-" in representation_id:
|
||||
# Example: 2432-openings-2468, where
|
||||
# 2432 is mapped representation id
|
||||
# and 2468 is IFCRELVOIDSELEMENT
|
||||
representation_id = int(re.sub(r"\D", "", representation_id.split("-")[0]))
|
||||
representation_id = re.sub(r"\D", "", representation_id.split("-")[0])
|
||||
else:
|
||||
representation_id = int(re.sub(r"\D", "", representation_id))
|
||||
representation_id = re.sub(r"\D", "", representation_id)
|
||||
return int(representation_id)
|
||||
|
||||
@classmethod
|
||||
def get_mesh_name_from_shape(cls, geometry: ifcopenshell.geom.ShapeType) -> str:
|
||||
representation_id = cls.get_representation_id_from_shape(geometry)
|
||||
representation = tool.Ifc.get().by_id(representation_id)
|
||||
context_id = representation.ContextOfItems.id() if hasattr(representation, "ContextOfItems") else 0
|
||||
return cls.get_mesh_name(context_id, representation_id)
|
||||
|
||||
Reference in New Issue
Block a user