mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-10-02 21:12:07 +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):
|
def draw_attributes(props, layout, copy_operator=None):
|
||||||
for attribute in props:
|
for attribute in props:
|
||||||
row = layout.row(align=True)
|
row = layout.row(align=True)
|
||||||
draw_attribute(attribute, row)
|
draw_attribute(attribute, row, copy_operator)
|
||||||
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})
|
|
||||||
|
|
||||||
|
|
||||||
def draw_attribute(attribute, layout):
|
def draw_attribute(attribute, layout, copy_operator=None):
|
||||||
if not attribute.get_value_attr():
|
value_name = attribute.get_value_name()
|
||||||
|
if not value_name:
|
||||||
layout.label(text=attribute.name)
|
layout.label(text=attribute.name)
|
||||||
else:
|
return
|
||||||
layout.prop(
|
layout.prop(
|
||||||
attribute,
|
attribute,
|
||||||
attribute.get_value_attr(),
|
value_name,
|
||||||
text=attribute.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):
|
def import_attributes(ifc_class, props, data, callback=None):
|
||||||
@@ -66,6 +66,6 @@ def export_attributes(props, callback=None):
|
|||||||
for prop in props:
|
for prop in props:
|
||||||
is_handled_by_callback = callback(attributes, prop) if callback else False
|
is_handled_by_callback = callback(attributes, prop) if callback else False
|
||||||
if is_handled_by_callback:
|
if is_handled_by_callback:
|
||||||
continue # Our job is done
|
continue # Our job is done
|
||||||
attributes[prop.name] = prop.get_value()
|
attributes[prop.name] = prop.get_value()
|
||||||
return attributes
|
return attributes
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import ifcopenshell
|
|||||||
import ifcopenshell.util.unit
|
import ifcopenshell.util.unit
|
||||||
import ifcopenshell.util.attribute
|
import ifcopenshell.util.attribute
|
||||||
import ifcopenshell.api
|
import ifcopenshell.api
|
||||||
|
import blenderbim.bim.helper
|
||||||
from blenderbim.bim.ifc import IfcStore
|
from blenderbim.bim.ifc import IfcStore
|
||||||
from ifcopenshell.api.georeference.data import Data
|
from ifcopenshell.api.georeference.data import Data
|
||||||
from math import radians, degrees, atan, tan, cos, sin
|
from math import radians, degrees, atan, tan, cos, sin
|
||||||
@@ -96,29 +97,13 @@ class EditGeoreferencing(bpy.types.Operator):
|
|||||||
self.file = IfcStore.get_file()
|
self.file = IfcStore.get_file()
|
||||||
props = context.scene.BIMGeoreferenceProperties
|
props = context.scene.BIMGeoreferenceProperties
|
||||||
|
|
||||||
projected_crs = {}
|
projected_crs = blenderbim.bim.helper.export_attributes(props.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()
|
|
||||||
|
|
||||||
map_unit = ""
|
map_unit = ""
|
||||||
if not props.is_map_unit_null:
|
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_unit = props.map_unit_si if props.map_unit_type == "IfcSIUnit" else props.map_unit_imperial
|
||||||
|
|
||||||
map_conversion = {}
|
map_conversion = blenderbim.bim.helper.export_attributes(props.map_conversion, self.export_attributes)
|
||||||
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)
|
|
||||||
|
|
||||||
true_north = None
|
true_north = None
|
||||||
if props.has_true_north:
|
if props.has_true_north:
|
||||||
@@ -141,6 +126,11 @@ class EditGeoreferencing(bpy.types.Operator):
|
|||||||
bpy.ops.bim.disable_editing_georeferencing()
|
bpy.ops.bim.disable_editing_georeferencing()
|
||||||
return {"FINISHED"}
|
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):
|
class SetBlenderGridNorth(bpy.types.Operator):
|
||||||
bl_idname = "bim.set_blender_grid_north"
|
bl_idname = "bim.set_blender_grid_north"
|
||||||
|
|||||||
@@ -655,7 +655,7 @@ class EditMaterialSetItem(bpy.types.Operator):
|
|||||||
props = obj.BIMObjectMaterialProperties
|
props = obj.BIMObjectMaterialProperties
|
||||||
product_data = Data.products[obj.BIMObjectProperties.ifc_definition_id]
|
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":
|
if product_data["type"] == "IfcMaterialConstituentSet":
|
||||||
ifcopenshell.api.run(
|
ifcopenshell.api.run(
|
||||||
@@ -680,7 +680,7 @@ class EditMaterialSetItem(bpy.types.Operator):
|
|||||||
)
|
)
|
||||||
Data.load_layers()
|
Data.load_layers()
|
||||||
elif product_data["type"] == "IfcMaterialProfileSet" or product_data["type"] == "IfcMaterialProfileSetUsage":
|
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(
|
ifcopenshell.api.run(
|
||||||
"material.edit_profile",
|
"material.edit_profile",
|
||||||
self.file,
|
self.file,
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
import os
|
import os
|
||||||
import bpy
|
import bpy
|
||||||
import json
|
import json
|
||||||
import ifcpatch
|
|
||||||
|
try:
|
||||||
|
import ifcpatch
|
||||||
|
except:
|
||||||
|
print("IfcPatch not available")
|
||||||
|
|
||||||
from .helper import extract_docs
|
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")
|
IfcStore.get_schema().declaration_by_name(prop_template.PrimaryMeasureType or "IfcLabel")
|
||||||
)
|
)
|
||||||
except:
|
except:
|
||||||
# TODO: Occurs if the data type is something that exists in IFC4 and not in IFC2X3. To fully fix
|
# TODO: Occurs if the data type is something that exists in
|
||||||
# this we need to generate the IFC2X3 pset template definitions.
|
# IFC4 and not in IFC2X3. To fully fix this we need to
|
||||||
|
# generate the IFC2X3 pset template definitions.
|
||||||
continue
|
continue
|
||||||
elif prop_template.TemplateType == "P_ENUMERATEDVALUE":
|
elif prop_template.TemplateType == "P_ENUMERATEDVALUE":
|
||||||
data_type = "enum"
|
data_type = "enum"
|
||||||
@@ -116,6 +117,7 @@ class EnablePsetEditing(bpy.types.Operator):
|
|||||||
new = self.props.properties.add()
|
new = self.props.properties.add()
|
||||||
new.name = prop_template.Name
|
new.name = prop_template.Name
|
||||||
new.is_null = data.get(prop_template.Name, None) is None
|
new.is_null = data.get(prop_template.Name, None) is None
|
||||||
|
new.is_optional = True
|
||||||
new.data_type = data_type
|
new.data_type = data_type
|
||||||
|
|
||||||
if data_type == "string":
|
if data_type == "string":
|
||||||
@@ -140,6 +142,7 @@ class EnablePsetEditing(bpy.types.Operator):
|
|||||||
new.set_value(value)
|
new.set_value(value)
|
||||||
new.name = prop["Name"]
|
new.name = prop["Name"]
|
||||||
new.is_null = value is None
|
new.is_null = value is None
|
||||||
|
new.is_optional = True
|
||||||
new.set_value(new.get_value_default() if new.is_null else value)
|
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):
|
def draw_psetqto_editable_ui(box, props, prop):
|
||||||
row = box.row()
|
row = box.row(align=True)
|
||||||
draw_attribute(prop, row)
|
draw_attribute(prop, row)
|
||||||
if (
|
if (
|
||||||
"length" in prop.name.lower()
|
"length" in prop.name.lower()
|
||||||
|
|||||||
@@ -279,7 +279,7 @@ class EditStructuralAnalysisModel(bpy.types.Operator):
|
|||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
props = context.scene.BIMStructuralProperties
|
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()
|
self.file = IfcStore.get_file()
|
||||||
ifcopenshell.api.run(
|
ifcopenshell.api.run(
|
||||||
"structural.edit_structural_analysis_model",
|
"structural.edit_structural_analysis_model",
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ class StrProperty(PropertyGroup):
|
|||||||
|
|
||||||
|
|
||||||
def updateAttributeValue(self, context):
|
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
|
self.is_null = False
|
||||||
|
|
||||||
|
|
||||||
@@ -146,8 +146,8 @@ class Attribute(PropertyGroup):
|
|||||||
def get_value(self):
|
def get_value(self):
|
||||||
if self.is_null:
|
if self.is_null:
|
||||||
return None
|
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):
|
def get_value_default(self):
|
||||||
if self.data_type == "string":
|
if self.data_type == "string":
|
||||||
return ""
|
return ""
|
||||||
@@ -159,8 +159,8 @@ class Attribute(PropertyGroup):
|
|||||||
return False
|
return False
|
||||||
elif self.data_type == "enum":
|
elif self.data_type == "enum":
|
||||||
return "0"
|
return "0"
|
||||||
|
|
||||||
def get_value_attr(self):
|
def get_value_name(self):
|
||||||
if self.data_type == "string":
|
if self.data_type == "string":
|
||||||
return "string_value"
|
return "string_value"
|
||||||
elif self.data_type == "boolean":
|
elif self.data_type == "boolean":
|
||||||
@@ -171,21 +171,21 @@ class Attribute(PropertyGroup):
|
|||||||
return "float_value"
|
return "float_value"
|
||||||
elif self.data_type == "enum":
|
elif self.data_type == "enum":
|
||||||
return "enum_value"
|
return "enum_value"
|
||||||
|
|
||||||
def set_value(self, value):
|
def set_value(self, value):
|
||||||
if isinstance(value, str):
|
if isinstance(value, str):
|
||||||
self.data_type = "string"
|
self.data_type = "string"
|
||||||
elif isinstance(value, float):
|
elif isinstance(value, float):
|
||||||
self.data_type = "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"
|
self.data_type = "boolean"
|
||||||
elif isinstance(value, int):
|
elif isinstance(value, int):
|
||||||
self.data_type = "integer"
|
self.data_type = "integer"
|
||||||
else:
|
else:
|
||||||
self.data_type = "string"
|
self.data_type = "string"
|
||||||
value = str(value)
|
value = str(value)
|
||||||
setattr(self, self.get_value_attr(), value)
|
setattr(self, self.get_value_name(), value)
|
||||||
|
|
||||||
|
|
||||||
class BIMProperties(PropertyGroup):
|
class BIMProperties(PropertyGroup):
|
||||||
schema_dir: StringProperty(
|
schema_dir: StringProperty(
|
||||||
|
|||||||
Reference in New Issue
Block a user