Files
IfcOpenShell/src/blenderbim/blenderbim/bim/module/group/operator.py
T
Andrej730 ebfc8ef619 remove BIMGroupProperties.is_adding attribute to avoid confusion
The problem with that attribute was that object's and project's group ui section were both using groups loaded to BIMGroupProperties.groups.

So you could run into situation when you try to load object's groups ui and it would show empty list because user never loaded the groups from the project's ui...

So it was either caching groups twice or just using same `is_editing` flag to check whether groups were previously loaded and I went with the single flag.
2023-11-08 15:13:49 +05:00

284 lines
9.8 KiB
Python

# BlenderBIM Add-on - OpenBIM Blender Add-on
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com>
#
# This file is part of BlenderBIM Add-on.
#
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# BlenderBIM Add-on is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
import bpy
import ifcopenshell.util.attribute
import ifcopenshell.api
import blenderbim.bim.helper
import blenderbim.tool as tool
from blenderbim.bim.ifc import IfcStore
from ifcopenshell.util.selector import Selector
import json
class LoadGroups(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.load_groups"
bl_label = "Load Groups"
bl_options = {"REGISTER", "UNDO"}
def _execute(self, context):
self.props = context.scene.BIMGroupProperties
self.expanded_groups = json.loads(context.scene.ExpandedGroups.json_string)
self.props.groups.clear()
for group in tool.Ifc.get().by_type("IfcGroup", include_subtypes=False):
if not group.HasAssignments:
self.load_group(group)
self.props.is_editing = True
bpy.ops.bim.disable_editing_group()
return {"FINISHED"}
def load_group(self, group, tree_depth=0):
new = self.props.groups.add()
new.ifc_definition_id = group.id()
new.name = group.Name or "Unnamed"
new.selection_query = ""
new.tree_depth = tree_depth
new.has_children = False
new.is_expanded = group.id() in self.expanded_groups
for rel in group.IsGroupedBy or []:
for related_object in rel.RelatedObjects:
if not related_object.is_a("IfcGroup"):
continue
new.has_children = True
if not new.is_expanded:
return
self.load_group(related_object, tree_depth=tree_depth + 1)
class ToggleGroup(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.toggle_group"
bl_label = "Toggle Group"
bl_options = {"REGISTER", "UNDO"}
ifc_definition_id: bpy.props.IntProperty()
index: bpy.props.IntProperty()
option: bpy.props.StringProperty(name="Expand or Collapse")
def _execute(self, context):
expanded_groups = set(json.loads(context.scene.ExpandedGroups.json_string))
if self.option == "Expand":
expanded_groups.add(self.ifc_definition_id)
elif self.ifc_definition_id in expanded_groups:
expanded_groups.remove(self.ifc_definition_id)
context.scene.ExpandedGroups.json_string = json.dumps(list(expanded_groups))
bpy.ops.bim.load_groups()
return {"FINISHED"}
class DisableGroupEditingUI(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.disable_group_editing_ui"
bl_label = "Disable Group Editing UI"
bl_options = {"REGISTER", "UNDO"}
def _execute(self, context):
context.scene.BIMGroupProperties.is_editing = False
context.scene.BIMGroupProperties.active_group_id = 0
return {"FINISHED"}
class AddGroup(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.add_group"
bl_label = "Add New Group"
bl_options = {"REGISTER", "UNDO"}
group: bpy.props.IntProperty()
def _execute(self, context):
result = ifcopenshell.api.run("group.add_group", tool.Ifc.get())
if self.group:
ifcopenshell.api.run(
"group.assign_group", tool.Ifc.get(), products=[result], group=tool.Ifc.get().by_id(self.group)
)
bpy.ops.bim.load_groups()
return {"FINISHED"}
class EditGroup(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.edit_group"
bl_label = "Edit Group"
bl_options = {"REGISTER", "UNDO"}
copy_from_selector: bpy.props.BoolProperty(name="Copy from Selector", default=False)
def _execute(self, context):
props = context.scene.BIMGroupProperties
attributes = {}
for attribute in props.group_attributes:
if attribute.is_null:
attributes[attribute.name] = None
else:
attributes[attribute.name] = attribute.string_value
if self.copy_from_selector:
attributes["Description"] = context.scene.IFCSelector.selection_query
self.file = IfcStore.get_file()
ifcopenshell.api.run(
"group.edit_group", self.file, **{"group": self.file.by_id(props.active_group_id), "attributes": attributes}
)
bpy.ops.bim.load_groups()
return {"FINISHED"}
class RemoveGroup(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.remove_group"
bl_label = "Remove Group"
bl_options = {"REGISTER", "UNDO"}
group: bpy.props.IntProperty()
def _execute(self, context):
props = context.scene.BIMGroupProperties
self.file = IfcStore.get_file()
ifcopenshell.api.run("group.remove_group", self.file, **{"group": self.file.by_id(self.group)})
bpy.ops.bim.load_groups()
return {"FINISHED"}
class EnableEditingGroup(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.enable_editing_group"
bl_label = "Enable Editing Group"
bl_options = {"REGISTER", "UNDO"}
group: bpy.props.IntProperty()
def _execute(self, context):
props = context.scene.BIMGroupProperties
props.group_attributes.clear()
blenderbim.bim.helper.import_attributes2(tool.Ifc.get().by_id(self.group), props.group_attributes)
props.active_group_id = self.group
return {"FINISHED"}
class DisableEditingGroup(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.disable_editing_group"
bl_label = "Disable Editing Group"
bl_options = {"REGISTER", "UNDO"}
def _execute(self, context):
context.scene.BIMGroupProperties.active_group_id = 0
return {"FINISHED"}
class AssignGroup(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.assign_group"
bl_label = "Assign Group"
bl_options = {"REGISTER", "UNDO"}
product: bpy.props.StringProperty()
group: bpy.props.IntProperty()
def _execute(self, context):
self.file = 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,
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):
bl_idname = "bim.unassign_group"
bl_label = "Unassign Group"
bl_options = {"REGISTER", "UNDO"}
product: bpy.props.StringProperty()
group: bpy.props.IntProperty()
def _execute(self, context):
self.file = 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.unassign_group",
self.file,
**{
"product": 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):
bl_idname = "bim.select_group_products"
bl_label = "Select Group Products"
bl_options = {"REGISTER", "UNDO"}
group: bpy.props.IntProperty()
def _execute(self, context):
self.file = IfcStore.get_file()
for obj in context.visible_objects:
obj.select_set(False)
element = tool.Ifc.get_entity(obj)
if not element:
continue
product_groups = [
r.RelatingGroup.id()
for r in getattr(element, "HasAssignments", []) or []
if r.is_a("IfcRelAssignsToGroup")
]
if self.group in product_groups:
obj.select_set(True)
return {"FINISHED"}
class UpdateGroup(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.update_group"
bl_label = "Update Group"
bl_options = {"REGISTER", "UNDO"}
query: bpy.props.StringProperty()
group_id: bpy.props.IntProperty()
def _execute(self, context):
self.file = IfcStore.get_file()
group = self.file.by_id(self.group_id)
query = self.query
new_products = Selector.parse(self.file, query)
ifcopenshell.api.run(
"group.update_group_products",
self.file,
**{
"group": group,
"products": new_products,
}
)
bpy.ops.bim.load_groups()
return {"FINISHED"}
class SelectGroupElements(bpy.types.Operator):
bl_idname = "bim.select_group_elements"
bl_label = "Select Group elements"
bl_options = {"REGISTER", "UNDO"}
group: bpy.props.IntProperty()
@classmethod
def poll(cls, context):
return bool(tool.Ifc.get() and context.active_object)
def execute(self, context):
elements = tool.Drawing.get_group_elements(tool.Ifc.get().by_id(self.group))
tool.Spatial.select_products(elements)
return {"FINISHED"}