mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 09:21:46 +00:00
Fix unfinished time/date/duration handling in edit task time, work plan, work schedule, and finally refactor attribute i/o like I promised
This commit is contained in:
@@ -1,153 +1,62 @@
|
||||
import bpy
|
||||
import json
|
||||
import math
|
||||
import ifcopenshell
|
||||
import ifcopenshell.util.attribute
|
||||
from mathutils import geometry
|
||||
from mathutils import Vector
|
||||
import bpy
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
|
||||
|
||||
# TODO: Deprecate this in favour of ifcopenshell.util.unit
|
||||
def import_attributes(ifc_class, props, data, callback=None):
|
||||
for attribute in IfcStore.get_schema().declaration_by_name(ifc_class).all_attributes():
|
||||
data_type = ifcopenshell.util.attribute.get_primitive_type(attribute)
|
||||
if data_type == "entity":
|
||||
continue
|
||||
new = props.add()
|
||||
new.name = attribute.name()
|
||||
new.is_null = data[attribute.name()] is None
|
||||
new.is_optional = attribute.optional()
|
||||
new.data_type = data_type
|
||||
is_handled_by_callback = callback(attribute.name(), new, data) if callback else False
|
||||
if is_handled_by_callback:
|
||||
pass # Our job is done
|
||||
elif data_type == "string":
|
||||
new.string_value = "" if new.is_null else data[attribute.name()]
|
||||
elif data_type == "boolean":
|
||||
new.bool_value = False if new.is_null else data[attribute.name()]
|
||||
elif data_type == "integer":
|
||||
new.int_value = 0 if new.is_null else data[attribute.name()]
|
||||
elif data_type == "float":
|
||||
new.float_value = 0.0 if new.is_null else data[attribute.name()]
|
||||
elif data_type == "enum":
|
||||
new.enum_items = json.dumps(ifcopenshell.util.attribute.get_enum_items(attribute))
|
||||
if data[attribute.name()]:
|
||||
new.enum_value = data[attribute.name()]
|
||||
|
||||
|
||||
class SIUnitHelper:
|
||||
prefixes = {
|
||||
"EXA": 1e18,
|
||||
"PETA": 1e15,
|
||||
"TERA": 1e12,
|
||||
"GIGA": 1e9,
|
||||
"MEGA": 1e6,
|
||||
"KILO": 1e3,
|
||||
"HECTO": 1e2,
|
||||
"DECA": 1e1,
|
||||
"DECI": 1e-1,
|
||||
"CENTI": 1e-2,
|
||||
"MILLI": 1e-3,
|
||||
"MICRO": 1e-6,
|
||||
"NANO": 1e-9,
|
||||
"PICO": 1e-12,
|
||||
"FEMTO": 1e-15,
|
||||
"ATTO": 1e-18,
|
||||
}
|
||||
unit_names = [
|
||||
"AMPERE",
|
||||
"BECQUEREL",
|
||||
"CANDELA",
|
||||
"COULOMB",
|
||||
"CUBIC_METRE",
|
||||
"DEGREE CELSIUS",
|
||||
"FARAD",
|
||||
"GRAM",
|
||||
"GRAY",
|
||||
"HENRY",
|
||||
"HERTZ",
|
||||
"JOULE",
|
||||
"KELVIN",
|
||||
"LUMEN",
|
||||
"LUX",
|
||||
"MOLE",
|
||||
"NEWTON",
|
||||
"OHM",
|
||||
"PASCAL",
|
||||
"RADIAN",
|
||||
"SECOND",
|
||||
"SIEMENS",
|
||||
"SIEVERT",
|
||||
"SQUARE METRE",
|
||||
"METRE",
|
||||
"STERADIAN",
|
||||
"TESLA",
|
||||
"VOLT",
|
||||
"WATT",
|
||||
"WEBER",
|
||||
]
|
||||
si_conversions = {
|
||||
"inch": 0.0254,
|
||||
"foot": 0.3048,
|
||||
"yard": 0.914,
|
||||
"mile": 1609,
|
||||
"square inch": 0.0006452,
|
||||
"square foot": 0.09290304,
|
||||
"square yard": 0.83612736,
|
||||
"acre": 4046.86,
|
||||
"square mile": 2588881,
|
||||
"cubic inch": 0.00001639,
|
||||
"cubic foot": 0.02831684671168849,
|
||||
"cubic yard": 0.7636,
|
||||
"litre": 0.001,
|
||||
"fluid ounce UK": 0.0000284130625,
|
||||
"fluid ounce US": 0.00002957353,
|
||||
"pint UK": 0.000568,
|
||||
"pint US": 0.000473,
|
||||
"gallon UK": 0.004546,
|
||||
"gallon US": 0.003785,
|
||||
"degree": math.pi / 180,
|
||||
"ounce": 0.02835,
|
||||
"pound": 0.454,
|
||||
"ton UK": 1016.0469088,
|
||||
"ton US": 907.18474,
|
||||
"lbf": 4.4482216153,
|
||||
"kip": 4448.2216153,
|
||||
"psi": 6894.7572932,
|
||||
"ksi": 6894757.2932,
|
||||
"minute": 60,
|
||||
"hour": 3600,
|
||||
"day": 86400,
|
||||
"btu": 1055.056,
|
||||
}
|
||||
def export_attributes(props, callback=None):
|
||||
attributes = {}
|
||||
for attribute in props:
|
||||
is_handled_by_callback = callback(attributes, attribute) if callback else False
|
||||
if attribute.is_null:
|
||||
attributes[attribute.name] = None
|
||||
elif is_handled_by_callback:
|
||||
pass # Our job is done
|
||||
elif attribute.data_type == "string":
|
||||
attributes[attribute.name] = attribute.string_value
|
||||
elif attribute.data_type == "boolean":
|
||||
attributes[attribute.name] = attribute.bool_value
|
||||
elif attribute.data_type == "integer":
|
||||
attributes[attribute.name] = attribute.int_value
|
||||
elif attribute.data_type == "float":
|
||||
attributes[attribute.name] = attribute.float_value
|
||||
elif attribute.data_type == "enum":
|
||||
attributes[attribute.name] = attribute.enum_value
|
||||
return attributes
|
||||
|
||||
@staticmethod
|
||||
def get_prefix(text):
|
||||
for prefix in SIUnitHelper.prefixes.keys():
|
||||
if prefix in text.upper():
|
||||
return prefix
|
||||
|
||||
@staticmethod
|
||||
def get_prefix_multiplier(text):
|
||||
if not text:
|
||||
return 1
|
||||
prefix = SIUnitHelper.get_prefix(text)
|
||||
if prefix:
|
||||
return SIUnitHelper.prefixes[prefix]
|
||||
return 1
|
||||
|
||||
@staticmethod
|
||||
def get_unit_name(text):
|
||||
for name in SIUnitHelper.unit_names:
|
||||
if name in text.upper().replace("METER", "METRE"):
|
||||
return name
|
||||
|
||||
@staticmethod
|
||||
def convert(value, from_prefix, from_unit, to_prefix, to_unit):
|
||||
"""Converts between length, area, and volume units
|
||||
|
||||
:param value: The numeric value you want to convert
|
||||
:type value: float
|
||||
:param from_prefix: A prefix from IfcSIPrefix. Can be None.
|
||||
:type from_prefix: string
|
||||
:param from_unit: IfcSIUnitName or IfcConversionBasedUnit.Name
|
||||
:type from_unit: string
|
||||
:param to_prefix: A prefix from IfcSIPrefix. Can be None.
|
||||
:type to_prefix: string
|
||||
:param to_unit: IfcSIUnitName or IfcConversionBasedUnit.Name
|
||||
:type to_unit: string
|
||||
"""
|
||||
if from_unit in SIUnitHelper.si_conversions:
|
||||
value *= SIUnitHelper.si_conversions[from_unit]
|
||||
elif from_prefix:
|
||||
value *= SIUnitHelper.get_prefix_multiplier(from_prefix)
|
||||
if "SQUARE" in from_unit:
|
||||
value *= SIUnitHelper.get_prefix_multiplier(from_prefix)
|
||||
elif "CUBIC" in from_unit:
|
||||
value *= SIUnitHelper.get_prefix_multiplier(from_prefix)
|
||||
value *= SIUnitHelper.get_prefix_multiplier(from_prefix)
|
||||
if to_unit in SIUnitHelper.si_conversions:
|
||||
return value * (1 / SIUnitHelper.si_conversions[to_unit])
|
||||
elif to_prefix:
|
||||
value *= 1 / SIUnitHelper.get_prefix_multiplier(to_prefix)
|
||||
if "SQUARE" in from_unit:
|
||||
value *= 1 / SIUnitHelper.get_prefix_multiplier(to_prefix)
|
||||
elif "CUBIC" in from_unit:
|
||||
value *= 1 / SIUnitHelper.get_prefix_multiplier(to_prefix)
|
||||
value *= 1 / SIUnitHelper.get_prefix_multiplier(to_prefix)
|
||||
return value
|
||||
# TODO: migrate the below helper functions into the drawing module, since it is specific to that module
|
||||
|
||||
|
||||
# This function stolen from https://github.com/kevancress/MeasureIt_ARCH/blob/dcf607ce0896aa2284463c6b4ae9cd023fc54cbe/measureit_arch_baseclass.py
|
||||
@@ -302,7 +211,7 @@ def parse_diagram_scale(camera):
|
||||
def get_project_collection(scene):
|
||||
"""Get main project collection"""
|
||||
|
||||
colls = [c for c in scene.collection.children if c.name.startswith('IfcProject')]
|
||||
colls = [c for c in scene.collection.children if c.name.startswith("IfcProject")]
|
||||
if len(colls) != 1:
|
||||
raise RuntimeError("project collection missing or not unique")
|
||||
return colls[0]
|
||||
@@ -315,7 +224,7 @@ def get_active_drawing(scene):
|
||||
return None, None
|
||||
try:
|
||||
drawing = props.drawings[props.active_drawing_index]
|
||||
return scene.collection.children['Views'].children[f"IfcGroup/{drawing.name}"], drawing.camera
|
||||
return scene.collection.children["Views"].children[f"IfcGroup/{drawing.name}"], drawing.camera
|
||||
except (KeyError, IndexError):
|
||||
raise RuntimeError("missing drawing collection")
|
||||
|
||||
@@ -333,8 +242,8 @@ def ortho_view_frame(camera, margin=0.015):
|
||||
"""
|
||||
aspect = camera.BIMCameraProperties.raster_y / camera.BIMCameraProperties.raster_x
|
||||
size = camera.ortho_scale
|
||||
hwidth = size * .5
|
||||
hheight = size * .5 * aspect
|
||||
hwidth = size * 0.5
|
||||
hheight = size * 0.5 * aspect
|
||||
scale = parse_diagram_scale(camera)
|
||||
xmarg = margin * scale
|
||||
ymarg = margin * scale * aspect
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import isodate
|
||||
from dateutil import parser
|
||||
from ifcopenshell.api.sequence.data import Data
|
||||
|
||||
|
||||
@@ -18,3 +20,19 @@ def derive_date(ifc_definition_id, attribute_name, date=None, is_earliest=False,
|
||||
if current_date and (date is None or current_date > date):
|
||||
date = current_date
|
||||
return date
|
||||
|
||||
|
||||
def parse_datetime(value):
|
||||
try:
|
||||
return parser.isoparse(value)
|
||||
except:
|
||||
try:
|
||||
return parser.parse(value, dayfirst=True, fuzzy=True)
|
||||
except:
|
||||
return None
|
||||
|
||||
def parse_duration(value):
|
||||
try:
|
||||
return isodate.parse_duration(value)
|
||||
except:
|
||||
return None
|
||||
|
||||
@@ -8,6 +8,7 @@ import pystache
|
||||
import webbrowser
|
||||
import ifcopenshell.api
|
||||
import ifcopenshell.util.date
|
||||
import blenderbim.bim.helper
|
||||
import blenderbim.bim.module.sequence.helper as helper
|
||||
from datetime import datetime
|
||||
from datetime import timedelta
|
||||
@@ -33,15 +34,7 @@ class EditWorkPlan(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
props = context.scene.BIMWorkPlanProperties
|
||||
attributes = {}
|
||||
for attribute in props.work_plan_attributes:
|
||||
if attribute.is_null:
|
||||
attributes[attribute.name] = None
|
||||
else:
|
||||
if attribute.data_type == "string":
|
||||
attributes[attribute.name] = attribute.string_value
|
||||
elif attribute.data_type == "enum":
|
||||
attributes[attribute.name] = attribute.enum_value
|
||||
attributes = blenderbim.bim.helper.export_attributes(props.work_plan_attributes, self.export_attributes)
|
||||
self.file = IfcStore.get_file()
|
||||
ifcopenshell.api.run(
|
||||
"sequence.edit_work_plan",
|
||||
@@ -52,6 +45,14 @@ class EditWorkPlan(bpy.types.Operator):
|
||||
bpy.ops.bim.disable_editing_work_plan()
|
||||
return {"FINISHED"}
|
||||
|
||||
def export_attributes(self, attributes, prop):
|
||||
if "Date" in prop.name or "Time" in prop.name:
|
||||
attributes[prop.name] = helper.parse_datetime(prop.string_value)
|
||||
return True
|
||||
elif prop.name == "Duration" or prop.name == "TotalFloat":
|
||||
attributes[prop.name] = helper.parse_duration(prop.string_value)
|
||||
return True
|
||||
|
||||
|
||||
class RemoveWorkPlan(bpy.types.Operator):
|
||||
bl_idname = "bim.remove_work_plan"
|
||||
@@ -77,27 +78,17 @@ class EnableEditingWorkPlan(bpy.types.Operator):
|
||||
|
||||
data = Data.work_plans[self.work_plan]
|
||||
|
||||
for attribute in IfcStore.get_schema().declaration_by_name("IfcWorkPlan").all_attributes():
|
||||
data_type = ifcopenshell.util.attribute.get_primitive_type(attribute)
|
||||
if data_type == "entity":
|
||||
continue
|
||||
new = props.work_plan_attributes.add()
|
||||
new.name = attribute.name()
|
||||
new.is_null = data[attribute.name()] is None
|
||||
new.is_optional = attribute.optional()
|
||||
new.data_type = data_type
|
||||
if attribute.name() in ["CreationDate", "StartTime", "FinishTime"]:
|
||||
new.string_value = "" if new.is_null else data[attribute.name()].isoformat()
|
||||
elif data_type == "string":
|
||||
new.string_value = "" if new.is_null else data[attribute.name()]
|
||||
elif data_type == "enum":
|
||||
new.enum_items = json.dumps(ifcopenshell.util.attribute.get_enum_items(attribute))
|
||||
if data[attribute.name()]:
|
||||
new.enum_value = data[attribute.name()]
|
||||
blenderbim.bim.helper.import_attributes("IfcWorkPlan", props.work_plan_attributes, data, self.import_attributes)
|
||||
|
||||
props.active_work_plan_id = self.work_plan
|
||||
props.editing_type = "ATTRIBUTES"
|
||||
return {"FINISHED"}
|
||||
|
||||
def import_attributes(self, name, prop, data):
|
||||
if name in ["CreationDate", "StartTime", "FinishTime"]:
|
||||
prop.string_value = "" if prop.is_null else data[name].isoformat()
|
||||
return True
|
||||
|
||||
|
||||
class DisableEditingWorkPlan(bpy.types.Operator):
|
||||
bl_idname = "bim.disable_editing_work_plan"
|
||||
@@ -176,15 +167,7 @@ class EditWorkSchedule(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
props = context.scene.BIMWorkScheduleProperties
|
||||
attributes = {}
|
||||
for attribute in props.work_schedule_attributes:
|
||||
if attribute.is_null:
|
||||
attributes[attribute.name] = None
|
||||
else:
|
||||
if attribute.data_type == "string":
|
||||
attributes[attribute.name] = attribute.string_value
|
||||
elif attribute.data_type == "enum":
|
||||
attributes[attribute.name] = attribute.enum_value
|
||||
attributes = blenderbim.bim.helper.export_attributes(props.work_schedule_attributes, self.export_attributes)
|
||||
self.file = IfcStore.get_file()
|
||||
ifcopenshell.api.run(
|
||||
"sequence.edit_work_schedule",
|
||||
@@ -195,6 +178,14 @@ class EditWorkSchedule(bpy.types.Operator):
|
||||
bpy.ops.bim.disable_editing_work_schedule()
|
||||
return {"FINISHED"}
|
||||
|
||||
def export_attributes(self, attributes, prop):
|
||||
if "Date" in prop.name or "Time" in prop.name:
|
||||
attributes[prop.name] = helper.parse_datetime(prop.string_value)
|
||||
return True
|
||||
elif prop.name == "Duration" or prop.name == "TotalFloat":
|
||||
attributes[prop.name] = helper.parse_duration(prop.string_value)
|
||||
return True
|
||||
|
||||
|
||||
class RemoveWorkSchedule(bpy.types.Operator):
|
||||
bl_idname = "bim.remove_work_schedule"
|
||||
@@ -227,23 +218,14 @@ class EnableEditingWorkSchedule(bpy.types.Operator):
|
||||
def enable_editing_work_schedule(self):
|
||||
data = Data.work_schedules[self.work_schedule]
|
||||
|
||||
for attribute in IfcStore.get_schema().declaration_by_name("IfcWorkSchedule").all_attributes():
|
||||
data_type = ifcopenshell.util.attribute.get_primitive_type(attribute)
|
||||
if data_type == "entity":
|
||||
continue
|
||||
new = self.props.work_schedule_attributes.add()
|
||||
new.name = attribute.name()
|
||||
new.is_null = data[attribute.name()] is None
|
||||
new.is_optional = attribute.optional()
|
||||
new.data_type = data_type
|
||||
if attribute.name() in ["CreationDate", "StartTime", "FinishTime"]:
|
||||
new.string_value = "" if new.is_null else data[attribute.name()].isoformat()
|
||||
elif data_type == "string":
|
||||
new.string_value = "" if new.is_null else data[attribute.name()]
|
||||
elif data_type == "enum":
|
||||
new.enum_items = json.dumps(ifcopenshell.util.attribute.get_enum_items(attribute))
|
||||
if data[attribute.name()]:
|
||||
new.enum_value = data[attribute.name()]
|
||||
blenderbim.bim.helper.import_attributes(
|
||||
"IfcWorkSchedule", self.props.work_schedule_attributes, data, self.import_attributes
|
||||
)
|
||||
|
||||
def import_attributes(self, name, prop, data):
|
||||
if name in ["CreationDate", "StartTime", "FinishTime"]:
|
||||
prop.string_value = "" if prop.is_null else data[name].isoformat()
|
||||
return True
|
||||
|
||||
|
||||
class EnableEditingTasks(bpy.types.Operator):
|
||||
@@ -439,39 +421,21 @@ class EnableEditingTaskTime(bpy.types.Operator):
|
||||
|
||||
data = Data.task_times[task_time_id]
|
||||
|
||||
for attribute in IfcStore.get_schema().declaration_by_name("IfcTaskTime").all_attributes():
|
||||
data_type = ifcopenshell.util.attribute.get_primitive_type(attribute)
|
||||
if data_type == "entity":
|
||||
continue
|
||||
new = props.task_time_attributes.add()
|
||||
new.name = attribute.name()
|
||||
new.is_null = data[attribute.name()] is None
|
||||
new.is_optional = attribute.optional()
|
||||
new.data_type = data_type
|
||||
if data_type == "string":
|
||||
if isinstance(data[attribute.name()], datetime):
|
||||
new.string_value = "" if new.is_null else data[attribute.name()].isoformat()
|
||||
elif isinstance(data[attribute.name()], isodate.Duration):
|
||||
new.string_value = (
|
||||
""
|
||||
if new.is_null
|
||||
else ifcopenshell.util.date.datetime2ifc(data[attribute.name()], "IfcDuration")
|
||||
)
|
||||
else:
|
||||
new.string_value = "" if new.is_null else data[attribute.name()]
|
||||
elif data_type == "boolean":
|
||||
new.bool_value = False if new.is_null else data[attribute.name()]
|
||||
elif data_type == "float":
|
||||
new.float_value = 0.0 if new.is_null else data[attribute.name()]
|
||||
elif data_type == "enum":
|
||||
new.enum_items = json.dumps(ifcopenshell.util.attribute.get_enum_items(attribute))
|
||||
if data[attribute.name()]:
|
||||
new.enum_value = data[attribute.name()]
|
||||
blenderbim.bim.helper.import_attributes("IfcTaskTime", props.task_time_attributes, data, self.import_attributes)
|
||||
props.active_task_time_id = task_time_id
|
||||
props.active_task_id = self.task
|
||||
props.editing_task_type = "TASKTIME"
|
||||
return {"FINISHED"}
|
||||
|
||||
def import_attributes(self, name, prop, data):
|
||||
if prop.data_type == "string":
|
||||
if isinstance(data[name], datetime):
|
||||
prop.string_value = "" if prop.is_null else data[name].isoformat()
|
||||
return True
|
||||
elif isinstance(data[name], isodate.Duration):
|
||||
prop.string_value = "" if prop.is_null else ifcopenshell.util.date.datetime2ifc(data[name], "IfcDuration")
|
||||
return True
|
||||
|
||||
def add_task_time(self):
|
||||
task_time = ifcopenshell.api.run("sequence.add_task_time", self.file, task=self.file.by_id(self.task))
|
||||
Data.load(IfcStore.get_file())
|
||||
@@ -484,20 +448,7 @@ class EditTaskTime(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
props = context.scene.BIMWorkScheduleProperties
|
||||
attributes = {}
|
||||
for attribute in props.task_time_attributes:
|
||||
if attribute.is_null:
|
||||
attributes[attribute.name] = None
|
||||
else:
|
||||
if attribute.data_type == "string":
|
||||
attributes[attribute.name] = attribute.string_value
|
||||
elif attribute.data_type == "boolean":
|
||||
attributes[attribute.name] = attribute.bool_value
|
||||
elif attribute.data_type == "float":
|
||||
attributes[attribute.name] = attribute.float_value
|
||||
elif attribute.data_type == "enum":
|
||||
attributes[attribute.name] = attribute.enum_value
|
||||
|
||||
attributes = blenderbim.bim.helper.export_attributes(props.task_time_attributes, self.export_attributes)
|
||||
attributes = self.convert_strings_to_date_times(attributes)
|
||||
|
||||
self.file = IfcStore.get_file()
|
||||
@@ -511,21 +462,13 @@ class EditTaskTime(bpy.types.Operator):
|
||||
bpy.ops.bim.load_task_properties(task=props.active_task_id)
|
||||
return {"FINISHED"}
|
||||
|
||||
def convert_strings_to_date_times(self, attributes):
|
||||
for key, value in attributes.items():
|
||||
if not value:
|
||||
continue
|
||||
if "Start" in key or "Finish" in key or key == "StatusTime":
|
||||
try:
|
||||
attributes[key] = parser.isoparse(value)
|
||||
except:
|
||||
try:
|
||||
attributes[key] = parser.parse(value, dayfirst=True, fuzzy=True)
|
||||
except:
|
||||
attributes[key] = None
|
||||
elif key == "ScheduleDuration":
|
||||
attributes[key] = isodate.parse_duration(value)
|
||||
return attributes
|
||||
def export_attributes(self, attributes, prop):
|
||||
if "Start" in prop.name or "Finish" in prop.name or prop.name == "StatusTime":
|
||||
attributes[prop.name] = helper.parse_datetime(value)
|
||||
return True
|
||||
elif prop.name == "ScheduleDuration":
|
||||
attributes[prop.name] = helper.parse_duration(value)
|
||||
return True
|
||||
|
||||
|
||||
class EnableEditingTask(bpy.types.Operator):
|
||||
@@ -540,25 +483,7 @@ class EnableEditingTask(bpy.types.Operator):
|
||||
|
||||
data = Data.tasks[self.task]
|
||||
|
||||
for attribute in IfcStore.get_schema().declaration_by_name("IfcTask").all_attributes():
|
||||
data_type = ifcopenshell.util.attribute.get_primitive_type(attribute)
|
||||
if data_type == "entity":
|
||||
continue
|
||||
new = props.task_attributes.add()
|
||||
new.name = attribute.name()
|
||||
new.is_null = data[attribute.name()] is None
|
||||
new.is_optional = attribute.optional()
|
||||
new.data_type = data_type
|
||||
if data_type == "string":
|
||||
new.string_value = "" if new.is_null else data[attribute.name()]
|
||||
elif data_type == "boolean":
|
||||
new.bool_value = False if new.is_null else data[attribute.name()]
|
||||
elif data_type == "integer":
|
||||
new.int_value = 0 if new.is_null else data[attribute.name()]
|
||||
elif data_type == "enum":
|
||||
new.enum_items = json.dumps(ifcopenshell.util.attribute.get_enum_items(attribute))
|
||||
if data[attribute.name()]:
|
||||
new.enum_value = data[attribute.name()]
|
||||
blenderbim.bim.helper.import_attributes("IfcTask", props.task_attributes, data)
|
||||
props.active_task_id = self.task
|
||||
props.editing_task_type = "ATTRIBUTES"
|
||||
return {"FINISHED"}
|
||||
@@ -580,19 +505,7 @@ class EditTask(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
props = context.scene.BIMWorkScheduleProperties
|
||||
attributes = {}
|
||||
for attribute in props.task_attributes:
|
||||
if attribute.is_null:
|
||||
attributes[attribute.name] = None
|
||||
else:
|
||||
if attribute.data_type == "string":
|
||||
attributes[attribute.name] = attribute.string_value
|
||||
elif attribute.data_type == "boolean":
|
||||
attributes[attribute.name] = attribute.bool_value
|
||||
elif attribute.data_type == "integer":
|
||||
attributes[attribute.name] = attribute.int_value
|
||||
elif attribute.data_type == "enum":
|
||||
attributes[attribute.name] = attribute.enum_value
|
||||
attributes = blenderbim.bim.export_attributes(props.task_attributes)
|
||||
self.file = IfcStore.get_file()
|
||||
ifcopenshell.api.run(
|
||||
"sequence.edit_task", self.file, **{"task": self.file.by_id(props.active_task_id), "attributes": attributes}
|
||||
@@ -778,15 +691,7 @@ class EditWorkCalendar(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
props = context.scene.BIMWorkCalendarProperties
|
||||
attributes = {}
|
||||
for attribute in props.work_calendar_attributes:
|
||||
if attribute.is_null:
|
||||
attributes[attribute.name] = None
|
||||
else:
|
||||
if attribute.data_type == "string":
|
||||
attributes[attribute.name] = attribute.string_value
|
||||
elif attribute.data_type == "enum":
|
||||
attributes[attribute.name] = attribute.enum_value
|
||||
attributes = blenderbim.bim.helper.export_attributes(props.work_calendar_attributes)
|
||||
self.file = IfcStore.get_file()
|
||||
ifcopenshell.api.run(
|
||||
"sequence.edit_work_calendar",
|
||||
@@ -824,21 +729,7 @@ class EnableEditingWorkCalendar(bpy.types.Operator):
|
||||
|
||||
data = Data.work_calendars[self.work_calendar]
|
||||
|
||||
for attribute in IfcStore.get_schema().declaration_by_name("IfcWorkCalendar").all_attributes():
|
||||
data_type = ifcopenshell.util.attribute.get_primitive_type(attribute)
|
||||
if data_type == "entity":
|
||||
continue
|
||||
new = self.props.work_calendar_attributes.add()
|
||||
new.name = attribute.name()
|
||||
new.is_null = data[attribute.name()] is None
|
||||
new.is_optional = attribute.optional()
|
||||
new.data_type = data_type
|
||||
if data_type == "string":
|
||||
new.string_value = "" if new.is_null else data[attribute.name()]
|
||||
elif data_type == "enum":
|
||||
new.enum_items = json.dumps(ifcopenshell.util.attribute.get_enum_items(attribute))
|
||||
if data[attribute.name()]:
|
||||
new.enum_value = data[attribute.name()]
|
||||
blenderbim.bim.helper.import_attributes("IfcWorkCalendar", self.props.work_calendar_attributes, data)
|
||||
self.props.active_work_calendar_id = self.work_calendar
|
||||
self.props.editing_type = "ATTRIBUTES"
|
||||
return {"FINISHED"}
|
||||
@@ -936,29 +827,20 @@ class EnableEditingWorkTime(bpy.types.Operator):
|
||||
|
||||
data = Data.work_times[self.work_time]
|
||||
|
||||
for attribute in IfcStore.get_schema().declaration_by_name("IfcWorkTime").all_attributes():
|
||||
data_type = ifcopenshell.util.attribute.get_primitive_type(attribute)
|
||||
if data_type == "entity":
|
||||
continue
|
||||
new = self.props.work_time_attributes.add()
|
||||
new.name = attribute.name()
|
||||
new.is_null = data[attribute.name()] is None
|
||||
new.is_optional = attribute.optional()
|
||||
new.data_type = data_type
|
||||
if attribute.name() in ["Start", "Finish"]:
|
||||
new.string_value = "" if new.is_null else data[attribute.name()].isoformat()
|
||||
elif data_type == "string":
|
||||
new.string_value = "" if new.is_null else data[attribute.name()]
|
||||
elif data_type == "enum":
|
||||
new.enum_items = json.dumps(ifcopenshell.util.attribute.get_enum_items(attribute))
|
||||
if data[attribute.name()]:
|
||||
new.enum_value = data[attribute.name()]
|
||||
blenderbim.bim.helper.import_attributes(
|
||||
"IfcWorkTime", self.props.work_time_attributes, data, self.import_attributes
|
||||
)
|
||||
|
||||
self.initialise_recurrence_components()
|
||||
self.load_recurrence_pattern_data(data)
|
||||
self.props.active_work_time_id = self.work_time
|
||||
return {"FINISHED"}
|
||||
|
||||
def import_attributes(self, name, prop, data):
|
||||
if name in ["Start", "Finish"]:
|
||||
prop.string_value = "" if prop.is_null else data[name].isoformat()
|
||||
return True
|
||||
|
||||
def initialise_recurrence_components(self):
|
||||
if len(self.props.day_components) == 0:
|
||||
for i in range(0, 31):
|
||||
@@ -1014,15 +896,7 @@ class EditWorkTime(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
self.props = context.scene.BIMWorkCalendarProperties
|
||||
attributes = {}
|
||||
for attribute in self.props.work_time_attributes:
|
||||
if attribute.is_null:
|
||||
attributes[attribute.name] = None
|
||||
else:
|
||||
if attribute.data_type == "string":
|
||||
attributes[attribute.name] = attribute.string_value
|
||||
elif attribute.data_type == "enum":
|
||||
attributes[attribute.name] = attribute.enum_value
|
||||
attributes = blenderbim.bim.helper.export_attributes(self.props.work_time_attributes)
|
||||
self.file = IfcStore.get_file()
|
||||
ifcopenshell.api.run(
|
||||
"sequence.edit_work_time",
|
||||
@@ -1251,21 +1125,7 @@ class EnableEditingSequenceAttributes(bpy.types.Operator):
|
||||
|
||||
def enable_editing_sequence_attributes(self):
|
||||
data = Data.sequences[self.sequence]
|
||||
for attribute in IfcStore.get_schema().declaration_by_name("IfcRelSequence").all_attributes():
|
||||
data_type = ifcopenshell.util.attribute.get_primitive_type(attribute)
|
||||
if data_type == "entity":
|
||||
continue
|
||||
new = self.props.sequence_attributes.add()
|
||||
new.name = attribute.name()
|
||||
new.is_null = data[attribute.name()] is None
|
||||
new.is_optional = attribute.optional()
|
||||
new.data_type = data_type
|
||||
if data_type == "string":
|
||||
new.string_value = "" if new.is_null else data[attribute.name()]
|
||||
elif data_type == "enum":
|
||||
new.enum_items = json.dumps(ifcopenshell.util.attribute.get_enum_items(attribute))
|
||||
if data[attribute.name()]:
|
||||
new.enum_value = data[attribute.name()]
|
||||
blenderbim.bim.helper.import_attributes("IfcRelSequence", self.props.sequence_attributes, data)
|
||||
|
||||
|
||||
class EnableEditingSequenceTimeLag(bpy.types.Operator):
|
||||
@@ -1285,34 +1145,24 @@ class EnableEditingSequenceTimeLag(bpy.types.Operator):
|
||||
|
||||
def enable_editing_attributes(self):
|
||||
data = Data.lag_times[self.lag_time]
|
||||
for attribute in IfcStore.get_schema().declaration_by_name("IfcLagTime").all_attributes():
|
||||
data_type = ifcopenshell.util.attribute.get_primitive_type(attribute)
|
||||
if data_type == "entity":
|
||||
continue
|
||||
new = self.props.time_lag_attributes.add()
|
||||
new.name = attribute.name()
|
||||
new.is_null = data[attribute.name()] is None
|
||||
new.is_optional = attribute.optional()
|
||||
new.data_type = data_type
|
||||
if attribute.name() == "LagValue":
|
||||
if isinstance(data[attribute.name()], isodate.Duration):
|
||||
new.data_type = "string"
|
||||
new.string_value = (
|
||||
""
|
||||
if new.is_null
|
||||
else ifcopenshell.util.date.datetime2ifc(data[attribute.name()], "IfcDuration")
|
||||
)
|
||||
else:
|
||||
new.data_type = "float"
|
||||
new.float_value = 0.0 if new.is_null else data[attribute.name()]
|
||||
elif data_type == "string":
|
||||
new.string_value = "" if new.is_null else data[attribute.name()]
|
||||
elif data_type == "float":
|
||||
new.float_value = 0.0 if new.is_null else data[attribute.name()]
|
||||
elif data_type == "enum":
|
||||
new.enum_items = json.dumps(ifcopenshell.util.attribute.get_enum_items(attribute))
|
||||
if data[attribute.name()]:
|
||||
new.enum_value = data[attribute.name()]
|
||||
blenderbim.bim.helper.import_attributes(
|
||||
"IfcLagTime", self.props.time_lag_attributes, data, self.import_attributes
|
||||
)
|
||||
|
||||
def import_attributes(self, name, prop, data):
|
||||
if name == "LagValue":
|
||||
if isinstance(data[name], isodate.Duration):
|
||||
prop.data_type = "string"
|
||||
prop.string_value = (
|
||||
""
|
||||
if prop.is_null
|
||||
else ifcopenshell.util.date.datetime2ifc(data[name], "IfcDuration")
|
||||
)
|
||||
return True
|
||||
else:
|
||||
prop.data_type = "float"
|
||||
prop.float_value = 0.0 if prop.is_null else data[name]
|
||||
return True
|
||||
|
||||
|
||||
class UnassignLagTime(bpy.types.Operator):
|
||||
@@ -1351,15 +1201,7 @@ class EditSequenceAttributes(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
props = context.scene.BIMWorkScheduleProperties
|
||||
attributes = {}
|
||||
for attribute in props.sequence_attributes:
|
||||
if attribute.is_null:
|
||||
attributes[attribute.name] = None
|
||||
else:
|
||||
if attribute.data_type == "string":
|
||||
attributes[attribute.name] = attribute.string_value
|
||||
elif attribute.data_type == "enum":
|
||||
attributes[attribute.name] = attribute.enum_value
|
||||
attributes = blenderbim.bim.helper.export_attributes(props.sequence_attributes)
|
||||
self.file = IfcStore.get_file()
|
||||
ifcopenshell.api.run(
|
||||
"sequence.edit_sequence",
|
||||
@@ -1378,17 +1220,7 @@ class EditSequenceTimeLag(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
props = context.scene.BIMWorkScheduleProperties
|
||||
attributes = {}
|
||||
for attribute in props.time_lag_attributes:
|
||||
if attribute.is_null:
|
||||
attributes[attribute.name] = None
|
||||
else:
|
||||
if attribute.data_type == "string":
|
||||
attributes[attribute.name] = attribute.string_value
|
||||
elif attribute.data_type == "float":
|
||||
attributes[attribute.name] = attribute.float_value
|
||||
elif attribute.data_type == "enum":
|
||||
attributes[attribute.name] = attribute.enum_value
|
||||
attributes = blenderbim.bim.helper.export_attributes(props.time_lag_attributes)
|
||||
self.file = IfcStore.get_file()
|
||||
ifcopenshell.api.run(
|
||||
"sequence.edit_lag_time",
|
||||
|
||||
@@ -10,10 +10,9 @@ class Usecase:
|
||||
|
||||
def execute(self):
|
||||
for name, value in self.settings["attributes"].items():
|
||||
if "Start" in name or "Finish" in name or name == "StatusTime":
|
||||
if value:
|
||||
if value:
|
||||
if "Start" in name or "Finish" in name or name == "StatusTime":
|
||||
value = ifcopenshell.util.date.datetime2ifc(value, "IfcDateTime")
|
||||
if name == "ScheduleDuration":
|
||||
if value:
|
||||
elif name == "ScheduleDuration":
|
||||
value = ifcopenshell.util.date.datetime2ifc(value, "IfcDuration")
|
||||
setattr(self.settings["task_time"], name, value)
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
import ifcopenshell.util.date
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
@@ -7,4 +10,9 @@ class Usecase:
|
||||
|
||||
def execute(self):
|
||||
for name, value in self.settings["attributes"].items():
|
||||
if value:
|
||||
if "Date" in name or "Time" in name:
|
||||
value = ifcopenshell.util.date.datetime2ifc(value, "IfcDateTime")
|
||||
elif name == "Duration" or name == "TotalFloat":
|
||||
value = ifcopenshell.util.date.datetime2ifc(value, "IfcDuration")
|
||||
setattr(self.settings["work_plan"], name, value)
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
import ifcopenshell.util.date
|
||||
|
||||
|
||||
class Usecase:
|
||||
def __init__(self, file, **settings):
|
||||
self.file = file
|
||||
@@ -7,4 +10,9 @@ class Usecase:
|
||||
|
||||
def execute(self):
|
||||
for name, value in self.settings["attributes"].items():
|
||||
if value:
|
||||
if "Date" in name or "Time" in name:
|
||||
value = ifcopenshell.util.date.datetime2ifc(value, "IfcDateTime")
|
||||
elif name == "Duration" or name == "TotalFloat":
|
||||
value = ifcopenshell.util.date.datetime2ifc(value, "IfcDuration")
|
||||
setattr(self.settings["work_schedule"], name, value)
|
||||
|
||||
Reference in New Issue
Block a user