fix container operators after a9a4b0c + mention a limitation

If you would select container1 + obj1 with intention to copy obj1 to container1 - running bim.copy_to_container would also copy container1.
Similar issue for referencing/dereferncing structures in other structures in ifc4x3.
This commit is contained in:
Andrej730
2024-07-31 16:15:09 +05:00
parent 2927eadada
commit 6be1b80a82
3 changed files with 54 additions and 12 deletions
@@ -29,11 +29,21 @@ import blenderbim.bim.handler
class ReferenceStructure(bpy.types.Operator, tool.Ifc.Operator): class ReferenceStructure(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.reference_structure" bl_idname = "bim.reference_structure"
bl_label = "Reference Structure" bl_label = "Reference Structure"
bl_description = (
"Reference selected objects from all selected structures.\n\n"
"Currently we do not support referencing structures in other structures "
"though it is allowed in IFC4X3"
)
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
def _execute(self, context): def _execute(self, context):
objs = tool.Spatial.get_selected_objects_without_containers()
if not objs:
self.report({"INFO"}, "No non-spatial objects are selected.")
return
containers = tool.Spatial.get_selected_containers() containers = tool.Spatial.get_selected_containers()
for obj in context.selected_objects: for obj in objs:
element = tool.Ifc.get_entity(obj) element = tool.Ifc.get_entity(obj)
if not element: if not element:
continue continue
@@ -44,11 +54,21 @@ class ReferenceStructure(bpy.types.Operator, tool.Ifc.Operator):
class DereferenceStructure(bpy.types.Operator, tool.Ifc.Operator): class DereferenceStructure(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.dereference_structure" bl_idname = "bim.dereference_structure"
bl_label = "Dereference Structure" bl_label = "Dereference Structure"
bl_description = (
"Dereference selected objects from all selected structures.\n\n"
"Currently we do not support referencing structures in other structures "
"though it is allowed in IFC4X3"
)
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
def _execute(self, context): def _execute(self, context):
objs = tool.Spatial.get_selected_objects_without_containers()
if not objs:
self.report({"INFO"}, "No non-spatial objects are selected.")
return
containers = tool.Spatial.get_selected_containers() containers = tool.Spatial.get_selected_containers()
for obj in context.selected_objects: for obj in objs:
element = tool.Ifc.get_entity(obj) element = tool.Ifc.get_entity(obj)
if not element: if not element:
continue continue
@@ -100,29 +120,36 @@ class RemoveContainer(bpy.types.Operator, tool.Ifc.Operator):
class CopyToContainer(bpy.types.Operator, tool.Ifc.Operator): class CopyToContainer(bpy.types.Operator, tool.Ifc.Operator):
""" """
Copies selected 3D elements in the viewport to checkmarked spatial containers Copies selected 3D elements in the viewport to the selected spatial containers
Example: bulk copy a wall to multiple storeys Example: bulk copy a wall to multiple storeys
1. Select one or more 3D elements in the viewport 1. Select one or more 3D elements in the viewport
2. Enable the checkmark next to one or more containers in the container list below to select it 2. Select one or more spatial containers in the viewport
3. Press this button 3. Press this button
4. The copied elements will have a new position relative to the destination containers 4. The copied elements will have a new position relative to the destination containers
"""
Copying containers to other containers currently is not supported."""
bl_idname = "bim.copy_to_container" bl_idname = "bim.copy_to_container"
bl_label = "Copy To Container" bl_label = "Copy To Container"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
def _execute(self, context): def _execute(self, context):
# Track decompositions so they can be recreated after the operation objs = tool.Spatial.get_selected_objects_without_containers()
relationships = tool.Root.get_decomposition_relationships(context.selected_objects) if not objs:
old_to_new = {} self.report({"INFO"}, "No non-spatial objects are selected.")
return
containers = tool.Spatial.get_selected_containers() containers = tool.Spatial.get_selected_containers()
for obj in context.selected_objects: # Track decompositions so they can be recreated after the operation
relationships = tool.Root.get_decomposition_relationships(objs)
old_to_new = {}
for obj in objs:
result_objs = core.copy_to_container(tool.Ifc, tool.Collector, tool.Spatial, obj=obj, containers=containers) result_objs = core.copy_to_container(tool.Ifc, tool.Collector, tool.Spatial, obj=obj, containers=containers)
if result_objs: if result_objs:
old_to_new[tool.Ifc.get_entity(obj)] = result_objs old_to_new[tool.Ifc.get_entity(obj)] = result_objs
# Recreate decompositions # Recreate decompositions
tool.Root.recreate_decompositions(relationships, old_to_new) tool.Root.recreate_decompositions(relationships, old_to_new)
blenderbim.bim.handler.refresh_ui_data() blenderbim.bim.handler.refresh_ui_data()
+15
View File
@@ -866,3 +866,18 @@ class Spatial(blenderbim.core.tool.Spatial):
if (element := tool.Ifc.get_entity(obj)) and tool.Root.is_spatial_element(element): if (element := tool.Ifc.get_entity(obj)) and tool.Root.is_spatial_element(element):
results.append(element) results.append(element)
return results return results
@classmethod
def get_selected_objects_without_containers(cls) -> list[bpy.types.Object]:
"""Get selected objects skipping spatial elements.
Useful for operators that are using selected objects to identify selected containers.
Note that those operators are typically have a limitation since they can't tell
objects to operate on from containers that should be used in the operation.
E.g. we cannot bim.copy_to_container containers to other containers."""
results: list[bpy.types.Object] = []
for obj in tool.Blender.get_selected_objects():
if (element := tool.Ifc.get_entity(obj)) and not tool.Root.is_spatial_element(element):
results.append(obj)
return results
@@ -38,10 +38,10 @@ Scenario: Copy to container
And I set "scene.BIMRootProperties.ifc_product" to "IfcElement" And I set "scene.BIMRootProperties.ifc_product" to "IfcElement"
And I set "scene.BIMRootProperties.ifc_class" to "IfcWall" And I set "scene.BIMRootProperties.ifc_class" to "IfcWall"
And I press "bim.assign_class" And I press "bim.assign_class"
And the object "IfcWall/Cube" is selected And the object "IfcSite/My Site" is selected
And additionally the object "IfcWall/Cube" is selected
And I press "bim.enable_editing_container" And I press "bim.enable_editing_container"
When I set "scene.BIMSpatialProperties.containers[0].is_selected" to "True" When I press "bim.copy_to_container"
And I press "bim.copy_to_container"
Then the object "IfcWall/Cube.001" is in the collection "IfcSite/My Site" Then the object "IfcWall/Cube.001" is in the collection "IfcSite/My Site"
Scenario: Reference structure Scenario: Reference structure