mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-13 10:57:49 +00:00
You can now mass enable edition, disable edition and validate edition of Ifc Entity Attributes.
This highlights a potential bug that already existed due to the way the attribute system is designed. Where the user mass-edits attributes from different IFC types, resulting in discrepancies due to the same attributes having a different index. eg IfcWindow has the Tag attribute at index 3, IfcDoor at index 4. So using the ALT modifier feature from vanilla Blender to mass-modify similarly named attributes on the Tag attribute of the IfcWindow will modify the PredefinedType attribute on the IfcDoor (index 3). For this reason I added the ALT modifier to the buttons so mass-operations are a conscious effort for more knowledgeable users. Might reconsider if problems arise but this is IMO a good QOL feature. Also fix floating point precision errors on Pset float values stored as strings (re last commit)
This commit is contained in:
@@ -28,20 +28,33 @@ import bonsai.core.attribute as core
|
||||
from bonsai.bim.ifc import IfcStore
|
||||
|
||||
|
||||
def get_objs_for_operation(operator_properties, context):
|
||||
if operator_properties.obj:
|
||||
return [bpy.data.objects[operator_properties.obj]]
|
||||
if operator_properties.mass_operation:
|
||||
return context.selected_objects[:]
|
||||
return [context.active_object]
|
||||
|
||||
|
||||
class EnableEditingAttributes(bpy.types.Operator):
|
||||
bl_idname = "bim.enable_editing_attributes"
|
||||
bl_label = "Enable Editing Attributes"
|
||||
bl_description = "ALT + Left Click to enable editing attributes on all selected objects"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
obj: bpy.props.StringProperty()
|
||||
obj: bpy.props.StringProperty(options={"SKIP_SAVE"})
|
||||
mass_operation: bpy.props.BoolProperty(default=False, options={"SKIP_SAVE"})
|
||||
|
||||
def execute(self, context):
|
||||
self.file = IfcStore.get_file()
|
||||
obj = bpy.data.objects[self.obj]
|
||||
def invoke(self, context, event):
|
||||
self.mass_operation = event.alt
|
||||
return self.execute(context)
|
||||
|
||||
def enable_editing_attribute_on_obj(self, obj):
|
||||
props = obj.BIMAttributeProperties
|
||||
props.attributes.clear()
|
||||
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
assert element
|
||||
if not element:
|
||||
return
|
||||
has_inherited_predefined_type = False
|
||||
if not element.is_a("IfcTypeObject") and (element_type := ifcopenshell.util.element.get_type(element)):
|
||||
# Allow for None due to https://github.com/buildingSMART/IFC4.3.x-development/issues/818
|
||||
@@ -67,31 +80,48 @@ class EnableEditingAttributes(bpy.types.Operator):
|
||||
|
||||
bonsai.bim.helper.import_attributes2(element, props.attributes, callback=callback)
|
||||
props.is_editing_attributes = True
|
||||
|
||||
def execute(self, context):
|
||||
for obj in get_objs_for_operation(self, context):
|
||||
self.enable_editing_attribute_on_obj(obj)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class DisableEditingAttributes(bpy.types.Operator):
|
||||
bl_idname = "bim.disable_editing_attributes"
|
||||
bl_label = "Disable Editing Attributes"
|
||||
bl_description = "ALT + Left Click to disable editing attributes on all selected objects"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
obj: bpy.props.StringProperty()
|
||||
obj: bpy.props.StringProperty(options={"SKIP_SAVE"})
|
||||
mass_operation: bpy.props.BoolProperty(default=False, options={"SKIP_SAVE"})
|
||||
|
||||
def execute(self, context):
|
||||
obj = bpy.data.objects.get(self.obj)
|
||||
def invoke(self, context, event):
|
||||
self.mass_operation = event.alt
|
||||
return self.execute(context)
|
||||
|
||||
def disable_editing_attributes_on_obj(self, obj):
|
||||
props = obj.BIMAttributeProperties
|
||||
props.is_editing_attributes = False
|
||||
|
||||
def execute(self, context):
|
||||
for obj in get_objs_for_operation(self, context):
|
||||
self.disable_editing_attributes_on_obj(obj)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class EditAttributes(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.edit_attributes"
|
||||
bl_label = "Edit Attributes"
|
||||
bl_description = "ALT + Left Click to edit attributes on all selected objects"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
obj: bpy.props.StringProperty()
|
||||
obj: bpy.props.StringProperty(options={"SKIP_SAVE"})
|
||||
mass_operation: bpy.props.BoolProperty(default=False, options={"SKIP_SAVE"})
|
||||
|
||||
def _execute(self, context):
|
||||
self.file = IfcStore.get_file()
|
||||
obj = bpy.data.objects.get(self.obj)
|
||||
def invoke(self, context, event):
|
||||
self.mass_operation = event.alt
|
||||
return self.execute(context)
|
||||
|
||||
def edit_attributes_on_obj(self, obj):
|
||||
props = obj.BIMAttributeProperties
|
||||
product = tool.Ifc.get_entity(obj)
|
||||
|
||||
@@ -112,6 +142,11 @@ class EditAttributes(bpy.types.Operator, tool.Ifc.Operator):
|
||||
if (name := tool.Loader.get_name(product)) and obj.name != name:
|
||||
obj.name = name
|
||||
bpy.ops.bim.disable_editing_attributes(obj=obj.name)
|
||||
|
||||
def _execute(self, context):
|
||||
self.file = IfcStore.get_file()
|
||||
for obj in get_objs_for_operation(self, context):
|
||||
self.edit_attributes_on_obj(obj)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
|
||||
@@ -31,15 +31,12 @@ def draw_ui(context, layout, attributes):
|
||||
if props.is_editing_attributes:
|
||||
row = layout.row(align=True)
|
||||
op = row.operator("bim.edit_attributes", icon="CHECKMARK", text="Save Attributes")
|
||||
op.obj = obj.name
|
||||
op = row.operator("bim.disable_editing_attributes", icon="CANCEL", text="")
|
||||
op.obj = obj.name
|
||||
|
||||
bonsai.bim.helper.draw_attributes(props.attributes, layout, copy_operator="bim.copy_attribute_to_selection")
|
||||
else:
|
||||
row = layout.row()
|
||||
op = row.operator("bim.enable_editing_attributes", icon="GREASEPENCIL", text="Edit")
|
||||
op.obj = obj.name
|
||||
|
||||
for attribute in attributes:
|
||||
row = layout.row(align=True)
|
||||
|
||||
@@ -20,7 +20,7 @@ import bpy
|
||||
import bonsai.tool as tool
|
||||
from bpy.types import Panel
|
||||
from bonsai.bim.ifc import IfcStore
|
||||
from bonsai.bim.helper import prop_with_search
|
||||
from bonsai.bim.helper import prop_with_search, get_display_value
|
||||
from bonsai.bim.module.pset.data import (
|
||||
ObjectPsetsData,
|
||||
ObjectQtosData,
|
||||
@@ -197,7 +197,7 @@ def draw_psetqto_ui(
|
||||
row = box.row(align=True)
|
||||
row.scale_y = 0.8
|
||||
row.label(text=prop["Name"])
|
||||
op = row.operator("bim.select_similar", text=nominal_value, icon="NONE", emboss=False)
|
||||
op = row.operator("bim.select_similar", text=get_display_value(nominal_value), icon="NONE", emboss=False)
|
||||
op.key = '"' + pset["Name"].replace('"', '\\"') + '"."' + prop["Name"].replace('"', '\\"') + '"'
|
||||
# calculate sum of all selected objects
|
||||
if active_operator:
|
||||
|
||||
Reference in New Issue
Block a user