Make remove opening more accessible in UI and refactor

This commit is contained in:
Dion Moult
2022-10-10 11:45:40 +11:00
parent 5d5ab3dafd
commit a5517071cc
4 changed files with 88 additions and 86 deletions
@@ -384,8 +384,7 @@ class OverrideDeleteTrait:
bpy.ops.bim.remove_opening(opening_id=element.id()) bpy.ops.bim.remove_opening(opening_id=element.id())
def remove_filling(self, element): def remove_filling(self, element):
obj = IfcStore.get_element(element.id()) bpy.ops.bim.remove_filling(filling=element.id())
bpy.ops.bim.remove_filling(obj=obj.name)
def remove_port(self, port): def remove_port(self, port):
blenderbim.core.system.remove_port(tool.Ifc, tool.System, port=port) blenderbim.core.system.remove_port(tool.Ifc, tool.System, port=port)
@@ -22,6 +22,50 @@ import blenderbim.tool as tool
def refresh(): def refresh():
BooleansData.is_loaded = False BooleansData.is_loaded = False
VoidsData.is_loaded = False
class VoidsData:
data = {}
is_loaded = False
@classmethod
def load(cls):
cls.data = {"active_opening": cls.active_opening(), "openings": cls.openings(), "fillings": cls.fillings()}
cls.is_loaded = True
@classmethod
def active_opening(cls):
element = tool.Ifc.get_entity(bpy.context.active_object)
if element and element.is_a("IfcOpeningElement"):
return element.id()
@classmethod
def openings(cls):
element = tool.Ifc.get_entity(bpy.context.active_object)
if not element:
return []
results = []
for rel in getattr(element, "HasOpenings", []) or []:
has_fillings = []
opening = rel.RelatedOpeningElement
for rel2 in getattr(opening, "HasFillings", []) or []:
filling = rel2.RelatedBuildingElement
has_fillings.append({"id": filling.id(), "Name": filling.Name or "Unnamed"})
results.append({"id": opening.id(), "Name": opening.Name or "Unnamed", "HasFillings": has_fillings})
return results
@classmethod
def fillings(cls):
element = tool.Ifc.get_entity(bpy.context.active_object)
if not element:
return []
results = []
for rel in getattr(element, "HasFillings", []) or []:
filling = rel.RelatedBuildingElement
results.append({"id": filling.id(), "Name": filling.Name or "Unnamed"})
return results
class BooleansData: class BooleansData:
@@ -22,7 +22,6 @@ import ifcopenshell.util.representation
import blenderbim.tool as tool import blenderbim.tool as tool
import blenderbim.core.geometry import blenderbim.core.geometry
from blenderbim.bim.ifc import IfcStore from blenderbim.bim.ifc import IfcStore
from ifcopenshell.api.void.data import Data
class AddOpening(bpy.types.Operator, tool.Ifc.Operator): class AddOpening(bpy.types.Operator, tool.Ifc.Operator):
@@ -89,7 +88,6 @@ class AddOpening(bpy.types.Operator, tool.Ifc.Operator):
is_global=True, is_global=True,
should_sync_changes_first=False, should_sync_changes_first=False,
) )
Data.load(tool.Ifc.get(), element1.id())
if not has_visible_openings: if not has_visible_openings:
tool.Ifc.unlink(obj=obj2) tool.Ifc.unlink(obj=obj2)
@@ -128,7 +126,6 @@ class RemoveOpening(bpy.types.Operator, tool.Ifc.Operator):
) )
tool.Geometry.clear_cache(element) tool.Geometry.clear_cache(element)
Data.load(tool.Ifc.get(), obj.BIMObjectProperties.ifc_definition_id)
return {"FINISHED"} return {"FINISHED"}
@@ -153,37 +150,23 @@ class AddFilling(bpy.types.Operator):
if not element_id or not opening_id or element_id == opening_id: if not element_id or not opening_id or element_id == opening_id:
return {"FINISHED"} return {"FINISHED"}
ifcopenshell.api.run( ifcopenshell.api.run(
"void.add_filling", "void.add_filling", self.file, opening=self.file.by_id(opening_id), element=self.file.by_id(element_id)
self.file,
**{
"opening": self.file.by_id(opening_id),
"element": self.file.by_id(element_id),
},
) )
Data.load(self.file, element_id)
return {"FINISHED"} return {"FINISHED"}
class RemoveFilling(bpy.types.Operator): class RemoveFilling(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.remove_filling" bl_idname = "bim.remove_filling"
bl_label = "Remove Filling" bl_label = "Remove Filling"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
obj: bpy.props.StringProperty() filling: bpy.props.IntProperty()
def execute(self, context):
return IfcStore.execute_ifc_operator(self, context)
def _execute(self, context): def _execute(self, context):
obj = bpy.data.objects.get(self.obj) if self.obj else context.active_object filling = tool.Ifc.get().by_id(self.filling)
if not obj: filling_obj = tool.Ifc.get_object(filling)
return {"FINISHED"} for rel in filling.FillsVoids:
element = tool.Ifc.get_entity(obj)
if not element:
return {"FINISHED"}
for rel in element.FillsVoids:
bpy.ops.bim.remove_opening(opening_id=rel.RelatingOpeningElement.id()) bpy.ops.bim.remove_opening(opening_id=rel.RelatingOpeningElement.id())
ifcopenshell.api.run("void.remove_filling", tool.Ifc.get(), element=element) ifcopenshell.api.run("void.remove_filling", tool.Ifc.get(), element=filling)
Data.load(tool.Ifc.get(), element.id())
return {"FINISHED"} return {"FINISHED"}
+36 -60
View File
@@ -17,10 +17,9 @@
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>. # along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
import bpy import bpy
import blenderbim.tool as tool
from bpy.types import Panel from bpy.types import Panel
from ifcopenshell.api.void.data import Data from blenderbim.bim.module.void.data import BooleansData, VoidsData
from blenderbim.bim.ifc import IfcStore
from blenderbim.bim.module.void.data import BooleansData
class BIM_PT_voids(Panel): class BIM_PT_voids(Panel):
@@ -34,71 +33,48 @@ class BIM_PT_voids(Panel):
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
if not context.active_object: if not tool.Ifc.get_entity(context.active_object):
return False return False
if not IfcStore.get_element(context.active_object.BIMObjectProperties.ifc_definition_id): return True
return False
return IfcStore.get_file()
def draw(self, context): def draw(self, context):
props = context.active_object.BIMObjectProperties if not VoidsData.is_loaded:
file = IfcStore.get_file() VoidsData.load()
if props.ifc_definition_id not in Data.products:
Data.load(file, props.ifc_definition_id)
active_object_is_an_opening = file.by_id(props.ifc_definition_id).is_a("IfcOpeningElement")
row = self.layout.row(align=True)
if len(context.selected_objects) == 2:
op = row.operator("bim.add_opening", icon="ADD", text="Add Opening")
opening_id = None
obj_name = None
for obj in context.selected_objects:
if obj.BIMObjectProperties.ifc_definition_id in Data.openings:
opening_id = obj.BIMObjectProperties.ifc_definition_id
elif obj.BIMObjectProperties.ifc_definition_id in Data.fillings:
opening_id = Data.fillings[obj.BIMObjectProperties.ifc_definition_id]["FillsVoid"]
else:
obj_name = obj.name
if opening_id and obj_name:
op = row.operator("bim.remove_opening", icon="X", text="Remove Opening").opening_id = opening_id
opening_ids = Data.products[props.ifc_definition_id] props = context.active_object.BIMObjectProperties
if not opening_ids and not active_object_is_an_opening:
if len(context.selected_objects) == 2:
row = self.layout.row(align=True) row = self.layout.row(align=True)
row.label(text="No Openings", icon="SELECT_SUBTRACT") op = row.operator("bim.add_opening", icon="ADD", text="Add Opening")
for opening_id in opening_ids:
opening = Data.openings[opening_id] if VoidsData.data["active_opening"]:
if opening["HasFillings"]: row = self.layout.row()
for filling_id in opening["HasFillings"]: op = row.operator("bim.remove_opening", icon="X", text="Remove Opening")
filling = Data.fillings.get(filling_id) op.opening_id = VoidsData.data["active_opening"]
if filling is None:
continue if not VoidsData.data["fillings"]:
row = self.layout.row(align=True) row = self.layout.row()
row.label(text=opening["Name"], icon="SELECT_SUBTRACT") row.label(text="No Fillings", icon="SELECT_INTERSECT")
row.label(text=filling["Name"], icon="SELECT_INTERSECT")
else: for filling in VoidsData.data["fillings"]:
row = self.layout.row(align=True)
row.label(text=opening["Name"], icon="SELECT_SUBTRACT")
op = row.operator("bim.remove_opening", icon="X", text="").opening_id = opening_id
if props.ifc_definition_id in Data.openings:
for filling_id in Data.openings[props.ifc_definition_id]["HasFillings"]:
filling = Data.fillings.get(filling_id)
if filling is None:
continue
row = self.layout.row(align=True) row = self.layout.row(align=True)
row.label(text=filling["Name"], icon="SELECT_INTERSECT") row.label(text=filling["Name"], icon="SELECT_INTERSECT")
op = row.operator("bim.remove_filling", icon="X", text="") row.operator("bim.remove_filling", icon="X", text="").filling = filling["id"]
op.obj = IfcStore.get_element(filling_id).name
if active_object_is_an_opening:
pass
elif props.ifc_definition_id not in Data.fillings:
row = self.layout.row(align=True)
row.prop(context.scene.VoidProperties, "desired_opening", text="", icon="SELECT_INTERSECT")
row.operator("bim.add_filling", icon="ADD", text="")
else: else:
opening = Data.openings[Data.fillings[props.ifc_definition_id]["FillsVoid"]] if not VoidsData.data["openings"]:
row = self.layout.row(align=True) row = self.layout.row()
row.label(text=opening["Name"], icon="SELECT_INTERSECT") row.label(text="No Openings", icon="SELECT_SUBTRACT")
row.operator("bim.remove_filling", icon="X", text="")
for opening in VoidsData.data["openings"]:
if opening["HasFillings"]:
for filling in opening["HasFillings"]:
row = self.layout.row(align=True)
row.label(text=opening["Name"], icon="SELECT_SUBTRACT")
row.label(text=filling["Name"], icon="SELECT_INTERSECT")
else:
row = self.layout.row(align=True)
row.label(text=opening["Name"], icon="SELECT_SUBTRACT")
row.operator("bim.remove_opening", icon="X", text="").opening_id = opening["id"]
class BIM_PT_booleans(Panel): class BIM_PT_booleans(Panel):