mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 17:31:45 +00:00
Deprecate "duplicate" spatial tree browser in favour of regular object selection
This commit is contained in:
@@ -21,7 +21,6 @@ from . import ui, prop, operator, workspace
|
|||||||
|
|
||||||
classes = (
|
classes = (
|
||||||
operator.AssignContainer,
|
operator.AssignContainer,
|
||||||
operator.ChangeSpatialLevel,
|
|
||||||
operator.ContractContainer,
|
operator.ContractContainer,
|
||||||
operator.CopyToContainer,
|
operator.CopyToContainer,
|
||||||
operator.DeleteContainer,
|
operator.DeleteContainer,
|
||||||
@@ -39,14 +38,11 @@ classes = (
|
|||||||
operator.SelectSimilarContainer,
|
operator.SelectSimilarContainer,
|
||||||
operator.SetContainerVisibility,
|
operator.SetContainerVisibility,
|
||||||
operator.SetDefaultContainer,
|
operator.SetDefaultContainer,
|
||||||
prop.SpatialElement,
|
|
||||||
prop.Element,
|
prop.Element,
|
||||||
prop.BIMSpatialProperties,
|
|
||||||
prop.BIMObjectSpatialProperties,
|
prop.BIMObjectSpatialProperties,
|
||||||
prop.BIMContainer,
|
prop.BIMContainer,
|
||||||
prop.BIMSpatialDecompositionProperties,
|
prop.BIMSpatialDecompositionProperties,
|
||||||
ui.BIM_PT_spatial,
|
ui.BIM_PT_spatial,
|
||||||
ui.BIM_UL_containers,
|
|
||||||
ui.BIM_UL_containers_manager,
|
ui.BIM_UL_containers_manager,
|
||||||
ui.BIM_UL_elements,
|
ui.BIM_UL_elements,
|
||||||
ui.BIM_PT_spatial_decomposition,
|
ui.BIM_PT_spatial_decomposition,
|
||||||
@@ -57,7 +53,6 @@ classes = (
|
|||||||
def register():
|
def register():
|
||||||
if not bpy.app.background:
|
if not bpy.app.background:
|
||||||
bpy.utils.register_tool(workspace.SpatialTool, after={"bim.annotation_tool"}, separator=False, group=False)
|
bpy.utils.register_tool(workspace.SpatialTool, after={"bim.annotation_tool"}, separator=False, group=False)
|
||||||
bpy.types.Scene.BIMSpatialProperties = bpy.props.PointerProperty(type=prop.BIMSpatialProperties)
|
|
||||||
bpy.types.Object.BIMObjectSpatialProperties = bpy.props.PointerProperty(type=prop.BIMObjectSpatialProperties)
|
bpy.types.Object.BIMObjectSpatialProperties = bpy.props.PointerProperty(type=prop.BIMObjectSpatialProperties)
|
||||||
bpy.types.Scene.BIMSpatialDecompositionProperties = bpy.props.PointerProperty(
|
bpy.types.Scene.BIMSpatialDecompositionProperties = bpy.props.PointerProperty(
|
||||||
type=prop.BIMSpatialDecompositionProperties
|
type=prop.BIMSpatialDecompositionProperties
|
||||||
@@ -67,6 +62,5 @@ def register():
|
|||||||
def unregister():
|
def unregister():
|
||||||
if not bpy.app.background:
|
if not bpy.app.background:
|
||||||
bpy.utils.unregister_tool(workspace.SpatialTool)
|
bpy.utils.unregister_tool(workspace.SpatialTool)
|
||||||
del bpy.types.Scene.BIMSpatialProperties
|
|
||||||
del bpy.types.Object.BIMObjectSpatialProperties
|
del bpy.types.Object.BIMObjectSpatialProperties
|
||||||
del bpy.types.Scene.BIMSpatialDecompositionProperties
|
del bpy.types.Scene.BIMSpatialDecompositionProperties
|
||||||
|
|||||||
@@ -37,7 +37,8 @@ class SpatialData:
|
|||||||
if cls.data["poll"]:
|
if cls.data["poll"]:
|
||||||
cls.data.update(
|
cls.data.update(
|
||||||
{
|
{
|
||||||
"parent_container_id": cls.parent_container_id(),
|
"default_container": cls.default_container(),
|
||||||
|
"selected_containers": cls.selected_containers(),
|
||||||
"is_directly_contained": cls.is_directly_contained(),
|
"is_directly_contained": cls.is_directly_contained(),
|
||||||
"label": cls.label(),
|
"label": cls.label(),
|
||||||
"references": cls.references(),
|
"references": cls.references(),
|
||||||
@@ -56,14 +57,17 @@ class SpatialData:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def parent_container_id(cls):
|
def default_container(cls) -> str | None:
|
||||||
container_id = bpy.context.scene.BIMSpatialProperties.active_container_id
|
props = bpy.context.scene.BIMSpatialDecompositionProperties
|
||||||
if not container_id:
|
if props.default_container:
|
||||||
return
|
try:
|
||||||
container = tool.Ifc.get_entity_by_id(container_id)
|
return tool.Ifc.get().by_id(props.default_container).Name
|
||||||
if not container or container.is_a("IfcProject"):
|
except:
|
||||||
return
|
pass
|
||||||
return container.Decomposes[0].RelatingObject.id()
|
|
||||||
|
@classmethod
|
||||||
|
def selected_containers(cls):
|
||||||
|
return sorted([e.Name or "Unnamed" for e in tool.Spatial.get_selected_containers()])
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def label(cls):
|
def label(cls):
|
||||||
|
|||||||
@@ -30,11 +30,9 @@ 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_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
structure: bpy.props.IntProperty()
|
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
sprops = context.scene.BIMSpatialProperties
|
containers = tool.Spatial.get_selected_containers()
|
||||||
containers = [tool.Ifc.get().by_id(c.ifc_definition_id) for c in sprops.containers if c.is_selected]
|
|
||||||
for obj in context.selected_objects:
|
for obj in context.selected_objects:
|
||||||
element = tool.Ifc.get_entity(obj)
|
element = tool.Ifc.get_entity(obj)
|
||||||
if not element:
|
if not element:
|
||||||
@@ -47,11 +45,9 @@ 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_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
structure: bpy.props.IntProperty()
|
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
sprops = context.scene.BIMSpatialProperties
|
containers = tool.Spatial.get_selected_containers()
|
||||||
containers = [tool.Ifc.get().by_id(c.ifc_definition_id) for c in sprops.containers if c.is_selected]
|
|
||||||
for obj in context.selected_objects:
|
for obj in context.selected_objects:
|
||||||
element = tool.Ifc.get_entity(obj)
|
element = tool.Ifc.get_entity(obj)
|
||||||
if not element:
|
if not element:
|
||||||
@@ -64,14 +60,13 @@ class AssignContainer(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
bl_idname = "bim.assign_container"
|
bl_idname = "bim.assign_container"
|
||||||
bl_label = "Assign Container"
|
bl_label = "Assign Container"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
structure: bpy.props.IntProperty()
|
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
structure_obj = tool.Ifc.get_object(tool.Ifc.get().by_id(self.structure))
|
if container := tool.Root.get_default_container():
|
||||||
for element_obj in context.selected_objects:
|
for element_obj in context.selected_objects:
|
||||||
core.assign_container(
|
core.assign_container(
|
||||||
tool.Ifc, tool.Collector, tool.Spatial, structure_obj=structure_obj, element_obj=element_obj
|
tool.Ifc, tool.Collector, tool.Spatial, container=container, element_obj=element_obj
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class EnableEditingContainer(bpy.types.Operator, tool.Ifc.Operator):
|
class EnableEditingContainer(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
@@ -83,16 +78,6 @@ class EnableEditingContainer(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
core.enable_editing_container(tool.Spatial, obj=context.active_object)
|
core.enable_editing_container(tool.Spatial, obj=context.active_object)
|
||||||
|
|
||||||
|
|
||||||
class ChangeSpatialLevel(bpy.types.Operator, tool.Ifc.Operator):
|
|
||||||
bl_idname = "bim.change_spatial_level"
|
|
||||||
bl_label = "Change Spatial Level"
|
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
|
||||||
parent: bpy.props.IntProperty()
|
|
||||||
|
|
||||||
def _execute(self, context):
|
|
||||||
core.change_spatial_level(tool.Spatial, parent=tool.Ifc.get().by_id(self.parent))
|
|
||||||
|
|
||||||
|
|
||||||
class DisableEditingContainer(bpy.types.Operator, tool.Ifc.Operator):
|
class DisableEditingContainer(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
bl_idname = "bim.disable_editing_container"
|
bl_idname = "bim.disable_editing_container"
|
||||||
bl_label = "Disable Editing Container"
|
bl_label = "Disable Editing Container"
|
||||||
@@ -129,11 +114,10 @@ class CopyToContainer(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
sprops = context.scene.BIMSpatialProperties
|
|
||||||
# Track decompositions so they can be recreated after the operation
|
# Track decompositions so they can be recreated after the operation
|
||||||
relationships = tool.Root.get_decomposition_relationships(context.selected_objects)
|
relationships = tool.Root.get_decomposition_relationships(context.selected_objects)
|
||||||
old_to_new = {}
|
old_to_new = {}
|
||||||
containers = [tool.Ifc.get().by_id(c.ifc_definition_id) for c in sprops.containers if c.is_selected]
|
containers = tool.Spatial.get_selected_containers()
|
||||||
for obj in context.selected_objects:
|
for obj in context.selected_objects:
|
||||||
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:
|
||||||
|
|||||||
@@ -82,20 +82,6 @@ def is_object_applicable(self, obj):
|
|||||||
return bool(element)
|
return bool(element)
|
||||||
|
|
||||||
|
|
||||||
class SpatialElement(PropertyGroup):
|
|
||||||
name: StringProperty(name="Name")
|
|
||||||
long_name: StringProperty(name="Long Name")
|
|
||||||
has_decomposition: BoolProperty(name="Has Decomposition")
|
|
||||||
ifc_definition_id: IntProperty(name="IFC Definition ID")
|
|
||||||
is_selected: BoolProperty(name="Is Selected")
|
|
||||||
|
|
||||||
|
|
||||||
class BIMSpatialProperties(PropertyGroup):
|
|
||||||
containers: CollectionProperty(name="Containers", type=SpatialElement)
|
|
||||||
active_container_index: IntProperty(name="Active Container Index")
|
|
||||||
active_container_id: IntProperty(name="Active Container Id")
|
|
||||||
|
|
||||||
|
|
||||||
class BIMObjectSpatialProperties(PropertyGroup):
|
class BIMObjectSpatialProperties(PropertyGroup):
|
||||||
is_editing: BoolProperty(name="Is Editing")
|
is_editing: BoolProperty(name="Is Editing")
|
||||||
relating_container_object: PointerProperty(
|
relating_container_object: PointerProperty(
|
||||||
|
|||||||
@@ -39,24 +39,32 @@ class BIM_PT_spatial(Panel):
|
|||||||
if not SpatialData.is_loaded:
|
if not SpatialData.is_loaded:
|
||||||
SpatialData.load()
|
SpatialData.load()
|
||||||
|
|
||||||
props = context.scene.BIMSpatialProperties
|
|
||||||
osprops = context.active_object.BIMObjectSpatialProperties
|
osprops = context.active_object.BIMObjectSpatialProperties
|
||||||
|
|
||||||
if osprops.is_editing:
|
if osprops.is_editing:
|
||||||
row = self.layout.row(align=True)
|
if SpatialData.data["default_container"]:
|
||||||
if SpatialData.data["parent_container_id"]:
|
row = self.layout.row(align=True)
|
||||||
op = row.operator("bim.change_spatial_level", text="", icon="FRAME_PREV")
|
row.label(text=f"Target: {SpatialData.data['default_container']}", icon="OUTLINER_COLLECTION")
|
||||||
op.parent = SpatialData.data["parent_container_id"]
|
row.operator("bim.assign_container", icon="CHECKMARK", text="Reassign Container")
|
||||||
if props.containers and props.active_container_index < len(props.containers):
|
row.operator("bim.disable_editing_container", icon="CANCEL", text="")
|
||||||
op = row.operator("bim.assign_container", icon="CHECKMARK")
|
|
||||||
op.structure = props.containers[props.active_container_index].ifc_definition_id
|
|
||||||
row.operator("bim.reference_structure", icon="LINKED", text="")
|
|
||||||
row.operator("bim.dereference_structure", icon="UNLINKED", text="")
|
|
||||||
row.operator("bim.copy_to_container", icon="COPYDOWN", text="")
|
|
||||||
row.operator("bim.disable_editing_container", icon="CANCEL", text="")
|
|
||||||
|
|
||||||
self.layout.template_list("BIM_UL_containers", "", props, "containers", props, "active_container_index")
|
if SpatialData.data["selected_containers"]:
|
||||||
self.layout.prop(osprops, "relating_container_object")
|
row = self.layout.row()
|
||||||
|
row.label(text=f"{len(SpatialData.data['selected_containers'])} Selected Containers")
|
||||||
|
for name in SpatialData.data['selected_containers'][:3]:
|
||||||
|
row = self.layout.row()
|
||||||
|
row.label(text=name, icon="OUTLINER_COLLECTION")
|
||||||
|
if len(SpatialData.data['selected_containers']) > 3:
|
||||||
|
row = self.layout.row()
|
||||||
|
row.label(text=f"... {len(SpatialData.data['selected_containers']) - 3} More")
|
||||||
|
row = self.layout.row(align=True)
|
||||||
|
row.operator("bim.reference_structure", icon="LINKED", text="Reference Selected")
|
||||||
|
row.operator("bim.dereference_structure", icon="UNLINKED", text="")
|
||||||
|
row = self.layout.row()
|
||||||
|
row.operator("bim.copy_to_container", icon="COPYDOWN", text="Copy Object To Selected")
|
||||||
|
else:
|
||||||
|
row = self.layout.row()
|
||||||
|
row.label(text="No Selected Containers")
|
||||||
else:
|
else:
|
||||||
row = self.layout.row(align=True)
|
row = self.layout.row(align=True)
|
||||||
if SpatialData.data["label"]:
|
if SpatialData.data["label"]:
|
||||||
@@ -74,23 +82,6 @@ class BIM_PT_spatial(Panel):
|
|||||||
row.label(text=reference, icon="LINKED")
|
row.label(text=reference, icon="LINKED")
|
||||||
|
|
||||||
|
|
||||||
class BIM_UL_containers(UIList):
|
|
||||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
|
||||||
if item:
|
|
||||||
if item.has_decomposition:
|
|
||||||
op = layout.operator("bim.change_spatial_level", text="", icon="DISCLOSURE_TRI_RIGHT", emboss=False)
|
|
||||||
op.parent = item.ifc_definition_id
|
|
||||||
layout.label(text=item.name)
|
|
||||||
layout.label(text=item.long_name)
|
|
||||||
layout.prop(
|
|
||||||
item,
|
|
||||||
"is_selected",
|
|
||||||
icon="CHECKBOX_HLT" if item.is_selected else "CHECKBOX_DEHLT",
|
|
||||||
text="",
|
|
||||||
emboss=False,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class BIM_PT_spatial_decomposition(Panel):
|
class BIM_PT_spatial_decomposition(Panel):
|
||||||
bl_label = "Spatial Decomposition"
|
bl_label = "Spatial Decomposition"
|
||||||
bl_idname = "BIM_PT_spatial_decomposition"
|
bl_idname = "BIM_PT_spatial_decomposition"
|
||||||
|
|||||||
@@ -49,17 +49,13 @@ def assign_container(
|
|||||||
ifc: tool.Ifc,
|
ifc: tool.Ifc,
|
||||||
collector: tool.Collector,
|
collector: tool.Collector,
|
||||||
spatial: tool.Spatial,
|
spatial: tool.Spatial,
|
||||||
structure_obj: Optional[bpy.types.Object] = None,
|
container: ifcopenshell.entity_instance,
|
||||||
element_obj: Optional[bpy.types.Object] = None,
|
element_obj: Optional[bpy.types.Object] = None,
|
||||||
) -> Union[ifcopenshell.entity_instance, None]:
|
) -> Union[ifcopenshell.entity_instance, None]:
|
||||||
if not spatial.can_contain(structure_obj, element_obj):
|
if not spatial.can_contain(container, element_obj):
|
||||||
return
|
return
|
||||||
assert element_obj and structure_obj # Type checker.
|
assert element_obj # Type checker.
|
||||||
rel = ifc.run(
|
rel = ifc.run("spatial.assign_container", products=[ifc.get_entity(element_obj)], relating_structure=container)
|
||||||
"spatial.assign_container",
|
|
||||||
products=[ifc.get_entity(element_obj)],
|
|
||||||
relating_structure=ifc.get_entity(structure_obj),
|
|
||||||
)
|
|
||||||
spatial.disable_editing(element_obj)
|
spatial.disable_editing(element_obj)
|
||||||
collector.assign(element_obj)
|
collector.assign(element_obj)
|
||||||
return rel
|
return rel
|
||||||
@@ -67,17 +63,12 @@ def assign_container(
|
|||||||
|
|
||||||
def enable_editing_container(spatial: tool.Spatial, obj: bpy.types.Object) -> None:
|
def enable_editing_container(spatial: tool.Spatial, obj: bpy.types.Object) -> None:
|
||||||
spatial.enable_editing(obj)
|
spatial.enable_editing(obj)
|
||||||
spatial.import_containers()
|
|
||||||
|
|
||||||
|
|
||||||
def disable_editing_container(spatial: tool.Spatial, obj: bpy.types.Object) -> None:
|
def disable_editing_container(spatial: tool.Spatial, obj: bpy.types.Object) -> None:
|
||||||
spatial.disable_editing(obj)
|
spatial.disable_editing(obj)
|
||||||
|
|
||||||
|
|
||||||
def change_spatial_level(spatial: tool.Spatial, parent: Union[ifcopenshell.entity_instance, None] = None) -> None:
|
|
||||||
spatial.import_containers(parent=parent)
|
|
||||||
|
|
||||||
|
|
||||||
def remove_container(ifc: tool.Ifc, collector: tool.Collector, obj: bpy.types.Object) -> None:
|
def remove_container(ifc: tool.Ifc, collector: tool.Collector, obj: bpy.types.Object) -> None:
|
||||||
ifc.run("spatial.unassign_container", products=[ifc.get_entity(obj)])
|
ifc.run("spatial.unassign_container", products=[ifc.get_entity(obj)])
|
||||||
collector.assign(obj)
|
collector.assign(obj)
|
||||||
|
|||||||
@@ -39,23 +39,20 @@ import json
|
|||||||
from math import pi
|
from math import pi
|
||||||
from mathutils import Vector, Matrix
|
from mathutils import Vector, Matrix
|
||||||
from shapely import Polygon
|
from shapely import Polygon
|
||||||
from typing import Generator, Optional, Union, Literal, Any, List
|
from typing import Generator, Optional, Union, Literal, List
|
||||||
|
|
||||||
|
|
||||||
class Spatial(blenderbim.core.tool.Spatial):
|
class Spatial(blenderbim.core.tool.Spatial):
|
||||||
@classmethod
|
@classmethod
|
||||||
def can_contain(
|
def can_contain(cls, container: ifcopenshell.entity_instance, element_obj: Union[bpy.types.Object, None]) -> bool:
|
||||||
cls, structure_obj: Union[bpy.types.Object, None], element_obj: Union[bpy.types.Object, None]
|
|
||||||
) -> bool:
|
|
||||||
structure = tool.Ifc.get_entity(structure_obj)
|
|
||||||
element = tool.Ifc.get_entity(element_obj)
|
element = tool.Ifc.get_entity(element_obj)
|
||||||
if not structure or not element:
|
if not element:
|
||||||
return False
|
return False
|
||||||
if tool.Ifc.get_schema() == "IFC2X3":
|
if tool.Ifc.get_schema() == "IFC2X3":
|
||||||
if not structure.is_a("IfcSpatialStructureElement"):
|
if not container.is_a("IfcSpatialStructureElement"):
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
if not structure.is_a("IfcSpatialStructureElement") and not structure.is_a(
|
if not container.is_a("IfcSpatialStructureElement") and not container.is_a(
|
||||||
"IfcExternalSpatialStructureElement"
|
"IfcExternalSpatialStructureElement"
|
||||||
):
|
):
|
||||||
return False
|
return False
|
||||||
@@ -111,31 +108,6 @@ class Spatial(blenderbim.core.tool.Spatial):
|
|||||||
def get_relative_object_matrix(cls, target_obj: bpy.types.Object, relative_to_obj: bpy.types.Object) -> Matrix:
|
def get_relative_object_matrix(cls, target_obj: bpy.types.Object, relative_to_obj: bpy.types.Object) -> Matrix:
|
||||||
return relative_to_obj.matrix_world.inverted() @ target_obj.matrix_world
|
return relative_to_obj.matrix_world.inverted() @ target_obj.matrix_world
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def import_containers(cls, parent: Optional[ifcopenshell.entity_instance] = None) -> None:
|
|
||||||
props = bpy.context.scene.BIMSpatialProperties
|
|
||||||
props.containers.clear()
|
|
||||||
|
|
||||||
if not parent:
|
|
||||||
parent = tool.Ifc.get().by_type("IfcProject")[0]
|
|
||||||
|
|
||||||
props.active_container_id = parent.id()
|
|
||||||
|
|
||||||
for rel in parent.IsDecomposedBy or []:
|
|
||||||
related_objects = []
|
|
||||||
for element in rel.RelatedObjects:
|
|
||||||
# skip objects without placements
|
|
||||||
if not element.is_a("IfcProduct"):
|
|
||||||
continue
|
|
||||||
related_objects.append((element, ifcopenshell.util.placement.get_storey_elevation(element)))
|
|
||||||
related_objects = sorted(related_objects, key=lambda e: e[1])
|
|
||||||
for element, _ in related_objects:
|
|
||||||
new = props.containers.add()
|
|
||||||
new.name = element.Name or "Unnamed"
|
|
||||||
new.long_name = element.LongName or ""
|
|
||||||
new.has_decomposition = bool(element.IsDecomposedBy)
|
|
||||||
new.ifc_definition_id = element.id()
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run_root_copy_class(cls, obj: bpy.types.Object) -> ifcopenshell.entity_instance:
|
def run_root_copy_class(cls, obj: bpy.types.Object) -> ifcopenshell.entity_instance:
|
||||||
return blenderbim.core.root.copy_class(tool.Ifc, tool.Collector, tool.Geometry, tool.Root, obj=obj)
|
return blenderbim.core.root.copy_class(tool.Ifc, tool.Collector, tool.Geometry, tool.Root, obj=obj)
|
||||||
@@ -886,3 +858,11 @@ class Spatial(blenderbim.core.tool.Spatial):
|
|||||||
if subelement:
|
if subelement:
|
||||||
return subelement
|
return subelement
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_selected_containers(cls) -> List[ifcopenshell.entity_instance]:
|
||||||
|
results = []
|
||||||
|
for obj in tool.Blender.get_selected_objects():
|
||||||
|
if (element := tool.Ifc.get_entity(obj)) and tool.Root.is_spatial_element(element):
|
||||||
|
results.append(element)
|
||||||
|
return results
|
||||||
|
|||||||
Reference in New Issue
Block a user