first revision

This commit is contained in:
Vukas Pajic
2021-11-26 13:00:06 +01:00
parent d7b27c0620
commit 17a81bef09
4 changed files with 270 additions and 0 deletions
@@ -29,12 +29,19 @@ classes = (
operator.GuessQuantity,
operator.RemovePset,
operator.TogglePsetExpansion,
operator.AddPropertyToEdit,
operator.RemovePropertyToEdit,
operator.ClearList,
operator.RenameParameters,
operator.AddEditCustomProperty,
prop.PsetProperties,
prop.MaterialPsetProperties,
prop.TaskPsetProperties,
prop.ResourcePsetProperties,
prop.ProfilePsetProperties,
prop.WorkSchedulePsetProperties,
prop.PropertiesToRename,
prop.PropertiesToAddOrEdit,
ui.BIM_PT_object_psets,
ui.BIM_PT_object_qtos,
ui.BIM_PT_material_psets,
@@ -43,6 +50,9 @@ classes = (
ui.BIM_PT_resource_psets,
ui.BIM_PT_profile_psets,
ui.BIM_PT_work_schedule_psets,
ui.BIM_PT_BulkPropertyEditor,
ui.BIM_PT_RenameParameters,
ui.BIM_PT_AddPropertiesOrEditValues
)
@@ -53,6 +63,8 @@ def register():
bpy.types.Scene.ResourcePsetProperties = bpy.props.PointerProperty(type=prop.ResourcePsetProperties)
bpy.types.Scene.ProfilePsetProperties = bpy.props.PointerProperty(type=prop.ProfilePsetProperties)
bpy.types.Scene.WorkSchedulePsetProperties = bpy.props.PointerProperty(type=prop.WorkSchedulePsetProperties)
bpy.types.Scene.PropertiesToRename = bpy.props.CollectionProperty(type=prop.PropertiesToRename)
bpy.types.Scene.PropertiesToAddOrEdit = bpy.props.CollectionProperty(type=prop.PropertiesToAddOrEdit)
def unregister():
@@ -62,3 +74,5 @@ def unregister():
del bpy.types.Scene.ResourcePsetProperties
del bpy.types.Scene.ProfilePsetProperties
del bpy.types.Scene.WorkSchedulePsetProperties
del bpy.types.Scene.PropertiesToRename
del bpy.types.Scene.PropertiesToAddOrEdit
@@ -374,3 +374,147 @@ class CopyPropertyToSelection(bpy.types.Operator, Operator):
prop_name=self.name,
prop_value=prop_value,
)
class AddPropertyToEdit(bpy.types.Operator):
bl_label = "Add new row"
bl_idname = "bim.add_property_to_edit"
bl_options = {"REGISTER", "UNDO"}
type: bpy.props.StringProperty()
def execute(self, context):
if self.type == "PropertiesToRename":
props = context.scene.PropertiesToRename
props.add()
elif self.type == "PropertiesToAddOrEdit":
props = context.scene.PropertiesToAddOrEdit
props.add()
return {"FINISHED"}
class RemovePropertyToEdit(bpy.types.Operator):
bl_label = "Remove property to be renamed"
bl_idname = "bim.remove_property_to_edit"
bl_options = {"REGISTER", "UNDO"}
index: bpy.props.IntProperty()
type: bpy.props.StringProperty()
def execute(self, context):
if self.type == "PropertiesToRename":
props = context.scene.PropertiesToRename
props.remove(self.index)
if self.type == "PropertiesToAddOrEdit":
props = context.scene.PropertiesToAddOrEdit
props.remove(self.index)
return {"FINISHED"}
class ClearList(bpy.types.Operator):
bl_label = "Clear list of properties"
bl_idname = "bim.clear_list"
bl_options = {"REGISTER", "UNDO"}
type: bpy.props.StringProperty()
def execute(self, context):
if self.type == "PropertiesToRename":
props = context.scene.PropertiesToRename
props.clear()
if self.type == "PropertiesToAddOrEdit":
props = context.scene.PropertiesToAddOrEdit
props.clear()
return {"FINISHED"}
class RenameParameters(bpy.types.Operator):
bl_label = "Rename Parameters"
bl_idname = "bim.rename_parameters"
bl_options = {"REGISTER", "UNDO"}
bl_description = "Rename parameters that are subclasses of IfcElement"
def execute(self, context):
return IfcStore.execute_ifc_operator(self, context)
def _execute(self, context):
props_to_map = context.scene.PropertiesToRename
ifc_file = IfcStore.get_file()
all_ifc_elements = ifc_file.by_type("IfcElement")
for ifc_element in all_ifc_elements:
for definition in ifc_element.IsDefinedBy:
if definition.is_a('IfcRelDefinesByProperties'):
prop_set = definition.RelatingPropertyDefinition
self.rename_property(prop_set, props_to_map, ifc_element)
self.report({'INFO'}, 'Finished applying changes')
return {"FINISHED"}
def rename_property(self, property_set, properties_to_map, ifc_element):
if property_set.is_a() == "IfcPropertySet":
property_container = property_set.HasProperties
elif property_set.is_a() == "IfcElementQuantity":
property_container = property_set.Quantities
for obj_prop in property_container:
for prop2map in properties_to_map:
if prop2map.pset_name != property_set.Name:
continue
if prop2map.existing_property_name == obj_prop.Name:
obj_prop.Name = prop2map.new_property_name
Data.load(IfcStore.get_file(), ifc_element.id())
class AddEditCustomProperty(bpy.types.Operator):
bl_label = "Add or edit a custom property"
bl_idname = "bim.add_edit_custom_property"
bl_options = {"REGISTER", "UNDO"}
index: bpy.props.IntProperty()
def execute(self, context):
return IfcStore.execute_ifc_operator(self, context)
def _execute(self, context):
self.file = IfcStore.get_file()
selected_objects = context.selected_objects
props = context.scene.PropertiesToAddOrEdit
for object in selected_objects:
ifc_definition_id = object.BIMObjectProperties.ifc_definition_id
if not ifc_definition_id:
continue
ifc_element = tool.Ifc.get().by_id(ifc_definition_id)
psets = ifcopenshell.util.element.get_psets(ifc_element)
for prop in props:
if prop.value_type == "String":
value = prop.string_value
elif prop.value_type == "Boolean":
value = prop.bool_value
elif prop.value_type == "Integer":
value = prop.int_value
elif prop.value_type == "Number":
value = prop.float_value
if prop.pset_name not in psets:
new_pset = ifcopenshell.api.run("pset.add_pset", self.file, product=ifc_element, name=prop.pset_name)
ifcopenshell.api.run("pset.edit_pset", self.file, pset=new_pset, properties={prop.property_name:value})
else:#1) delete the existing property first, in case the value type has also been changed, and then
#2) re-add the property
#TODOUpdate this code to incorporate the dion's latest commit
self.delete_ifc_property(ifc_element, prop)
ifcopenshell.api.run("pset.edit_pset", self.file, pset=self.file.by_id(psets[prop.pset_name]["id"]), properties={prop.property_name:value})
self.report({'INFO'}, 'Finished applying changes')
return {"FINISHED"}
def delete_ifc_property(self, element, property):
for definition in element.IsDefinedBy:
if definition.is_a('IfcRelDefinesByProperties'):
prop_set = definition.RelatingPropertyDefinition
if prop_set.Name != property.pset_name:
continue
for hasprop in prop_set.HasProperties:
if hasprop.Name != property.property_name:
continue
self.file.remove(hasprop)
Data.load(IfcStore.get_file(), element.id())
return
@@ -173,3 +173,26 @@ class WorkSchedulePsetProperties(PropertyGroup):
active_pset_name: StringProperty(name="Pset Name")
properties: CollectionProperty(name="Properties", type=Attribute)
pset_name: EnumProperty(items=getWorkSchedulePsetNames, name="Pset Name")
class PropertiesToRename(PropertyGroup):
pset_name: StringProperty(name="Pset")
existing_property_name: StringProperty(name="Existing Property Name")
new_property_name: StringProperty(name="New Property Name")
class PropertiesToAddOrEdit(PropertyGroup):
pset_name: StringProperty(name="Pset")
property_name: StringProperty(name="Property")
string_value: StringProperty(name="Value")
bool_value: BoolProperty(name="Property Value")
int_value: IntProperty(name="Property Value")
float_value: FloatProperty(name="Property Value")
value_type: EnumProperty(
items=[
("String", "String", "" ),
("Boolean", "True/False", "" ),
("Integer", "Integer", "" ),
("Number", "Number", "" )],
default="String"
)
@@ -375,3 +375,92 @@ class BIM_PT_work_schedule_psets(Panel):
for pset in WorkSchedulePsetsData.data["psets"]:
draw_psetqto_ui(context, pset["id"], pset, props, self.layout, "WorkSchedule")
class BIM_PT_BulkPropertyEditor(Panel):
bl_label = "IFC Bulk Property Editor"
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "object"
def draw(self, context):
pass
class BIM_PT_RenameParameters(Panel):
bl_label = "Rename all building elements"
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "object"
bl_parent_id = "BIM_PT_BulkPropertyEditor"
bl_options = {"DEFAULT_CLOSED"}
bl_order = 0
def draw(self, context):
layout = self.layout
props = context.scene.PropertiesToRename
if props:
for index, property in enumerate(props):
row = layout.row()
row.prop(property, "pset_name", text="")
row.prop(property, "existing_property_name", text="")
row.prop(property, "new_property_name", text="")
op = row.operator("bim.remove_property_to_edit",icon="PANEL_CLOSE", text="")
op.index = index
op.type = "properties_to_map"
row = layout.row()
row.label()
op = row.operator("bim.add_property_to_edit", icon="ADD",text="")
op.type = "PropertiesToRename"
if props:
row = layout.row()
clear = row.operator("bim.clear_list")
clear.type = "PropertiesToRename"
row.operator("bim.rename_parameters")
class BIM_PT_AddPropertiesOrEditValues(Panel):
"""Creates a Panel in the Object properties window"""
bl_label = "Add/Edit Custom Properties and Values (to selected objects)"
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "object"
bl_parent_id = "BIM_PT_BulkPropertyEditor"
bl_options = {"DEFAULT_CLOSED"}
bl_order = 1
def draw(self, context):
layout = self.layout
props = context.scene.PropertiesToAddOrEdit
if props:
for index, property in enumerate(props):
row = layout.row()
row.prop(property, "pset_name", text="")
row.prop(property, "property_name", text="")
if property.value_type == "String":
row.prop(property, "string_value", text="")
elif property.value_type == "Boolean":
row.prop(property, "bool_value", text="")
elif property.value_type == "Integer":
row.prop(property, "int_value", text="")
elif property.value_type == "Number":
row.prop(property, "float_value", text="")
row.prop(property, "value_type", text="")
op = row.operator("bim.remove_property_to_edit",icon="PANEL_CLOSE", text="")
op.index = index
op.type = "PropertiesToAddOrEdit"
row = layout.row()
row.label()
op = row.operator("bim.add_property_to_edit", icon="ADD",text="")
op.type = "PropertiesToAddOrEdit"
if props:
row = layout.row()
clear = row.operator("bim.clear_list")
clear.type = "PropertiesToAddOrEdit"
op = row.operator("bim.add_edit_custom_property",icon="ADD", text="Apply Changes")