mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 09:21:46 +00:00
Improve groups and systems interface (#1688)
* Enable Batch adding/removing objects from groups Might hang up Blender for a few secs with a big number of object on execution * Enable Batch adding/removing objects from systems Might hang up Blender for a few secs with a big number of object on execution * Add Group Panel in object properties + Transfer adding object(s) to group into the object properties * Add Systems Panel in object properties + Transfer adding object(s) to system into the object properties * Simplify group & systems operators * Disabling Editing of groups/systems also disables individual edition
This commit is contained in:
@@ -26,6 +26,7 @@ classes = (
|
||||
operator.AddGroup,
|
||||
operator.EditGroup,
|
||||
operator.RemoveGroup,
|
||||
operator.ToggleAssigningGroup,
|
||||
operator.AssignGroup,
|
||||
operator.UnassignGroup,
|
||||
operator.EnableEditingGroup,
|
||||
@@ -34,7 +35,9 @@ classes = (
|
||||
prop.Group,
|
||||
prop.BIMGroupProperties,
|
||||
ui.BIM_PT_groups,
|
||||
ui.BIM_PT_object_groups,
|
||||
ui.BIM_UL_groups,
|
||||
ui.BIM_UL_object_groups,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ class DisableGroupEditingUI(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
context.scene.BIMGroupProperties.is_editing = False
|
||||
context.scene.BIMGroupProperties.active_group_id = 0
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -145,6 +146,16 @@ class DisableEditingGroup(bpy.types.Operator):
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class ToggleAssigningGroup(bpy.types.Operator):
|
||||
bl_idname = "bim.toggle_assigning_group"
|
||||
bl_label = "Toggle Assigning Group"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
context.scene.BIMGroupProperties.is_adding = not context.scene.BIMGroupProperties.is_adding
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class AssignGroup(bpy.types.Operator):
|
||||
bl_idname = "bim.assign_group"
|
||||
bl_label = "Assign Group"
|
||||
@@ -156,17 +167,20 @@ class AssignGroup(bpy.types.Operator):
|
||||
return IfcStore.execute_ifc_operator(self, context)
|
||||
|
||||
def _execute(self, context):
|
||||
product = bpy.data.objects.get(self.product) if self.product else context.active_object
|
||||
self.file = IfcStore.get_file()
|
||||
ifcopenshell.api.run(
|
||||
"group.assign_group",
|
||||
self.file,
|
||||
**{
|
||||
"product": self.file.by_id(product.BIMObjectProperties.ifc_definition_id),
|
||||
"group": self.file.by_id(self.group),
|
||||
}
|
||||
)
|
||||
Data.load(IfcStore.get_file())
|
||||
products = [bpy.data.objects.get(self.product)] if self.product else context.selected_objects
|
||||
for product in products:
|
||||
if not product.BIMObjectProperties.ifc_definition_id:
|
||||
continue
|
||||
ifcopenshell.api.run(
|
||||
"group.assign_group",
|
||||
self.file,
|
||||
**{
|
||||
"product": self.file.by_id(product.BIMObjectProperties.ifc_definition_id),
|
||||
"group": self.file.by_id(self.group),
|
||||
}
|
||||
)
|
||||
Data.load(self.file)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -181,16 +195,19 @@ class UnassignGroup(bpy.types.Operator):
|
||||
return IfcStore.execute_ifc_operator(self, context)
|
||||
|
||||
def _execute(self, context):
|
||||
product = bpy.data.objects.get(self.product) if self.product else context.active_object
|
||||
self.file = IfcStore.get_file()
|
||||
ifcopenshell.api.run(
|
||||
"group.unassign_group",
|
||||
self.file,
|
||||
**{
|
||||
"product": self.file.by_id(product.BIMObjectProperties.ifc_definition_id),
|
||||
"group": self.file.by_id(self.group),
|
||||
}
|
||||
)
|
||||
products = [bpy.data.objects.get(self.product)] if self.product else context.selected_objects
|
||||
for product in products:
|
||||
if not product.BIMObjectProperties.ifc_definition_id:
|
||||
continue
|
||||
ifcopenshell.api.run(
|
||||
"group.unassign_group",
|
||||
self.file,
|
||||
**{
|
||||
"product": self.file.by_id(product.BIMObjectProperties.ifc_definition_id),
|
||||
"group": self.file.by_id(self.group),
|
||||
}
|
||||
)
|
||||
Data.load(IfcStore.get_file())
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ class Group(PropertyGroup):
|
||||
class BIMGroupProperties(PropertyGroup):
|
||||
group_attributes: CollectionProperty(name="Group Attributes", type=Attribute)
|
||||
is_editing: BoolProperty(name="Is Editing", default=False)
|
||||
is_adding: BoolProperty(name="Is Adding", default=False)
|
||||
groups: CollectionProperty(name="Groups", type=Group)
|
||||
active_group_index: IntProperty(name="Active Group Index")
|
||||
active_group_id: IntProperty(name="Active Group Id")
|
||||
|
||||
@@ -68,37 +68,78 @@ class BIM_PT_groups(Panel):
|
||||
row.prop(attribute, "is_null", icon="RADIOBUT_OFF" if attribute.is_null else "RADIOBUT_ON", text="")
|
||||
|
||||
|
||||
class BIM_PT_object_groups(Panel):
|
||||
bl_label = "IFC Groups"
|
||||
bl_idname = "BIM_PT_object_groups"
|
||||
bl_options = {"DEFAULT_CLOSED"}
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "object"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return IfcStore.get_file() and context.active_object.BIMObjectProperties.ifc_definition_id
|
||||
|
||||
def draw(self, context):
|
||||
if not Data.is_loaded:
|
||||
Data.load(IfcStore.get_file())
|
||||
self.props = context.scene.BIMGroupProperties
|
||||
row = self.layout.row(align=True)
|
||||
if self.props.is_adding:
|
||||
row.label(text="Adding Groups", icon="OUTLINER")
|
||||
row.operator("bim.toggle_assigning_group", text="", icon="CANCEL")
|
||||
self.layout.template_list(
|
||||
"BIM_UL_object_groups",
|
||||
"",
|
||||
self.props,
|
||||
"groups",
|
||||
self.props,
|
||||
"active_group_index",
|
||||
)
|
||||
else:
|
||||
row.label(text=f"{len(Data.groups)} Groups in IFC Project", icon="OUTLINER")
|
||||
row.operator("bim.toggle_assigning_group", text="", icon="ADD")
|
||||
|
||||
groups_object = Data.products.get(context.active_object.BIMObjectProperties.ifc_definition_id, [])
|
||||
for group_id in groups_object:
|
||||
row = self.layout.row(align=True)
|
||||
row.label(text=Data.groups[group_id].get("Name", "Unnamed"))
|
||||
op = row.operator("bim.unassign_group", text="", icon="X")
|
||||
op.group = group_id
|
||||
|
||||
if not groups_object:
|
||||
self.layout.label(text="No Group associated with Active Object")
|
||||
|
||||
|
||||
class BIM_UL_groups(UIList):
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
||||
if item:
|
||||
row = layout.row(align=True)
|
||||
row.label(text=item.name)
|
||||
|
||||
if context.active_object:
|
||||
oprops = context.active_object.BIMObjectProperties
|
||||
if (
|
||||
oprops.ifc_definition_id in Data.products
|
||||
and item.ifc_definition_id in Data.products[oprops.ifc_definition_id]
|
||||
):
|
||||
op = row.operator("bim.unassign_group", text="", icon="KEYFRAME_HLT", emboss=False)
|
||||
op.group = item.ifc_definition_id
|
||||
else:
|
||||
op = row.operator("bim.assign_group", text="", icon="KEYFRAME", emboss=False)
|
||||
op.group = item.ifc_definition_id
|
||||
|
||||
if context.scene.BIMGroupProperties.active_group_id == item.ifc_definition_id:
|
||||
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 = item.ifc_definition_id
|
||||
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 = item.ifc_definition_id
|
||||
row.operator("bim.remove_group", text="", icon="X").group = item.ifc_definition_id
|
||||
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 = item.ifc_definition_id
|
||||
op.group = group_id
|
||||
op = row.operator("bim.enable_editing_group", text="", icon="GREASEPENCIL")
|
||||
op.group = item.ifc_definition_id
|
||||
row.operator("bim.remove_group", text="", icon="X").group = item.ifc_definition_id
|
||||
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):
|
||||
if item:
|
||||
row = layout.row(align=True)
|
||||
row.label(text=item.name)
|
||||
op = row.operator("bim.assign_group", text="", icon="ADD")
|
||||
op.group = item.ifc_definition_id
|
||||
|
||||
@@ -26,6 +26,7 @@ classes = (
|
||||
operator.AddSystem,
|
||||
operator.EditSystem,
|
||||
operator.RemoveSystem,
|
||||
operator.ToggleAssigningSystem,
|
||||
operator.AssignSystem,
|
||||
operator.UnassignSystem,
|
||||
operator.EnableEditingSystem,
|
||||
@@ -34,7 +35,9 @@ classes = (
|
||||
prop.System,
|
||||
prop.BIMSystemProperties,
|
||||
ui.BIM_PT_systems,
|
||||
ui.BIM_PT_object_systems,
|
||||
ui.BIM_UL_systems,
|
||||
ui.BIM_UL_object_systems,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ class DisableSystemEditingUI(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
context.scene.BIMSystemProperties.is_editing = False
|
||||
context.scene.BIMSystemProperties.active_system_id = 0
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -145,6 +146,16 @@ class DisableEditingSystem(bpy.types.Operator):
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class ToggleAssigningSystem(bpy.types.Operator):
|
||||
bl_idname = "bim.toggle_assigning_system"
|
||||
bl_label = "Toggle Assigning System"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
context.scene.BIMSystemProperties.is_adding = not context.scene.BIMSystemProperties.is_adding
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class AssignSystem(bpy.types.Operator):
|
||||
bl_idname = "bim.assign_system"
|
||||
bl_label = "Assign System"
|
||||
@@ -156,17 +167,20 @@ class AssignSystem(bpy.types.Operator):
|
||||
return IfcStore.execute_ifc_operator(self, context)
|
||||
|
||||
def _execute(self, context):
|
||||
product = bpy.data.objects.get(self.product) if self.product else context.active_object
|
||||
self.file = IfcStore.get_file()
|
||||
ifcopenshell.api.run(
|
||||
"system.assign_system",
|
||||
self.file,
|
||||
**{
|
||||
"product": self.file.by_id(product.BIMObjectProperties.ifc_definition_id),
|
||||
"system": self.file.by_id(self.system),
|
||||
}
|
||||
)
|
||||
Data.load(IfcStore.get_file())
|
||||
products = [bpy.data.objects.get(self.product)] if self.product else context.selected_objects
|
||||
for product in products:
|
||||
if not product.BIMObjectProperties.ifc_definition_id:
|
||||
continue
|
||||
ifcopenshell.api.run(
|
||||
"system.assign_system",
|
||||
self.file,
|
||||
**{
|
||||
"product": self.file.by_id(product.BIMObjectProperties.ifc_definition_id),
|
||||
"system": self.file.by_id(self.system),
|
||||
}
|
||||
)
|
||||
Data.load(self.file)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -181,17 +195,23 @@ class UnassignSystem(bpy.types.Operator):
|
||||
return IfcStore.execute_ifc_operator(self, context)
|
||||
|
||||
def _execute(self, context):
|
||||
product = bpy.data.objects.get(self.product) if self.product else context.active_object
|
||||
self.file = IfcStore.get_file()
|
||||
ifcopenshell.api.run(
|
||||
"system.unassign_system",
|
||||
self.file,
|
||||
**{
|
||||
"product": self.file.by_id(product.BIMObjectProperties.ifc_definition_id),
|
||||
"system": self.file.by_id(self.system),
|
||||
}
|
||||
)
|
||||
Data.load(IfcStore.get_file())
|
||||
products = [bpy.data.objects.get(self.product)] if self.product else context.selected_objects
|
||||
for product in products:
|
||||
props = product.BIMObjectProperties
|
||||
if not props.ifc_definition_id:
|
||||
continue
|
||||
if not (props.ifc_definition_id in Data.products and self.system in Data.products[props.ifc_definition_id]):
|
||||
continue
|
||||
ifcopenshell.api.run(
|
||||
"system.unassign_system",
|
||||
self.file,
|
||||
**{
|
||||
"product": self.file.by_id(product.BIMObjectProperties.ifc_definition_id),
|
||||
"system": self.file.by_id(self.system),
|
||||
}
|
||||
)
|
||||
Data.load(self.file)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -202,7 +222,6 @@ class SelectSystemProducts(bpy.types.Operator):
|
||||
system: bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
self.file = IfcStore.get_file()
|
||||
for obj in context.visible_objects:
|
||||
obj.select_set(False)
|
||||
if not obj.BIMObjectProperties.ifc_definition_id:
|
||||
|
||||
@@ -40,6 +40,7 @@ class System(PropertyGroup):
|
||||
class BIMSystemProperties(PropertyGroup):
|
||||
system_attributes: CollectionProperty(name="System Attributes", type=Attribute)
|
||||
is_editing: BoolProperty(name="Is Editing", default=False)
|
||||
is_adding: BoolProperty(name="Is Adding", default=False)
|
||||
systems: CollectionProperty(name="Systems", type=System)
|
||||
active_system_index: IntProperty(name="Active System Index")
|
||||
active_system_id: IntProperty(name="Active System Id")
|
||||
|
||||
@@ -68,37 +68,78 @@ class BIM_PT_systems(Panel):
|
||||
row.prop(attribute, "is_null", icon="RADIOBUT_OFF" if attribute.is_null else "RADIOBUT_ON", text="")
|
||||
|
||||
|
||||
class BIM_PT_object_systems(Panel):
|
||||
bl_label = "IFC Systems"
|
||||
bl_idname = "BIM_PT_object_systems"
|
||||
bl_options = {"DEFAULT_CLOSED"}
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "object"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return IfcStore.get_file() and context.active_object.BIMObjectProperties.ifc_definition_id
|
||||
|
||||
def draw(self, context):
|
||||
if not Data.is_loaded:
|
||||
Data.load(IfcStore.get_file())
|
||||
self.props = context.scene.BIMSystemProperties
|
||||
row = self.layout.row(align=True)
|
||||
if self.props.is_adding:
|
||||
row.label(text="Adding Systems", icon="OUTLINER")
|
||||
row.operator("bim.toggle_assigning_system", text="", icon="CANCEL")
|
||||
self.layout.template_list(
|
||||
"BIM_UL_object_systems",
|
||||
"",
|
||||
self.props,
|
||||
"systems",
|
||||
self.props,
|
||||
"active_system_index",
|
||||
)
|
||||
else:
|
||||
row.label(text=f"{len(Data.systems)} Systems in IFC Project", icon="OUTLINER")
|
||||
row.operator("bim.toggle_assigning_system", text="", icon="ADD")
|
||||
|
||||
systems_object = Data.products.get(context.active_object.BIMObjectProperties.ifc_definition_id, [])
|
||||
for system_id in systems_object:
|
||||
row = self.layout.row(align=True)
|
||||
row.label(text=Data.systems[system_id].get("Name", "Unnamed"))
|
||||
op = row.operator("bim.unassign_system", text="", icon="X")
|
||||
op.system = system_id
|
||||
|
||||
if not systems_object:
|
||||
self.layout.label(text="No System associated with Active Object")
|
||||
|
||||
|
||||
class BIM_UL_systems(UIList):
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
||||
if item:
|
||||
row = layout.row(align=True)
|
||||
row.label(text=item.name)
|
||||
|
||||
if context.active_object:
|
||||
oprops = context.active_object.BIMObjectProperties
|
||||
if (
|
||||
oprops.ifc_definition_id in Data.products
|
||||
and item.ifc_definition_id in Data.products[oprops.ifc_definition_id]
|
||||
):
|
||||
op = row.operator("bim.unassign_system", text="", icon="KEYFRAME_HLT", emboss=False)
|
||||
op.system = item.ifc_definition_id
|
||||
else:
|
||||
op = row.operator("bim.assign_system", text="", icon="KEYFRAME", emboss=False)
|
||||
op.system = item.ifc_definition_id
|
||||
|
||||
if context.scene.BIMSystemProperties.active_system_id == item.ifc_definition_id:
|
||||
system_id = item.ifc_definition_id
|
||||
if context.scene.BIMSystemProperties.active_system_id == system_id:
|
||||
op = row.operator("bim.select_system_products", text="", icon="RESTRICT_SELECT_OFF")
|
||||
op.system = item.ifc_definition_id
|
||||
op.system = system_id
|
||||
row.operator("bim.edit_system", text="", icon="CHECKMARK")
|
||||
row.operator("bim.disable_editing_system", text="", icon="CANCEL")
|
||||
elif context.scene.BIMSystemProperties.active_system_id:
|
||||
op = row.operator("bim.select_system_products", text="", icon="RESTRICT_SELECT_OFF")
|
||||
op.system = item.ifc_definition_id
|
||||
row.operator("bim.remove_system", text="", icon="X").system = item.ifc_definition_id
|
||||
op.system = system_id
|
||||
op = row.operator("bim.remove_system", text="", icon="X")
|
||||
op.system = system_id
|
||||
else:
|
||||
op = row.operator("bim.select_system_products", text="", icon="RESTRICT_SELECT_OFF")
|
||||
op.system = item.ifc_definition_id
|
||||
op.system = system_id
|
||||
op = row.operator("bim.enable_editing_system", text="", icon="GREASEPENCIL")
|
||||
op.system = item.ifc_definition_id
|
||||
row.operator("bim.remove_system", text="", icon="X").system = item.ifc_definition_id
|
||||
op.system = system_id
|
||||
op = row.operator("bim.remove_system", text="", icon="X")
|
||||
op.system = system_id
|
||||
|
||||
|
||||
class BIM_UL_object_systems(UIList):
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
||||
if item:
|
||||
row = layout.row(align=True)
|
||||
row.label(text=item.name)
|
||||
op = row.operator("bim.assign_system", text="", icon="ADD")
|
||||
op.system = item.ifc_definition_id
|
||||
|
||||
Reference in New Issue
Block a user