Rebuild pset template UI to be less confusing and match the UX paradigm of other modules

This commit is contained in:
Dion Moult
2021-02-24 21:07:27 +11:00
parent 28c2d7248e
commit e1b90ed3b2
13 changed files with 380 additions and 145 deletions
@@ -14,7 +14,7 @@ from bpy.props import (
class BIMGeometryProperties(PropertyGroup):
should_auto_update_mesh_representations: BoolProperty(name="Should Auto Update Representations", default=True)
should_auto_update_mesh_representations: BoolProperty(name="Should Auto Update Representations", default=False)
# Revit workaround
should_use_presentation_style_assignment: BoolProperty(name="Force Presentation Style Assignment", default=False)
# RIB iTwo, DESITE BIM workaround
@@ -2,14 +2,19 @@ import bpy
from . import ui, prop, operator
classes = (
operator.AddPropertySetTemplate,
operator.RemovePropertySetTemplate,
operator.EditPropertySetTemplate,
operator.SavePropertySetTemplate,
operator.AddPropertyTemplate,
operator.RemovePropertyTemplate,
prop.PropertySetTemplate,
prop.PropertyTemplate,
operator.SavePsetTemplateFile,
operator.AddPsetTemplate,
operator.EditPsetTemplate,
operator.RemovePsetTemplate,
operator.AddPropTemplate,
operator.EditPropTemplate,
operator.RemovePropTemplate,
operator.EnableEditingPsetTemplate,
operator.DisableEditingPsetTemplate,
operator.EnableEditingPropTemplate,
operator.DisableEditingPropTemplate,
prop.PsetTemplate,
prop.PropTemplate,
prop.BIMPsetTemplateProperties,
ui.BIM_PT_pset_template,
)
@@ -0,0 +1,22 @@
import ifcopenshell
class Usecase:
def __init__(self, file, settings={}):
self.file = file
self.settings = {"pset_template": None}
for key, value in settings.items():
self.settings[key] = value
def execute(self):
prop_template = self.file.create_entity("IfcSimplePropertyTemplate", **{
"GlobalId": ifcopenshell.guid.new(),
"Name": "NewProperty",
"PrimaryMeasureType": "IfcLabel",
"TemplateType": "P_SINGLEVALUE",
"AccessState": "READWRITE"
})
has_property_templates = list(self.settings["pset_template"].HasPropertyTemplates) or []
has_property_templates.append(prop_template)
self.settings["pset_template"].HasPropertyTemplates = has_property_templates
return prop_template
@@ -0,0 +1,17 @@
import ifcopenshell
class Usecase:
def __init__(self, file, settings={}):
self.file = file
self.settings = {}
for key, value in settings.items():
self.settings[key] = value
def execute(self):
self.file.create_entity("IfcPropertySetTemplate", **{
"GlobalId": ifcopenshell.guid.new(),
"Name": "New_Pset",
"TemplateType": "PSET_TYPEDRIVENONLY",
"ApplicableEntity": "IfcTypeObject"
})
@@ -0,0 +1,37 @@
from blenderbim.bim.ifc import IfcStore
class Data:
is_loaded = False
pset_templates = {}
prop_templates = {}
@classmethod
def purge(cls):
cls.is_loaded = False
cls.pset_templates = {}
cls.prop_templates = {}
@classmethod
def load(cls):
cls._file = IfcStore.pset_template_file
cls.pset_templates = {}
cls.prop_templates = {}
for pset_template in cls._file.by_type("IfcPropertySetTemplate"):
data = pset_template.get_info()
data["HasPropertyTemplates"] = [e.id() for e in pset_template.HasPropertyTemplates or []]
if "OwnerHistory" in data:
del data["OwnerHistory"]
cls.pset_templates[pset_template.id()] = data
for prop_template in cls._file.by_type("IfcSimplePropertyTemplate"):
data = prop_template.get_info()
cls.prop_templates[prop_template.id()] = {
"GlobalId": data["GlobalId"],
"Name": data["Name"],
"Description": data["Description"],
"PrimaryMeasureType": data["PrimaryMeasureType"]
}
cls.is_loaded = True
@@ -0,0 +1,10 @@
class Usecase:
def __init__(self, file, settings=None):
self.file = file
self.settings = {"prop_template": None, "attributes": {}}
for key, value in settings.items():
self.settings[key] = value
def execute(self):
for name, value in self.settings["attributes"].items():
setattr(self.settings["prop_template"], name, value)
@@ -0,0 +1,10 @@
class Usecase:
def __init__(self, file, settings=None):
self.file = file
self.settings = {"pset_template": None, "attributes": {}}
for key, value in settings.items():
self.settings[key] = value
def execute(self):
for name, value in self.settings["attributes"].items():
setattr(self.settings["pset_template"], name, value)
@@ -1,127 +1,167 @@
import bpy
import ifcopenshell
from blenderbim.bim.module.pset_template.prop import refreshPropertySetTemplates
import blenderbim.bim.module.pset_template.add_pset_template as add_pset_template
import blenderbim.bim.module.pset_template.edit_pset_template as edit_pset_template
import blenderbim.bim.module.pset_template.remove_pset_template as remove_pset_template
import blenderbim.bim.module.pset_template.add_prop_template as add_prop_template
import blenderbim.bim.module.pset_template.edit_prop_template as edit_prop_template
import blenderbim.bim.module.pset_template.remove_prop_template as remove_prop_template
from blenderbim.bim.module.pset_template.prop import updatePsetTemplateFiles, updatePsetTemplates
from blenderbim.bim.module.pset_template.data import Data
from blenderbim.bim.ifc import IfcStore
class AddPropertySetTemplate(bpy.types.Operator):
bl_idname = "bim.add_property_set_template"
bl_label = "Add Property Set Template"
class AddPsetTemplate(bpy.types.Operator):
bl_idname = "bim.add_pset_template"
bl_label = "Add Pset Template"
def execute(self, context):
props = context.scene.BIMPsetTemplateProperties
props.active_property_set_template.global_id = ""
props.active_property_set_template.name = "New_Pset"
props.active_property_set_template.description = ""
props.active_property_set_template.template_type = "PSET_TYPEDRIVENONLY"
props.active_property_set_template.applicable_entity = "IfcTypeObject"
while len(props.property_templates) > 0:
props.property_templates.remove(0)
add_pset_template.Usecase(IfcStore.pset_template_file).execute()
Data.load()
updatePsetTemplates(self, context)
return {"FINISHED"}
class RemovePropertySetTemplate(bpy.types.Operator):
bl_idname = "bim.remove_property_set_template"
bl_label = "Remove Property Set Template"
class RemovePsetTemplate(bpy.types.Operator):
bl_idname = "bim.remove_pset_template"
bl_label = "Remove Pset Template"
def execute(self, context):
props = context.scene.BIMPsetTemplateProperties
template = IfcStore.pset_template_file.by_guid(props.property_set_templates)
IfcStore.pset_template_file.remove(template)
if props.active_pset_template_id == int(props.pset_templates):
bpy.ops.bim.disable_editing_pset_template()
remove_pset_template.Usecase(IfcStore.pset_template_file, {
"pset_template": IfcStore.pset_template_file.by_id(int(props.pset_templates))
}).execute()
Data.load()
updatePsetTemplates(self, context)
return {"FINISHED"}
class EnableEditingPsetTemplate(bpy.types.Operator):
bl_idname = "bim.enable_editing_pset_template"
bl_label = "Enable Editing Pset Template"
def execute(self, context):
props = context.scene.BIMPsetTemplateProperties
props.active_pset_template_id = int(props.pset_templates)
template = Data.pset_templates[props.active_pset_template_id]
props.active_pset_template.global_id = template["GlobalId"]
props.active_pset_template.name = template["Name"] or ""
props.active_pset_template.description = template["Description"] or ""
props.active_pset_template.template_type = template["TemplateType"]
props.active_pset_template.applicable_entity = template["ApplicableEntity"] or ""
return {"FINISHED"}
class DisableEditingPsetTemplate(bpy.types.Operator):
bl_idname = "bim.disable_editing_pset_template"
bl_label = "Disable Editing Pset Template"
def execute(self, context):
props = context.scene.BIMPsetTemplateProperties
props.active_pset_template_id = 0
return {"FINISHED"}
class EnableEditingPropTemplate(bpy.types.Operator):
bl_idname = "bim.enable_editing_prop_template"
bl_label = "Enable Editing Prop Template"
prop_template: bpy.props.IntProperty()
def execute(self, context):
props = context.scene.BIMPsetTemplateProperties
props.active_prop_template_id = self.prop_template
template = Data.prop_templates[props.active_prop_template_id]
props.active_prop_template.name = template["Name"] or ""
props.active_prop_template.description = template["Description"] or ""
props.active_prop_template.primary_measure_type = template["PrimaryMeasureType"]
return {"FINISHED"}
class DisableEditingPropTemplate(bpy.types.Operator):
bl_idname = "bim.disable_editing_prop_template"
bl_label = "Disable Editing Prop Template"
def execute(self, context):
props = context.scene.BIMPsetTemplateProperties
props.active_prop_template_id = 0
return {"FINISHED"}
class EditPsetTemplate(bpy.types.Operator):
bl_idname = "bim.edit_pset_template"
bl_label = "Edit Pset Template"
def execute(self, context):
props = context.scene.BIMPsetTemplateProperties
edit_pset_template.Usecase(IfcStore.pset_template_file, {
"pset_template": IfcStore.pset_template_file.by_id(props.active_pset_template_id),
"attributes": {
"Name": props.active_pset_template.name,
"Description": props.active_pset_template.description,
"TemplateType": props.active_pset_template.template_type,
"ApplicableEntity": props.active_pset_template.applicable_entity,
}
}).execute()
Data.load()
updatePsetTemplates(self, context)
bpy.ops.bim.disable_editing_pset_template()
return {"FINISHED"}
class SavePsetTemplateFile(bpy.types.Operator):
bl_idname = "bim.save_pset_template_file"
bl_label = "Save Pset Template File"
def execute(self, context):
IfcStore.pset_template_file.write(IfcStore.pset_template_path)
refreshPropertySetTemplates(self, context)
return {"FINISHED"}
class EditPropertySetTemplate(bpy.types.Operator):
bl_idname = "bim.edit_property_set_template"
bl_label = "Edit Property Set Template"
class AddPropTemplate(bpy.types.Operator):
bl_idname = "bim.add_prop_template"
bl_label = "Add Prop Template"
def execute(self, context):
props = context.scene.BIMPsetTemplateProperties
template = IfcStore.pset_template_file.by_guid(props.property_set_templates)
props.active_property_set_template.global_id = template.GlobalId
props.active_property_set_template.name = template.Name
props.active_property_set_template.description = template.Description
props.active_property_set_template.template_type = template.TemplateType
props.active_property_set_template.applicable_entity = template.ApplicableEntity
while len(props.property_templates) > 0:
props.property_templates.remove(0)
if template.HasPropertyTemplates:
for property_template in template.HasPropertyTemplates:
if not property_template.is_a("IfcSimplePropertyTemplate"):
continue
new = props.property_templates.add()
new.global_id = property_template.GlobalId
new.name = property_template.Name
new.description = property_template.Description
new.primary_measure_type = property_template.PrimaryMeasureType
pset_template_id = props.active_pset_template_id or int(props.pset_templates)
add_prop_template.Usecase(IfcStore.pset_template_file, {
"pset_template": IfcStore.pset_template_file.by_id(pset_template_id)
}).execute()
Data.load()
return {"FINISHED"}
class SavePropertySetTemplate(bpy.types.Operator):
bl_idname = "bim.save_property_set_template"
bl_label = "Save Property Set Template"
class RemovePropTemplate(bpy.types.Operator):
bl_idname = "bim.remove_prop_template"
bl_label = "Remove Prop Template"
prop_template: bpy.props.IntProperty()
def execute(self, context):
props = context.scene.BIMPsetTemplateProperties
blender_property_set_template = props.active_property_set_template
if blender_property_set_template.global_id:
template = IfcStore.pset_template_file.by_guid(blender_property_set_template.global_id)
else:
template = IfcStore.pset_template_file.createIfcPropertySetTemplate()
template.GlobalId = ifcopenshell.guid.new()
template.Name = blender_property_set_template.name
template.Description = blender_property_set_template.description
template.TemplateType = blender_property_set_template.template_type
template.ApplicableEntity = blender_property_set_template.applicable_entity
saved_global_ids = []
for blender_property_template in props.property_templates:
if blender_property_template.global_id:
property_template = IfcStore.pset_template_file.by_guid(blender_property_template.global_id)
else:
property_template = IfcStore.pset_template_file.createIfcSimplePropertyTemplate()
property_template.GlobalId = ifcopenshell.guid.new()
if template.HasPropertyTemplates:
has_property_templates = list(template.HasPropertyTemplates)
else:
has_property_templates = []
has_property_templates.append(property_template)
template.HasPropertyTemplates = has_property_templates
property_template.Name = blender_property_template.name
property_template.Description = blender_property_template.description
property_template.PrimaryMeasureType = blender_property_template.primary_measure_type
property_template.TemplateType = "P_SINGLEVALUE"
property_template.AccessState = "READWRITE"
saved_global_ids.append(property_template.GlobalId)
for element in template.HasPropertyTemplates:
if element.GlobalId not in saved_global_ids:
IfcStore.pset_template_file.remove(element)
IfcStore.pset_template_file.write(IfcStore.pset_template_path)
refreshPropertySetTemplates(self, context)
remove_prop_template.Usecase(IfcStore.pset_template_file, {
"prop_template": IfcStore.pset_template_file.by_id(self.prop_template)
}).execute()
Data.load()
return {"FINISHED"}
class AddPropertyTemplate(bpy.types.Operator):
bl_idname = "bim.add_property_template"
bl_label = "Add Property Template"
class EditPropTemplate(bpy.types.Operator):
bl_idname = "bim.edit_prop_template"
bl_label = "Edit Prop Template"
def execute(self, context):
context.scene.BIMPsetTemplateProperties.property_templates.add()
return {"FINISHED"}
class RemovePropertyTemplate(bpy.types.Operator):
bl_idname = "bim.remove_property_template"
bl_label = "Remove Property Template"
index: bpy.props.IntProperty()
def execute(self, context):
bpy.context.scene.BIMPsetTemplateProperties.property_templates.remove(self.index)
props = context.scene.BIMPsetTemplateProperties
edit_prop_template.Usecase(IfcStore.pset_template_file, {
"prop_template": IfcStore.pset_template_file.by_id(props.active_prop_template_id),
"attributes": {
"Name": props.active_prop_template.name,
"Description": props.active_prop_template.description,
"PrimaryMeasureType": props.active_prop_template.primary_measure_type,
}
}).execute()
Data.load()
bpy.ops.bim.disable_editing_prop_template()
return {"FINISHED"}
@@ -14,16 +14,22 @@ from bpy.props import (
FloatVectorProperty,
CollectionProperty,
)
from blenderbim.bim.module.pset_template.data import Data
psettemplatefiles_enum = []
propertysettemplates_enum = []
psettemplates_enum = []
def refreshPropertySetTemplates(self, context):
global propertysettemplates_enum
propertysettemplates_enum.clear()
getPropertySetTemplates(self, context)
def updatePsetTemplateFiles(self, context):
global psettemplates_enum
IfcStore.pset_template_path = os.path.join(
context.scene.BIMProperties.data_dir,
"pset",
context.scene.BIMPsetTemplateProperties.pset_template_files + ".ifc",
)
IfcStore.pset_template_file = ifcopenshell.open(IfcStore.pset_template_path)
updatePsetTemplates(self, context)
def getPsetTemplateFiles(self, context):
@@ -34,19 +40,29 @@ def getPsetTemplateFiles(self, context):
return psettemplatefiles_enum
def getPropertySetTemplates(self, context):
global propertysettemplates_enum
if len(propertysettemplates_enum) < 1:
IfcStore.pset_template_path = os.path.join(
context.scene.BIMProperties.data_dir, "pset", context.scene.BIMPsetTemplateProperties.pset_template_files + ".ifc"
)
IfcStore.pset_template_file = ifcopenshell.open(IfcStore.pset_template_path)
def updatePsetTemplates(self, context):
global psettemplates_enum
psettemplates_enum.clear()
getPsetTemplates(self, context)
def getPsetTemplates(self, context):
global psettemplates_enum
if len(psettemplates_enum) < 1:
if not IfcStore.pset_template_file:
IfcStore.pset_template_path = os.path.join(
context.scene.BIMProperties.data_dir,
"pset",
context.scene.BIMPsetTemplateProperties.pset_template_files + ".ifc",
)
IfcStore.pset_template_file = ifcopenshell.open(IfcStore.pset_template_path)
templates = IfcStore.pset_template_file.by_type("IfcPropertySetTemplate")
propertysettemplates_enum.extend([(t.GlobalId, t.Name, "") for t in templates])
return propertysettemplates_enum
psettemplates_enum.extend([(str(t.id()), t.Name, "") for t in templates])
Data.load()
return psettemplates_enum
class PropertySetTemplate(PropertyGroup):
class PsetTemplate(PropertyGroup):
global_id: StringProperty(name="Global ID")
name: StringProperty(name="Name")
description: StringProperty(name="Description")
@@ -98,7 +114,7 @@ class PropertySetTemplate(PropertyGroup):
applicable_entity: StringProperty(name="Applicable Entity")
class PropertyTemplate(PropertyGroup):
class PropTemplate(PropertyGroup):
global_id: StringProperty(name="Global ID")
name: StringProperty(name="Name")
description: StringProperty(name="Description")
@@ -222,8 +238,10 @@ class PropertyTemplate(PropertyGroup):
class BIMPsetTemplateProperties(PropertyGroup):
pset_template_files: EnumProperty(
items=getPsetTemplateFiles, name="Pset Template Files", update=refreshPropertySetTemplates
items=getPsetTemplateFiles, name="Pset Template Files", update=updatePsetTemplateFiles
)
property_set_templates: EnumProperty(items=getPropertySetTemplates, name="Pset Template Files")
active_property_set_template: PointerProperty(type=PropertySetTemplate)
property_templates: CollectionProperty(name="Property Templates", type=PropertyTemplate)
pset_templates: EnumProperty(items=getPsetTemplates, name="Pset Template Files")
active_pset_template_id: IntProperty(name="Active Pset Template Id")
active_prop_template_id: IntProperty(name="Active Prop Template Id")
active_pset_template: PointerProperty(type=PsetTemplate)
active_prop_template: PointerProperty(type=PropTemplate)
@@ -0,0 +1,21 @@
import ifcopenshell.util.element
class Usecase:
def __init__(self, file, settings=None):
self.file = file
self.settings = {
"prop_template": None
}
for key, value in settings.items():
self.settings[key] = value
def execute(self):
for inverse in self.file.get_inverse(self.settings["prop_template"]):
if len(inverse.HasPropertyTemplates) == 1:
inverse.HasPropertyTemplates = []
else:
has_property_templates = list(inverse.HasPropertyTemplates)
has_property_templates.remove(self.settings["prop_template"])
inverse.HasPropertyTemplates = has_property_templates
ifcopenshell.util.element.remove_deep(self.file, self.settings["prop_template"])
@@ -0,0 +1,14 @@
import ifcopenshell.util.element
class Usecase:
def __init__(self, file, settings=None):
self.file = file
self.settings = {
"pset_template": None
}
for key, value in settings.items():
self.settings[key] = value
def execute(self):
ifcopenshell.util.element.remove_deep(self.file, self.settings["pset_template"])
@@ -1,5 +1,6 @@
import bpy
from bpy.types import Panel
from blenderbim.bim.module.pset_template.data import Data
class BIM_PT_pset_template(Panel):
@@ -16,32 +17,72 @@ class BIM_PT_pset_template(Panel):
row = layout.row(align=True)
row.prop(props, "pset_template_files", text="")
row.operator("bim.save_pset_template_file", text="", icon="EXPORT")
row = layout.row(align=True)
row.prop(props, "property_set_templates", text="")
row.operator("bim.add_property_set_template", text="", icon="ADD")
row.operator("bim.remove_property_set_template", text="", icon="PANEL_CLOSE")
row.operator("bim.edit_property_set_template", text="", icon="IMPORT")
row.operator("bim.save_property_set_template", text="", icon="EXPORT")
if props.pset_templates:
row.prop(props, "pset_templates", text="", icon="COPY_ID")
else:
row.label(text="No Pset Templates", icon="COPY_ID")
if props.active_pset_template_id:
row.operator("bim.edit_pset_template", text="", icon="CHECKMARK")
row.operator("bim.disable_editing_pset_template", text="", icon="X")
else:
row.operator("bim.add_pset_template", text="", icon="ADD")
row.operator("bim.enable_editing_pset_template", text="", icon="GREASEPENCIL")
row.operator("bim.remove_pset_template", text="", icon="X")
# row.operator("bim.save_pset_template", text="", icon="EXPORT")
if not Data.is_loaded and props.pset_template_files:
Data.load()
if not Data.pset_templates:
return
if props.active_pset_template_id:
pset_template = Data.pset_templates[int(props.active_pset_template_id)]
row = layout.row()
row.prop(props.active_pset_template, "name")
row = layout.row()
row.prop(props.active_pset_template, "description")
row = layout.row()
row.prop(props.active_pset_template, "template_type")
row = layout.row()
row.prop(props.active_pset_template, "applicable_entity")
else:
pset_template = Data.pset_templates[int(props.pset_templates)]
for name, value in pset_template.items():
if name == "id" or name == "type" or name == "HasPropertyTemplates":
continue
row = layout.row(align=True)
row.label(text=name)
row.label(text=str(value))
row = layout.row(align=True)
row.prop(props.active_property_set_template, "name")
row = layout.row(align=True)
row.prop(props.active_property_set_template, "description")
row = layout.row(align=True)
row.prop(props.active_property_set_template, "template_type")
row = layout.row(align=True)
row.prop(props.active_property_set_template, "applicable_entity")
row.label(text="Property Templates", icon="COPY_ID")
row.operator("bim.add_prop_template", icon="ADD", text="")
layout.label(text="Property Templates:")
row = layout.row(align=True)
row.operator("bim.add_property_template")
for index, template in enumerate(props.property_templates):
for prop_template_id in pset_template["HasPropertyTemplates"]:
prop_template = Data.prop_templates[prop_template_id]
row = layout.row(align=True)
row.prop(template, "name", text="")
row.prop(template, "description", text="")
row.prop(template, "primary_measure_type", text="")
row.operator("bim.remove_property_template", icon="X", text="").index = index
if props.active_prop_template_id and props.active_prop_template_id == prop_template_id:
row.prop(props.active_prop_template, "name", text="")
row.prop(props.active_prop_template, "description", text="")
row.prop(props.active_prop_template, "primary_measure_type", text="")
else:
row.label(text=prop_template["Name"])
row.label(text=prop_template["PrimaryMeasureType"])
if props.active_prop_template_id and props.active_prop_template_id == prop_template_id:
op = row.operator("bim.edit_prop_template", icon="CHECKMARK", text="")
row.operator("bim.disable_editing_prop_template", icon="X", text="")
elif props.active_prop_template_id and props.active_prop_template_id != prop_template_id:
row.operator("bim.remove_prop_template", icon="X", text="").prop_template = prop_template_id
else:
op = row.operator("bim.enable_editing_prop_template", icon="GREASEPENCIL", text="")
op.prop_template = prop_template_id
row.operator("bim.remove_prop_template", icon="X", text="").prop_template = prop_template_id