You can now lock and unlock spatial / grid elements, which affects your ability to delete or move them

This commit is contained in:
Dion Moult
2024-09-06 17:58:45 +10:00
parent d6098a0b6d
commit 4a5e180479
5 changed files with 68 additions and 15 deletions
@@ -612,10 +612,11 @@ class OverrideDelete(bpy.types.Operator):
return self.execute(context)
def draw(self, context):
row = self.layout.row()
row.label(text="Warning: Faster deletion will use more memory.", icon="ERROR")
row = self.layout.row()
row.prop(self, "is_batch", text="Enable Faster Deletion")
if self.is_batch:
row = self.layout.row()
row.label(text="Warning: Faster deletion will use more memory.", icon="ERROR")
def _execute(self, context):
start_time = time()
@@ -627,7 +628,7 @@ class OverrideDelete(bpy.types.Operator):
for obj in context.selected_objects:
element = tool.Ifc.get_entity(obj)
if element:
if tool.Geometry.is_lockable(element):
if tool.Geometry.is_locked(element):
continue
if ifcopenshell.util.element.get_pset(element, "BBIM_Array"):
self.report({"INFO"}, "Elements that are part of an array cannot be deleted.")
@@ -736,10 +737,11 @@ class OverrideOutlinerDelete(bpy.types.Operator):
return self.execute(context)
def draw(self, context):
row = self.layout.row()
row.label(text="Warning: Faster deletion will use more memory.", icon="ERROR")
row = self.layout.row()
row.prop(self, "is_batch", text="Enable Faster Deletion")
if self.is_batch:
row = self.layout.row()
row.label(text="Warning: Faster deletion will use more memory.", icon="ERROR")
def _execute(self, context):
if self.is_batch:
@@ -757,7 +759,7 @@ class OverrideOutlinerDelete(bpy.types.Operator):
objects_to_delete.add(bpy.data.objects.get(item.name))
for obj in objects_to_delete:
if element := tool.Ifc.get_entity(obj):
if tool.Geometry.is_lockable(element):
if tool.Geometry.is_locked(element):
if collection := obj.BIMObjectProperties.collection:
collections_to_delete.discard(collection)
continue
@@ -86,6 +86,35 @@ def update_container_obj(self, context):
self.container_obj = None
def update_grid_is_locked(self, context):
if not tool.Ifc.get():
return
if tool.Ifc.get().schema in ("IFC2X3", "IFC4"):
elements = tool.Ifc.get().by_type("IfcGrid") + tool.Ifc.get().by_type("IfcGridAxis")
else:
elements = tool.Ifc.get().by_type("IfcPositioningElement")
for element in elements:
if obj := tool.Ifc.get_object(element):
if self.is_locked:
tool.Geometry.lock_object(obj)
else:
tool.Geometry.unlock_object(obj)
def update_spatial_is_locked(self, context):
if not tool.Ifc.get():
return
if tool.Ifc.get().schema == "IFC2X3":
elements = tool.Ifc.get().by_type("IfcSpatialStructureElement")
else:
elements = tool.Ifc.get().by_type("IfcSpatialElement")
for element in elements:
if obj := tool.Ifc.get_object(element):
if self.is_locked:
tool.Geometry.lock_object(obj)
else:
tool.Geometry.unlock_object(obj)
def poll_container_obj(self, obj):
return obj is None or tool.Ifc.get_entity(obj)
@@ -133,6 +162,7 @@ class Element(PropertyGroup):
class BIMSpatialDecompositionProperties(PropertyGroup):
is_locked: BoolProperty(name="Is Locked", default=True, update=update_spatial_is_locked)
container_filter: StringProperty(name="Container Filter", default="", options={"TEXTEDIT_UPDATE"})
containers: CollectionProperty(name="Containers", type=BIMContainer)
contracted_containers: StringProperty(name="Contracted containers", default="[]")
@@ -169,4 +199,5 @@ class BIMSpatialDecompositionProperties(PropertyGroup):
class BIMGridProperties(PropertyGroup):
is_locked: BoolProperty(name="Is Locked", default=True, update=update_grid_is_locked)
grid_axes: CollectionProperty(name="Grid Axes", type=ObjProperty)
@@ -96,11 +96,19 @@ class BIM_PT_spatial_decomposition(Panel):
bl_region_type = "WINDOW"
bl_context = "scene"
bl_parent_id = "BIM_PT_tab_spatial"
bl_options = {"HEADER_LAYOUT_EXPAND"}
@classmethod
def poll(cls, context):
return tool.Ifc.get()
def draw_header(self, context):
row = self.layout.row(align=True)
row.label(text="") # empty text occupies the left of the row
icon = "VIEW_LOCKED" if context.scene.BIMSpatialDecompositionProperties.is_locked else "VIEW_UNLOCKED"
row.prop(context.scene.BIMSpatialDecompositionProperties, "is_locked", text="", icon=icon)
def draw(self, context):
if not SpatialDecompositionData.is_loaded:
SpatialDecompositionData.load()
@@ -203,10 +211,17 @@ class BIM_PT_grids(Panel):
bl_region_type = "WINDOW"
bl_context = "scene"
bl_parent_id = "BIM_PT_tab_spatial"
bl_options = {"HEADER_LAYOUT_EXPAND"}
def draw(self, context):
self.layout.row().operator("mesh.add_grid", icon="ADD", text="Add Grids")
def draw_header(self, context):
row = self.layout.row(align=True)
row.label(text="") # empty text occupies the left of the row
icon = "VIEW_LOCKED" if context.scene.BIMGridProperties.is_locked else "VIEW_UNLOCKED"
row.prop(context.scene.BIMGridProperties, "is_locked", text="", icon=icon)
class BIM_UL_containers_manager(UIList):
def __init__(self):
+1 -1
View File
@@ -41,7 +41,7 @@ class Collector(bonsai.core.tool.Collector):
element = tool.Ifc.get_entity(obj)
assert element
if tool.Geometry.is_lockable(element):
if tool.Geometry.is_locked(element):
tool.Geometry.lock_object(obj)
if element.is_a("IfcGridAxis"):
+13 -8
View File
@@ -92,14 +92,14 @@ class Geometry(bonsai.core.tool.Geometry):
bpy.data.meshes.remove(data)
@classmethod
def is_lockable(cls, element: ifcopenshell.entity_instance) -> bool:
if (
element.is_a("IfcProject")
or tool.Root.is_spatial_element(element)
or element.is_a("IfcPositioningElement")
or element.is_a("IfcGrid")
or element.is_a("IfcGridAxis")
):
def is_locked(cls, element: ifcopenshell.entity_instance) -> bool:
if element.is_a("IfcProject"):
return True
elif tool.Root.is_spatial_element(element) and bpy.context.scene.BIMSpatialDecompositionProperties.is_locked:
return True
elif (
element.is_a("IfcPositioningElement") or element.is_a("IfcGrid") or element.is_a("IfcGridAxis")
) and bpy.context.scene.BIMGridProperties.is_locked:
return True
return False
@@ -108,6 +108,11 @@ class Geometry(bonsai.core.tool.Geometry):
obj.lock_location = (True, True, True)
obj.lock_rotation = (True, True, True)
@classmethod
def unlock_object(cls, obj: bpy.types.Object) -> None:
obj.lock_location = (False, False, False)
obj.lock_rotation = (False, False, False)
@classmethod
def delete_ifc_object(cls, obj: bpy.types.Object) -> None:
element = tool.Ifc.get_entity(obj)