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):
bl_idname = "bim.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"}
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()
for obj in context.selected_objects:
for obj in objs:
element = tool.Ifc.get_entity(obj)
if not element:
continue
@@ -44,11 +54,21 @@ class ReferenceStructure(bpy.types.Operator, tool.Ifc.Operator):
class DereferenceStructure(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.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"}
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()
for obj in context.selected_objects:
for obj in objs:
element = tool.Ifc.get_entity(obj)
if not element:
continue
@@ -100,29 +120,36 @@ class RemoveContainer(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
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
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_label = "Copy To Container"
bl_options = {"REGISTER", "UNDO"}
def _execute(self, context):
# Track decompositions so they can be recreated after the operation
relationships = tool.Root.get_decomposition_relationships(context.selected_objects)
old_to_new = {}
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()
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)
if result_objs:
old_to_new[tool.Ifc.get_entity(obj)] = result_objs
# Recreate decompositions
tool.Root.recreate_decompositions(relationships, old_to_new)
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):
results.append(element)
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_class" to "IfcWall"
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"
When I set "scene.BIMSpatialProperties.containers[0].is_selected" to "True"
And I press "bim.copy_to_container"
When I press "bim.copy_to_container"
Then the object "IfcWall/Cube.001" is in the collection "IfcSite/My Site"
Scenario: Reference structure