mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-19 06:39:13 +00:00
Add UI for pset overrides without the need to create a CSV.
This commit is contained in:
@@ -61,6 +61,8 @@ if bpy is not None:
|
|||||||
operator.UnassignPset,
|
operator.UnassignPset,
|
||||||
operator.AddPset,
|
operator.AddPset,
|
||||||
operator.RemovePset,
|
operator.RemovePset,
|
||||||
|
operator.AddOverridePset,
|
||||||
|
operator.RemoveOverridePset,
|
||||||
operator.AddMaterialPset,
|
operator.AddMaterialPset,
|
||||||
operator.RemoveMaterialPset,
|
operator.RemoveMaterialPset,
|
||||||
operator.AddDocument,
|
operator.AddDocument,
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import os
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from mathutils import Vector, Matrix
|
from mathutils import Vector, Matrix
|
||||||
from .helper import SIUnitHelper
|
from .helper import SIUnitHelper
|
||||||
|
from . import schema
|
||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
import addon_utils
|
import addon_utils
|
||||||
|
|
||||||
@@ -408,6 +409,18 @@ class IfcParser():
|
|||||||
self.rel_defines_by_pset.setdefault(
|
self.rel_defines_by_pset.setdefault(
|
||||||
'{}/{}'.format(pset.name, pset.file), []).append(product)
|
'{}/{}'.format(pset.name, pset.file), []).append(product)
|
||||||
|
|
||||||
|
for pset in obj.BIMObjectProperties.override_psets:
|
||||||
|
pset_key = '{}/{}'.format(pset.name, obj.name)
|
||||||
|
raw = {p.name: p.string_value for p in pset.properties if p.string_value}
|
||||||
|
if not raw:
|
||||||
|
continue
|
||||||
|
self.psets[pset_key] = {
|
||||||
|
'ifc': None,
|
||||||
|
'raw': raw,
|
||||||
|
'attributes': { 'Name': pset.name }
|
||||||
|
}
|
||||||
|
self.rel_defines_by_pset.setdefault(pset_key, []).append(product)
|
||||||
|
|
||||||
for document in obj.BIMObjectProperties.documents:
|
for document in obj.BIMObjectProperties.documents:
|
||||||
self.rel_associates_document_object.setdefault(
|
self.rel_associates_document_object.setdefault(
|
||||||
document.file, []).append(product)
|
document.file, []).append(product)
|
||||||
@@ -943,10 +956,9 @@ class IfcParser():
|
|||||||
|
|
||||||
|
|
||||||
class IfcExporter():
|
class IfcExporter():
|
||||||
def __init__(self, ifc_export_settings, ifc_schema, ifc_parser, qto_calculator):
|
def __init__(self, ifc_export_settings, ifc_parser, qto_calculator):
|
||||||
self.template_file = '{}template.ifc'.format(ifc_export_settings.schema_dir)
|
self.template_file = '{}template.ifc'.format(ifc_export_settings.schema_dir)
|
||||||
self.ifc_export_settings = ifc_export_settings
|
self.ifc_export_settings = ifc_export_settings
|
||||||
self.ifc_schema = ifc_schema
|
|
||||||
self.ifc_parser = ifc_parser
|
self.ifc_parser = ifc_parser
|
||||||
self.qto_calculator = qto_calculator
|
self.qto_calculator = qto_calculator
|
||||||
|
|
||||||
@@ -1206,7 +1218,7 @@ class IfcExporter():
|
|||||||
})
|
})
|
||||||
|
|
||||||
def create_pset_properties(self, pset):
|
def create_pset_properties(self, pset):
|
||||||
if pset['attributes']['Name'] in self.ifc_schema.psets:
|
if pset['attributes']['Name'] in schema.ifc.psets:
|
||||||
return self.create_templated_pset_properties(pset)
|
return self.create_templated_pset_properties(pset)
|
||||||
return self.create_custom_pset_properties(pset)
|
return self.create_custom_pset_properties(pset)
|
||||||
|
|
||||||
@@ -1222,7 +1234,7 @@ class IfcExporter():
|
|||||||
|
|
||||||
def create_templated_pset_properties(self, pset):
|
def create_templated_pset_properties(self, pset):
|
||||||
properties = []
|
properties = []
|
||||||
templates = self.ifc_schema.psets[pset['attributes']['Name']]['HasPropertyTemplates']
|
templates = schema.ifc.psets[pset['attributes']['Name']]['HasPropertyTemplates']
|
||||||
for name, data in templates.items():
|
for name, data in templates.items():
|
||||||
if name not in pset['raw']:
|
if name not in pset['raw']:
|
||||||
continue
|
continue
|
||||||
@@ -1250,13 +1262,13 @@ class IfcExporter():
|
|||||||
return properties
|
return properties
|
||||||
|
|
||||||
def cast_to_base_type(self, var_type, value):
|
def cast_to_base_type(self, var_type, value):
|
||||||
if var_type not in self.ifc_schema.type_map:
|
if var_type not in schema.ifc.type_map:
|
||||||
return value
|
return value
|
||||||
elif self.ifc_schema.type_map[var_type] == 'float':
|
elif schema.ifc.type_map[var_type] == 'float':
|
||||||
return float(value)
|
return float(value)
|
||||||
elif self.ifc_schema.type_map[var_type] == 'integer':
|
elif schema.ifc.type_map[var_type] == 'integer':
|
||||||
return int(value)
|
return int(value)
|
||||||
elif self.ifc_schema.type_map[var_type] == 'bool':
|
elif schema.ifc.type_map[var_type] == 'bool':
|
||||||
return True if value.lower() in ['1', 't', 'true', 'yes', 'y', 'uh-huh'] else False
|
return True if value.lower() in ['1', 't', 'true', 'yes', 'y', 'uh-huh'] else False
|
||||||
return str(value)
|
return str(value)
|
||||||
|
|
||||||
@@ -1551,11 +1563,11 @@ class IfcExporter():
|
|||||||
)
|
)
|
||||||
|
|
||||||
def get_product_attribute_type(self, product_class, attribute_name):
|
def get_product_attribute_type(self, product_class, attribute_name):
|
||||||
element_schema = self.ifc_schema.elements[product_class]
|
element_schema = schema.ifc.elements[product_class]
|
||||||
for a in element_schema['attributes']:
|
for a in element_schema['attributes']:
|
||||||
if a['name'] == attribute_name:
|
if a['name'] == attribute_name:
|
||||||
return a['type']
|
return a['type']
|
||||||
if element_schema['parent'] in self.ifc_schema.elements:
|
if element_schema['parent'] in schema.ifc.elements:
|
||||||
return self.get_product_attribute_type(element_schema['parent'], attribute_name)
|
return self.get_product_attribute_type(element_schema['parent'], attribute_name)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|||||||
@@ -7,9 +7,7 @@ import time
|
|||||||
import mathutils
|
import mathutils
|
||||||
import multiprocessing
|
import multiprocessing
|
||||||
from .helper import SIUnitHelper
|
from .helper import SIUnitHelper
|
||||||
from .schema import IfcSchema
|
from . import schema
|
||||||
|
|
||||||
ifc_schema = IfcSchema()
|
|
||||||
|
|
||||||
class MaterialCreator():
|
class MaterialCreator():
|
||||||
def __init__(self, ifc_import_settings):
|
def __init__(self, ifc_import_settings):
|
||||||
@@ -402,8 +400,8 @@ class IfcImporter():
|
|||||||
|
|
||||||
def add_element_attributes(self, element, obj):
|
def add_element_attributes(self, element, obj):
|
||||||
attributes = element.get_info()
|
attributes = element.get_info()
|
||||||
if element.is_a() in ifc_schema.elements:
|
if element.is_a() in schema.ifc.elements:
|
||||||
applicable_attributes = [a['name'] for a in ifc_schema.elements[element.is_a()]['attributes']]
|
applicable_attributes = [a['name'] for a in schema.ifc.elements[element.is_a()]['attributes']]
|
||||||
for key, value in attributes.items():
|
for key, value in attributes.items():
|
||||||
if key not in applicable_attributes \
|
if key not in applicable_attributes \
|
||||||
or value is None:
|
or value is None:
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ from . import export_ifc
|
|||||||
from . import import_ifc
|
from . import import_ifc
|
||||||
from . import cut_ifc
|
from . import cut_ifc
|
||||||
from . import sheeter
|
from . import sheeter
|
||||||
|
from . import schema
|
||||||
from bpy_extras.io_utils import ImportHelper
|
from bpy_extras.io_utils import ImportHelper
|
||||||
from itertools import cycle
|
from itertools import cycle
|
||||||
from mathutils import Vector
|
from mathutils import Vector
|
||||||
from .schema import IfcSchema
|
|
||||||
|
|
||||||
class ExportIFC(bpy.types.Operator):
|
class ExportIFC(bpy.types.Operator):
|
||||||
bl_idname = "export.ifc"
|
bl_idname = "export.ifc"
|
||||||
@@ -54,9 +54,8 @@ class ExportIFC(bpy.types.Operator):
|
|||||||
]
|
]
|
||||||
})
|
})
|
||||||
ifc_parser = export_ifc.IfcParser(ifc_export_settings)
|
ifc_parser = export_ifc.IfcParser(ifc_export_settings)
|
||||||
ifc_schema = IfcSchema()
|
|
||||||
qto_calculator = export_ifc.QtoCalculator()
|
qto_calculator = export_ifc.QtoCalculator()
|
||||||
ifc_exporter = export_ifc.IfcExporter(ifc_export_settings, ifc_schema, ifc_parser, qto_calculator)
|
ifc_exporter = export_ifc.IfcExporter(ifc_export_settings, ifc_parser, qto_calculator)
|
||||||
ifc_exporter.export()
|
ifc_exporter.export()
|
||||||
ifc_export_settings.logger.info('Export finished in {:.2f} seconds'.format(time.time() - start))
|
ifc_export_settings.logger.info('Export finished in {:.2f} seconds'.format(time.time() - start))
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
@@ -323,6 +322,32 @@ class RemovePset(bpy.types.Operator):
|
|||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
|
class AddOverridePset(bpy.types.Operator):
|
||||||
|
bl_idname = 'bim.add_override_pset'
|
||||||
|
bl_label = 'Add Override Pset'
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
pset_name = bpy.context.active_object.BIMObjectProperties.override_pset_name
|
||||||
|
if pset_name not in schema.ifc.psets:
|
||||||
|
return {'FINISHED'}
|
||||||
|
pset = bpy.context.active_object.BIMObjectProperties.override_psets.add()
|
||||||
|
pset.name = pset_name
|
||||||
|
for prop_name in schema.ifc.psets[pset_name]['HasPropertyTemplates'].keys():
|
||||||
|
prop = pset.properties.add()
|
||||||
|
prop.name = prop_name
|
||||||
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
|
class RemoveOverridePset(bpy.types.Operator):
|
||||||
|
bl_idname = 'bim.remove_override_pset'
|
||||||
|
bl_label = 'Remove Override Pset'
|
||||||
|
pset_index: bpy.props.IntProperty()
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
bpy.context.active_object.BIMObjectProperties.override_psets.remove(self.pset_index)
|
||||||
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
class AddMaterialPset(bpy.types.Operator):
|
class AddMaterialPset(bpy.types.Operator):
|
||||||
bl_idname = 'bim.add_material_pset'
|
bl_idname = 'bim.add_material_pset'
|
||||||
bl_label = 'Add Material Pset'
|
bl_label = 'Add Material Pset'
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import os
|
|||||||
import csv
|
import csv
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from . import export_ifc
|
from . import export_ifc
|
||||||
from .schema import IfcSchema
|
from . import schema
|
||||||
import bpy
|
import bpy
|
||||||
from bpy.types import PropertyGroup
|
from bpy.types import PropertyGroup
|
||||||
from bpy.app.handlers import persistent
|
from bpy.app.handlers import persistent
|
||||||
@@ -18,8 +18,6 @@ from bpy.props import (
|
|||||||
|
|
||||||
cwd = os.path.dirname(os.path.realpath(__file__))
|
cwd = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
|
||||||
ifc_schema = IfcSchema()
|
|
||||||
|
|
||||||
diagram_scales_enum = []
|
diagram_scales_enum = []
|
||||||
products_enum = []
|
products_enum = []
|
||||||
profiledef_enum = []
|
profiledef_enum = []
|
||||||
@@ -53,7 +51,7 @@ def setDefaultProperties(scene):
|
|||||||
def getIfcPredefinedTypes(self, context):
|
def getIfcPredefinedTypes(self, context):
|
||||||
global types_enum
|
global types_enum
|
||||||
if len(types_enum) < 1:
|
if len(types_enum) < 1:
|
||||||
for name, data in ifc_schema.elements.items():
|
for name, data in schema.ifc.elements.items():
|
||||||
if name != self.ifc_class.strip():
|
if name != self.ifc_class.strip():
|
||||||
continue
|
continue
|
||||||
for attribute in data['attributes']:
|
for attribute in data['attributes']:
|
||||||
@@ -106,14 +104,14 @@ def getIfcProducts(self, context):
|
|||||||
def getIfcClasses(self, context):
|
def getIfcClasses(self, context):
|
||||||
global classes_enum
|
global classes_enum
|
||||||
if len(classes_enum) < 1:
|
if len(classes_enum) < 1:
|
||||||
classes_enum.extend([(e, e, '') for e in getattr(ifc_schema, self.ifc_product)])
|
classes_enum.extend([(e, e, '') for e in getattr(schema.ifc, self.ifc_product)])
|
||||||
return classes_enum
|
return classes_enum
|
||||||
|
|
||||||
|
|
||||||
def getProfileDef(self, context):
|
def getProfileDef(self, context):
|
||||||
global profiledef_enum
|
global profiledef_enum
|
||||||
if len(profiledef_enum) < 1:
|
if len(profiledef_enum) < 1:
|
||||||
profiledef_enum.extend([(e, e, '') for e in getattr(ifc_schema, 'IfcParameterizedProfileDef')])
|
profiledef_enum.extend([(e, e, '') for e in getattr(schema.ifc, 'IfcParameterizedProfileDef')])
|
||||||
return profiledef_enum
|
return profiledef_enum
|
||||||
|
|
||||||
|
|
||||||
@@ -206,9 +204,9 @@ def getApplicableAttributes(self, context):
|
|||||||
global attributes_enum
|
global attributes_enum
|
||||||
attributes_enum.clear()
|
attributes_enum.clear()
|
||||||
if '/' in context.active_object.name \
|
if '/' in context.active_object.name \
|
||||||
and context.active_object.name.split('/')[0] in ifc_schema.elements:
|
and context.active_object.name.split('/')[0] in schema.ifc.elements:
|
||||||
attributes_enum.extend([(a['name'], a['name'], '') for a in
|
attributes_enum.extend([(a['name'], a['name'], '') for a in
|
||||||
ifc_schema.elements[context.active_object.name.split('/')[0]]['attributes']
|
schema.ifc.elements[context.active_object.name.split('/')[0]]['attributes']
|
||||||
if self.attributes.find(a['name']) == -1])
|
if self.attributes.find(a['name']) == -1])
|
||||||
return attributes_enum
|
return attributes_enum
|
||||||
|
|
||||||
@@ -217,12 +215,12 @@ def getApplicableMaterialAttributes(self, context):
|
|||||||
global materialattributes_enum
|
global materialattributes_enum
|
||||||
materialattributes_enum.clear()
|
materialattributes_enum.clear()
|
||||||
if '/' in context.active_object.name \
|
if '/' in context.active_object.name \
|
||||||
and context.active_object.name.split('/')[0] in ifc_schema.elements:
|
and context.active_object.name.split('/')[0] in schema.ifc.elements:
|
||||||
material_type = context.active_object.BIMObjectProperties.material_type
|
material_type = context.active_object.BIMObjectProperties.material_type
|
||||||
if material_type[-3:] == 'Set':
|
if material_type[-3:] == 'Set':
|
||||||
material_type = material_type[0:-3]
|
material_type = material_type[0:-3]
|
||||||
materialattributes_enum.extend([(a['name'], a['name'], '') for a in
|
materialattributes_enum.extend([(a['name'], a['name'], '') for a in
|
||||||
ifc_schema.IfcMaterialDefinition[material_type]['attributes']
|
schema.ifc.IfcMaterialDefinition[material_type]['attributes']
|
||||||
if self.attributes.find(a['name']) == -1])
|
if self.attributes.find(a['name']) == -1])
|
||||||
return materialattributes_enum
|
return materialattributes_enum
|
||||||
|
|
||||||
@@ -230,7 +228,7 @@ def getApplicableMaterialAttributes(self, context):
|
|||||||
def refreshProfileAttributes(self, context):
|
def refreshProfileAttributes(self, context):
|
||||||
while len(context.active_object.active_material.BIMMaterialProperties.profile_attributes) > 0:
|
while len(context.active_object.active_material.BIMMaterialProperties.profile_attributes) > 0:
|
||||||
context.active_object.active_material.BIMMaterialProperties.profile_attributes.remove(0)
|
context.active_object.active_material.BIMMaterialProperties.profile_attributes.remove(0)
|
||||||
for attribute in ifc_schema.IfcParameterizedProfileDef[self.profile_def]['attributes']:
|
for attribute in schema.ifc.IfcParameterizedProfileDef[self.profile_def]['attributes']:
|
||||||
profile_attribute = context.active_object.active_material.BIMMaterialProperties.profile_attributes.add()
|
profile_attribute = context.active_object.active_material.BIMMaterialProperties.profile_attributes.add()
|
||||||
profile_attribute.name = attribute['name']
|
profile_attribute.name = attribute['name']
|
||||||
|
|
||||||
@@ -384,6 +382,7 @@ class Attribute(PropertyGroup):
|
|||||||
class Pset(PropertyGroup):
|
class Pset(PropertyGroup):
|
||||||
name: StringProperty(name="Name")
|
name: StringProperty(name="Name")
|
||||||
file: StringProperty(name="File")
|
file: StringProperty(name="File")
|
||||||
|
properties: CollectionProperty(name="Properties", type=Attribute)
|
||||||
|
|
||||||
class Document(PropertyGroup):
|
class Document(PropertyGroup):
|
||||||
file: StringProperty(name="File")
|
file: StringProperty(name="File")
|
||||||
@@ -406,6 +405,8 @@ class BIMObjectProperties(PropertyGroup):
|
|||||||
applicable_documents: EnumProperty(items=getApplicableDocuments, name="Available Documents")
|
applicable_documents: EnumProperty(items=getApplicableDocuments, name="Available Documents")
|
||||||
classifications: CollectionProperty(name="Classifications", type=Classification)
|
classifications: CollectionProperty(name="Classifications", type=Classification)
|
||||||
material_type: EnumProperty(items=getMaterialTypes, name="Material Type")
|
material_type: EnumProperty(items=getMaterialTypes, name="Material Type")
|
||||||
|
override_psets: CollectionProperty(name="Override Psets", type=Pset)
|
||||||
|
override_pset_name: StringProperty(name="Override Pset Name")
|
||||||
|
|
||||||
|
|
||||||
class BIMMaterialProperties(PropertyGroup):
|
class BIMMaterialProperties(PropertyGroup):
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
cwd = os.path.dirname(os.path.realpath(__file__))
|
cwd = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
|
||||||
@@ -15,7 +16,10 @@ class IfcSchema():
|
|||||||
'IfcParameterizedProfileDef'
|
'IfcParameterizedProfileDef'
|
||||||
]
|
]
|
||||||
self.elements = {}
|
self.elements = {}
|
||||||
self.property_file = ifcopenshell.open(os.path.join(self.schema_dir, 'IFC4_ADD2.ifc'))
|
self.property_files = []
|
||||||
|
property_paths = Path(self.schema_dir).glob('Pset_*.ifc')
|
||||||
|
for path in property_paths:
|
||||||
|
self.property_files.append(ifcopenshell.open(path))
|
||||||
self.psets = {}
|
self.psets = {}
|
||||||
self.qtos = {}
|
self.qtos = {}
|
||||||
self.load()
|
self.load()
|
||||||
@@ -29,10 +33,13 @@ class IfcSchema():
|
|||||||
with open(os.path.join(self.schema_dir, 'ifc_types_IFC4.json')) as f:
|
with open(os.path.join(self.schema_dir, 'ifc_types_IFC4.json')) as f:
|
||||||
self.type_map = json.load(f)
|
self.type_map = json.load(f)
|
||||||
|
|
||||||
for property in self.property_file.by_type('IfcPropertySetTemplate'):
|
for property_file in self.property_files:
|
||||||
if property.Name[0:4] == 'Qto_':
|
for property in property_file.by_type('IfcPropertySetTemplate'):
|
||||||
# self.qtos.append({ })
|
if property.Name[0:4] == 'Qto_':
|
||||||
pass
|
# self.qtos.append({ })
|
||||||
else:
|
pass
|
||||||
self.psets[property.Name] = {
|
else:
|
||||||
'HasPropertyTemplates': {p.Name: p for p in property.HasPropertyTemplates}}
|
self.psets[property.Name] = {
|
||||||
|
'HasPropertyTemplates': {p.Name: p for p in property.HasPropertyTemplates}}
|
||||||
|
|
||||||
|
ifc = IfcSchema()
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
ISO-10303-21;
|
||||||
|
HEADER;
|
||||||
|
FILE_DESCRIPTION((),'2;1');
|
||||||
|
FILE_NAME('Pset_Custom.ifc','2020-01-01T00:00:00',(),(),'Sample','Sample',$);
|
||||||
|
FILE_SCHEMA(('IFC4'));
|
||||||
|
ENDSEC;
|
||||||
|
|
||||||
|
DATA;
|
||||||
|
#1= IFCPROPERTYSETTEMPLATE('05N2Dhepb9ouTCSmWBh22D',$,'Custom_Pset','An example custom pset.',.PSET_TYPEDRIVENOVERRIDE.,'IfcObject',(#2,#3));
|
||||||
|
#2= IFCSIMPLEPROPERTYTEMPLATE('37EpTDq4v96gTZh196BBXQ',$,'NumericProperty','An example numeric property',.P_SINGLEVALUE.,'IfcCountMeasure','',$,$,$,$,.READWRITE.);
|
||||||
|
#3= IFCSIMPLEPROPERTYTEMPLATE('22H7CzDvz1XfVHKkGWoYUK',$,'StringProperty','An example string property',.P_SINGLEVALUE.,'IfcLabel','',$,$,$,$,.READWRITE.);
|
||||||
|
ENDSEC;
|
||||||
|
|
||||||
|
END-ISO-10303-21;
|
||||||
@@ -54,6 +54,19 @@ class BIM_PT_object(Panel):
|
|||||||
row = layout.row()
|
row = layout.row()
|
||||||
row.prop(props, 'psets')
|
row.prop(props, 'psets')
|
||||||
|
|
||||||
|
row = layout.row(align=True)
|
||||||
|
row.prop(props, 'override_pset_name', text='')
|
||||||
|
row.operator('bim.add_override_pset')
|
||||||
|
|
||||||
|
for index, pset in enumerate(props.override_psets):
|
||||||
|
row = layout.row(align=True)
|
||||||
|
row.prop(pset, 'name', text='')
|
||||||
|
row.operator('bim.remove_override_pset', icon='X', text='').pset_index = index
|
||||||
|
for prop in pset.properties:
|
||||||
|
row = layout.row(align=True)
|
||||||
|
row.prop(prop, 'name', text='')
|
||||||
|
row.prop(prop, 'string_value', text='')
|
||||||
|
|
||||||
layout.label(text="Documents:")
|
layout.label(text="Documents:")
|
||||||
row = layout.row(align=True)
|
row = layout.row(align=True)
|
||||||
row.prop(props, 'applicable_documents', text='')
|
row.prop(props, 'applicable_documents', text='')
|
||||||
|
|||||||
Reference in New Issue
Block a user