Fix #6030. Consolidate group management into single UI and allow for bulk assign / unassign.

This commit is contained in:
Dion Moult
2025-01-25 14:01:56 +11:00
parent 5fbb496818
commit a2a4da596f
5 changed files with 48 additions and 110 deletions
@@ -38,7 +38,6 @@ classes = (
ui.BIM_PT_groups, ui.BIM_PT_groups,
ui.BIM_PT_object_groups, ui.BIM_PT_object_groups,
ui.BIM_UL_groups, ui.BIM_UL_groups,
ui.BIM_UL_object_groups,
) )
+1 -5
View File
@@ -48,13 +48,9 @@ class ObjectGroupsData:
@classmethod @classmethod
def load(cls): def load(cls):
cls.data = {"total_groups": cls.total_groups(), "groups": cls.groups()} cls.data = {"groups": cls.groups()}
cls.is_loaded = True cls.is_loaded = True
@classmethod
def total_groups(cls):
return len(tool.Ifc.get().by_type("IfcGroup", include_subtypes=False))
@classmethod @classmethod
def groups(cls): def groups(cls):
element = tool.Ifc.get_entity(bpy.context.active_object) element = tool.Ifc.get_entity(bpy.context.active_object)
+26 -30
View File
@@ -164,52 +164,48 @@ class AssignGroup(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.assign_group" bl_idname = "bim.assign_group"
bl_label = "Assign Group" bl_label = "Assign Group"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
product: bpy.props.StringProperty() bl_description = "Assign the selected objects to the selected group\nALT + CLICK to unassign."
group: bpy.props.IntProperty() group: bpy.props.IntProperty(options={"SKIP_SAVE"})
is_assigning: bpy.props.BoolProperty(default=True, options={"SKIP_SAVE"})
def invoke(self, context, event):
self.is_assigning = not event.alt
return self.execute(context)
def _execute(self, context): def _execute(self, context):
self.file = IfcStore.get_file() if not self.is_assigning:
products = [bpy.data.objects.get(self.product)] if self.product else context.selected_objects return bpy.ops.bim.unassign_group(group=self.group)
for product in products: products = [
if not product.BIMObjectProperties.ifc_definition_id: tool.Ifc.get_entity(o)
continue for o in tool.Blender.get_selected_objects(include_active=False)
ifcopenshell.api.run( if tool.Ifc.get_entity(o)
"group.assign_group", ]
self.file, ifcopenshell.api.group.assign_group(tool.Ifc.get(), products=products, group=tool.Ifc.get().by_id(self.group))
products=[self.file.by_id(product.BIMObjectProperties.ifc_definition_id)],
group=self.file.by_id(self.group),
)
return {"FINISHED"}
class UnassignGroup(bpy.types.Operator, tool.Ifc.Operator): class UnassignGroup(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.unassign_group" bl_idname = "bim.unassign_group"
bl_label = "Unassign Group" bl_label = "Unassign Group"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
product: bpy.props.StringProperty() bl_description = "Unassign the selected objects from the selected group"
group: bpy.props.IntProperty() group: bpy.props.IntProperty(options={"SKIP_SAVE"})
def _execute(self, context): def _execute(self, context):
self.file = IfcStore.get_file() products = [
products = [bpy.data.objects.get(self.product)] if self.product else context.selected_objects tool.Ifc.get_entity(o)
for product in products: for o in tool.Blender.get_selected_objects(include_active=False)
if not product.BIMObjectProperties.ifc_definition_id: if tool.Ifc.get_entity(o)
continue ]
ifcopenshell.api.run( if not products:
"group.unassign_group", return
self.file, ifcopenshell.api.group.unassign_group(tool.Ifc.get(), products=products, group=tool.Ifc.get().by_id(self.group))
**{
"products": [self.file.by_id(product.BIMObjectProperties.ifc_definition_id)],
"group": self.file.by_id(self.group),
}
)
return {"FINISHED"}
class SelectGroupProducts(bpy.types.Operator, tool.Ifc.Operator): class SelectGroupProducts(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.select_group_products" bl_idname = "bim.select_group_products"
bl_label = "Select Group Products" bl_label = "Select Group Products"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
bl_description = "Select objects assigned to the selected group"
group: bpy.props.IntProperty() group: bpy.props.IntProperty()
def _execute(self, context): def _execute(self, context):
@@ -55,3 +55,8 @@ class BIMGroupProperties(PropertyGroup):
groups: CollectionProperty(name="Groups", type=Group) groups: CollectionProperty(name="Groups", type=Group)
active_group_index: IntProperty(name="Active Group Index", update=update_active_group_index) active_group_index: IntProperty(name="Active Group Index", update=update_active_group_index)
active_group_id: IntProperty(name="Active Group Id") active_group_id: IntProperty(name="Active Group Id")
@property
def active_group(self):
if self.active_group_index < len(self.groups):
return self.groups[self.active_group_index]
+16 -74
View File
@@ -49,21 +49,25 @@ class BIM_PT_groups(Panel):
else: else:
row.operator("bim.load_groups", text="", icon="GREASEPENCIL") row.operator("bim.load_groups", text="", icon="GREASEPENCIL")
if self.props.is_editing: if not self.props.is_editing:
self.layout.template_list( return
"BIM_UL_groups",
"", if (group := self.props.active_group) and (group_id := group.ifc_definition_id):
self.props, row = self.layout.row(align=True)
"groups", row.alignment = "RIGHT"
self.props, row.operator("bim.select_group_products", text="", icon="RESTRICT_SELECT_OFF").group = group_id
"active_group_index", row.operator("bim.assign_group", text="", icon="FOLDER_REDIRECT").group = group_id
) row.operator("bim.enable_editing_group", text="", icon="GREASEPENCIL").group = group_id
row.operator("bim.add_group", text="", icon="ADD").group = group_id
row.operator("bim.remove_group", text="", icon="X").group = group_id
if self.props.active_group_id: if self.props.active_group_id:
self.draw_editable_ui(context) draw_attributes(self.props.group_attributes, self.layout)
row = self.layout.row(align=True)
row.operator("bim.edit_group", text="Save Group", icon="CHECKMARK")
row.operator("bim.disable_editing_group", text="", icon="CANCEL")
def draw_editable_ui(self, context: bpy.types.Context) -> None: self.layout.template_list("BIM_UL_groups", "", self.props, "groups", self.props, "active_group_index")
draw_attributes(self.props.group_attributes, self.layout)
class BIM_PT_object_groups(Panel): class BIM_PT_object_groups(Panel):
@@ -86,21 +90,6 @@ class BIM_PT_object_groups(Panel):
if not ObjectGroupsData.is_loaded: if not ObjectGroupsData.is_loaded:
ObjectGroupsData.load() ObjectGroupsData.load()
self.props = context.scene.BIMGroupProperties self.props = context.scene.BIMGroupProperties
row = self.layout.row(align=True)
if self.props.is_editing:
row.label(text="Adding Groups", icon="OUTLINER")
row.operator("bim.disable_group_editing_ui", text="", icon="CANCEL")
self.layout.template_list(
"BIM_UL_object_groups",
"",
self.props,
"groups",
self.props,
"active_group_index",
)
else:
row.label(text=f"{ObjectGroupsData.data['total_groups']} Groups in IFC Project", icon="OUTLINER")
row.operator("bim.load_groups", text="", icon="GREASEPENCIL")
for group in ObjectGroupsData.data["groups"]: for group in ObjectGroupsData.data["groups"]:
row = self.layout.row(align=True) row = self.layout.row(align=True)
@@ -126,51 +115,4 @@ class BIM_UL_groups(UIList):
op.ifc_definition_id = item.ifc_definition_id op.ifc_definition_id = item.ifc_definition_id
op.index = index op.index = index
op.option = "Collapse" if item.is_expanded else "Expand" op.option = "Collapse" if item.is_expanded else "Expand"
else:
row.label(text="", icon="BLANK1")
row.label(text=item.name) row.label(text=item.name)
group_id = item.ifc_definition_id
if context.scene.BIMGroupProperties.active_group_id == group_id:
op = row.operator("bim.select_group_products", text="", icon="RESTRICT_SELECT_OFF")
op.group = group_id
row.operator("bim.edit_group", text="", icon="CHECKMARK")
row.operator("bim.disable_editing_group", text="", icon="CANCEL")
elif context.scene.BIMGroupProperties.active_group_id:
op = row.operator("bim.select_group_products", text="", icon="RESTRICT_SELECT_OFF")
op.group = group_id
op = row.operator("bim.add_group", text="", icon="ADD")
op.group = group_id
op = row.operator("bim.remove_group", text="", icon="X")
op.group = group_id
else:
op = row.operator("bim.select_group_products", text="", icon="RESTRICT_SELECT_OFF")
op.group = group_id
op = row.operator("bim.enable_editing_group", text="", icon="GREASEPENCIL")
op.group = group_id
op = row.operator("bim.add_group", text="", icon="ADD")
op.group = group_id
op = row.operator("bim.remove_group", text="", icon="X")
op.group = group_id
class BIM_UL_object_groups(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
if item:
row = layout.row(align=True)
for i in range(0, item.tree_depth):
row.label(text="", icon="BLANK1")
if item.has_children:
op = row.operator(
"bim.toggle_group", icon="TRIA_DOWN" if item.is_expanded else "TRIA_RIGHT", text="", emboss=False
)
op.ifc_definition_id = item.ifc_definition_id
op.index = index
op.option = "Collapse" if item.is_expanded else "Expand"
else:
row.label(text="", icon="BLANK1")
row.label(text=item.name)
op = row.operator("bim.remove_group", text="", icon="X")
op.group = item.ifc_definition_id
op = row.operator("bim.assign_group", text="", icon="ADD")
op.group = item.ifc_definition_id