Merge branch 'IfcOpenShell:v0.7.0' into v0.7.0

This commit is contained in:
Carlos Villagrasa
2022-07-04 18:50:53 +02:00
committed by GitHub
25 changed files with 349 additions and 68 deletions
+1 -1
View File
@@ -40,7 +40,7 @@ def draw_attribute(attribute, layout, copy_operator=None):
return return
if len(attribute.enumerated_values) != 0: if len(attribute.enumerated_values) != 0:
layout.label(text=attribute.name) layout.label(text=attribute.name)
grid = layout.column_flow(columns=4) grid = layout.column_flow(columns=3)
for e in attribute.enumerated_values: for e in attribute.enumerated_values:
grid.prop( grid.prop(
e, e,
@@ -69,3 +69,9 @@ class BIMBrickProperties(PropertyGroup):
libraries: EnumProperty(name="Libraries", items=get_libraries) libraries: EnumProperty(name="Libraries", items=get_libraries)
namespace: EnumProperty(name="Namespace", items=get_namespaces) namespace: EnumProperty(name="Namespace", items=get_namespaces)
brick_equipment_class: EnumProperty(name="Brick Equipment Class", items=get_brick_equipment_classes) brick_equipment_class: EnumProperty(name="Brick Equipment Class", items=get_brick_equipment_classes)
getter_enum = {
"libraries": get_libraries,
"namespace": get_namespaces,
"brick_equipment_class": get_brick_equipment_classes,
}
@@ -18,6 +18,7 @@
import blenderbim.tool as tool import blenderbim.tool as tool
from bpy.types import Panel, UIList from bpy.types import Panel, UIList
from blenderbim.bim.ui import prop_with_search
from blenderbim.bim.module.brick.data import BrickschemaData, BrickschemaReferencesData from blenderbim.bim.module.brick.data import BrickschemaData, BrickschemaReferencesData
@@ -48,7 +49,8 @@ class BIM_PT_brickschema(Panel):
row.operator("bim.close_brick_project", text="", icon="CANCEL") row.operator("bim.close_brick_project", text="", icon="CANCEL")
row = self.layout.row(align=True) row = self.layout.row(align=True)
row.prop(self.props, "namespace", text="") prop_with_search(row, self.props, "namespace", text="")
prop_with_search(row, self.props, "brick_equipment_class", text="")
row.prop(self.props, "brick_equipment_class", text="") row.prop(self.props, "brick_equipment_class", text="")
row.operator("bim.add_brick", text="", icon="ADD") row.operator("bim.add_brick", text="", icon="ADD")
@@ -101,7 +103,7 @@ class BIM_PT_ifc_brickschema_references(Panel):
return return
row = self.layout.row(align=True) row = self.layout.row(align=True)
row.prop(self.props, "libraries") prop_with_search(row, self.props, "libraries")
row.operator("bim.convert_brick_project", text="", icon="ADD") row.operator("bim.convert_brick_project", text="", icon="ADD")
row = self.layout.row(align=True) row = self.layout.row(align=True)
@@ -19,6 +19,7 @@
import bpy import bpy
from bpy.types import Panel from bpy.types import Panel
from blenderbim.bim.ifc import IfcStore from blenderbim.bim.ifc import IfcStore
from blenderbim.bim.ui import prop_with_search
from blenderbim.bim.module.geometry.data import RepresentationsData, DerivedPlacementsData from blenderbim.bim.module.geometry.data import RepresentationsData, DerivedPlacementsData
@@ -50,7 +51,7 @@ class BIM_PT_representations(Panel):
layout.label(text="No representations found") layout.label(text="No representations found")
row = layout.row(align=True) row = layout.row(align=True)
row.prop(context.scene.BIMRootProperties, "contexts", text="") prop_with_search(row, context.scene.BIMRootProperties, "contexts", text="")
row.operator("bim.add_representation", icon="ADD", text="") row.operator("bim.add_representation", icon="ADD", text="")
for representation in RepresentationsData.data["representations"]: for representation in RepresentationsData.data["representations"]:
@@ -66,3 +66,7 @@ class BIMPatchProperties(PropertyGroup):
ifc_patch_output: StringProperty(default="", name="IFC Patch Output IFC") ifc_patch_output: StringProperty(default="", name="IFC Patch Output IFC")
ifc_patch_args: StringProperty(default="", name="Arguments") ifc_patch_args: StringProperty(default="", name="Arguments")
ifc_patch_args_attr: CollectionProperty(type=Attribute, name="Arguments") ifc_patch_args_attr: CollectionProperty(type=Attribute, name="Arguments")
getter_enum = {
"ifc_patch_recipes": get_ifcpatch_recipes,
}
@@ -16,6 +16,7 @@
# You should have received a copy of the GNU General Public License # 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/>. # along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
from blenderbim.bim.ui import prop_with_search
import bpy import bpy
from blenderbim.bim.helper import draw_attributes from blenderbim.bim.helper import draw_attributes
@@ -37,7 +38,7 @@ class BIM_PT_patch(bpy.types.Panel):
scene = context.scene scene = context.scene
props = scene.BIMPatchProperties props = scene.BIMPatchProperties
row = layout.row() row = layout.row()
row.prop(props, "ifc_patch_recipes") prop_with_search(row, props, "ifc_patch_recipes")
row = layout.row(align=True) row = layout.row(align=True)
row.prop(props, "ifc_patch_input") row.prop(props, "ifc_patch_input")
@@ -167,3 +167,28 @@ class BIMProjectProperties(PropertyGroup):
def get_library_element_index(self, lib_element): def get_library_element_index(self, lib_element):
return next((i for i in range(len(self.library_elements)) if self.library_elements[i] == lib_element)) return next((i for i in range(len(self.library_elements)) if self.library_elements[i] == lib_element))
getter_enum = {
"collection_mode": lambda self, context: [
("DECOMPOSITION", "Decomposition", "Collections represent aggregates and spatial containers"),
("SPATIAL_DECOMPOSITION", "Spatial Decomposition", "Collections represent spatial containers"),
("IFC_CLASS", "IFC Class", "Collections represent IFC class"),
("NONE", "None", "No collections are created"),
],
"filter_mode": lambda self, context: [
("NONE", "None", "No filtering is performed"),
("DECOMPOSITION", "Decomposition", "Filter objects by decomposition"),
("IFC_CLASS", "IFC Class", "Filter objects by class"),
("IFC_TYPE", "IFC Type", "Filter objects by type"),
("WHITELIST", "Whitelist", "Filter objects using a custom whitelist query"),
("BLACKLIST", "Blacklist", "Filter objects using a custom blacklist query"),
],
"merge_mode": lambda self, context: [
("NONE", "None", "No objects are merged"),
("IFC_CLASS", "IFC Class", "One object per IFC class"),
("IFC_TYPE", "IFC Type", "One object per IFC construction type"),
("MATERIAL", "Material", "One object per material"),
],
"export_schema": get_export_schema,
"template_file": get_template_file,
}
@@ -17,6 +17,7 @@
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>. # along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
import os import os
from blenderbim.bim.ui import prop_with_search
from bpy.types import Panel, UIList from bpy.types import Panel, UIList
from blenderbim.bim.ifc import IfcStore from blenderbim.bim.ifc import IfcStore
from blenderbim.bim.module.project.data import ProjectData from blenderbim.bim.module.project.data import ProjectData
@@ -48,10 +49,8 @@ class BIM_PT_project(Panel):
def draw_load_ui(self, context): def draw_load_ui(self, context):
pprops = context.scene.BIMProjectProperties pprops = context.scene.BIMProjectProperties
row = self.layout.row() prop_with_search(self.layout, pprops, "collection_mode")
row.prop(pprops, "collection_mode") prop_with_search(self.layout, pprops, "filter_mode")
row = self.layout.row()
row.prop(pprops, "filter_mode")
if pprops.filter_mode in ["DECOMPOSITION", "IFC_CLASS", "IFC_TYPE"]: if pprops.filter_mode in ["DECOMPOSITION", "IFC_CLASS", "IFC_TYPE"]:
row = self.layout.row(align=True) row = self.layout.row(align=True)
row.label(text=f"Total: {pprops.total_elements}") row.label(text=f"Total: {pprops.total_elements}")
@@ -84,8 +83,7 @@ class BIM_PT_project(Panel):
row = self.layout.row() row = self.layout.row()
row.prop(pprops, "is_coordinating") row.prop(pprops, "is_coordinating")
if pprops.is_coordinating: if pprops.is_coordinating:
row = self.layout.row() prop_with_search(self.layout, pprops, "merge_mode")
row.prop(pprops, "merge_mode")
row = self.layout.row() row = self.layout.row()
row.prop(pprops, "deflection_tolerance") row.prop(pprops, "deflection_tolerance")
row = self.layout.row() row = self.layout.row()
@@ -170,8 +168,7 @@ class BIM_PT_project(Panel):
def draw_create_project_ui(self, context): def draw_create_project_ui(self, context):
props = context.scene.BIMProperties props = context.scene.BIMProperties
pprops = context.scene.BIMProjectProperties pprops = context.scene.BIMProjectProperties
row = self.layout.row() prop_with_search(self.layout, pprops, "export_schema")
row.prop(pprops, "export_schema")
row = self.layout.row() row = self.layout.row()
row.prop(context.scene.unit_settings, "system") row.prop(context.scene.unit_settings, "system")
row = self.layout.row() row = self.layout.row()
@@ -180,8 +177,7 @@ class BIM_PT_project(Panel):
row.prop(props, "area_unit", text="Area Unit") row.prop(props, "area_unit", text="Area Unit")
row = self.layout.row() row = self.layout.row()
row.prop(props, "volume_unit", text="Volume Unit") row.prop(props, "volume_unit", text="Volume Unit")
row = self.layout.row() prop_with_search(self.layout, pprops, "template_file", text="Template")
row.prop(pprops, "template_file", text="Template")
row = self.layout.row(align=True) row = self.layout.row(align=True)
row.operator("bim.create_project") row.operator("bim.create_project")
@@ -412,7 +412,7 @@ class BIM_OT_add_property_to_edit(bpy.types.Operator):
bl_idname = "bim.add_property_to_edit" bl_idname = "bim.add_property_to_edit"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
option: bpy.props.StringProperty() option: bpy.props.StringProperty()
index: bpy.props.IntProperty() index: bpy.props.IntProperty(default=-1)
def execute(self, context): def execute(self, context):
if self.index == -1: if self.index == -1:
@@ -18,7 +18,7 @@
import bpy import bpy
import blenderbim.bim.schema import blenderbim.bim.schema
from blenderbim.bim.prop import Attribute from blenderbim.bim.prop import Attribute, StrProperty
import ifcopenshell import ifcopenshell
from ifcopenshell.api.pset.data import Data from ifcopenshell.api.pset.data import Data
from blenderbim.bim.module.pset.data import AddEditCustomPropertiesData from blenderbim.bim.module.pset.data import AddEditCustomPropertiesData
@@ -47,7 +47,7 @@ def purge():
qtonames = {} qtonames = {}
def getPsetNames(self, context): def get_pset_names(self, context):
global psetnames global psetnames
obj = context.active_object obj = context.active_object
if not obj.BIMObjectProperties.ifc_definition_id: if not obj.BIMObjectProperties.ifc_definition_id:
@@ -122,7 +122,7 @@ def getWorkSchedulePsetNames(self, context):
return psetnames[ifc_class] return psetnames[ifc_class]
def getQtoNames(self, context): def get_qto_names(self, context):
global qtonames global qtonames
if "/" in context.active_object.name: if "/" in context.active_object.name:
ifc_class = context.active_object.name.split("/")[0] ifc_class = context.active_object.name.split("/")[0]
@@ -148,19 +148,24 @@ class EnumerationValues(PropertyGroup):
class IfcSimpleProperty(Attribute): class IfcSimpleProperty(Attribute):
#bounded_values: # bounded_values:
enumerated_values: CollectionProperty(type=EnumerationValues) enumerated_values: CollectionProperty(type=EnumerationValues)
#list_values: # list_values:
#reference_values: # reference_values:
#table_values: # table_values:
class PsetProperties(PropertyGroup): class PsetProperties(PropertyGroup):
active_pset_id: IntProperty(name="Active Pset ID") active_pset_id: IntProperty(name="Active Pset ID")
active_pset_name: StringProperty(name="Pset Name") active_pset_name: StringProperty(name="Pset Name")
properties: CollectionProperty(name="Properties", type=IfcSimpleProperty) properties: CollectionProperty(name="Properties", type=IfcSimpleProperty)
pset_name: EnumProperty(items=getPsetNames, name="Pset Name") pset_name: EnumProperty(items=get_pset_names, name="Pset Name")
qto_name: EnumProperty(items=getQtoNames, name="Qto Name") qto_name: EnumProperty(items=get_qto_names, name="Qto Name")
getter_enum = {
"qto_name": get_qto_names,
"pset_name": get_pset_names,
}
class MaterialPsetProperties(PropertyGroup): class MaterialPsetProperties(PropertyGroup):
@@ -215,13 +220,21 @@ class AddEditProperties(PropertyGroup):
primary_measure_type: EnumProperty(items=get_primary_measure_type, name="Primary Measure Type") primary_measure_type: EnumProperty(items=get_primary_measure_type, name="Primary Measure Type")
template_type: EnumProperty( template_type: EnumProperty(
items=[ items=[
("IfcPropertySingleValue","IfcPropertySingleValue","IfcPropertySingleValue"), ("IfcPropertySingleValue", "IfcPropertySingleValue", "IfcPropertySingleValue"),
("IfcPropertyEnumeratedValue","IfcPropertyEnumeratedValue","IfcPropertyEnumeratedValue") ("IfcPropertyEnumeratedValue", "IfcPropertyEnumeratedValue", "IfcPropertyEnumeratedValue"),
], ],
name="Template Type" name="Template Type",
) )
enum_values: CollectionProperty(name="Enum Values", type=EnumerationValues) enum_values: CollectionProperty(name="Enum Values", type=EnumerationValues)
getter_enum = {
"primary_measure_type": get_primary_measure_type,
"template_type": lambda self, context: [
("IfcPropertySingleValue", "IfcPropertySingleValue", "IfcPropertySingleValue"),
("IfcPropertyEnumeratedValue", "IfcPropertyEnumeratedValue", "IfcPropertyEnumeratedValue"),
],
}
def get_value_name(self): def get_value_name(self):
ifc_data_type = IfcStore.get_schema().declaration_by_name(self.primary_measure_type) ifc_data_type = IfcStore.get_schema().declaration_by_name(self.primary_measure_type)
data_type = ifcopenshell.util.attribute.get_primitive_type(ifc_data_type) data_type = ifcopenshell.util.attribute.get_primitive_type(ifc_data_type)
@@ -18,6 +18,7 @@
from bpy.types import Panel from bpy.types import Panel
from blenderbim.bim.ifc import IfcStore from blenderbim.bim.ifc import IfcStore
from blenderbim.bim.ui import prop_with_search
from blenderbim.bim.helper import draw_attribute from blenderbim.bim.helper import draw_attribute
from blenderbim.bim.module.pset.data import ( from blenderbim.bim.module.pset.data import (
ObjectPsetsData, ObjectPsetsData,
@@ -95,7 +96,7 @@ def draw_psetqto_ui(context, pset_id, pset, props, layout, obj_type):
def draw_psetqto_editable_ui(box, props, prop): def draw_psetqto_editable_ui(box, props, prop):
row = box.row(align=True) row = box.row(align=True)
draw_attribute(box, prop, row, copy_operator="bim.copy_property_to_selection") draw_attribute(prop, row, copy_operator="bim.copy_property_to_selection")
if ( if (
"length" in prop.name.lower() "length" in prop.name.lower()
or "width" in prop.name.lower() or "width" in prop.name.lower()
@@ -138,7 +139,7 @@ class BIM_PT_object_psets(Panel):
props = context.active_object.PsetProperties props = context.active_object.PsetProperties
row = self.layout.row(align=True) row = self.layout.row(align=True)
row.prop(props, "pset_name", text="") prop_with_search(row, props, "pset_name", text="")
op = row.operator("bim.add_pset", icon="ADD", text="") op = row.operator("bim.add_pset", icon="ADD", text="")
op.obj = context.active_object.name op.obj = context.active_object.name
op.obj_type = "Object" op.obj_type = "Object"
@@ -177,7 +178,7 @@ class BIM_PT_object_qtos(Panel):
props = context.active_object.PsetProperties props = context.active_object.PsetProperties
row = self.layout.row(align=True) row = self.layout.row(align=True)
row.prop(props, "qto_name", text="") prop_with_search(row, props, "qto_name", text="")
op = row.operator("bim.add_qto", icon="ADD", text="") op = row.operator("bim.add_qto", icon="ADD", text="")
op.obj = context.active_object.name op.obj = context.active_object.name
op.obj_type = "Object" op.obj_type = "Object"
@@ -450,8 +451,8 @@ class BIM_PT_add_edit_custom_properties(Panel):
row.prop(prop, "property_name", text="") row.prop(prop, "property_name", text="")
if prop.template_type == "IfcPropertySingleValue": if prop.template_type == "IfcPropertySingleValue":
row.prop(prop, prop.get_value_name(), text="") row.prop(prop, prop.get_value_name(), text="")
row.prop(prop, "primary_measure_type", text="") prop_with_search(row, prop, "primary_measure_type", text="")
row.prop(prop, "template_type", text="") prop_with_search(row, prop, "template_type", text="")
op = row.operator("bim.remove_property_to_edit", icon="X", text="") op = row.operator("bim.remove_property_to_edit", icon="X", text="")
op.index = index op.index = index
op.option = "AddEditProperties" op.option = "AddEditProperties"
@@ -20,6 +20,8 @@ import bpy
from . import ui, prop, operator from . import ui, prop, operator
classes = ( classes = (
operator.RefreshPsetTemplates,
operator.AddPsetFile,
operator.SavePsetTemplateFile, operator.SavePsetTemplateFile,
operator.AddPsetTemplate, operator.AddPsetTemplate,
operator.EditPsetTemplate, operator.EditPsetTemplate,
@@ -30,8 +32,11 @@ classes = (
operator.EnableEditingPsetTemplate, operator.EnableEditingPsetTemplate,
operator.DisableEditingPsetTemplate, operator.DisableEditingPsetTemplate,
operator.EnableEditingPropTemplate, operator.EnableEditingPropTemplate,
operator.DeletePropEnum,
operator.AddPropEnum,
operator.DisableEditingPropTemplate, operator.DisableEditingPropTemplate,
prop.PsetTemplate, prop.PsetTemplate,
prop.EnumerationValues,
prop.PropTemplate, prop.PropTemplate,
prop.BIMPsetTemplateProperties, prop.BIMPsetTemplateProperties,
ui.BIM_PT_pset_template, ui.BIM_PT_pset_template,
@@ -16,16 +16,66 @@
# You should have received a copy of the GNU General Public License # 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/>. # along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
import os
import bpy import bpy
import ifcopenshell import ifcopenshell
import ifcopenshell.api import ifcopenshell.api
import blenderbim.bim.schema import blenderbim.bim.schema
import blenderbim.bim.handler import blenderbim.bim.handler
from blenderbim.bim.module.pset_template.prop import updatePsetTemplateFiles, updatePsetTemplates, getPsetTemplates from blenderbim.bim.module.pset_template.prop import purge as purge_templates, updatePsetTemplates, getPsetTemplates
from blenderbim.bim.module.pset.prop import purge as purge_psets
from ifcopenshell.api.pset_template.data import Data from ifcopenshell.api.pset_template.data import Data
from blenderbim.bim.ifc import IfcStore from blenderbim.bim.ifc import IfcStore
#This is just a temporary operator until
#@Moult performs some of his refactor-magic ;) - vulevukusej
class RefreshPsetTemplates(bpy.types.Operator):
bl_idname = "bim.refresh_psettemplates"
bl_label = "Refresh the data for PsetTemplates"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
purge_templates()
purge_psets()
return {"FINISHED"}
class AddPsetFile(bpy.types.Operator):
bl_idname = "bim.add_pset_file"
bl_label = "Add Pset File"
bl_options = {"REGISTER", "UNDO"}
def invoke(self, context, event):
return context.window_manager.invoke_props_dialog(self, width=250)
def draw(self, context):
self.props = context.scene.BIMPsetTemplateProperties
self.layout.prop(self.props, "new_template_filename", text="Filename:")
def execute(self, context):
template = ifcopenshell.file()
filepath = os.path.join(
context.scene.BIMProperties.data_dir,
"pset",
self.props.new_template_filename + ".ifc",
)
template.create_entity(
"IFCPROPERTYSETTEMPLATE",
**{
"GlobalId": ifcopenshell.guid.new(),
"Name": "Name",
"Description": "Description",
"TemplateType": "PSET_TYPEDRIVENONLY",
"ApplicableEntity": "IfcTypeObject"
}
)
template.write(filepath)
self.props.new_template_filename = ""
return {"FINISHED"}
class AddPsetTemplate(bpy.types.Operator): class AddPsetTemplate(bpy.types.Operator):
bl_idname = "bim.add_pset_template" bl_idname = "bim.add_pset_template"
bl_label = "Add Pset Template" bl_label = "Add Pset Template"
@@ -41,7 +91,6 @@ class AddPsetTemplate(bpy.types.Operator):
return result return result
def _execute(self, context): def _execute(self, context):
props = context.scene.BIMPsetTemplateProperties
ifcopenshell.api.run("pset_template.add_pset_template", IfcStore.pset_template_file) ifcopenshell.api.run("pset_template.add_pset_template", IfcStore.pset_template_file)
Data.load(IfcStore.pset_template_file) Data.load(IfcStore.pset_template_file)
updatePsetTemplates(self, context) updatePsetTemplates(self, context)
@@ -139,6 +188,38 @@ class EnableEditingPropTemplate(bpy.types.Operator):
props.active_prop_template.name = template["Name"] or "" props.active_prop_template.name = template["Name"] or ""
props.active_prop_template.description = template["Description"] or "" props.active_prop_template.description = template["Description"] or ""
props.active_prop_template.primary_measure_type = template["PrimaryMeasureType"] props.active_prop_template.primary_measure_type = template["PrimaryMeasureType"]
props.active_prop_template.template_type = template["TemplateType"]
props.active_prop_template.enum_values.clear()
if template["Enumerators"]:
props.active_prop_template.enum_values.clear()
data_type = props.active_prop_template.get_value_name()
for e in template["Enumerators"].EnumerationValues:
new = props.active_prop_template.enum_values.add()
setattr(new, data_type, e.wrappedValue)
return {"FINISHED"}
class DeletePropEnum(bpy.types.Operator):
bl_idname = "bim.delete_prop_enum"
bl_label = "delete property enumeration"
bl_options = {"REGISTER", "UNDO"}
index: bpy.props.IntProperty()
def execute(self, context):
active_prop = context.scene.BIMPsetTemplateProperties.active_prop_template
active_prop.enum_values.remove(self.index)
return {"FINISHED"}
class AddPropEnum(bpy.types.Operator):
bl_idname = "bim.add_prop_enum"
bl_label = "add property enumeration"
bl_options = {"REGISTER", "UNDO"}
index: bpy.props.IntProperty()
def execute(self, context):
active_prop = context.scene.BIMPsetTemplateProperties.active_prop_template
active_prop.enum_values.add()
return {"FINISHED"} return {"FINISHED"}
@@ -285,6 +366,10 @@ class EditPropTemplate(bpy.types.Operator):
def _execute(self, context): def _execute(self, context):
props = context.scene.BIMPsetTemplateProperties props = context.scene.BIMPsetTemplateProperties
if props.active_prop_template.template_type == "P_ENUMERATEDVALUE":
enumerator = self.generate_prop_enum(props)
else:
enumerator = None
ifcopenshell.api.run( ifcopenshell.api.run(
"pset_template.edit_prop_template", "pset_template.edit_prop_template",
IfcStore.pset_template_file, IfcStore.pset_template_file,
@@ -294,6 +379,8 @@ class EditPropTemplate(bpy.types.Operator):
"Name": props.active_prop_template.name, "Name": props.active_prop_template.name,
"Description": props.active_prop_template.description, "Description": props.active_prop_template.description,
"PrimaryMeasureType": props.active_prop_template.primary_measure_type, "PrimaryMeasureType": props.active_prop_template.primary_measure_type,
"TemplateType": props.active_prop_template.template_type,
"Enumerators": enumerator
}, },
} }
) )
@@ -301,6 +388,20 @@ class EditPropTemplate(bpy.types.Operator):
bpy.ops.bim.disable_editing_prop_template() bpy.ops.bim.disable_editing_prop_template()
return {"FINISHED"} return {"FINISHED"}
#TODO -This will need to go into the
# api code at some point - vulevukusej
def generate_prop_enum(self, props):
self.file = IfcStore.pset_template_file
data_type = props.active_prop_template.get_value_name()
prop = props.active_prop_template
prop_enum = self.file.create_entity(
"IFCPROPERTYENUMERATION",
Name=prop.name,
EnumerationValues=tuple(self.file.create_entity(
prop.primary_measure_type, ev[data_type]) for ev in prop.enum_values)
)
return prop_enum
def rollback(self, data): def rollback(self, data):
IfcStore.pset_template_file.undo() IfcStore.pset_template_file.undo()
@@ -146,11 +146,42 @@ class PsetTemplate(PropertyGroup):
applicable_entity: StringProperty(name="Applicable Entity") applicable_entity: StringProperty(name="Applicable Entity")
class EnumerationValues(PropertyGroup):
string_value: StringProperty(name="Value")
bool_value: BoolProperty(name="Value")
int_value: IntProperty(name="Value")
float_value: FloatProperty(name="Value")
class PropTemplate(PropertyGroup): class PropTemplate(PropertyGroup):
global_id: StringProperty(name="Global ID") global_id: StringProperty(name="Global ID")
name: StringProperty(name="Name") name: StringProperty(name="Name")
description: StringProperty(name="Description") description: StringProperty(name="Description")
primary_measure_type: EnumProperty(items=get_primary_measure_type, name="Primary Measure Type") primary_measure_type: EnumProperty(items=get_primary_measure_type, name="Primary Measure Type")
template_type: EnumProperty(
items=[
("P_SINGLEVALUE","P_SINGLEVALUE",""),
("P_ENUMERATEDVALUE","P_ENUMERATEDVALUE","")
],
name="Template Type"
)
enum_values: CollectionProperty(type=EnumerationValues)
getter_enum = {
"primary_measure_type": get_primary_measure_type,
}
def get_value_name(self):
ifc_data_type = IfcStore.get_schema().declaration_by_name(self.primary_measure_type)
data_type = ifcopenshell.util.attribute.get_primitive_type(ifc_data_type)
if data_type == "string":
return "string_value"
elif data_type == "boolean":
return "bool_value"
elif data_type == "integer":
return "int_value"
elif data_type == "float":
return "float_value"
class BIMPsetTemplateProperties(PropertyGroup): class BIMPsetTemplateProperties(PropertyGroup):
@@ -162,3 +193,9 @@ class BIMPsetTemplateProperties(PropertyGroup):
active_prop_template_id: IntProperty(name="Active Prop Template Id") active_prop_template_id: IntProperty(name="Active Prop Template Id")
active_pset_template: PointerProperty(type=PsetTemplate) active_pset_template: PointerProperty(type=PsetTemplate)
active_prop_template: PointerProperty(type=PropTemplate) active_prop_template: PointerProperty(type=PropTemplate)
new_template_filename: StringProperty("New TemplateFileName")
getter_enum = {
"pset_template_files": getPsetTemplateFiles,
"pset_templates": getPsetTemplates,
}
@@ -19,6 +19,7 @@
import bpy import bpy
from bpy.types import Panel from bpy.types import Panel
from blenderbim.bim.ifc import IfcStore from blenderbim.bim.ifc import IfcStore
from blenderbim.bim.ui import prop_with_search
from blenderbim.bim.module.pset_template.prop import ( from blenderbim.bim.module.pset_template.prop import (
getPsetTemplates, getPsetTemplates,
) )
@@ -39,13 +40,15 @@ class BIM_PT_pset_template(Panel):
props = context.scene.BIMPsetTemplateProperties props = context.scene.BIMPsetTemplateProperties
row = layout.row(align=True) row = layout.row(align=True)
row.prop(props, "pset_template_files", text="") prop_with_search(row, props, "pset_template_files", text="")
row.operator("bim.save_pset_template_file", text="", icon="EXPORT") row.operator("bim.save_pset_template_file", text="", icon="EXPORT")
row.operator("bim.add_pset_file",icon="ADD",text="")
row.operator("bim.refresh_psettemplates", icon="FILE_REFRESH", text="")
row = layout.row(align=True) row = layout.row(align=True)
if bool(getPsetTemplates(props, context)): if bool(getPsetTemplates(props, context)):
row.prop(props, "pset_templates", text="", icon="COPY_ID") prop_with_search(row, props, "pset_templates", text="", icon="COPY_ID")
else: else:
row.label(text="No Pset Templates", icon="COPY_ID") row.label(text="No Pset Templates", icon="COPY_ID")
@@ -86,6 +89,9 @@ class BIM_PT_pset_template(Panel):
row.label(text="Property Templates", icon="COPY_ID") row.label(text="Property Templates", icon="COPY_ID")
row.operator("bim.add_prop_template", icon="ADD", text="") row.operator("bim.add_prop_template", icon="ADD", text="")
row = layout.row()
row.label(text="Name | Description | PrimaryMeasureType | TemplateType")
for prop_template_id in pset_template["HasPropertyTemplates"]: for prop_template_id in pset_template["HasPropertyTemplates"]:
prop_template = Data.prop_templates[prop_template_id] prop_template = Data.prop_templates[prop_template_id]
row = layout.row(align=True) row = layout.row(align=True)
@@ -93,11 +99,33 @@ class BIM_PT_pset_template(Panel):
if props.active_prop_template_id and props.active_prop_template_id == prop_template_id: 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, "name", text="")
row.prop(props.active_prop_template, "description", text="") row.prop(props.active_prop_template, "description", text="")
row.prop(props.active_prop_template, "primary_measure_type", text="") prop_with_search(row, props.active_prop_template, "primary_measure_type", text="")
row.prop(props.active_prop_template, "template_type", text="")
if props.active_prop_template.template_type == "P_ENUMERATEDVALUE":
row = layout.row(align=True)
split = row.split(factor=0.2)
c=split.column()
c.label(text="Enumerations:",)
c=split.column()
box = c.box()
grid = box.column_flow(columns=4)
value_name = props.active_prop_template.get_value_name()
r = grid.row()
r.operator("bim.add_prop_enum", text="Add Enum")
for k,v in enumerate(props.active_prop_template.enum_values):
r = grid.row(align=True)
r.prop(v, value_name, text="")
op = r.operator("bim.delete_prop_enum", icon="X", text="")
op.index = k
else: else:
row.label(text=prop_template["Name"]) row.label(text=prop_template["Name"])
row.label(text=prop_template["Description"]) row.label(text=prop_template["Description"])
row.label(text=prop_template["PrimaryMeasureType"]) row.label(text=prop_template["PrimaryMeasureType"])
row.label(text=prop_template["TemplateType"])
if props.active_prop_template_id and props.active_prop_template_id == prop_template_id: 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="") op = row.operator("bim.edit_prop_template", icon="CHECKMARK", text="")
@@ -26,6 +26,7 @@ classes = (
operator.EnableReassignClass, operator.EnableReassignClass,
operator.ReassignClass, operator.ReassignClass,
operator.UnlinkObject, operator.UnlinkObject,
operator.BIM_OT_enum_property_search,
prop.BIMRootProperties, prop.BIMRootProperties,
ui.BIM_PT_class, ui.BIM_PT_class,
) )
@@ -32,6 +32,7 @@ import blenderbim.tool as tool
from ifcopenshell.api.void.data import Data as VoidData from ifcopenshell.api.void.data import Data as VoidData
from blenderbim.bim.ifc import IfcStore from blenderbim.bim.ifc import IfcStore
from blenderbim.bim.module.root.prop import get_contexts from blenderbim.bim.module.root.prop import get_contexts
from blenderbim.bim.prop import StrProperty
class Operator: class Operator:
@@ -189,3 +190,27 @@ class CopyClass(bpy.types.Operator, Operator):
for obj in objects: for obj in objects:
core.copy_class(tool.Ifc, tool.Collector, tool.Geometry, tool.Root, obj=obj) core.copy_class(tool.Ifc, tool.Collector, tool.Geometry, tool.Root, obj=obj)
blenderbim.bim.handler.purge_module_data() blenderbim.bim.handler.purge_module_data()
class BIM_OT_enum_property_search(bpy.types.Operator):
bl_idname = "bim.enum_property_search"
bl_label = "Search For Property"
bl_options = {"REGISTER", "UNDO"}
prop_name: bpy.props.StringProperty()
collection: bpy.props.CollectionProperty(type=StrProperty)
def invoke(self, context, event):
self.data = context.data
getter = self.data.getter_enum.get(self.prop_name, None)
if getter is None:
return {"FINISHED"}
self.collection.clear()
for item in getter(self.data, context):
self.collection.add().name = item[0]
return context.window_manager.invoke_props_dialog(self)
def execute(self, context):
return {"FINISHED"}
def draw(self, context):
self.layout.prop_search(self.data, self.prop_name, self, "collection")
@@ -21,6 +21,7 @@ import ifcopenshell
import ifcopenshell.util.schema import ifcopenshell.util.schema
from blenderbim.bim.module.root.data import IfcClassData from blenderbim.bim.module.root.data import IfcClassData
from blenderbim.bim.ifc import IfcStore from blenderbim.bim.ifc import IfcStore
from blenderbim.bim.prop import StrProperty
from bpy.types import PropertyGroup from bpy.types import PropertyGroup
from bpy.props import ( from bpy.props import (
PointerProperty, PointerProperty,
@@ -34,11 +35,14 @@ from bpy.props import (
) )
types_enum = [] types_enum = []
classes_enum = []
def purge(): def purge():
global types_enum global types_enum
types_enum = [] types_enum = []
global classes_enum
classes_enum = []
def getIfcPredefinedTypes(self, context): def getIfcPredefinedTypes(self, context):
@@ -69,6 +73,10 @@ def refreshPredefinedTypes(self, context):
context.scene.BIMRootProperties.ifc_predefined_type = enum[0][0] context.scene.BIMRootProperties.ifc_predefined_type = enum[0][0]
def update_class_enum(self, context):
self.ifc_class = self.ifc_class_filter_enum
def get_ifc_products(self, context): def get_ifc_products(self, context):
if not IfcClassData.is_loaded: if not IfcClassData.is_loaded:
IfcClassData.load() IfcClassData.load()
@@ -93,3 +101,10 @@ class BIMRootProperties(PropertyGroup):
ifc_class: EnumProperty(items=get_ifc_classes, name="Class", update=refreshPredefinedTypes) ifc_class: EnumProperty(items=get_ifc_classes, name="Class", update=refreshPredefinedTypes)
ifc_predefined_type: EnumProperty(items=getIfcPredefinedTypes, name="Predefined Type", default=None) ifc_predefined_type: EnumProperty(items=getIfcPredefinedTypes, name="Predefined Type", default=None)
ifc_userdefined_type: StringProperty(name="Userdefined Type") ifc_userdefined_type: StringProperty(name="Userdefined Type")
getter_enum = {
"contexts": get_contexts,
"ifc_product": get_ifc_products,
"ifc_class": get_ifc_classes,
"ifc_predefined_type": getIfcPredefinedTypes,
}
@@ -20,6 +20,7 @@ import bpy
import blenderbim.bim.module.root.prop as root_prop import blenderbim.bim.module.root.prop as root_prop
from bpy.types import Panel from bpy.types import Panel
from blenderbim.bim.ifc import IfcStore from blenderbim.bim.ifc import IfcStore
from blenderbim.bim.ui import prop_with_search
from blenderbim.bim.module.root.data import IfcClassData from blenderbim.bim.module.root.data import IfcClassData
@@ -76,17 +77,14 @@ class BIM_PT_class(Panel):
def draw_class_dropdowns(self, context, ifc_predefined_types, is_reassigning_class=False): def draw_class_dropdowns(self, context, ifc_predefined_types, is_reassigning_class=False):
props = context.scene.BIMRootProperties props = context.scene.BIMRootProperties
layout = self.layout
if not is_reassigning_class: if not is_reassigning_class:
row = self.layout.row() prop_with_search(layout, props, "ifc_product")
row.prop(props, "ifc_product") prop_with_search(layout, props, "ifc_class")
row = self.layout.row()
row.prop(props, "ifc_class")
if ifc_predefined_types: if ifc_predefined_types:
row = self.layout.row() prop_with_search(layout, props, "ifc_predefined_type")
row.prop(props, "ifc_predefined_type") if props.ifc_predefined_type == "USERDEFINED":
if ifc_predefined_types == "USERDEFINED": row = layout.row()
row = self.layout.row() row.prop(props, "ifc_userdefined_type")
row.prop(props, "ifc_userdefined_type")
if not is_reassigning_class: if not is_reassigning_class:
row = self.layout.row() prop_with_search(layout, props, "contexts")
row.prop(context.scene.BIMRootProperties, "contexts")
@@ -68,3 +68,9 @@ class BIMUnitProperties(PropertyGroup):
conversion_unit_types: EnumProperty(items=get_conversion_unit_types, name="Conversion Unit Types") conversion_unit_types: EnumProperty(items=get_conversion_unit_types, name="Conversion Unit Types")
named_unit_types: EnumProperty(items=get_named_unit_types, name="Named Unit Types") named_unit_types: EnumProperty(items=get_named_unit_types, name="Named Unit Types")
unit_attributes: CollectionProperty(name="Unit Attributes", type=Attribute) unit_attributes: CollectionProperty(name="Unit Attributes", type=Attribute)
getter_enum = {
"unit_classes": get_unit_classes,
"conversion_unit_types": get_conversion_unit_types,
"named_unit_types": get_named_unit_types,
}
@@ -19,6 +19,7 @@
import blenderbim.bim.helper import blenderbim.bim.helper
from bpy.types import Panel, UIList from bpy.types import Panel, UIList
from blenderbim.bim.ifc import IfcStore from blenderbim.bim.ifc import IfcStore
from blenderbim.bim.ui import prop_with_search
from blenderbim.bim.module.unit.data import UnitsData from blenderbim.bim.module.unit.data import UnitsData
@@ -53,22 +54,22 @@ class BIM_PT_units(Panel):
return return
row = self.layout.row(align=True) row = self.layout.row(align=True)
row.prop(self.props, "unit_classes", text="") prop_with_search(row, self.props, "unit_classes", text="")
if self.props.unit_classes == "IfcMonetaryUnit": if self.props.unit_classes == "IfcMonetaryUnit":
row.operator("bim.add_monetary_unit", text="", icon="ADD") row.operator("bim.add_monetary_unit", text="", icon="ADD")
elif self.props.unit_classes in ("IfcConversionBasedUnit", "IfcConversionBasedUnitWithOffset"): elif self.props.unit_classes in ("IfcConversionBasedUnit", "IfcConversionBasedUnitWithOffset"):
row.prop(self.props, "conversion_unit_types", text="") prop_with_search(row, self.props, "conversion_unit_types", text="")
op = row.operator("bim.add_conversion_based_unit", text="", icon="ADD") op = row.operator("bim.add_conversion_based_unit", text="", icon="ADD")
op.name = self.props.conversion_unit_types op.name = self.props.conversion_unit_types
elif self.props.unit_classes == "IfcDerivedUnit": elif self.props.unit_classes == "IfcDerivedUnit":
pass # TODO pass # TODO
elif self.props.unit_classes == "IfcSIUnit": elif self.props.unit_classes == "IfcSIUnit":
row.prop(self.props, "named_unit_types", text="") prop_with_search(row, self.props, "named_unit_types", text="")
op = row.operator("bim.add_si_unit", text="", icon="ADD") op = row.operator("bim.add_si_unit", text="", icon="ADD")
op.unit_type = self.props.named_unit_types op.unit_type = self.props.named_unit_types
elif self.props.unit_classes == "IfcContextDependentUnit": elif self.props.unit_classes == "IfcContextDependentUnit":
row.prop(self.props, "named_unit_types", text="") prop_with_search(row, self.props, "named_unit_types", text="")
op = row.operator("bim.add_context_dependent_unit", text="", icon="ADD") op = row.operator("bim.add_context_dependent_unit", text="", icon="ADD")
op.name = "THINGAMAJIG" op.name = "THINGAMAJIG"
op.unit_type = self.props.named_unit_types op.unit_type = self.props.named_unit_types
+9
View File
@@ -170,6 +170,15 @@ class BIM_ADDON_preferences(bpy.types.AddonPreferences):
row.operator("bim.configure_visibility") row.operator("bim.configure_visibility")
def prop_with_search(layout, data, prop_name, **kwargs): # Kwargs are layout.prop arguments (text, icon, etc.)
row = layout.row(align=True)
# Magick courtesy of https://blender.stackexchange.com/a/203443/86891
row.context_pointer_set(name="data", data=data)
row.prop(data, prop_name, **kwargs)
op = row.operator("bim.enum_property_search", text="", icon="VIEWZOOM")
op.prop_name = prop_name
def ifc_units(self, context): def ifc_units(self, context):
scene = context.scene scene = context.scene
props = scene.BIMProperties props = scene.BIMProperties
@@ -102,9 +102,11 @@ class Usecase:
if value is None: if value is None:
continue continue
if isinstance(value, ifcopenshell.entity_instance): if isinstance(value, ifcopenshell.entity_instance):
nominal_value = value
if value.is_a(True) == "IFC4.IfcPropertyEnumeratedValue": if value.is_a(True) == "IFC4.IfcPropertyEnumeratedValue":
properties.append(value) properties.append(value)
continue
else:
nominal_value = value
#TODO-The following "elif" is temporary code, will need to refactor at some point - vulevukusej #TODO-The following "elif" is temporary code, will need to refactor at some point - vulevukusej
elif isinstance(value, list): elif isinstance(value, list):
for pset_template in self.settings["pset_template"].HasPropertyTemplates: for pset_template in self.settings["pset_template"].HasPropertyTemplates:
@@ -122,17 +124,18 @@ class Usecase:
EnumerationReference=prop_enum EnumerationReference=prop_enum
) )
properties.append(prop_enum_value) properties.append(prop_enum_value)
continue
else: else:
primary_measure_type = self.get_primary_measure_type(name, new_value=value) primary_measure_type = self.get_primary_measure_type(name, new_value=value)
value = self.cast_value_to_primary_measure_type(value, primary_measure_type) value = self.cast_value_to_primary_measure_type(value, primary_measure_type)
nominal_value = self.file.create_entity(primary_measure_type, value) nominal_value = self.file.create_entity(primary_measure_type, value)
properties.append( properties.append(
self.file.create_entity( self.file.create_entity(
"IfcPropertySingleValue", "IfcPropertySingleValue",
**{"Name": name, "NominalValue": nominal_value}, **{"Name": name, "NominalValue": nominal_value},
)
) )
)
return properties return properties
def extend_pset_with_new_properties(self, new_properties): def extend_pset_with_new_properties(self, new_properties):
@@ -35,6 +35,7 @@ class Usecase:
"PrimaryMeasureType": "IfcLabel", "PrimaryMeasureType": "IfcLabel",
"TemplateType": "P_SINGLEVALUE", "TemplateType": "P_SINGLEVALUE",
"AccessState": "READWRITE", "AccessState": "READWRITE",
"Enumerators": None
} }
) )
has_property_templates = list(self.settings["pset_template"].HasPropertyTemplates or []) has_property_templates = list(self.settings["pset_template"].HasPropertyTemplates or [])
@@ -49,5 +49,7 @@ class Data:
"Name": data["Name"], "Name": data["Name"],
"Description": data["Description"], "Description": data["Description"],
"PrimaryMeasureType": data["PrimaryMeasureType"], "PrimaryMeasureType": data["PrimaryMeasureType"],
"TemplateType": data["TemplateType"],
"Enumerators": data["Enumerators"]
} }
cls.is_loaded = True cls.is_loaded = True