mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-12 02:23:34 +00:00
Fix #6060. Updating long name in spatial manager now also edits attribute for convenience.
Editing attributes now also refreshes the spatial manager (i.e. vice versa), and so does bulk attribute copying.
This commit is contained in:
@@ -19,12 +19,13 @@
|
||||
import bpy
|
||||
import json
|
||||
import ifcopenshell
|
||||
import ifcopenshell.api
|
||||
import ifcopenshell.api.attribute
|
||||
import ifcopenshell.guid
|
||||
import ifcopenshell.util.element
|
||||
import bonsai.bim.helper
|
||||
import bonsai.tool as tool
|
||||
import bonsai.core.attribute as core
|
||||
import bonsai.core.spatial
|
||||
from bonsai.bim.ifc import IfcStore
|
||||
|
||||
|
||||
@@ -112,20 +113,14 @@ class DisableEditingAttributes(bpy.types.Operator):
|
||||
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_description = "Edit the attributes of the active object"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
obj: bpy.props.StringProperty(options={"SKIP_SAVE"})
|
||||
mass_operation: bpy.props.BoolProperty(default=False, options={"SKIP_SAVE"})
|
||||
|
||||
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)
|
||||
assert product
|
||||
object_name = tool.Loader.get_name(product)
|
||||
def _execute(self, context):
|
||||
self.file = IfcStore.get_file()
|
||||
obj = tool.Blender.get_active_object(is_selected=False)
|
||||
if not (element := tool.Ifc.get_entity(obj)):
|
||||
return
|
||||
|
||||
def callback(attributes, prop):
|
||||
if prop.name in ("RefLatitude", "RefLongitude"):
|
||||
@@ -136,17 +131,15 @@ class EditAttributes(bpy.types.Operator, tool.Ifc.Operator):
|
||||
attributes[prop.name] = None
|
||||
return True
|
||||
|
||||
props = obj.BIMAttributeProperties
|
||||
attributes = bonsai.bim.helper.export_attributes(props.attributes, callback=callback)
|
||||
ifcopenshell.api.run("attribute.edit_attributes", self.file, product=product, attributes=attributes)
|
||||
ifcopenshell.api.attribute.edit_attributes(self.file, product=element, attributes=attributes)
|
||||
|
||||
tool.Root.set_object_name(obj, product)
|
||||
tool.Root.set_object_name(obj, element)
|
||||
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"}
|
||||
if tool.Root.is_spatial_element(element):
|
||||
bonsai.core.spatial.import_spatial_decomposition(tool.Spatial)
|
||||
|
||||
|
||||
class GenerateGlobalId(bpy.types.Operator, tool.Ifc.Operator):
|
||||
@@ -195,14 +188,12 @@ class GenerateGlobalId(bpy.types.Operator, tool.Ifc.Operator):
|
||||
class CopyAttributeToSelection(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.copy_attribute_to_selection"
|
||||
bl_label = "Copy Attribute To Selection"
|
||||
name: bpy.props.StringProperty()
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
name: bpy.props.StringProperty()
|
||||
|
||||
def _execute(self, context):
|
||||
value = context.active_object.BIMAttributeProperties.attributes.get(self.name).get_value()
|
||||
i = 0
|
||||
for obj in tool.Blender.get_selected_objects():
|
||||
success = core.copy_attribute_to_selection(tool.Ifc, tool.Root, name=self.name, value=value, obj=obj)
|
||||
if success:
|
||||
i += 1
|
||||
self.report({"INFO"}, f"Attribute was successfully copied to {i} elements.")
|
||||
value = tool.Blender.get_active_object().BIMAttributeProperties.attributes.get(self.name).get_value()
|
||||
total = core.copy_attribute_to_selection(
|
||||
tool.Ifc, tool.Blender, tool.Root, tool.Spatial, name=self.name, value=value
|
||||
)
|
||||
self.report({"INFO"}, f"Attribute was successfully copied to {total} elements.")
|
||||
|
||||
@@ -25,13 +25,12 @@ import bonsai.tool as tool
|
||||
|
||||
def draw_ui(context, layout, attributes):
|
||||
obj = context.active_object
|
||||
oprops = obj.BIMObjectProperties
|
||||
props = obj.BIMAttributeProperties
|
||||
|
||||
if props.is_editing_attributes:
|
||||
row = layout.row(align=True)
|
||||
op = row.operator("bim.edit_attributes", icon="CHECKMARK", text="Save Attributes")
|
||||
op = row.operator("bim.disable_editing_attributes", icon="CANCEL", text="")
|
||||
row.operator("bim.edit_attributes", icon="CHECKMARK", text="Save Attributes")
|
||||
row.operator("bim.disable_editing_attributes", icon="CANCEL", text="")
|
||||
|
||||
bonsai.bim.helper.draw_attributes(props.attributes, layout, copy_operator="bim.copy_attribute_to_selection")
|
||||
else:
|
||||
|
||||
@@ -65,7 +65,14 @@ def update_name(self: "BIMContainer", context: bpy.types.Context) -> None:
|
||||
element = tool.Ifc.get().by_id(ifc_definition_id)
|
||||
tool.Spatial.edit_container_name(element, self.name)
|
||||
if obj := tool.Ifc.get_object(element):
|
||||
obj.name = tool.Loader.get_name(element)
|
||||
tool.Root.set_object_name(obj, element)
|
||||
bonsai.bim.handler.refresh_ui_data()
|
||||
|
||||
|
||||
def update_long_name(self: "BIMContainer", context: bpy.types.Context) -> None:
|
||||
if ifc_definition_id := self.ifc_definition_id:
|
||||
element = tool.Ifc.get().by_id(ifc_definition_id)
|
||||
tool.Ifc.run("attribute.edit_attributes", product=element, attributes={"LongName": self.long_name})
|
||||
bonsai.bim.handler.refresh_ui_data()
|
||||
|
||||
|
||||
@@ -148,7 +155,7 @@ class BIMContainer(PropertyGroup):
|
||||
name: StringProperty(name="Name", update=update_name)
|
||||
ifc_class: StringProperty(name="IFC Class")
|
||||
description: StringProperty(name="Description")
|
||||
long_name: StringProperty(name="Long Name")
|
||||
long_name: StringProperty(name="Long Name", update=update_long_name)
|
||||
elevation: StringProperty(name="Elevation", update=update_elevation)
|
||||
level_index: IntProperty(name="Level Index")
|
||||
has_children: BoolProperty(name="Has Children")
|
||||
|
||||
@@ -26,14 +26,21 @@ if TYPE_CHECKING:
|
||||
|
||||
|
||||
def copy_attribute_to_selection(
|
||||
ifc: tool.Ifc, root: tool.Root, name: str, value: Union[str, None], obj: bpy.types.Object
|
||||
) -> bool:
|
||||
if element := ifc.get_entity(obj):
|
||||
try:
|
||||
ifc.run("attribute.edit_attributes", product=element, attributes={name: value})
|
||||
if name in ("Name", "AxisTag"):
|
||||
root.set_object_name(obj, element)
|
||||
return True
|
||||
except:
|
||||
pass
|
||||
return False
|
||||
ifc: tool.Ifc, blender: tool.Blender, root: tool.Root, spatial: tool.Spatial, name: str, value: Union[str, None]
|
||||
) -> int:
|
||||
total_changed = 0
|
||||
has_edited_spatial_name = False
|
||||
for obj in blender.get_selected_objects(include_active=False):
|
||||
if element := ifc.get_entity(obj):
|
||||
try:
|
||||
ifc.run("attribute.edit_attributes", product=element, attributes={name: value})
|
||||
if name in ("Name", "AxisTag"):
|
||||
root.set_object_name(obj, element)
|
||||
if name in ("Name", "LongName") and root.is_spatial_element(element):
|
||||
has_edited_spatial_name = True
|
||||
total_changed += 1
|
||||
except:
|
||||
pass
|
||||
if has_edited_spatial_name:
|
||||
spatial.import_spatial_decomposition()
|
||||
return total_changed
|
||||
|
||||
Reference in New Issue
Block a user