mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-11 02:02:22 +00:00
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:
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user