Dynamic enumerators

Dynamic enums require to hold proper reference to enum array. (may lead to access violation and strange ui behaviour)
Cleanup bpy.props.xxx and bpy.types.xxx
Fix in path for files with hardcoded "/"
BIM_PT_ prefixes for Panel classes
Use poll method for panels
This commit is contained in:
s-leger
2019-11-15 01:44:29 +01:00
committed by GitHub
parent 21e87095dc
commit 7140b2c4e8
+252 -171
View File
@@ -3,247 +3,317 @@ import json
import os
import csv
from pathlib import Path
from bpy.types import PropertyGroup, Panel
from bpy.props import (
StringProperty,
EnumProperty,
BoolProperty,
IntProperty,
FloatProperty,
CollectionProperty
)
cwd = os.path.dirname(os.path.realpath(__file__)) + os.path.sep
class IfcSchema():
def __init__(self):
with open('{}ifc_elements_IFC4.json'.format(cwd + 'schema/')) as f:
with open('{}schema{}ifc_elements_IFC4.json'.format(cwd, os.path.sep)) as f:
self.elements = json.load(f)
ifc_schema = IfcSchema()
class BIMProperties(bpy.types.PropertyGroup):
def getIfcClasses(self, context):
return [(e, e, '') for e in ifc_schema.elements]
# hold reference to dynamic enum
classes_enum = []
types_enum = []
psetnames_enum = []
psetfiles_enum = []
classification_enum = []
attributes_enum = []
documents_enum = []
def getIfcPredefinedTypes(self, context):
results = []
for name, data in ifc_schema.elements.items():
if name != bpy.context.scene.BIMProperties.ifc_class:
# Note: unless we need dynamic behaviour
# enums should be cached especially when file io is involved
# we may clear on need to regen
def getIfcPredefinedTypes(self):
global types_enum
types_enum.clear()
for name, data in ifc_schema.elements.items():
if name != bpy.context.scene.BIMProperties.ifc_class:
continue
for attribute in data['attributes']:
if attribute['name'] != 'PredefinedType':
continue
for attribute in data['attributes']:
if attribute['name'] != 'PredefinedType':
continue
return [(e, e, '') for e in attribute['enum_values']]
types_enum.extend([(e, e, '') for e in attribute['enum_values']])
return types_enum
def getPsetNames(self, context):
files = os.listdir(bpy.context.scene.BIMProperties.data_dir + 'pset/')
return [(f, f, '') for f in files]
def getIfcClasses(self):
global classes_enum
classes_enum.clear()
classes_enum.extend([(e, e, '') for e in ifc_schema.elements])
return classes_enum
def getPsetFiles(self, context):
if not bpy.context.scene.BIMProperties.pset_name:
return []
files = os.listdir(bpy.context.scene.BIMProperties.data_dir + 'pset/{}/'.format(bpy.context.scene.BIMProperties.pset_name))
return [(f.replace('.csv', ''), f.replace('.csv', ''), '') for f in files]
def getPsetNames(self):
global psetnames_enum
psetnames_enum.clear()
files = os.listdir(bpy.context.scene.BIMProperties.data_dir + 'pset' + os.path.sep)
psetnames_enum.extend([(f, f, '') for f in files])
return psetnames_enum
def getClassifications(self, context):
with open(bpy.context.scene.BIMProperties.data_dir + 'class/classifications.csv', 'r') as f:
data = list(csv.reader(f))
keys = data.pop(0)
index = keys.index('Name')
return [(str(i), d[index], '') for i, d in enumerate(data)]
def getPsetFiles(self):
global psetfiles_enum
psetfiles_enum.clear()
if not bpy.context.scene.BIMProperties.pset_name:
return psetfiles_enum
files = os.listdir(
bpy.context.scene.BIMProperties.data_dir + 'pset{}{}{}'.format(
os.path.sep,
bpy.context.scene.BIMProperties.pset_name,
os.path.sep))
psetfiles_enum.extend([(f.replace('.csv', ''), f.replace('.csv', ''), '') for f in files])
return psetfiles_enum
def getReferences(self, context):
if not bpy.context.scene.BIMProperties.classification:
return []
with open(bpy.context.scene.BIMProperties.data_dir + 'class/references.csv', 'r') as f:
data = list(csv.reader(f))
keys = data.pop(0)
return [(d[0], '{} - {}'.format(d[0], d[1]), '') for d in data if
d[2] == bpy.context.scene.BIMProperties.classification]
def getClassifications(self):
global classification_enum
classification_enum.clear()
with open(bpy.context.scene.BIMProperties.data_dir + 'class/classifications.csv', 'r') as f:
data = list(csv.reader(f))
keys = data.pop(0)
index = keys.index('Name')
classification_enum.extend([(str(i), d[index], '') for i, d in enumerate(data)])
return classification_enum
schema_dir: bpy.props.StringProperty(default=cwd + 'schema/', name="Schema Directory")
data_dir: bpy.props.StringProperty(default=cwd + 'data/', name="Data Directory")
ifc_class: bpy.props.EnumProperty(items = getIfcClasses, name="Class")
ifc_predefined_type: bpy.props.EnumProperty(
def getReferences(self):
global reference_enum
reference_enum.clear()
if not bpy.context.scene.BIMProperties.classification:
return reference_enum
with open(bpy.context.scene.BIMProperties.data_dir + 'class' + os.path.sep + 'references.csv', 'r') as f:
data = list(csv.reader(f))
keys = data.pop(0)
reference_enum.extend([(d[0], '{} - {}'.format(d[0], d[1]), '') for d in data if
d[2] == bpy.context.scene.BIMProperties.classification])
return reference_enum
def getApplicableAttributes(self):
global attributes_enum
attributes_enum.clear()
if '/' in bpy.context.active_object.name \
and bpy.context.active_object.name.split('/')[0] in ifc_schema.elements:
attributes_enum.extend([(a['name'], a['name'], '') for a in
ifc_schema.elements[bpy.context.active_object.name.split('/')[0]]['attributes']
if bpy.context.active_object.BIMObjectProperties.attributes.find(a['name']) == -1])
return attributes_enum
def getApplicableDocuments(self):
global documents_enum
documents_enum.clear()
doc_path = bpy.context.scene.BIMProperties.data_dir + 'doc' + os.path.sep
for filename in Path(doc_path).glob('**/*'):
uri = str(filename.relative_to(doc_path).as_posix())
documents_enum.append((uri, uri, ''))
return documents_enum
class BIMProperties(PropertyGroup):
schema_dir: StringProperty(default=cwd + 'schema' + os.path.sep, name="Schema Directory")
data_dir: StringProperty(default=cwd + 'data' + os.path.sep, name="Data Directory")
ifc_class: EnumProperty(items = getIfcClasses, name="Class")
ifc_predefined_type: EnumProperty(
items = getIfcPredefinedTypes,
name="Predefined Type", default=None)
ifc_userdefined_type: bpy.props.StringProperty(name="Userdefined Type")
export_has_representations: bpy.props.BoolProperty(name="Export Representations", default=True)
export_should_export_all_materials_as_styled_items: bpy.props.BoolProperty(name="Export All Materials as Styled Items", default=False)
export_should_use_presentation_style_assignment: bpy.props.BoolProperty(name="Export with Presentation Style Assignment", default=False)
import_should_ignore_site_coordinates: bpy.props.BoolProperty(name="Import Ignoring Site Coordinates", default=False)
import_should_import_curves: bpy.props.BoolProperty(name="Import Curves", default=False)
qa_reject_element_reason: bpy.props.StringProperty(name="Element Rejection Reason")
pset_name: bpy.props.EnumProperty(items=getPsetNames, name="Pset Name")
pset_file: bpy.props.EnumProperty(items=getPsetFiles, name="Pset File")
has_georeferencing: bpy.props.BoolProperty(name="Has Georeferencing", default=False)
global_id: bpy.props.StringProperty(name="GlobalId")
features_dir: bpy.props.StringProperty(default='', name="Features Directory")
diff_json_file: bpy.props.StringProperty(default='', name="Diff JSON File")
aggregate_class: bpy.props.EnumProperty(items = getIfcClasses, name="Aggregate Class")
aggregate_name: bpy.props.StringProperty(name="Aggregate Name")
classification: bpy.props.EnumProperty(items = getClassifications, name="Classification")
reference: bpy.props.EnumProperty(items = getReferences, name="Reference")
ifc_userdefined_type: StringProperty(name="Userdefined Type")
export_has_representations: BoolProperty(name="Export Representations", default=True)
export_should_export_all_materials_as_styled_items: BoolProperty(name="Export All Materials as Styled Items", default=False)
export_should_use_presentation_style_assignment: BoolProperty(name="Export with Presentation Style Assignment", default=False)
import_should_ignore_site_coordinates: BoolProperty(name="Import Ignoring Site Coordinates", default=False)
import_should_import_curves: BoolProperty(name="Import Curves", default=False)
qa_reject_element_reason: StringProperty(name="Element Rejection Reason")
pset_name: EnumProperty(items=getPsetNames, name="Pset Name")
pset_file: EnumProperty(items=getPsetFiles, name="Pset File")
has_georeferencing: BoolProperty(name="Has Georeferencing", default=False)
global_id: StringProperty(name="GlobalId")
features_dir: StringProperty(default='', name="Features Directory")
diff_json_file: StringProperty(default='', name="Diff JSON File")
aggregate_class: EnumProperty(items = getIfcClasses, name="Aggregate Class")
aggregate_name: StringProperty(name="Aggregate Name")
classification: EnumProperty(items = getClassifications, name="Classification")
reference: EnumProperty(items = getReferences, name="Reference")
class MapConversion(bpy.types.PropertyGroup):
eastings: bpy.props.StringProperty(name="Eastings")
northings: bpy.props.StringProperty(name="Northings")
orthogonal_height: bpy.props.StringProperty(name="Orthogonal Height")
x_axis_abscissa: bpy.props.StringProperty(name="X Axis Abscissa")
x_axis_ordinate: bpy.props.StringProperty(name="X Axis Ordinate")
scale: bpy.props.StringProperty(name="Scale")
class MapConversion(PropertyGroup):
eastings: StringProperty(name="Eastings")
northings: StringProperty(name="Northings")
orthogonal_height: StringProperty(name="Orthogonal Height")
x_axis_abscissa: StringProperty(name="X Axis Abscissa")
x_axis_ordinate: StringProperty(name="X Axis Ordinate")
scale: StringProperty(name="Scale")
class TargetCRS(bpy.types.PropertyGroup):
name: bpy.props.StringProperty(name="Name")
description: bpy.props.StringProperty(name="Description")
geodetic_datum: bpy.props.StringProperty(name="Geodetic Datum")
vertical_datum: bpy.props.StringProperty(name="Vertical Datum")
map_projection: bpy.props.StringProperty(name="Map Projection")
map_zone: bpy.props.StringProperty(name="Map Zone")
map_unit: bpy.props.StringProperty(name="Map Unit")
class TargetCRS(PropertyGroup):
name: StringProperty(name="Name")
description: StringProperty(name="Description")
geodetic_datum: StringProperty(name="Geodetic Datum")
vertical_datum: StringProperty(name="Vertical Datum")
map_projection: StringProperty(name="Map Projection")
map_zone: StringProperty(name="Map Zone")
map_unit: StringProperty(name="Map Unit")
class Attribute(bpy.types.PropertyGroup):
name: bpy.props.StringProperty(name="Name")
data_type: bpy.props.StringProperty(name="Data Type")
string_value: bpy.props.StringProperty(name="Value")
bool_value: bpy.props.BoolProperty(name="Value")
int_value: bpy.props.IntProperty(name="Value")
float_value: bpy.props.FloatProperty(name="Value")
class Attribute(PropertyGroup):
name: StringProperty(name="Name")
data_type: StringProperty(name="Data Type")
string_value: StringProperty(name="Value")
bool_value: BoolProperty(name="Value")
int_value: IntProperty(name="Value")
float_value: FloatProperty(name="Value")
class Pset(bpy.types.PropertyGroup):
name: bpy.props.StringProperty(name="Name")
file: bpy.props.StringProperty(name="File")
class Pset(PropertyGroup):
name: StringProperty(name="Name")
file: StringProperty(name="File")
class Document(bpy.types.PropertyGroup):
file: bpy.props.StringProperty(name="File")
class Document(PropertyGroup):
file: StringProperty(name="File")
class Classification(bpy.types.PropertyGroup):
name: bpy.props.StringProperty(name="Name")
identification: bpy.props.StringProperty(name="Identification")
class Classification(PropertyGroup):
name: StringProperty(name="Name")
identification: StringProperty(name="Identification")
class GlobalId(bpy.types.PropertyGroup):
name: bpy.props.StringProperty(name="Name")
class BIMObjectProperties(bpy.types.PropertyGroup):
def getApplicableAttributes(self, context):
if '/' in bpy.context.active_object.name \
and bpy.context.active_object.name.split('/')[0] in ifc_schema.elements:
return [(a['name'], a['name'], '') for a in
ifc_schema.elements[bpy.context.active_object.name.split('/')[0]]['attributes']
if bpy.context.active_object.BIMObjectProperties.attributes.find(a['name']) == -1]
return []
class GlobalId(PropertyGroup):
name: StringProperty(name="Name")
def getApplicableDocuments(self, context):
results = []
doc_path = bpy.context.scene.BIMProperties.data_dir + 'doc/'
for filename in Path(doc_path).glob('**/*'):
uri = str(filename.relative_to(doc_path).as_posix())
results.append((uri, uri, ''))
return results
global_ids: bpy.props.CollectionProperty(name="GlobalIds", type=GlobalId)
attributes: bpy.props.CollectionProperty(name="Attributes", type=Attribute)
psets: bpy.props.CollectionProperty(name="Psets", type=Pset)
applicable_attributes: bpy.props.EnumProperty(items=getApplicableAttributes, name="Attribute Names")
documents: bpy.props.CollectionProperty(name="Documents", type=Document)
applicable_documents: bpy.props.EnumProperty(items=getApplicableDocuments, name="Available Documents")
classifications: bpy.props.CollectionProperty(name="Classifications", type=Classification)
class BIMObjectProperties(PropertyGroup):
class BIMMaterialProperties(bpy.types.PropertyGroup):
is_external: bpy.props.BoolProperty(name="Has External Definition")
location: bpy.props.StringProperty(name="Location")
identification: bpy.props.StringProperty(name="Identification")
name: bpy.props.StringProperty(name="Name")
class SweptSolid(bpy.types.PropertyGroup):
name: bpy.props.StringProperty(name="Name")
outer_curve: bpy.props.StringProperty(name="Outer Curve")
inner_curves: bpy.props.StringProperty(name="Inner Curves")
extrusion: bpy.props.StringProperty(name="Extrusion")
global_ids: CollectionProperty(name="GlobalIds", type=GlobalId)
attributes: CollectionProperty(name="Attributes", type=Attribute)
psets: CollectionProperty(name="Psets", type=Pset)
applicable_attributes: EnumProperty(items=getApplicableAttributes, name="Attribute Names")
documents: CollectionProperty(name="Documents", type=Document)
applicable_documents: EnumProperty(items=getApplicableDocuments, name="Available Documents")
classifications: CollectionProperty(name="Classifications", type=Classification)
class BIMMeshProperties(bpy.types.PropertyGroup):
is_wireframe: bpy.props.BoolProperty(name="Is Wireframe")
is_swept_solid: bpy.props.BoolProperty(name="Is Swept Solid")
swept_solids: bpy.props.CollectionProperty(name="Swept Solids", type=SweptSolid)
class ObjectPanel(bpy.types.Panel):
class BIMMaterialProperties(PropertyGroup):
is_external: BoolProperty(name="Has External Definition")
location: StringProperty(name="Location")
identification: StringProperty(name="Identification")
name: StringProperty(name="Name")
class SweptSolid(PropertyGroup):
name: StringProperty(name="Name")
outer_curve: StringProperty(name="Outer Curve")
inner_curves: StringProperty(name="Inner Curves")
extrusion: StringProperty(name="Extrusion")
class BIMMeshProperties(PropertyGroup):
is_wireframe: BoolProperty(name="Is Wireframe")
is_swept_solid: BoolProperty(name="Is Swept Solid")
swept_solids: CollectionProperty(name="Swept Solids", type=SweptSolid)
class BIM_PT_object(Panel):
bl_label = 'IFC Object'
bl_idname = 'BIM_PT_object'
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = 'object'
@classmethod
def poll(cls, context):
return context.active_object is not None and hasattr(context.active_object, "BIMObjectProperties")
def draw(self, context):
if not bpy.context.active_object:
if context.active_object is None:
return
layout = self.layout
props = context.active_object.BIMObjectProperties
layout.label(text="Software Identity:")
row = layout.row()
row.operator('bim.generate_global_id')
layout.label(text="Attributes:")
row = layout.row(align=True)
row.prop(bpy.context.active_object.BIMObjectProperties, 'applicable_attributes', text='')
row.prop(props, 'applicable_attributes', text='')
row.operator('bim.add_attribute')
for index, attribute in enumerate(bpy.context.active_object.BIMObjectProperties.attributes):
for index, attribute in enumerate(props.attributes):
row = layout.row(align=True)
row.prop(attribute, 'name', text='')
row.prop(attribute, 'string_value', text='')
row.operator('bim.remove_attribute', icon='X', text='').attribute_index = index
row = layout.row()
row.prop(bpy.context.active_object.BIMObjectProperties, 'attributes')
row.prop(props, 'attributes')
layout.label(text="Property Sets:")
row = layout.row()
row.operator('bim.add_pset')
for index, pset in enumerate(bpy.context.active_object.BIMObjectProperties.psets):
for index, pset in enumerate(props.psets):
row = layout.row(align=True)
row.prop(pset, 'name', text='')
row.prop(pset, 'file', text='')
row.operator('bim.remove_pset', icon='X', text='').pset_index = index
row = layout.row()
row.prop(bpy.context.active_object.BIMObjectProperties, 'psets')
row.prop(props, 'psets')
layout.label(text="Documents:")
row = layout.row(align=True)
row.prop(bpy.context.active_object.BIMObjectProperties, 'applicable_documents', text='')
row.prop(props, 'applicable_documents', text='')
row.operator('bim.add_document')
for index, document in enumerate(bpy.context.active_object.BIMObjectProperties.documents):
for index, document in enumerate(props.documents):
row = layout.row(align=True)
row.prop(document, 'file', text='')
row.operator('bim.remove_document', icon='X', text='').document_index = index
row = layout.row()
row.prop(bpy.context.active_object.BIMObjectProperties, 'documents')
row.prop(props, 'documents')
layout.label(text="Classification:")
for index, classification in enumerate(bpy.context.active_object.BIMObjectProperties.classifications):
for index, classification in enumerate(props.classifications):
row = layout.row(align=True)
row.prop(classification, 'identification', text='')
row.prop(classification, 'name', text='')
row.operator('bim.remove_classification', icon='X', text='').classification_index = index
row = layout.row()
row.prop(bpy.context.active_object.BIMObjectProperties, 'classifications')
row.prop(props, 'classifications')
class MeshPanel(bpy.types.Panel):
class BIM_PT_mesh(Panel):
bl_label = 'IFC Representations'
bl_idname = 'BIM_PT_mesh'
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = 'data'
@classmethod
def poll(cls, context):
return context.active_object is not None and context.active_object.type == "MESH" and \
hasattr(context.active_object.data, "BIMMeshProperties")
def draw(self, context):
if not bpy.context.active_object.data:
if not context.active_object.data:
return
layout = self.layout
props = context.active_object.data.BIMMeshProperties
row = layout.row()
row.prop(bpy.context.active_object.data.BIMMeshProperties, 'is_wireframe')
row.prop(props, 'is_wireframe')
row = layout.row()
row.prop(bpy.context.active_object.data.BIMMeshProperties, 'is_swept_solid')
row.prop(props, 'is_swept_solid')
row = layout.row()
row.operator('bim.add_swept_solid')
for index, swept_solid in enumerate(bpy.context.active_object.data.BIMMeshProperties.swept_solids):
for index, swept_solid in enumerate(props.swept_solids):
row = layout.row(align=True)
row.prop(swept_solid, 'name', text='')
row.operator('bim.remove_swept_solid', icon='X', text='').index = index
@@ -258,30 +328,37 @@ class MeshPanel(bpy.types.Panel):
row.operator('bim.assign_swept_solid_extrusion').index = index
row.operator('bim.select_swept_solid_extrusion', icon='RESTRICT_SELECT_OFF', text='').index = index
row = layout.row()
row.prop(bpy.context.active_object.data.BIMMeshProperties, 'swept_solids')
row.prop(props, 'swept_solids')
class MaterialPanel(bpy.types.Panel):
class BIM_PT_material(Panel):
bl_label = 'IFC Materials'
bl_idname = 'BIM_PT_material'
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = 'material'
@classmethod
def poll(cls, context):
return context.active_object is not None and context.active_object.active_material is not None
def draw(self, context):
if not bpy.context.active_object.active_material:
return
props = context.active_object.active_material.BIMMaterialProperties
layout = self.layout
row = layout.row()
row.prop(bpy.context.active_object.active_material.BIMMaterialProperties, 'is_external')
row.prop(props, 'is_external')
row = layout.row(align=True)
row.prop(bpy.context.active_object.active_material.BIMMaterialProperties, 'location')
row.prop(props, 'location')
row.operator('bim.select_external_material_dir', icon="FILE_FOLDER", text="")
row = layout.row()
row.prop(bpy.context.active_object.active_material.BIMMaterialProperties, 'identification')
row.prop(props, 'identification')
row = layout.row()
row.prop(bpy.context.active_object.active_material.BIMMaterialProperties, 'name')
row.prop(props, 'name')
class GISPanel(bpy.types.Panel):
class BIM_PT_gis(Panel):
bl_label = 'IFC Georeferencing'
bl_idname = "BIM_PT_gis"
bl_space_type = 'PROPERTIES'
@@ -291,27 +368,28 @@ class GISPanel(bpy.types.Panel):
def draw(self, context):
layout = self.layout
layout.use_property_split = True
layout.row().prop(bpy.context.scene.BIMProperties, 'has_georeferencing')
scene = context.scene
layout.row().prop(scene.BIMProperties, 'has_georeferencing')
layout.label(text="Map Conversion:")
layout.row().prop(bpy.context.scene.MapConversion, 'eastings')
layout.row().prop(bpy.context.scene.MapConversion, 'northings')
layout.row().prop(bpy.context.scene.MapConversion, 'orthogonal_height')
layout.row().prop(bpy.context.scene.MapConversion, 'x_axis_abscissa')
layout.row().prop(bpy.context.scene.MapConversion, 'x_axis_ordinate')
layout.row().prop(bpy.context.scene.MapConversion, 'scale')
layout.row().prop(scene.MapConversion, 'eastings')
layout.row().prop(scene.MapConversion, 'northings')
layout.row().prop(scene.MapConversion, 'orthogonal_height')
layout.row().prop(scene.MapConversion, 'x_axis_abscissa')
layout.row().prop(scene.MapConversion, 'x_axis_ordinate')
layout.row().prop(scene.MapConversion, 'scale')
layout.label(text="Target CRS:")
layout.row().prop(bpy.context.scene.TargetCRS, 'name')
layout.row().prop(bpy.context.scene.TargetCRS, 'description')
layout.row().prop(bpy.context.scene.TargetCRS, 'geodetic_datum')
layout.row().prop(bpy.context.scene.TargetCRS, 'vertical_datum')
layout.row().prop(bpy.context.scene.TargetCRS, 'map_projection')
layout.row().prop(bpy.context.scene.TargetCRS, 'map_zone')
layout.row().prop(bpy.context.scene.TargetCRS, 'map_unit')
layout.row().prop(scene.TargetCRS, 'name')
layout.row().prop(scene.TargetCRS, 'description')
layout.row().prop(scene.TargetCRS, 'geodetic_datum')
layout.row().prop(scene.TargetCRS, 'vertical_datum')
layout.row().prop(scene.TargetCRS, 'map_projection')
layout.row().prop(scene.TargetCRS, 'map_zone')
layout.row().prop(scene.TargetCRS, 'map_unit')
class BIMPanel(bpy.types.Panel):
class BIM_PT_bim(Panel):
bl_label = "Building Information Modeling"
bl_idname = "BIM_PT_bim"
bl_space_type = 'PROPERTIES'
@@ -323,7 +401,7 @@ class BIMPanel(bpy.types.Panel):
layout.use_property_split = True
scene = context.scene
bim_properties = bpy.context.scene.BIMProperties
bim_properties = scene.BIMProperties
layout.label(text="System Setup:")
@@ -394,7 +472,8 @@ class BIMPanel(bpy.types.Panel):
row.operator("bim.assign_classification")
row.operator("bim.unassign_classification")
class QAPanel(bpy.types.Panel):
class BIM_PT_qa(Panel):
bl_label = "BIMTester Quality Auditing"
bl_idname = "BIM_PT_qa"
bl_space_type = 'PROPERTIES'
@@ -432,7 +511,8 @@ class QAPanel(bpy.types.Panel):
row = layout.row()
row.operator("bim.select_audited")
class DiffPanel(bpy.types.Panel):
class BIM_PT_diff(Panel):
bl_label = "IFC Diff"
bl_idname = "BIM_PT_diff"
bl_space_type = 'PROPERTIES'
@@ -444,7 +524,7 @@ class DiffPanel(bpy.types.Panel):
layout.use_property_split = True
scene = context.scene
bim_properties = bpy.context.scene.BIMProperties
bim_properties = scene.BIMProperties
layout.label(text="IFC Diff Setup:")
@@ -452,7 +532,8 @@ class DiffPanel(bpy.types.Panel):
row.prop(bim_properties, "diff_json_file")
row.operator("bim.select_diff_json_file", icon="FILE_FOLDER", text="")
class MVDPanel(bpy.types.Panel):
class BIM_PT_mvd(Panel):
bl_label = "Model View Definitions"
bl_idname = "BIM_PT_mvd"
bl_space_type = 'PROPERTIES'
@@ -463,7 +544,7 @@ class MVDPanel(bpy.types.Panel):
layout = self.layout
scene = context.scene
bim_properties = bpy.context.scene.BIMProperties
bim_properties = scene.BIMProperties
layout.label(text="Custom MVD:")