mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-14 03:14:23 +00:00
Minor fix & refactor, run black, fix pset optionality. See #1655.
This commit is contained in:
@@ -11,24 +11,24 @@ from blenderbim.bim.ifc import IfcStore
|
||||
def draw_attributes(props, layout, copy_operator=None):
|
||||
for attribute in props:
|
||||
row = layout.row(align=True)
|
||||
draw_attribute(attribute, row)
|
||||
value = attribute.get_value()
|
||||
if attribute.is_optional:
|
||||
row.prop(attribute, "is_null", icon="RADIOBUT_OFF" if attribute.is_null else "RADIOBUT_ON", text="")
|
||||
if copy_operator:
|
||||
op = row.operator(f"{copy_operator}", text="", icon="COPYDOWN")
|
||||
op.data = json.dumps({"name": attribute.name, "value": value, "is_null": attribute.is_null})
|
||||
draw_attribute(attribute, row, copy_operator)
|
||||
|
||||
|
||||
def draw_attribute(attribute, layout):
|
||||
if not attribute.get_value_attr():
|
||||
def draw_attribute(attribute, layout, copy_operator=None):
|
||||
value_name = attribute.get_value_name()
|
||||
if not value_name:
|
||||
layout.label(text=attribute.name)
|
||||
else:
|
||||
layout.prop(
|
||||
attribute,
|
||||
attribute.get_value_attr(),
|
||||
text=attribute.name,
|
||||
)
|
||||
return
|
||||
layout.prop(
|
||||
attribute,
|
||||
value_name,
|
||||
text=attribute.name,
|
||||
)
|
||||
if attribute.is_optional:
|
||||
layout.prop(attribute, "is_null", icon="RADIOBUT_OFF" if attribute.is_null else "RADIOBUT_ON", text="")
|
||||
if copy_operator:
|
||||
op = layout.operator(f"{copy_operator}", text="", icon="COPYDOWN")
|
||||
op.data = json.dumps({"name": attribute.name, "value": attribute.get_value(), "is_null": attribute.is_null})
|
||||
|
||||
|
||||
def import_attributes(ifc_class, props, data, callback=None):
|
||||
@@ -66,6 +66,6 @@ def export_attributes(props, callback=None):
|
||||
for prop in props:
|
||||
is_handled_by_callback = callback(attributes, prop) if callback else False
|
||||
if is_handled_by_callback:
|
||||
continue # Our job is done
|
||||
continue # Our job is done
|
||||
attributes[prop.name] = prop.get_value()
|
||||
return attributes
|
||||
|
||||
@@ -4,6 +4,7 @@ import ifcopenshell
|
||||
import ifcopenshell.util.unit
|
||||
import ifcopenshell.util.attribute
|
||||
import ifcopenshell.api
|
||||
import blenderbim.bim.helper
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
from ifcopenshell.api.georeference.data import Data
|
||||
from math import radians, degrees, atan, tan, cos, sin
|
||||
@@ -96,29 +97,13 @@ class EditGeoreferencing(bpy.types.Operator):
|
||||
self.file = IfcStore.get_file()
|
||||
props = context.scene.BIMGeoreferenceProperties
|
||||
|
||||
projected_crs = {}
|
||||
for attribute in IfcStore.get_schema().declaration_by_name("IfcProjectedCRS").all_attributes():
|
||||
data_type = ifcopenshell.util.attribute.get_primitive_type(attribute)
|
||||
if data_type == "entity":
|
||||
continue
|
||||
blender_attribute = props.projected_crs.get(attribute.name())
|
||||
projected_crs[attribute.name()] = blender_attribute.get_value()
|
||||
projected_crs = blenderbim.bim.helper.export_attributes(props.projected_crs)
|
||||
|
||||
map_unit = ""
|
||||
if not props.is_map_unit_null:
|
||||
map_unit = props.map_unit_si if props.map_unit_type == "IfcSIUnit" else props.map_unit_imperial
|
||||
|
||||
map_conversion = {}
|
||||
for attribute in IfcStore.get_schema().declaration_by_name("IfcMapConversion").all_attributes():
|
||||
data_type = ifcopenshell.util.attribute.get_primitive_type(attribute)
|
||||
if data_type == "entity" or data_type == "select":
|
||||
continue
|
||||
blender_attribute = props.map_conversion.get(attribute.name())
|
||||
if blender_attribute.is_null:
|
||||
map_conversion[attribute.name()] = None
|
||||
elif blender_attribute.data_type == "string":
|
||||
# We store our floats as string to prevent single precision data loss
|
||||
map_conversion[attribute.name()] = float(blender_attribute.string_value)
|
||||
map_conversion = blenderbim.bim.helper.export_attributes(props.map_conversion, self.export_attributes)
|
||||
|
||||
true_north = None
|
||||
if props.has_true_north:
|
||||
@@ -141,6 +126,11 @@ class EditGeoreferencing(bpy.types.Operator):
|
||||
bpy.ops.bim.disable_editing_georeferencing()
|
||||
return {"FINISHED"}
|
||||
|
||||
def export_attributes(self, attributes, prop):
|
||||
if not prop.is_null and prop.data_type == "string":
|
||||
attributes[prop.name] = float(prop.string_value)
|
||||
return True
|
||||
|
||||
|
||||
class SetBlenderGridNorth(bpy.types.Operator):
|
||||
bl_idname = "bim.set_blender_grid_north"
|
||||
|
||||
@@ -655,7 +655,7 @@ class EditMaterialSetItem(bpy.types.Operator):
|
||||
props = obj.BIMObjectMaterialProperties
|
||||
product_data = Data.products[obj.BIMObjectProperties.ifc_definition_id]
|
||||
|
||||
attributes = {attribute.name: attribute.get_value() for attribute in props.material_set_item_attributes}
|
||||
attributes = blenderbim.bim.helper.export_attributes(props.material_set_item_attributes)
|
||||
|
||||
if product_data["type"] == "IfcMaterialConstituentSet":
|
||||
ifcopenshell.api.run(
|
||||
@@ -680,7 +680,7 @@ class EditMaterialSetItem(bpy.types.Operator):
|
||||
)
|
||||
Data.load_layers()
|
||||
elif product_data["type"] == "IfcMaterialProfileSet" or product_data["type"] == "IfcMaterialProfileSetUsage":
|
||||
profile_attributes = {attr.name: attr.get_value() for attr in props.material_set_item_profile_attributes}
|
||||
profile_attributes = blenderbim.bim.helper.export_attributes(props.material_set_item_profile_attributes)
|
||||
ifcopenshell.api.run(
|
||||
"material.edit_profile",
|
||||
self.file,
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
import os
|
||||
import bpy
|
||||
import json
|
||||
import ifcpatch
|
||||
|
||||
try:
|
||||
import ifcpatch
|
||||
except:
|
||||
print("IfcPatch not available")
|
||||
|
||||
from .helper import extract_docs
|
||||
|
||||
|
||||
|
||||
@@ -100,8 +100,9 @@ class EnablePsetEditing(bpy.types.Operator):
|
||||
IfcStore.get_schema().declaration_by_name(prop_template.PrimaryMeasureType or "IfcLabel")
|
||||
)
|
||||
except:
|
||||
# TODO: Occurs if the data type is something that exists in IFC4 and not in IFC2X3. To fully fix
|
||||
# this we need to generate the IFC2X3 pset template definitions.
|
||||
# TODO: Occurs if the data type is something that exists in
|
||||
# IFC4 and not in IFC2X3. To fully fix this we need to
|
||||
# generate the IFC2X3 pset template definitions.
|
||||
continue
|
||||
elif prop_template.TemplateType == "P_ENUMERATEDVALUE":
|
||||
data_type = "enum"
|
||||
@@ -116,6 +117,7 @@ class EnablePsetEditing(bpy.types.Operator):
|
||||
new = self.props.properties.add()
|
||||
new.name = prop_template.Name
|
||||
new.is_null = data.get(prop_template.Name, None) is None
|
||||
new.is_optional = True
|
||||
new.data_type = data_type
|
||||
|
||||
if data_type == "string":
|
||||
@@ -140,6 +142,7 @@ class EnablePsetEditing(bpy.types.Operator):
|
||||
new.set_value(value)
|
||||
new.name = prop["Name"]
|
||||
new.is_null = value is None
|
||||
new.is_optional = True
|
||||
new.set_value(new.get_value_default() if new.is_null else value)
|
||||
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ def draw_psetqto_ui(context, pset_id, pset, props, layout, obj_type):
|
||||
|
||||
|
||||
def draw_psetqto_editable_ui(box, props, prop):
|
||||
row = box.row()
|
||||
row = box.row(align=True)
|
||||
draw_attribute(prop, row)
|
||||
if (
|
||||
"length" in prop.name.lower()
|
||||
|
||||
@@ -279,7 +279,7 @@ class EditStructuralAnalysisModel(bpy.types.Operator):
|
||||
|
||||
def _execute(self, context):
|
||||
props = context.scene.BIMStructuralProperties
|
||||
attributes = {attribute.name: attribute.get_value() for attribute in props.structural_analysis_model_attributes}
|
||||
attributes = blenderbim.bim.helper.export_attributes(props.structural_analysis_model_attributes)
|
||||
self.file = IfcStore.get_file()
|
||||
ifcopenshell.api.run(
|
||||
"structural.edit_structural_analysis_model",
|
||||
|
||||
@@ -127,7 +127,7 @@ class StrProperty(PropertyGroup):
|
||||
|
||||
|
||||
def updateAttributeValue(self, context):
|
||||
if getattr(self, str(self.get_value_attr()), None): # Do not use get_value since it returns None if is_null is True
|
||||
if getattr(self, str(self.get_value_name()), None): # Do not use get_value since it returns None if is_null is True
|
||||
self.is_null = False
|
||||
|
||||
|
||||
@@ -146,8 +146,8 @@ class Attribute(PropertyGroup):
|
||||
def get_value(self):
|
||||
if self.is_null:
|
||||
return None
|
||||
return getattr(self, str(self.get_value_attr()), None)
|
||||
|
||||
return getattr(self, str(self.get_value_name()), None)
|
||||
|
||||
def get_value_default(self):
|
||||
if self.data_type == "string":
|
||||
return ""
|
||||
@@ -159,8 +159,8 @@ class Attribute(PropertyGroup):
|
||||
return False
|
||||
elif self.data_type == "enum":
|
||||
return "0"
|
||||
|
||||
def get_value_attr(self):
|
||||
|
||||
def get_value_name(self):
|
||||
if self.data_type == "string":
|
||||
return "string_value"
|
||||
elif self.data_type == "boolean":
|
||||
@@ -171,21 +171,21 @@ class Attribute(PropertyGroup):
|
||||
return "float_value"
|
||||
elif self.data_type == "enum":
|
||||
return "enum_value"
|
||||
|
||||
|
||||
def set_value(self, value):
|
||||
if isinstance(value, str):
|
||||
self.data_type = "string"
|
||||
elif isinstance(value, float):
|
||||
self.data_type = "float"
|
||||
elif isinstance(value, bool): # Make sure this is evaluated BEFORE integer
|
||||
elif isinstance(value, bool): # Make sure this is evaluated BEFORE integer
|
||||
self.data_type = "boolean"
|
||||
elif isinstance(value, int):
|
||||
self.data_type = "integer"
|
||||
else:
|
||||
self.data_type = "string"
|
||||
value = str(value)
|
||||
setattr(self, self.get_value_attr(), value)
|
||||
|
||||
setattr(self, self.get_value_name(), value)
|
||||
|
||||
|
||||
class BIMProperties(PropertyGroup):
|
||||
schema_dir: StringProperty(
|
||||
|
||||
Reference in New Issue
Block a user