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:
Gorgious56
2021-08-24 13:58:52 +02:00
committed by GitHub
parent 486eb4d9a0
commit 112ce48350
8 changed files with 206 additions and 80 deletions
@@ -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