mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-12 10:33:20 +00:00
typing
This commit is contained in:
@@ -76,8 +76,8 @@ def draw_attribute(
|
||||
elif value_name == "filepath_value":
|
||||
attribute.filepath_value.layout_file_select(layout, filter_glob=attribute.filter_glob, text=attribute.name)
|
||||
elif attribute.name in ("ScheduleDuration", "ActualDuration", "FreeFloat", "TotalFloat"):
|
||||
propis = bpy.context.scene.BIMWorkScheduleProperties
|
||||
for item in propis.durations_attributes:
|
||||
props = tool.Sequence.get_work_schedule_props()
|
||||
for item in props.durations_attributes:
|
||||
if item.name == attribute.name:
|
||||
duration_props = item
|
||||
layout.label(text=attribute.name)
|
||||
|
||||
@@ -145,11 +145,8 @@ class CostClassificationsData(ReferencesData):
|
||||
@classmethod
|
||||
def references(cls):
|
||||
results = []
|
||||
element = tool.Ifc.get().by_id(
|
||||
bpy.context.scene.BIMCostProperties.cost_items[
|
||||
bpy.context.scene.BIMCostProperties.active_cost_item_index
|
||||
].ifc_definition_id
|
||||
)
|
||||
props = tool.Cost.get_cost_props()
|
||||
element = tool.Ifc.get().by_id(props.cost_items[props.active_cost_item_index].ifc_definition_id)
|
||||
if element:
|
||||
for reference in ifcopenshell.util.classification.get_references(element):
|
||||
data = reference.get_info()
|
||||
|
||||
@@ -338,7 +338,8 @@ class BIM_PT_cost_classifications(Panel, ReferenceUI):
|
||||
def poll(cls, context):
|
||||
if not tool.Ifc.get():
|
||||
return False
|
||||
return bool(context.scene.BIMCostProperties.cost_items)
|
||||
props = tool.Cost.get_cost_props()
|
||||
return bool(props.cost_items)
|
||||
|
||||
def draw(self, context):
|
||||
if not CostClassificationsData.is_loaded:
|
||||
|
||||
@@ -66,8 +66,9 @@ class CostSchedulesData:
|
||||
@classmethod
|
||||
def schedules(cls):
|
||||
results = []
|
||||
if bpy.context.scene.BIMCostProperties.active_cost_schedule_id:
|
||||
schedule = tool.Ifc.get().by_id(bpy.context.scene.BIMCostProperties.active_cost_schedule_id)
|
||||
props = tool.Cost.get_cost_props()
|
||||
if props.active_cost_schedule_id:
|
||||
schedule = tool.Ifc.get().by_id(props.active_cost_schedule_id)
|
||||
results.append(
|
||||
{
|
||||
"id": schedule.id(),
|
||||
@@ -88,7 +89,8 @@ class CostSchedulesData:
|
||||
|
||||
@classmethod
|
||||
def is_editing_rates(cls):
|
||||
ifc_id = bpy.context.scene.BIMCostProperties.active_cost_schedule_id
|
||||
props = tool.Cost.get_cost_props()
|
||||
ifc_id = props.active_cost_schedule_id
|
||||
if not ifc_id:
|
||||
return
|
||||
return tool.Ifc.get().by_id(ifc_id).PredefinedType == "SCHEDULEOFRATES"
|
||||
@@ -256,7 +258,8 @@ class CostSchedulesData:
|
||||
@classmethod
|
||||
def cost_quantities(cls):
|
||||
results = []
|
||||
ifc_id = bpy.context.scene.BIMCostProperties.active_cost_item_id
|
||||
props = tool.Cost.get_cost_props()
|
||||
ifc_id = props.active_cost_item_id
|
||||
if not ifc_id:
|
||||
return results
|
||||
for quantity in tool.Ifc.get().by_id(ifc_id).CostQuantities or []:
|
||||
@@ -265,7 +268,8 @@ class CostSchedulesData:
|
||||
|
||||
@classmethod
|
||||
def cost_values(cls):
|
||||
ifc_id = bpy.context.scene.BIMCostProperties.active_cost_item_id
|
||||
props = tool.Cost.get_cost_props()
|
||||
ifc_id = props.active_cost_item_id
|
||||
if not ifc_id:
|
||||
return []
|
||||
return ifcopenshell.util.cost.get_cost_values(tool.Ifc.get().by_id(ifc_id))
|
||||
@@ -324,7 +328,8 @@ class CostItemQuantitiesData:
|
||||
|
||||
@classmethod
|
||||
def process_quantity_names(cls):
|
||||
active_task_index = bpy.context.scene.BIMWorkScheduleProperties.active_task_index
|
||||
props = tool.Sequence.get_work_schedule_props()
|
||||
active_task_index = props.active_task_index
|
||||
tprops = tool.Sequence.get_task_tree_props()
|
||||
total_tasks = len(tprops.tasks)
|
||||
if not total_tasks or active_task_index >= total_tasks:
|
||||
|
||||
@@ -36,16 +36,18 @@ class AddCostSchedule(bpy.types.Operator, tool.Ifc.Operator):
|
||||
object_type: bpy.props.StringProperty()
|
||||
|
||||
def _execute(self, context):
|
||||
predefined_type = context.scene.BIMCostProperties.cost_schedule_predefined_types
|
||||
props = tool.Cost.get_cost_props()
|
||||
predefined_type = props.cost_schedule_predefined_types
|
||||
if predefined_type == "USERDEFINED":
|
||||
predefined_type = self.object_type
|
||||
core.add_cost_schedule(tool.Ifc, name=self.name, predefined_type=predefined_type)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
props = tool.Cost.get_cost_props()
|
||||
layout.prop(self, "name", text="Name")
|
||||
layout.prop(context.scene.BIMCostProperties, "cost_schedule_predefined_types", text="Type")
|
||||
if context.scene.BIMCostProperties.cost_schedule_predefined_types == "USERDEFINED":
|
||||
layout.prop(props, "cost_schedule_predefined_types", text="Type")
|
||||
if props.cost_schedule_predefined_types == "USERDEFINED":
|
||||
layout.prop(self, "object_type", text="Object type")
|
||||
|
||||
def invoke(self, context, event):
|
||||
@@ -58,10 +60,11 @@ class EditCostSchedule(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def _execute(self, context):
|
||||
props = tool.Cost.get_cost_props()
|
||||
core.edit_cost_schedule(
|
||||
tool.Ifc,
|
||||
tool.Cost,
|
||||
cost_schedule=tool.Ifc.get().by_id(context.scene.BIMCostProperties.active_cost_schedule_id),
|
||||
cost_schedule=tool.Ifc.get().by_id(props.active_cost_schedule_id),
|
||||
)
|
||||
|
||||
|
||||
@@ -559,7 +562,8 @@ class AddCostColumn(bpy.types.Operator):
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
if not context.scene.BIMCostProperties.cost_column:
|
||||
props = tool.Cost.get_cost_props()
|
||||
if not props.cost_column:
|
||||
cls.poll_message_set("Cost column name is empty")
|
||||
return False
|
||||
return True
|
||||
|
||||
@@ -33,6 +33,7 @@ from bpy.props import (
|
||||
FloatVectorProperty,
|
||||
CollectionProperty,
|
||||
)
|
||||
from typing import TYPE_CHECKING, Literal
|
||||
|
||||
|
||||
def get_schedule_of_rates(self, context):
|
||||
@@ -78,8 +79,8 @@ def update_active_cost_item_index(self, context):
|
||||
CostClassificationsData.load()
|
||||
|
||||
|
||||
def update_cost_item_identification(self, context):
|
||||
props = context.scene.BIMCostProperties
|
||||
def update_cost_item_identification(self: "CostItem", context: bpy.types.Context):
|
||||
props = tool.Cost.get_cost_props()
|
||||
if not props.is_cost_update_enabled or self.identification == "XXX":
|
||||
return
|
||||
self.file = tool.Ifc.get()
|
||||
@@ -93,8 +94,8 @@ def update_cost_item_identification(self, context):
|
||||
attribute.string_value = self.identification
|
||||
|
||||
|
||||
def update_cost_item_name(self, context):
|
||||
props = context.scene.BIMCostProperties
|
||||
def update_cost_item_name(self: "CostItem", context: bpy.types.Context) -> None:
|
||||
props = tool.Cost.get_cost_props()
|
||||
if not props.is_cost_update_enabled or self.name == "Unnamed":
|
||||
return
|
||||
self.file = tool.Ifc.get()
|
||||
@@ -142,6 +143,14 @@ class CostItem(PropertyGroup):
|
||||
is_expanded: BoolProperty(name="Is Expanded")
|
||||
level_index: IntProperty(name="Level Index")
|
||||
|
||||
if TYPE_CHECKING:
|
||||
name: str
|
||||
identification: str
|
||||
ifc_definition_id: int
|
||||
has_children: bool
|
||||
is_expanded: bool
|
||||
level_index: int
|
||||
|
||||
|
||||
class CostItemQuantity(PropertyGroup):
|
||||
name: StringProperty(name="Name")
|
||||
@@ -150,11 +159,22 @@ class CostItemQuantity(PropertyGroup):
|
||||
unit_symbol: StringProperty(name="Unit Symbol")
|
||||
total_cost_quantity: FloatProperty(name="Total Quantity")
|
||||
|
||||
if TYPE_CHECKING:
|
||||
name: str
|
||||
ifc_definition_id: int
|
||||
total_quantity: float
|
||||
unit_symbol: str
|
||||
total_cost_quantity: float
|
||||
|
||||
|
||||
class CostItemType(PropertyGroup):
|
||||
name: StringProperty(name="Name")
|
||||
ifc_definition_id: IntProperty(name="IFC Definition ID")
|
||||
|
||||
if TYPE_CHECKING:
|
||||
name: str
|
||||
ifc_definition_id: int
|
||||
|
||||
|
||||
def update_cost_item_parent(self, context):
|
||||
cost_item = tool.Cost.get_highlighted_cost_item()
|
||||
@@ -176,6 +196,9 @@ def update_active_cost_item_resources(self, context):
|
||||
class ScheduleColumn(PropertyGroup):
|
||||
schedule_id: IntProperty()
|
||||
|
||||
if TYPE_CHECKING:
|
||||
schedule_id: int
|
||||
|
||||
|
||||
class BIMCostProperties(PropertyGroup):
|
||||
cost_schedule_predefined_types: EnumProperty(
|
||||
@@ -249,3 +272,57 @@ class BIMCostProperties(PropertyGroup):
|
||||
custom_currency: StringProperty(
|
||||
name="Custom Currency", default="USD", description="Custom Currency in ISO 4217 format"
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
cost_schedule_predefined_types: str
|
||||
is_cost_update_enabled: bool
|
||||
cost_schedule_attributes: bpy.types.bpy_prop_collection_idprop[Attribute]
|
||||
is_editing: str
|
||||
active_cost_schedule_id: int
|
||||
cost_items: bpy.types.bpy_prop_collection_idprop[CostItem]
|
||||
active_cost_item_id: int
|
||||
cost_item_editing_type: str
|
||||
active_cost_item_index: int
|
||||
cost_item_attributes: bpy.types.bpy_prop_collection_idprop[Attribute]
|
||||
contracted_cost_items: str
|
||||
quantity_types: str
|
||||
product_quantity_names: str
|
||||
process_quantity_names: str
|
||||
resource_quantity_names: str
|
||||
active_cost_item_quantity_id: int
|
||||
quantity_attributes: bpy.types.bpy_prop_collection_idprop[Attribute]
|
||||
cost_types: Literal["FIXED", "SUM", "CATEGORY"]
|
||||
cost_category: str
|
||||
fixed_cost_value: float
|
||||
active_cost_value_id: int
|
||||
cost_value_editing_type: str
|
||||
cost_value_attributes: bpy.types.bpy_prop_collection_idprop[Attribute]
|
||||
cost_value_formula: str
|
||||
cost_column: str
|
||||
should_show_column_ui: bool
|
||||
should_show_currency_ui: bool
|
||||
columns: bpy.types.bpy_prop_collection_idprop[StrProperty]
|
||||
columns_storage: bpy.types.bpy_prop_collection_idprop[ScheduleColumn]
|
||||
active_column_index: int
|
||||
cost_item_products: bpy.types.bpy_prop_collection_idprop[CostItemQuantity]
|
||||
active_cost_item_product_index: int
|
||||
cost_item_processes: bpy.types.bpy_prop_collection_idprop[CostItemQuantity]
|
||||
active_cost_item_process_index: int
|
||||
cost_item_resources: bpy.types.bpy_prop_collection_idprop[CostItemQuantity]
|
||||
active_cost_item_resource_index: int
|
||||
cost_item_type_products: bpy.types.bpy_prop_collection_idprop[CostItemType]
|
||||
active_cost_item_type_product_index: int
|
||||
schedule_of_rates: str
|
||||
cost_item_rates: bpy.types.bpy_prop_collection_idprop[CostItem]
|
||||
active_cost_item_rate_index: int
|
||||
contracted_cost_item_rates: str
|
||||
product_cost_items: bpy.types.bpy_prop_collection_idprop[CostItemQuantity]
|
||||
active_product_cost_item_index: int
|
||||
enable_reorder: bool
|
||||
show_nested_elements: bool
|
||||
show_nested_tasks: bool
|
||||
show_nested_resources: bool
|
||||
change_cost_item_parent: bool
|
||||
show_cost_item_operators: bool
|
||||
currency: str
|
||||
custom_currency: str
|
||||
|
||||
@@ -16,13 +16,17 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import annotations
|
||||
import bpy
|
||||
import bonsai.bim.helper
|
||||
import bonsai.bim.module.cost.prop as CostProp
|
||||
import bonsai.tool as tool
|
||||
from bpy.types import Panel, UIList
|
||||
from bonsai.bim.module.cost.data import CostSchedulesData
|
||||
from typing import Any
|
||||
from typing import Any, TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from bonsai.bim.module.cost.prop import BIMCostProperties, CostItemQuantity
|
||||
|
||||
|
||||
class BIM_PT_cost_schedules(Panel):
|
||||
@@ -43,7 +47,7 @@ class BIM_PT_cost_schedules(Panel):
|
||||
if not CostSchedulesData.is_loaded:
|
||||
CostSchedulesData.load()
|
||||
|
||||
self.props = context.scene.BIMCostProperties
|
||||
self.props = tool.Cost.get_cost_props()
|
||||
if not self.props.active_cost_schedule_id:
|
||||
row = self.layout.row(align=True)
|
||||
if CostSchedulesData.data["total_cost_schedules"]:
|
||||
@@ -299,7 +303,7 @@ class BIM_PT_cost_item_types(Panel):
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
props = context.scene.BIMCostProperties
|
||||
props = tool.Cost.get_cost_props()
|
||||
total_cost_items = len(props.cost_items)
|
||||
if not props.active_cost_schedule_id:
|
||||
return False
|
||||
@@ -312,7 +316,7 @@ class BIM_PT_cost_item_types(Panel):
|
||||
return False
|
||||
|
||||
def draw(self, context):
|
||||
self.props = context.scene.BIMCostProperties
|
||||
self.props = tool.Cost.get_cost_props()
|
||||
cost_item = self.props.cost_items[self.props.active_cost_item_index]
|
||||
grid = self.layout.grid_flow(columns=3, even_columns=True)
|
||||
|
||||
@@ -385,7 +389,7 @@ class BIM_PT_cost_item_quantities(Panel):
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
props = context.scene.BIMCostProperties
|
||||
props = tool.Cost.get_cost_props()
|
||||
total_cost_items = len(props.cost_items)
|
||||
if not props.active_cost_schedule_id:
|
||||
return False
|
||||
@@ -398,7 +402,7 @@ class BIM_PT_cost_item_quantities(Panel):
|
||||
return False
|
||||
|
||||
def draw(self, context):
|
||||
self.props = context.scene.BIMCostProperties
|
||||
self.props = tool.Cost.get_cost_props()
|
||||
|
||||
cost_item = self.props.cost_items[self.props.active_cost_item_index]
|
||||
|
||||
@@ -462,7 +466,7 @@ class BIM_PT_cost_item_quantities(Panel):
|
||||
row2.label(text="Tasks ({})".format(total_cost_item_processes))
|
||||
|
||||
tprops = tool.Sequence.get_task_tree_props()
|
||||
wprops = context.scene.BIMWorkScheduleProperties
|
||||
wprops = tool.Sequence.get_work_schedule_props()
|
||||
if tprops.tasks and wprops.active_task_index < len(tprops.tasks):
|
||||
if has_quantity_names:
|
||||
op = row2.operator("bim.assign_cost_item_quantity", text="", icon="PROPERTIES")
|
||||
@@ -557,7 +561,7 @@ class BIM_PT_cost_item_rates(Panel):
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
props = context.scene.BIMCostProperties
|
||||
props = tool.Cost.get_cost_props()
|
||||
total_cost_items = len(props.cost_items)
|
||||
if not props.active_cost_schedule_id:
|
||||
return False
|
||||
@@ -570,7 +574,7 @@ class BIM_PT_cost_item_rates(Panel):
|
||||
return False
|
||||
|
||||
def draw(self, context):
|
||||
self.props = context.scene.BIMCostProperties
|
||||
self.props = tool.Cost.get_cost_props()
|
||||
row = self.layout.row(align=True)
|
||||
row.prop(self.props, "schedule_of_rates", text="")
|
||||
if self.props.active_cost_item_rate_index < len(self.props.cost_item_rates):
|
||||
@@ -606,13 +610,14 @@ class BIM_UL_cost_items_trait:
|
||||
split2.label(text="Quantity")
|
||||
split2.label(text="Value")
|
||||
|
||||
for column in bpy.context.scene.BIMCostProperties.columns:
|
||||
props = tool.Cost.get_cost_props()
|
||||
for column in props.columns:
|
||||
split2.label(text=column.name)
|
||||
split2.label(text="Total Cost")
|
||||
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
||||
if item:
|
||||
self.props = context.scene.BIMCostProperties
|
||||
self.props = tool.Cost.get_cost_props()
|
||||
cost_item = CostSchedulesData.data["cost_items"][item.ifc_definition_id]
|
||||
row = layout.row(align=True)
|
||||
|
||||
@@ -728,7 +733,6 @@ class BIM_UL_cost_item_rates(BIM_UL_cost_items_trait, UIList):
|
||||
|
||||
class BIM_UL_cost_columns(UIList):
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
||||
props = context.scene.BIMCostProperties
|
||||
if item:
|
||||
row = layout.row(align=True)
|
||||
row.prop(item, "name", emboss=False, text="")
|
||||
@@ -737,7 +741,7 @@ class BIM_UL_cost_columns(UIList):
|
||||
|
||||
class BIM_UL_cost_item_types(UIList):
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
||||
props = context.scene.BIMCostProperties
|
||||
props = tool.Cost.get_cost_props()
|
||||
cost_item = props.cost_items[props.active_cost_item_index]
|
||||
|
||||
if item:
|
||||
@@ -749,9 +753,17 @@ class BIM_UL_cost_item_types(UIList):
|
||||
|
||||
|
||||
class BIM_UL_cost_item_quantities(UIList):
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
||||
props = context.scene.BIMCostProperties
|
||||
cost_item = props.cost_items[props.active_cost_item_index]
|
||||
def draw_item(
|
||||
self,
|
||||
context: bpy.types.Context,
|
||||
layout: bpy.types.UILayout,
|
||||
data: BIMCostProperties,
|
||||
item: CostItemQuantity,
|
||||
icon,
|
||||
active_data,
|
||||
active_propname,
|
||||
):
|
||||
cost_item = data.cost_items[data.active_cost_item_index]
|
||||
if item:
|
||||
row = layout.row(align=True)
|
||||
op = row.operator("bim.select_product", text="", icon="RESTRICT_SELECT_OFF")
|
||||
@@ -788,15 +800,15 @@ class BIM_PT_Costing_Tools(Panel):
|
||||
bl_parent_id = "BIM_PT_tab_cost"
|
||||
|
||||
def draw(self, context):
|
||||
self.props = context.scene.BIMCostProperties
|
||||
props = tool.Cost.get_cost_props()
|
||||
row = self.layout.row()
|
||||
row.operator("bim.load_product_cost_items", icon="FILE_REFRESH")
|
||||
row = self.layout.row()
|
||||
row.template_list(
|
||||
"BIM_UL_product_cost_items",
|
||||
"",
|
||||
self.props,
|
||||
props,
|
||||
"product_cost_items",
|
||||
self.props,
|
||||
props,
|
||||
"active_product_cost_item_index",
|
||||
)
|
||||
|
||||
@@ -61,6 +61,7 @@ class CsvAttribute(PropertyGroup):
|
||||
formatting: StringProperty(default="{{value}}", name="Formatting")
|
||||
|
||||
if TYPE_CHECKING:
|
||||
name: str
|
||||
header: str
|
||||
sort: Literal["NONE", "ASC", "DESC"]
|
||||
group: Literal["NONE", "GROUP", "CONCAT", "VARIES", "SUM", "AVERAGE", "MIN", "MAX"]
|
||||
|
||||
@@ -281,9 +281,12 @@ class UnassignMaterial(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
obj: bpy.props.StringProperty()
|
||||
|
||||
if TYPE_CHECKING:
|
||||
obj: str
|
||||
|
||||
def _execute(self, context):
|
||||
objects = [bpy.data.objects.get(self.obj)] if self.obj else tool.Blender.get_selected_objects()
|
||||
core.unassign_material(tool.Ifc, tool.Material, objects=objects)
|
||||
objects = [bpy.data.objects[self.obj]] if self.obj else tool.Blender.get_selected_objects()
|
||||
core.unassign_material(tool.Ifc, tool.Material, objects=list(objects))
|
||||
|
||||
|
||||
class AddConstituent(bpy.types.Operator, tool.Ifc.Operator):
|
||||
|
||||
@@ -227,7 +227,7 @@ class TaskQtosData(Data):
|
||||
|
||||
@classmethod
|
||||
def load(cls):
|
||||
wprops = bpy.context.scene.BIMWorkScheduleProperties
|
||||
wprops = tool.Sequence.get_work_schedule_props()
|
||||
tprops = tool.Sequence.get_task_tree_props()
|
||||
ifc_definition_id = tprops.tasks[wprops.active_task_index].ifc_definition_id
|
||||
cls.data = {"qtos": cls.psetqtos(tool.Ifc.get().by_id(ifc_definition_id), qtos_only=True)}
|
||||
@@ -311,7 +311,8 @@ class WorkSchedulePsetsData(Data):
|
||||
|
||||
@classmethod
|
||||
def load(cls):
|
||||
ifc_definition_id = bpy.context.scene.BIMWorkScheduleProperties.active_work_schedule_id
|
||||
props = tool.Sequence.get_work_schedule_props()
|
||||
ifc_definition_id = props.active_work_schedule_id
|
||||
cls.data = {"psets": cls.psetqtos(tool.Ifc.get().by_id(ifc_definition_id), psets_only=True)}
|
||||
cls.is_loaded = True
|
||||
|
||||
|
||||
@@ -494,7 +494,7 @@ class BIM_PT_task_qtos(Panel):
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
props = context.scene.BIMWorkScheduleProperties
|
||||
props = tool.Sequence.get_work_schedule_props()
|
||||
if not props.active_work_schedule_id:
|
||||
return False
|
||||
tprops = tool.Sequence.get_task_tree_props()
|
||||
@@ -712,9 +712,8 @@ class BIM_PT_work_schedule_psets(Panel):
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
if not context.scene.BIMWorkScheduleProperties.active_work_schedule_id:
|
||||
return False
|
||||
return True
|
||||
props = tool.Sequence.get_work_schedule_props()
|
||||
return bool(props.active_work_schedule_id)
|
||||
|
||||
def draw(self, context):
|
||||
if not WorkSchedulePsetsData.is_loaded:
|
||||
|
||||
@@ -307,20 +307,19 @@ class WorkScheduleData:
|
||||
cls.is_loaded = True
|
||||
|
||||
@classmethod
|
||||
def can_have_baselines(cls):
|
||||
if not bpy.context.scene.BIMWorkScheduleProperties.active_work_schedule_id:
|
||||
def can_have_baselines(cls) -> bool:
|
||||
props = tool.Sequence.get_work_schedule_props()
|
||||
if not props.active_work_schedule_id:
|
||||
return False
|
||||
return (
|
||||
tool.Ifc.get().by_id(bpy.context.scene.BIMWorkScheduleProperties.active_work_schedule_id).PredefinedType
|
||||
== "PLANNED"
|
||||
)
|
||||
return tool.Ifc.get().by_id(props.active_work_schedule_id).PredefinedType == "PLANNED"
|
||||
|
||||
@classmethod
|
||||
def active_work_schedule_baselines(cls):
|
||||
def active_work_schedule_baselines(cls) -> list[dict[str, Any]]:
|
||||
results = []
|
||||
if not bpy.context.scene.BIMWorkScheduleProperties.active_work_schedule_id:
|
||||
props = tool.Sequence.get_work_schedule_props()
|
||||
if not props.active_work_schedule_id:
|
||||
return []
|
||||
for rel in tool.Ifc.get().by_id(bpy.context.scene.BIMWorkScheduleProperties.active_work_schedule_id).Declares:
|
||||
for rel in tool.Ifc.get().by_id(props.active_work_schedule_id).Declares:
|
||||
for work_schedule in rel.RelatedObjects:
|
||||
if work_schedule.PredefinedType == "BASELINE":
|
||||
results.append(
|
||||
|
||||
@@ -232,7 +232,7 @@ class AddWorkSchedule(bpy.types.Operator, tool.Ifc.Operator):
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.prop(self, "name", text="Name")
|
||||
self.props = context.scene.BIMWorkScheduleProperties
|
||||
self.props = tool.Sequence.get_work_schedule_props()
|
||||
layout.prop(self.props, "work_schedule_predefined_types", text="Type")
|
||||
if self.props.work_schedule_predefined_types == "USERDEFINED":
|
||||
layout.prop(self.props, "object_type", text="Object type")
|
||||
@@ -247,10 +247,11 @@ class EditWorkSchedule(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def _execute(self, context):
|
||||
props = tool.Sequence.get_work_schedule_props()
|
||||
core.edit_work_schedule(
|
||||
tool.Ifc,
|
||||
tool.Sequence,
|
||||
work_schedule=tool.Ifc.get().by_id(context.scene.BIMWorkScheduleProperties.active_work_schedule_id),
|
||||
work_schedule=tool.Ifc.get().by_id(props.active_work_schedule_id),
|
||||
)
|
||||
|
||||
|
||||
@@ -376,11 +377,12 @@ class EditTaskTime(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def _execute(self, context):
|
||||
props = tool.Sequence.get_work_schedule_props()
|
||||
core.edit_task_time(
|
||||
tool.Ifc,
|
||||
tool.Sequence,
|
||||
tool.Resource,
|
||||
task_time=tool.Ifc.get().by_id(context.scene.BIMWorkScheduleProperties.active_task_time_id),
|
||||
task_time=tool.Ifc.get().by_id(props.active_task_time_id),
|
||||
)
|
||||
|
||||
|
||||
@@ -411,9 +413,8 @@ class EditTask(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def _execute(self, context):
|
||||
core.edit_task(
|
||||
tool.Ifc, tool.Sequence, task=tool.Ifc.get().by_id(context.scene.BIMWorkScheduleProperties.active_task_id)
|
||||
)
|
||||
props = tool.Sequence.get_work_schedule_props()
|
||||
core.edit_task(tool.Ifc, tool.Sequence, task=tool.Ifc.get().by_id(props.active_task_id))
|
||||
|
||||
|
||||
class CopyTaskAttribute(bpy.types.Operator, tool.Ifc.Operator):
|
||||
@@ -1083,10 +1084,11 @@ class EditSequenceAttributes(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def _execute(self, context):
|
||||
props = tool.Sequence.get_work_schedule_props()
|
||||
core.edit_sequence_attributes(
|
||||
tool.Ifc,
|
||||
tool.Sequence,
|
||||
rel_sequence=tool.Ifc.get().by_id(context.scene.BIMWorkScheduleProperties.active_sequence_id),
|
||||
rel_sequence=tool.Ifc.get().by_id(props.active_sequence_id),
|
||||
)
|
||||
|
||||
|
||||
@@ -1138,7 +1140,8 @@ class VisualiseWorkScheduleDate(bpy.types.Operator):
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return bool(bpy.context.scene.BIMWorkScheduleProperties.visualisation_start)
|
||||
props = tool.Sequence.get_work_schedule_props()
|
||||
return bool(props.visualisation_start)
|
||||
|
||||
def execute(self, context):
|
||||
core.visualise_work_schedule_date(tool.Sequence, work_schedule=tool.Ifc.get().by_id(self.work_schedule))
|
||||
@@ -1163,10 +1166,8 @@ class VisualiseWorkScheduleDateRange(bpy.types.Operator):
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
has_start, has_finish = (
|
||||
bpy.context.scene.BIMWorkScheduleProperties.visualisation_start,
|
||||
bpy.context.scene.BIMWorkScheduleProperties.visualisation_finish,
|
||||
)
|
||||
props = tool.Sequence.get_work_schedule_props()
|
||||
has_start, has_finish = props.visualisation_start, props.visualisation_finish
|
||||
return bool(has_start and has_finish) and not "-" in (has_start, has_finish)
|
||||
|
||||
def execute(self, context):
|
||||
@@ -1421,11 +1422,12 @@ class LoadAnimationColorScheme(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_description = "Loads the animation color scheme"
|
||||
|
||||
def _execute(self, context):
|
||||
group = tool.Ifc.get().by_id(int(context.scene.BIMAnimationProperties.saved_color_schemes))
|
||||
props = tool.Sequence.get_animation_props()
|
||||
group = tool.Ifc.get().by_id(int(props.saved_color_schemes))
|
||||
core.load_animation_color_scheme(tool.Sequence, scheme=group)
|
||||
|
||||
def draw(self, context):
|
||||
props = context.scene.BIMAnimationProperties
|
||||
props = tool.Sequence.get_animation_props()
|
||||
row = self.layout.row()
|
||||
row.prop(props, "saved_color_schemes", text="")
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
import bpy
|
||||
import isodate
|
||||
import ifcopenshell.api
|
||||
import ifcopenshell.api.sequence
|
||||
import ifcopenshell.util.attribute
|
||||
import ifcopenshell.util.date
|
||||
import bonsai.tool as tool
|
||||
@@ -26,6 +27,7 @@ import bonsai.core.sequence as core
|
||||
from bonsai.bim.module.sequence.data import SequenceData, AnimationColorSchemeData, refresh as refresh_sequence_data
|
||||
import bonsai.bim.module.resource.data
|
||||
import bonsai.bim.module.pset.data
|
||||
from mathutils import Color
|
||||
from bonsai.bim.prop import StrProperty, Attribute
|
||||
from dateutil import parser
|
||||
from bpy.types import PropertyGroup
|
||||
@@ -39,7 +41,7 @@ from bpy.props import (
|
||||
FloatVectorProperty,
|
||||
CollectionProperty,
|
||||
)
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, Literal
|
||||
|
||||
|
||||
def getTaskColumns(self, context):
|
||||
@@ -93,48 +95,48 @@ def update_active_task_inputs(self, context):
|
||||
tool.Sequence.load_task_inputs(inputs)
|
||||
|
||||
|
||||
def updateTaskName(self, context):
|
||||
props = context.scene.BIMWorkScheduleProperties
|
||||
def updateTaskName(self: "Task", context: bpy.types.Context) -> None:
|
||||
props = tool.Sequence.get_work_schedule_props()
|
||||
if not props.is_task_update_enabled or self.name == "Unnamed":
|
||||
return
|
||||
self.file = tool.Ifc.get()
|
||||
ifcopenshell.api.run(
|
||||
"sequence.edit_task",
|
||||
self.file,
|
||||
**{"task": self.file.by_id(self.ifc_definition_id), "attributes": {"Name": self.name}},
|
||||
ifc_file = tool.Ifc.get()
|
||||
ifcopenshell.api.sequence.edit_task(
|
||||
ifc_file,
|
||||
task=ifc_file.by_id(self.ifc_definition_id),
|
||||
attributes={"Name": self.name},
|
||||
)
|
||||
SequenceData.load()
|
||||
if props.active_task_id == self.ifc_definition_id:
|
||||
attribute = props.task_attributes.get("Name")
|
||||
attribute = props.task_attributes["Name"]
|
||||
attribute.string_value = self.name
|
||||
|
||||
|
||||
def updateTaskIdentification(self, context):
|
||||
props = context.scene.BIMWorkScheduleProperties
|
||||
def updateTaskIdentification(self: "Task", context: bpy.types.Context) -> None:
|
||||
props = tool.Sequence.get_work_schedule_props()
|
||||
if not props.is_task_update_enabled or self.identification == "XXX":
|
||||
return
|
||||
self.file = tool.Ifc.get()
|
||||
ifcopenshell.api.run(
|
||||
"sequence.edit_task",
|
||||
self.file,
|
||||
**{"task": self.file.by_id(self.ifc_definition_id), "attributes": {"Identification": self.identification}},
|
||||
ifc_file = tool.Ifc.get()
|
||||
ifcopenshell.api.sequence.edit_task(
|
||||
ifc_file,
|
||||
task=ifc_file.by_id(self.ifc_definition_id),
|
||||
attributes={"Identification": self.identification},
|
||||
)
|
||||
SequenceData.load()
|
||||
if props.active_task_id == self.ifc_definition_id:
|
||||
attribute = props.task_attributes.get("Identification")
|
||||
attribute = props.task_attributes["Identification"]
|
||||
attribute.string_value = self.identification
|
||||
|
||||
|
||||
def updateTaskTimeStart(self, context):
|
||||
def updateTaskTimeStart(self: "Task", context: bpy.types.Context) -> None:
|
||||
updateTaskTimeDateTime(self, context, "start")
|
||||
|
||||
|
||||
def updateTaskTimeFinish(self, context):
|
||||
def updateTaskTimeFinish(self: "Task", context: bpy.types.Context) -> None:
|
||||
updateTaskTimeDateTime(self, context, "finish")
|
||||
|
||||
|
||||
def updateTaskTimeDateTime(self, context, startfinish):
|
||||
props = context.scene.BIMWorkScheduleProperties
|
||||
def updateTaskTimeDateTime(self: "Task", context: bpy.types.Context, startfinish: Literal["start", "finish"]) -> None:
|
||||
props = tool.Sequence.get_work_schedule_props()
|
||||
|
||||
if not props.is_task_update_enabled:
|
||||
return
|
||||
@@ -149,7 +151,7 @@ def updateTaskTimeDateTime(self, context, startfinish):
|
||||
if startfinish_value == "-":
|
||||
return
|
||||
|
||||
self.file = tool.Ifc.get()
|
||||
ifc_file = tool.Ifc.get()
|
||||
|
||||
try:
|
||||
startfinish_datetime = parser.isoparse(startfinish_value)
|
||||
@@ -160,11 +162,11 @@ def updateTaskTimeDateTime(self, context, startfinish):
|
||||
setattr(self, startfinish, "-")
|
||||
return
|
||||
|
||||
task = self.file.by_id(self.ifc_definition_id)
|
||||
task = ifc_file.by_id(self.ifc_definition_id)
|
||||
if task.TaskTime:
|
||||
task_time = task.TaskTime
|
||||
else:
|
||||
task_time = ifcopenshell.api.run("sequence.add_task_time", self.file, task=task)
|
||||
task_time = ifcopenshell.api.sequence.add_task_time(ifc_file, task=task)
|
||||
SequenceData.load()
|
||||
|
||||
startfinish_key = "Schedule" + startfinish.capitalize()
|
||||
@@ -174,17 +176,17 @@ def updateTaskTimeDateTime(self, context, startfinish):
|
||||
setattr(self, startfinish, canonical_startfinish_value)
|
||||
return
|
||||
|
||||
ifcopenshell.api.run(
|
||||
"sequence.edit_task_time",
|
||||
self.file,
|
||||
**{"task_time": task_time, "attributes": {startfinish_key: startfinish_datetime}},
|
||||
ifcopenshell.api.sequence.edit_task_time(
|
||||
ifc_file,
|
||||
task_time=task_time,
|
||||
attributes={startfinish_key: startfinish_datetime},
|
||||
)
|
||||
SequenceData.load()
|
||||
bpy.ops.bim.load_task_properties()
|
||||
|
||||
|
||||
def updateTaskDuration(self, context):
|
||||
props = context.scene.BIMWorkScheduleProperties
|
||||
def updateTaskDuration(self: "Task", context: bpy.types.Context) -> None:
|
||||
props = tool.Sequence.get_work_schedule_props()
|
||||
if not props.is_task_update_enabled:
|
||||
return
|
||||
|
||||
@@ -196,12 +198,17 @@ def updateTaskDuration(self, context):
|
||||
self.duration = "-"
|
||||
return
|
||||
|
||||
task = tool.Ifc.get().by_id(self.ifc_definition_id)
|
||||
ifc_file = tool.Ifc.get()
|
||||
task = ifc_file.by_id(self.ifc_definition_id)
|
||||
if task.TaskTime:
|
||||
task_time = task.TaskTime
|
||||
else:
|
||||
task_time = tool.Ifc.run("sequence.add_task_time", task=task)
|
||||
tool.Ifc.run("sequence.edit_task_time", task_time=task_time, attributes={"ScheduleDuration": duration})
|
||||
task_time = ifcopenshell.api.sequence.add_task_time(ifc_file, task=task)
|
||||
ifcopenshell.api.sequence.edit_task_time(
|
||||
ifc_file,
|
||||
task_time=task_time,
|
||||
attributes={"ScheduleDuration": duration},
|
||||
)
|
||||
core.load_task_properties(tool.Sequence)
|
||||
tool.Sequence.refresh_task_resources()
|
||||
|
||||
@@ -212,15 +219,19 @@ def get_schedule_predefined_types(self, context):
|
||||
return SequenceData.data["schedule_predefined_types_enum"]
|
||||
|
||||
|
||||
def update_visualisation_start(self, context):
|
||||
def update_visualisation_start(self: "BIMWorkScheduleProperties", context: bpy.types.Context) -> None:
|
||||
update_visualisation_start_finish(self, context, "visualisation_start")
|
||||
|
||||
|
||||
def update_visualisation_finish(self, context):
|
||||
def update_visualisation_finish(self: "BIMWorkScheduleProperties", context: bpy.types.Context) -> None:
|
||||
update_visualisation_start_finish(self, context, "visualisation_finish")
|
||||
|
||||
|
||||
def update_visualisation_start_finish(self, context, startfinish):
|
||||
def update_visualisation_start_finish(
|
||||
self: "BIMWorkScheduleProperties",
|
||||
context: bpy.types.Context,
|
||||
startfinish: Literal["visualisation_start", "visualisation_finish"],
|
||||
) -> None:
|
||||
def canonicalise_time(time):
|
||||
if not time:
|
||||
return "-"
|
||||
@@ -243,34 +254,34 @@ def update_visualisation_start_finish(self, context, startfinish):
|
||||
def update_color_full(self, context):
|
||||
material = bpy.data.materials.get("color_full")
|
||||
if material:
|
||||
color_full = bpy.context.scene.BIMAnimationProperties.color_full
|
||||
props = tool.Sequence.get_animation_props()
|
||||
inputs = tool.Blender.get_material_node(material, "BSDF_PRINCIPLED").inputs
|
||||
color = inputs["Base Color"].default_value
|
||||
color[0] = color_full.r
|
||||
color[1] = color_full.g
|
||||
color[2] = color_full.b
|
||||
color[0] = props.color_full.r
|
||||
color[1] = props.color_full.g
|
||||
color[2] = props.color_full.b
|
||||
|
||||
|
||||
def update_color_progress(self, context):
|
||||
material = bpy.data.materials.get("color_progress")
|
||||
if material:
|
||||
color_progress = bpy.context.scene.BIMAnimationProperties.color_progress
|
||||
props = tool.Sequence.get_animation_props()
|
||||
inputs = tool.Blender.get_material_node(material, "BSDF_PRINCIPLED").inputs
|
||||
color = inputs["Base Color"].default_value
|
||||
color[0] = color_progress.r
|
||||
color[1] = color_progress.g
|
||||
color[2] = color_progress.b
|
||||
color[0] = props.color_progress.r
|
||||
color[1] = props.color_progress.g
|
||||
color[2] = props.color_progress.b
|
||||
|
||||
|
||||
def update_sort_reversed(self, context):
|
||||
if context.scene.BIMWorkScheduleProperties.active_work_schedule_id:
|
||||
def update_sort_reversed(self: "BIMWorkScheduleProperties", context: bpy.types.Context) -> None:
|
||||
if self.active_work_schedule_id:
|
||||
core.load_task_tree(
|
||||
tool.Sequence,
|
||||
work_schedule=tool.Ifc.get().by_id(context.scene.BIMWorkScheduleProperties.active_work_schedule_id),
|
||||
work_schedule=tool.Ifc.get().by_id(self.active_work_schedule_id),
|
||||
)
|
||||
|
||||
|
||||
def update_filter_by_active_schedule(self, context):
|
||||
def update_filter_by_active_schedule(self: "BIMWorkScheduleProperties", context: bpy.types.Context) -> None:
|
||||
if obj := context.active_object:
|
||||
product = tool.Ifc.get_entity(obj)
|
||||
assert product
|
||||
@@ -314,8 +325,9 @@ def updateAssignedResourceUsage(self, context):
|
||||
bonsai.bim.module.pset.data.refresh()
|
||||
|
||||
|
||||
def update_task_bar_list(self, context):
|
||||
if not context.scene.BIMWorkScheduleProperties.is_task_update_enabled:
|
||||
def update_task_bar_list(self: "Task", context: bpy.types.Context) -> None:
|
||||
props = tool.Sequence.get_work_schedule_props()
|
||||
if not props.is_task_update_enabled:
|
||||
return
|
||||
if self.has_bar_visual:
|
||||
tool.Sequence.add_task_bar(self.ifc_definition_id)
|
||||
@@ -368,17 +380,30 @@ class WorkPlan(PropertyGroup):
|
||||
name: StringProperty(name="Name")
|
||||
ifc_definition_id: IntProperty(name="IFC Definition ID")
|
||||
|
||||
if TYPE_CHECKING:
|
||||
name: str
|
||||
ifc_definition_id: int
|
||||
|
||||
|
||||
class TaskResource(PropertyGroup):
|
||||
name: StringProperty(name="Name", update=updateAssignedResourceName)
|
||||
ifc_definition_id: IntProperty(name="IFC Definition ID")
|
||||
schedule_usage: FloatProperty(name="Schedule Usage", update=updateAssignedResourceUsage)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
name: str
|
||||
ifc_definition_id: int
|
||||
schedule_usage: float
|
||||
|
||||
|
||||
class TaskProduct(PropertyGroup):
|
||||
name: StringProperty(name="Name")
|
||||
ifc_definition_id: IntProperty(name="IFC Definition ID")
|
||||
|
||||
if TYPE_CHECKING:
|
||||
name: str
|
||||
ifc_definition_id: int
|
||||
|
||||
|
||||
class BIMWorkPlanProperties(PropertyGroup):
|
||||
work_plan_attributes: CollectionProperty(name="Work Plan Attributes", type=Attribute)
|
||||
@@ -388,6 +413,14 @@ class BIMWorkPlanProperties(PropertyGroup):
|
||||
active_work_plan_id: IntProperty(name="Active Work Plan Id")
|
||||
work_schedules: EnumProperty(items=getWorkSchedules, name="Work Schedules")
|
||||
|
||||
if TYPE_CHECKING:
|
||||
work_plan_attributes: bpy.types.bpy_prop_collection_idprop[Attribute]
|
||||
editing_type: str
|
||||
work_plans: bpy.types.bpy_prop_collection_idprop[WorkPlan]
|
||||
active_work_plan_index: int
|
||||
active_work_plan_id: int
|
||||
work_schedules: str
|
||||
|
||||
|
||||
class ISODuration(PropertyGroup):
|
||||
name: StringProperty(name="Name")
|
||||
@@ -398,16 +431,33 @@ class ISODuration(PropertyGroup):
|
||||
minutes: IntProperty(name="Minutes", default=0)
|
||||
seconds: IntProperty(name="Seconds", default=0)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
name: str
|
||||
years: int
|
||||
months: int
|
||||
days: int
|
||||
hours: int
|
||||
minutes: int
|
||||
seconds: int
|
||||
|
||||
|
||||
class IFCStatus(PropertyGroup):
|
||||
name: StringProperty(name="Name")
|
||||
is_visible: BoolProperty(name="Is Visible", default=True, update=lambda x, y: bpy.ops.bim.activate_status_filters())
|
||||
|
||||
if TYPE_CHECKING:
|
||||
name: str
|
||||
is_visible: bool
|
||||
|
||||
|
||||
class BIMStatusProperties(PropertyGroup):
|
||||
is_enabled: BoolProperty(name="Is Enabled")
|
||||
statuses: CollectionProperty(name="Statuses", type=IFCStatus)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
is_enabled: bool
|
||||
statuses: bpy.types.bpy_prop_collection_idprop[IFCStatus]
|
||||
|
||||
|
||||
class BIMWorkScheduleProperties(PropertyGroup):
|
||||
work_schedule_predefined_types: EnumProperty(
|
||||
@@ -493,6 +543,66 @@ class BIMWorkScheduleProperties(PropertyGroup):
|
||||
name="Filter By Active Schedule", default=False, update=update_filter_by_active_schedule
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
work_schedule_predefined_types: str
|
||||
object_type: str
|
||||
durations_attributes: bpy.types.bpy_prop_collection_idprop[ISODuration]
|
||||
work_calendars: str
|
||||
work_schedule_attributes: bpy.types.bpy_prop_collection_idprop[Attribute]
|
||||
editing_type: str
|
||||
editing_task_type: str
|
||||
active_work_schedule_index: int
|
||||
active_work_schedule_id: int
|
||||
active_task_index: int
|
||||
active_task_id: int
|
||||
highlighted_task_id: int
|
||||
task_attributes: bpy.types.bpy_prop_collection_idprop[Attribute]
|
||||
should_show_visualisation_ui: bool
|
||||
should_show_task_bar_selection: bool
|
||||
should_show_snapshot_ui: bool
|
||||
should_show_column_ui: bool
|
||||
columns: bpy.types.bpy_prop_collection_idprop[Attribute]
|
||||
active_column_index: int
|
||||
sort_column: str
|
||||
is_sort_reversed: bool
|
||||
column_types: str
|
||||
task_columns: str
|
||||
task_time_columns: str
|
||||
other_columns: str
|
||||
active_task_time_id: int
|
||||
task_time_attributes: bpy.types.bpy_prop_collection_idprop[Attribute]
|
||||
contracted_tasks: str
|
||||
task_bars: str
|
||||
is_task_update_enabled: bool
|
||||
editing_sequence_type: str
|
||||
active_sequence_id: int
|
||||
sequence_attributes: bpy.types.bpy_prop_collection_idprop[Attribute]
|
||||
lag_time_attributes: bpy.types.bpy_prop_collection_idprop[Attribute]
|
||||
visualisation_start: str
|
||||
visualisation_finish: str
|
||||
speed_multiplier: float
|
||||
speed_animation_duration: str
|
||||
speed_animation_frames: int
|
||||
speed_real_duration: str
|
||||
speed_types: str
|
||||
task_resources: bpy.types.bpy_prop_collection_idprop[TaskResource]
|
||||
active_task_resource_index: int
|
||||
task_inputs: bpy.types.bpy_prop_collection_idprop[TaskProduct]
|
||||
active_task_input_index: int
|
||||
task_outputs: bpy.types.bpy_prop_collection_idprop[TaskProduct]
|
||||
active_task_output_index: int
|
||||
show_nested_outputs: bool
|
||||
show_nested_resources: bool
|
||||
show_nested_inputs: bool
|
||||
product_input_tasks: bpy.types.bpy_prop_collection_idprop[TaskProduct]
|
||||
product_output_tasks: bpy.types.bpy_prop_collection_idprop[TaskProduct]
|
||||
active_product_output_task_index: int
|
||||
active_product_input_task_index: int
|
||||
enable_reorder: bool
|
||||
show_task_operators: bool
|
||||
should_show_schedule_baseline_ui: bool
|
||||
filter_by_active_schedule: bool
|
||||
|
||||
|
||||
class BIMTaskTreeProperties(PropertyGroup):
|
||||
# This belongs by itself for performance reasons. https://developer.blender.org/T87737
|
||||
@@ -507,11 +617,19 @@ class WorkCalendar(PropertyGroup):
|
||||
name: StringProperty(name="Name")
|
||||
ifc_definition_id: IntProperty(name="IFC Definition ID")
|
||||
|
||||
if TYPE_CHECKING:
|
||||
name: str
|
||||
ifc_definition_id: int
|
||||
|
||||
|
||||
class RecurrenceComponent(PropertyGroup):
|
||||
name: StringProperty(name="Name")
|
||||
is_specified: BoolProperty(name="Is Specified")
|
||||
|
||||
if TYPE_CHECKING:
|
||||
name: str
|
||||
is_specified: bool
|
||||
|
||||
|
||||
class BIMWorkCalendarProperties(PropertyGroup):
|
||||
work_calendar_attributes: CollectionProperty(name="Work Calendar Attributes", type=Attribute)
|
||||
@@ -542,6 +660,22 @@ class BIMWorkCalendarProperties(PropertyGroup):
|
||||
start_time: StringProperty(name="Start Time")
|
||||
end_time: StringProperty(name="End Time")
|
||||
|
||||
if TYPE_CHECKING:
|
||||
work_calendar_attributes: bpy.types.bpy_prop_collection_idprop[Attribute]
|
||||
work_time_attributes: bpy.types.bpy_prop_collection_idprop[Attribute]
|
||||
editing_type: str
|
||||
active_work_calendar_id: int
|
||||
active_work_time_id: int
|
||||
day_components: bpy.types.bpy_prop_collection_idprop[RecurrenceComponent]
|
||||
weekday_components: bpy.types.bpy_prop_collection_idprop[RecurrenceComponent]
|
||||
month_components: bpy.types.bpy_prop_collection_idprop[RecurrenceComponent]
|
||||
position: int
|
||||
interval: int
|
||||
occurrences: int
|
||||
recurrence_types: str
|
||||
start_time: str
|
||||
end_time: str
|
||||
|
||||
|
||||
def update_selected_date(self: "DatePickerProperties", context: bpy.types.Context) -> None:
|
||||
# `include_time` is `True`, otherwise time props are not displayed in UI.
|
||||
@@ -561,6 +695,13 @@ class DatePickerProperties(PropertyGroup):
|
||||
selected_min: IntProperty(min=0, max=59, update=update_selected_date)
|
||||
selected_sec: IntProperty(min=0, max=59, update=update_selected_date)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
display_date: str
|
||||
selected_date: str
|
||||
selected_hour: int
|
||||
selected_min: int
|
||||
selected_sec: int
|
||||
|
||||
|
||||
class BIMDateTextProperties(PropertyGroup):
|
||||
start_frame: IntProperty(name="Start Frame")
|
||||
@@ -568,6 +709,12 @@ class BIMDateTextProperties(PropertyGroup):
|
||||
start: StringProperty(name="Start")
|
||||
finish: StringProperty(name="Finish")
|
||||
|
||||
if TYPE_CHECKING:
|
||||
start_frame: int
|
||||
total_frames: int
|
||||
start: str
|
||||
finish: str
|
||||
|
||||
|
||||
class BIMTaskTypeColor(PropertyGroup):
|
||||
name: StringProperty(name="Name")
|
||||
@@ -580,6 +727,11 @@ class BIMTaskTypeColor(PropertyGroup):
|
||||
max=1.0,
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
name: str
|
||||
animation_type: str
|
||||
color: tuple[float, float, float]
|
||||
|
||||
|
||||
class BIMAnimationProperties(PropertyGroup):
|
||||
is_editing: BoolProperty(name="Is Loaded", default=False)
|
||||
@@ -607,3 +759,14 @@ class BIMAnimationProperties(PropertyGroup):
|
||||
update=update_color_progress,
|
||||
)
|
||||
should_show_task_bar_options: BoolProperty(name="Show Task Bar Options", default=False)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
is_editing: bool
|
||||
saved_color_schemes: str
|
||||
active_color_component_outputs_index: int
|
||||
active_color_component_inputs_index: int
|
||||
task_input_colors: bpy.types.bpy_prop_collection_idprop[BIMTaskTypeColor]
|
||||
task_output_colors: bpy.types.bpy_prop_collection_idprop[BIMTaskTypeColor]
|
||||
color_full: Color
|
||||
color_progress: Color
|
||||
should_show_task_bar_options: bool
|
||||
|
||||
@@ -30,7 +30,11 @@ from bonsai.bim.module.sequence.data import (
|
||||
TaskICOMData,
|
||||
AnimationColorSchemeData,
|
||||
)
|
||||
from typing import Any, Optional
|
||||
from typing import Any, Optional, TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from bonsai.bim.prop import Attribute
|
||||
from bonsai.bim.module.sequence.prop import BIMWorkScheduleProperties, BIMTaskTreeProperties, Task
|
||||
|
||||
|
||||
class BIM_PT_status(Panel):
|
||||
@@ -154,7 +158,7 @@ class BIM_PT_work_schedules(Panel):
|
||||
SequenceData.load()
|
||||
if not WorkScheduleData.is_loaded:
|
||||
WorkScheduleData.load()
|
||||
self.props = context.scene.BIMWorkScheduleProperties
|
||||
self.props = tool.Sequence.get_work_schedule_props()
|
||||
self.tprops = tool.Sequence.get_task_tree_props()
|
||||
|
||||
if not self.props.active_work_schedule_id:
|
||||
@@ -479,14 +483,14 @@ class BIM_PT_animation_tools(Panel):
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
props = context.scene.BIMWorkScheduleProperties
|
||||
props = tool.Sequence.get_work_schedule_props()
|
||||
if props.active_work_schedule_id:
|
||||
return True
|
||||
return False
|
||||
|
||||
def draw(self, context):
|
||||
self.props = context.scene.BIMWorkScheduleProperties
|
||||
self.animation_props = context.scene.BIMAnimationProperties
|
||||
self.props = tool.Sequence.get_work_schedule_props()
|
||||
self.animation_props = tool.Sequence.get_animation_props()
|
||||
row = self.layout.row(align=True)
|
||||
row.alignment = "RIGHT"
|
||||
row.prop(self.props, "should_show_visualisation_ui", text="Animation Settings", icon="SETTINGS")
|
||||
@@ -598,7 +602,7 @@ class BIM_PT_animation_Color_Scheme(Panel):
|
||||
if not AnimationColorSchemeData.is_loaded:
|
||||
AnimationColorSchemeData.load()
|
||||
|
||||
self.animation_props = context.scene.BIMAnimationProperties
|
||||
self.animation_props = tool.Sequence.get_animation_props()
|
||||
row = self.layout.row(align=True)
|
||||
row.alignment = "RIGHT"
|
||||
row.operator("bim.load_default_animation_color_scheme", text="Load default", icon="SEQUENCE_COLOR_04")
|
||||
@@ -645,7 +649,7 @@ class BIM_PT_task_icom(Panel):
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
props = context.scene.BIMWorkScheduleProperties
|
||||
props = tool.Sequence.get_work_schedule_props()
|
||||
if not props.active_work_schedule_id:
|
||||
return False
|
||||
tprops = tool.Sequence.get_task_tree_props()
|
||||
@@ -658,7 +662,7 @@ class BIM_PT_task_icom(Panel):
|
||||
if not TaskICOMData.is_loaded:
|
||||
TaskICOMData.load()
|
||||
|
||||
self.props = context.scene.BIMWorkScheduleProperties
|
||||
self.props = tool.Sequence.get_work_schedule_props()
|
||||
self.tprops = tool.Sequence.get_task_tree_props()
|
||||
task = self.tprops.tasks[self.props.active_task_index]
|
||||
|
||||
@@ -751,8 +755,17 @@ class BIM_PT_task_icom(Panel):
|
||||
|
||||
|
||||
class BIM_UL_task_columns(UIList):
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
||||
props = context.scene.BIMWorkScheduleProperties
|
||||
def draw_item(
|
||||
self,
|
||||
context,
|
||||
layout: bpy.types.UILayout,
|
||||
data: "BIMWorkScheduleProperties",
|
||||
item: "Attribute",
|
||||
icon,
|
||||
active_data,
|
||||
active_propname,
|
||||
):
|
||||
props = tool.Sequence.get_work_schedule_props()
|
||||
if item:
|
||||
row = layout.row(align=True)
|
||||
row.prop(item, "name", emboss=False, text="")
|
||||
@@ -820,7 +833,7 @@ class BIM_UL_product_output_tasks(UIList):
|
||||
class BIM_UL_tasks(UIList):
|
||||
@classmethod
|
||||
def draw_header(cls, layout: bpy.types.UILayout):
|
||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||
props = tool.Sequence.get_work_schedule_props()
|
||||
row = layout.row(align=True)
|
||||
|
||||
split1 = row.split(factor=0.1)
|
||||
@@ -829,9 +842,18 @@ class BIM_UL_tasks(UIList):
|
||||
split2.label(text="Name")
|
||||
cls.draw_custom_columns(props, split2, header=True)
|
||||
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
||||
def draw_item(
|
||||
self,
|
||||
context,
|
||||
layout: bpy.types.UILayout,
|
||||
data: "BIMTaskTreeProperties",
|
||||
item: "Task",
|
||||
icon,
|
||||
active_data,
|
||||
active_propname,
|
||||
):
|
||||
if item:
|
||||
self.props = context.scene.BIMWorkScheduleProperties
|
||||
self.props = tool.Sequence.get_work_schedule_props()
|
||||
task = SequenceData.data["tasks"][item.ifc_definition_id]
|
||||
row = layout.row(align=True)
|
||||
|
||||
@@ -1140,7 +1162,7 @@ class BIM_PT_4D_Tools(Panel):
|
||||
bl_parent_id = "BIM_PT_tab_sequence"
|
||||
|
||||
def draw(self, context):
|
||||
self.props = context.scene.BIMWorkScheduleProperties
|
||||
self.props = tool.Sequence.get_work_schedule_props()
|
||||
row = self.layout.row()
|
||||
row.operator("bim.load_product_related_tasks", text="Load Tasks", icon="FILE_REFRESH")
|
||||
row.prop(self.props, "filter_by_active_schedule", text="Filter by Active Schedule")
|
||||
|
||||
@@ -214,11 +214,11 @@ class Blender(bonsai.core.tool.Blender):
|
||||
return omprops.active_material_set_item_id
|
||||
elif obj_type == "Task":
|
||||
tprops = tool.Sequence.get_task_tree_props()
|
||||
return tprops.tasks[context.scene.BIMWorkScheduleProperties.active_task_index].ifc_definition_id
|
||||
wsprops = tool.Sequence.get_work_schedule_props()
|
||||
return tprops.tasks[wsprops.active_task_index].ifc_definition_id
|
||||
elif obj_type == "Cost":
|
||||
return context.scene.BIMCostProperties.cost_items[
|
||||
context.scene.BIMCostProperties.active_cost_item_index
|
||||
].ifc_definition_id
|
||||
cost_props = tool.Cost.get_cost_props()
|
||||
return cost_props.cost_items[cost_props.active_cost_item_index].ifc_definition_id
|
||||
elif obj_type == "Resource":
|
||||
return context.scene.BIMResourceTreeProperties.resources[
|
||||
context.scene.BIMResourceProperties.active_resource_index
|
||||
@@ -227,7 +227,8 @@ class Blender(bonsai.core.tool.Blender):
|
||||
props = tool.Profile.get_profile_props()
|
||||
return props.profiles[props.active_profile_index].ifc_definition_id
|
||||
elif obj_type == "WorkSchedule":
|
||||
return context.scene.BIMWorkScheduleProperties.active_work_schedule_id
|
||||
wsprops = tool.Sequence.get_work_schedule_props()
|
||||
return wsprops.active_work_schedule_id
|
||||
elif obj_type == "Group":
|
||||
prop = context.scene.BIMGroupProperties
|
||||
return prop.groups[prop.active_group_index].ifc_definition_id
|
||||
|
||||
+108
-74
@@ -1,4 +1,22 @@
|
||||
import os
|
||||
# Bonsai - OpenBIM Blender Add-on
|
||||
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>, 2022 Yassine Oualid <yassine@sigmadimensions.com>
|
||||
#
|
||||
# This file is part of Bonsai.
|
||||
#
|
||||
# Bonsai is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Bonsai is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import annotations
|
||||
import bpy
|
||||
import bonsai.core.tool
|
||||
import bonsai.tool as tool
|
||||
@@ -10,27 +28,35 @@ import ifcopenshell.util.unit
|
||||
import bonsai.bim.helper
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import Optional, Any, Generator, Union, Literal
|
||||
from typing import Optional, Any, Generator, Union, Literal, TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from bonsai.bim.module.cost.prop import BIMCostProperties, CostItemQuantity
|
||||
|
||||
|
||||
class Cost(bonsai.core.tool.Cost):
|
||||
|
||||
RELATED_OBJECT_TYPE = Literal["PRODUCT", "PROCESS", "RESOURCE"]
|
||||
|
||||
@classmethod
|
||||
def get_cost_props(cls) -> "BIMCostProperties":
|
||||
return bpy.context.scene.BIMCostProperties
|
||||
|
||||
@classmethod
|
||||
def get_cost_schedule_attributes(cls) -> dict[str, Any]:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
props = cls.get_cost_props()
|
||||
return bonsai.bim.helper.export_attributes(props.cost_schedule_attributes)
|
||||
|
||||
@classmethod
|
||||
def disable_editing_cost_schedule(cls) -> None:
|
||||
cls.store_active_schedule_columns()
|
||||
bpy.context.scene.BIMCostProperties.active_cost_schedule_id = 0
|
||||
props = cls.get_cost_props()
|
||||
props.active_cost_schedule_id = 0
|
||||
cls.disable_editing_cost_item()
|
||||
|
||||
@classmethod
|
||||
def load_active_schedule_columns(cls) -> None:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
props = cls.get_cost_props()
|
||||
active_columns = props.columns
|
||||
storage = props.columns_storage
|
||||
active_cost_schedule_id = cls.get_active_cost_schedule().id()
|
||||
@@ -53,7 +79,7 @@ class Cost(bonsai.core.tool.Cost):
|
||||
|
||||
@classmethod
|
||||
def store_active_schedule_columns(cls) -> None:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
props = cls.get_cost_props()
|
||||
active_columns = props.columns
|
||||
storage = props.columns_storage
|
||||
active_cost_schedule_id = cls.get_active_cost_schedule().id()
|
||||
@@ -67,7 +93,7 @@ class Cost(bonsai.core.tool.Cost):
|
||||
|
||||
@classmethod
|
||||
def remove_stored_schedule_columns(cls, cost_schedule: ifcopenshell.entity_instance) -> None:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
props = cls.get_cost_props()
|
||||
storage = props.columns_storage
|
||||
active_cost_schedule_id = cost_schedule.id()
|
||||
|
||||
@@ -79,8 +105,9 @@ class Cost(bonsai.core.tool.Cost):
|
||||
|
||||
@classmethod
|
||||
def enable_editing_cost_schedule_attributes(cls, cost_schedule: ifcopenshell.entity_instance) -> None:
|
||||
bpy.context.scene.BIMCostProperties.active_cost_schedule_id = cost_schedule.id()
|
||||
bpy.context.scene.BIMCostProperties.is_editing = "COST_SCHEDULE_ATTRIBUTES"
|
||||
props = cls.get_cost_props()
|
||||
props.active_cost_schedule_id = cost_schedule.id()
|
||||
props.is_editing = "COST_SCHEDULE_ATTRIBUTES"
|
||||
|
||||
@classmethod
|
||||
def load_cost_schedule_attributes(cls, cost_schedule: ifcopenshell.entity_instance) -> None:
|
||||
@@ -89,13 +116,13 @@ class Cost(bonsai.core.tool.Cost):
|
||||
prop.string_value = "" if prop.is_null else ifcopenshell.util.date.ifc2datetime(data[name]).isoformat()
|
||||
return True
|
||||
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
props = cls.get_cost_props()
|
||||
props.cost_schedule_attributes.clear()
|
||||
bonsai.bim.helper.import_attributes2(cost_schedule, props.cost_schedule_attributes, callback=special_import)
|
||||
|
||||
@classmethod
|
||||
def enable_editing_cost_items(cls, cost_schedule: ifcopenshell.entity_instance) -> None:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
props = cls.get_cost_props()
|
||||
props.active_cost_schedule_id = cost_schedule.id()
|
||||
props.is_editing = "COST_ITEMS"
|
||||
|
||||
@@ -123,7 +150,7 @@ class Cost(bonsai.core.tool.Cost):
|
||||
|
||||
@classmethod
|
||||
def load_cost_schedule_tree(cls) -> None:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
props = cls.get_cost_props()
|
||||
props.is_cost_update_enabled = False
|
||||
cost_schedule = tool.Ifc.get().by_id(props.active_cost_schedule_id)
|
||||
props.cost_items.clear()
|
||||
@@ -137,7 +164,7 @@ class Cost(bonsai.core.tool.Cost):
|
||||
|
||||
@classmethod
|
||||
def expand_cost_item(cls, cost_item: ifcopenshell.entity_instance) -> None:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
props = cls.get_cost_props()
|
||||
if not hasattr(cls, "contracted_cost_items"):
|
||||
cls.contracted_cost_items = json.loads(props.contracted_cost_items)
|
||||
if cost_item.id() in cls.contracted_cost_items:
|
||||
@@ -146,7 +173,7 @@ class Cost(bonsai.core.tool.Cost):
|
||||
|
||||
@classmethod
|
||||
def expand_cost_items(cls) -> None:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
props = cls.get_cost_props()
|
||||
cls.contracted_cost_items = json.loads(props.contracted_cost_items)
|
||||
for cost_item in props.cost_items:
|
||||
if cost_item.ifc_definition_id in cls.contracted_cost_items:
|
||||
@@ -155,7 +182,7 @@ class Cost(bonsai.core.tool.Cost):
|
||||
|
||||
@classmethod
|
||||
def contract_cost_item(cls, cost_item: ifcopenshell.entity_instance) -> None:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
props = cls.get_cost_props()
|
||||
if not hasattr(cls, "contracted_cost_items"):
|
||||
cls.contracted_cost_items = json.loads(props.contracted_cost_items)
|
||||
cls.contracted_cost_items.append(cost_item.id())
|
||||
@@ -163,7 +190,7 @@ class Cost(bonsai.core.tool.Cost):
|
||||
|
||||
@classmethod
|
||||
def contract_cost_items(cls) -> None:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
props = cls.get_cost_props()
|
||||
if not hasattr(cls, "contracted_cost_items"):
|
||||
cls.contracted_cost_items = json.loads(props.contracted_cost_items)
|
||||
for cost_item in props.cost_items:
|
||||
@@ -173,7 +200,7 @@ class Cost(bonsai.core.tool.Cost):
|
||||
|
||||
@classmethod
|
||||
def clean_up_cost_item_tree(cls, cost_item_id: int) -> None:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
props = cls.get_cost_props()
|
||||
if not hasattr(cls, "contracted_cost_items"):
|
||||
cls.contracted_cost_items = json.loads(props.contracted_cost_items)
|
||||
if props.active_cost_item_id == cost_item_id:
|
||||
@@ -185,35 +212,37 @@ class Cost(bonsai.core.tool.Cost):
|
||||
|
||||
@classmethod
|
||||
def enable_editing_cost_item_attributes(cls, cost_item: ifcopenshell.entity_instance):
|
||||
bpy.context.scene.BIMCostProperties.active_cost_item_id = cost_item.id()
|
||||
bpy.context.scene.BIMCostProperties.cost_item_editing_type = "ATTRIBUTES"
|
||||
props = cls.get_cost_props()
|
||||
props.active_cost_item_id = cost_item.id()
|
||||
props.cost_item_editing_type = "ATTRIBUTES"
|
||||
|
||||
@classmethod
|
||||
def load_cost_item_attributes(cls, cost_item: ifcopenshell.entity_instance) -> None:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
props = cls.get_cost_props()
|
||||
props.cost_item_attributes.clear()
|
||||
bonsai.bim.helper.import_attributes2(cost_item, props.cost_item_attributes)
|
||||
|
||||
@classmethod
|
||||
def disable_editing_cost_item(cls) -> None:
|
||||
bpy.context.scene.BIMCostProperties.active_cost_item_id = 0
|
||||
bpy.context.scene.BIMCostProperties.change_cost_item_parent = False
|
||||
props = cls.get_cost_props()
|
||||
props.active_cost_item_id = 0
|
||||
props.change_cost_item_parent = False
|
||||
|
||||
@classmethod
|
||||
def get_cost_item_attributes(cls) -> dict[str, Any]:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
props = cls.get_cost_props()
|
||||
return bonsai.bim.helper.export_attributes(props.cost_item_attributes)
|
||||
|
||||
@classmethod
|
||||
def get_active_cost_item(cls) -> Union[ifcopenshell.entity_instance, None]:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
props = cls.get_cost_props()
|
||||
if not props.active_cost_item_id:
|
||||
return None
|
||||
return tool.Ifc.get().by_id(bpy.context.scene.BIMCostProperties.active_cost_item_id)
|
||||
return tool.Ifc.get().by_id(props.active_cost_item_id)
|
||||
|
||||
@classmethod
|
||||
def get_highlighted_cost_item(cls) -> Union[ifcopenshell.entity_instance, None]:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
props = cls.get_cost_props()
|
||||
if not props.active_cost_schedule_id:
|
||||
return
|
||||
if props.active_cost_item_index < len(props.cost_items):
|
||||
@@ -226,7 +255,7 @@ class Cost(bonsai.core.tool.Cost):
|
||||
cost_item = cls.get_highlighted_cost_item()
|
||||
if not cost_item:
|
||||
return
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
props = cls.get_cost_props()
|
||||
props.cost_item_type_products.clear()
|
||||
# TODO implement process and resource types
|
||||
# props.cost_item_processes.clear()
|
||||
@@ -248,7 +277,9 @@ class Cost(bonsai.core.tool.Cost):
|
||||
cls, cost_item: ifcopenshell.entity_instance, related_object_type: RELATED_OBJECT_TYPE
|
||||
) -> None:
|
||||
def create_list_items(
|
||||
collection: bpy.types.CollectionProperty, cost_item: ifcopenshell.entity_instance, is_deep: bool
|
||||
collection: bpy.types.bpy_prop_collection_idprop[CostItemQuantity],
|
||||
cost_item: ifcopenshell.entity_instance,
|
||||
is_deep: bool,
|
||||
) -> None:
|
||||
products = cls.get_cost_item_assignments(cost_item, filter_by_type=related_object_type, is_deep=False)
|
||||
for product in products:
|
||||
@@ -262,18 +293,18 @@ class Cost(bonsai.core.tool.Cost):
|
||||
for cost_item in ifcopenshell.util.cost.get_nested_cost_items(cost_item, is_deep):
|
||||
create_list_items(collection, cost_item, is_deep=False)
|
||||
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
props = cls.get_cost_props()
|
||||
if related_object_type == "PRODUCT":
|
||||
props.cost_item_products.clear()
|
||||
is_deep = bpy.context.scene.BIMCostProperties.show_nested_elements
|
||||
is_deep = props.show_nested_elements
|
||||
create_list_items(props.cost_item_products, cost_item, is_deep)
|
||||
elif related_object_type == "PROCESS":
|
||||
props.cost_item_processes.clear()
|
||||
is_deep = bpy.context.scene.BIMCostProperties.show_nested_tasks
|
||||
is_deep = props.show_nested_tasks
|
||||
create_list_items(props.cost_item_processes, cost_item, is_deep)
|
||||
elif related_object_type == "RESOURCE":
|
||||
props.cost_item_resources.clear()
|
||||
is_deep = bpy.context.scene.BIMCostProperties.show_nested_resources
|
||||
is_deep = props.show_nested_resources
|
||||
create_list_items(props.cost_item_resources, cost_item, is_deep)
|
||||
|
||||
@classmethod
|
||||
@@ -321,33 +352,35 @@ class Cost(bonsai.core.tool.Cost):
|
||||
|
||||
@classmethod
|
||||
def enable_editing_cost_item_quantities(cls, cost_item: ifcopenshell.entity_instance) -> None:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
props = cls.get_cost_props()
|
||||
props.active_cost_item_id = cost_item.id()
|
||||
props.cost_item_editing_type = "QUANTITIES"
|
||||
|
||||
@classmethod
|
||||
def enable_editing_cost_item_quantity(cls, physical_quantity: ifcopenshell.entity_instance) -> None:
|
||||
bpy.context.scene.BIMCostProperties.active_cost_item_quantity_id = physical_quantity.id()
|
||||
props = cls.get_cost_props()
|
||||
props.active_cost_item_quantity_id = physical_quantity.id()
|
||||
|
||||
@classmethod
|
||||
def load_cost_item_quantity_attributes(cls, physical_quantity: ifcopenshell.entity_instance) -> None:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
props = cls.get_cost_props()
|
||||
props.quantity_attributes.clear()
|
||||
bonsai.bim.helper.import_attributes2(physical_quantity, props.quantity_attributes)
|
||||
|
||||
@classmethod
|
||||
def enable_editing_cost_item_values(cls, cost_item: ifcopenshell.entity_instance) -> None:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
props = cls.get_cost_props()
|
||||
props.active_cost_item_id = cost_item.id()
|
||||
props.cost_item_editing_type = "VALUES"
|
||||
|
||||
@classmethod
|
||||
def disable_editing_cost_item_quantity(cls) -> None:
|
||||
bpy.context.scene.BIMCostProperties.active_cost_item_quantity_id = 0
|
||||
props = cls.get_cost_props()
|
||||
props.active_cost_item_quantity_id = 0
|
||||
|
||||
@classmethod
|
||||
def get_cost_item_quantity_attributes(cls) -> dict[str, Any]:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
props = cls.get_cost_props()
|
||||
return bonsai.bim.helper.export_attributes(props.quantity_attributes)
|
||||
|
||||
@classmethod
|
||||
@@ -356,7 +389,8 @@ class Cost(bonsai.core.tool.Cost):
|
||||
) -> dict[str, Any]:
|
||||
if cost_type == "FIXED":
|
||||
category = None
|
||||
attributes = {"AppliedValue": bpy.context.scene.BIMCostProperties.fixed_cost_value}
|
||||
props = cls.get_cost_props()
|
||||
attributes = {"AppliedValue": props.fixed_cost_value}
|
||||
elif cost_type == "SUM":
|
||||
category = "*"
|
||||
attributes = {"Category": category}
|
||||
@@ -404,7 +438,7 @@ class Cost(bonsai.core.tool.Cost):
|
||||
break
|
||||
return True
|
||||
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
props = cls.get_cost_props()
|
||||
props.cost_value_attributes.clear()
|
||||
is_rates = cls.is_active_schedule_of_rates()
|
||||
callback = lambda name, prop, data: import_attributes(
|
||||
@@ -420,38 +454,37 @@ class Cost(bonsai.core.tool.Cost):
|
||||
|
||||
@classmethod
|
||||
def is_active_schedule_of_rates(cls) -> bool:
|
||||
return (
|
||||
tool.Ifc.get().by_id(bpy.context.scene.BIMCostProperties.active_cost_schedule_id).PredefinedType
|
||||
== "SCHEDULEOFRATES"
|
||||
)
|
||||
props = cls.get_cost_props()
|
||||
return tool.Ifc.get().by_id(props.active_cost_schedule_id).PredefinedType == "SCHEDULEOFRATES"
|
||||
|
||||
@classmethod
|
||||
def enable_editing_cost_item_value(cls, cost_value: ifcopenshell.entity_instance) -> None:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
props = cls.get_cost_props()
|
||||
props.active_cost_value_id = cost_value.id()
|
||||
props.cost_value_editing_type = "ATTRIBUTES"
|
||||
|
||||
@classmethod
|
||||
def disable_editing_cost_item_value(cls) -> None:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
props = cls.get_cost_props()
|
||||
props.active_cost_value_id = 0
|
||||
props.cost_value_editing_type = ""
|
||||
|
||||
@classmethod
|
||||
def load_cost_item_value_formula_attributes(cls, cost_value: ifcopenshell.entity_instance) -> None:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
props = cls.get_cost_props()
|
||||
props.cost_value_attributes.clear()
|
||||
bpy.context.scene.BIMCostProperties.cost_value_formula = ifcopenshell.util.cost.serialise_cost_value(cost_value)
|
||||
props.cost_value_formula = ifcopenshell.util.cost.serialise_cost_value(cost_value)
|
||||
|
||||
@classmethod
|
||||
def enable_editing_cost_item_value_formula(cls, cost_value: ifcopenshell.entity_instance) -> None:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
props = cls.get_cost_props()
|
||||
props.active_cost_value_id = cost_value.id()
|
||||
props.cost_value_editing_type = "FORMULA"
|
||||
|
||||
@classmethod
|
||||
def get_cost_item_value_formula(cls) -> str:
|
||||
return bpy.context.scene.BIMCostProperties.cost_value_formula
|
||||
props = cls.get_cost_props()
|
||||
return props.cost_value_formula
|
||||
|
||||
@classmethod
|
||||
def get_cost_value_attributes(cls) -> dict[str, Any]:
|
||||
@@ -468,15 +501,14 @@ class Cost(bonsai.core.tool.Cost):
|
||||
if prop.name == "UnitBasisUnit":
|
||||
return True
|
||||
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
props = cls.get_cost_props()
|
||||
callback = lambda attributes, prop: export_attributes(attributes, prop)
|
||||
return bonsai.bim.helper.export_attributes(props.cost_value_attributes, callback)
|
||||
|
||||
@classmethod
|
||||
def get_cost_value_unit_component(cls) -> ifcopenshell.entity_instance:
|
||||
return tool.Ifc.get().by_id(
|
||||
int(bpy.context.scene.BIMCostProperties.cost_value_attributes.get("UnitBasisUnit").enum_value)
|
||||
)
|
||||
props = cls.get_cost_props()
|
||||
return tool.Ifc.get().by_id(int(props.cost_value_attributes["UnitBasisUnit"].enum_value))
|
||||
|
||||
@classmethod
|
||||
def get_cost_item_assignments(
|
||||
@@ -491,7 +523,8 @@ class Cost(bonsai.core.tool.Cost):
|
||||
|
||||
@classmethod
|
||||
def show_nested_cost_item_elements(cls) -> bool:
|
||||
return bpy.context.scene.BIMCostProperties.show_nested_elements
|
||||
props = cls.get_cost_props()
|
||||
return props.show_nested_elements
|
||||
|
||||
@classmethod
|
||||
def get_cost_item_products(
|
||||
@@ -543,18 +576,18 @@ class Cost(bonsai.core.tool.Cost):
|
||||
|
||||
@classmethod
|
||||
def add_cost_column(cls, name: str) -> None:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
props = cls.get_cost_props()
|
||||
new = props.columns.add()
|
||||
new.name = name
|
||||
|
||||
@classmethod
|
||||
def remove_cost_column(cls, name: str) -> None:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
props = cls.get_cost_props()
|
||||
props.columns.remove(props.columns.find(name))
|
||||
|
||||
@classmethod
|
||||
def get_active_schedule_of_rates(cls) -> Union[ifcopenshell.entity_instance, None]:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
props = cls.get_cost_props()
|
||||
schedule_id = tool.Blender.get_enum_safe(props, "schedule_of_rates")
|
||||
if schedule_id is None:
|
||||
return
|
||||
@@ -562,7 +595,7 @@ class Cost(bonsai.core.tool.Cost):
|
||||
|
||||
@classmethod
|
||||
def expand_cost_item_rate(cls, cost_item: ifcopenshell.entity_instance) -> None:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
props = cls.get_cost_props()
|
||||
contracted_cost_item_rates = json.loads(props.contracted_cost_item_rates)
|
||||
contracted_cost_item_rates.remove(cost_item)
|
||||
props.contracted_cost_item_rates = json.dumps(contracted_cost_item_rates)
|
||||
@@ -570,7 +603,7 @@ class Cost(bonsai.core.tool.Cost):
|
||||
|
||||
@classmethod
|
||||
def contract_cost_item_rate(cls, cost_item: ifcopenshell.entity_instance) -> None:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
props = cls.get_cost_props()
|
||||
contracted_cost_item_rates = json.loads(props.contracted_cost_item_rates)
|
||||
contracted_cost_item_rates.append(cost_item)
|
||||
props.contracted_cost_item_rates = json.dumps(contracted_cost_item_rates)
|
||||
@@ -605,7 +638,7 @@ class Cost(bonsai.core.tool.Cost):
|
||||
|
||||
@classmethod
|
||||
def load_schedule_of_rates_tree(cls, schedule_of_rates: ifcopenshell.entity_instance) -> None:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
props = cls.get_cost_props()
|
||||
props.is_cost_update_enabled = False
|
||||
props.cost_item_rates.clear()
|
||||
props.columns.clear()
|
||||
@@ -689,13 +722,15 @@ class Cost(bonsai.core.tool.Cost):
|
||||
|
||||
@classmethod
|
||||
def is_cost_schedule_active(cls, cost_schedule: ifcopenshell.entity_instance) -> bool:
|
||||
return True if cost_schedule.id() == bpy.context.scene.BIMCostProperties.active_cost_schedule_id else False
|
||||
props = cls.get_cost_props()
|
||||
return True if cost_schedule.id() == props.active_cost_schedule_id else False
|
||||
|
||||
@classmethod
|
||||
def get_active_cost_schedule(cls) -> Union[ifcopenshell.entity_instance, None]:
|
||||
if not bpy.context.scene.BIMCostProperties.active_cost_schedule_id:
|
||||
props = cls.get_cost_props()
|
||||
if not props.active_cost_schedule_id:
|
||||
return None
|
||||
return tool.Ifc.get().by_id(bpy.context.scene.BIMCostProperties.active_cost_schedule_id)
|
||||
return tool.Ifc.get().by_id(props.active_cost_schedule_id)
|
||||
|
||||
@classmethod
|
||||
def highlight_cost_item(cls, cost_item: ifcopenshell.entity_instance) -> None:
|
||||
@@ -707,13 +742,11 @@ class Cost(bonsai.core.tool.Cost):
|
||||
expand_ancestors(parent_cost)
|
||||
cls.load_cost_schedule_tree()
|
||||
|
||||
cost_props = bpy.context.scene.BIMCostProperties
|
||||
cost_props = cls.get_cost_props()
|
||||
if not cost_item.id() in [item.ifc_definition_id for item in cost_props.cost_items]:
|
||||
expand_ancestors(cost_item)
|
||||
cost_item_index = [item.ifc_definition_id for item in bpy.context.scene.BIMCostProperties.cost_items].index(
|
||||
cost_item.id()
|
||||
) or 0
|
||||
bpy.context.scene.BIMCostProperties.active_cost_item_index = cost_item_index
|
||||
cost_item_index = [item.ifc_definition_id for item in cost_props.cost_items].index(cost_item.id()) or 0
|
||||
cost_props.active_cost_item_index = cost_item_index
|
||||
|
||||
@classmethod
|
||||
def get_cost_items_for_product(cls, product: ifcopenshell.entity_instance) -> list[ifcopenshell.entity_instance]:
|
||||
@@ -732,7 +765,7 @@ class Cost(bonsai.core.tool.Cost):
|
||||
|
||||
@classmethod
|
||||
def load_product_cost_items(cls, product: ifcopenshell.entity_instance) -> None:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
props = cls.get_cost_props()
|
||||
props.is_cost_update_enabled = False
|
||||
props.product_cost_items.clear()
|
||||
cost_items = ifcopenshell.util.cost.get_cost_items_for_product(product)
|
||||
@@ -766,7 +799,7 @@ class Cost(bonsai.core.tool.Cost):
|
||||
def toggle_cost_item_parent_change(cls, cost_item: Optional[ifcopenshell.entity_instance] = None) -> None:
|
||||
if not cost_item:
|
||||
return
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
props = cls.get_cost_props()
|
||||
if props.change_cost_item_parent:
|
||||
props.active_cost_item_id = cost_item.id()
|
||||
props.cost_item_editing_type = "PARENT"
|
||||
@@ -781,8 +814,9 @@ class Cost(bonsai.core.tool.Cost):
|
||||
|
||||
@classmethod
|
||||
def disable_editing_cost_item_parent(cls) -> None:
|
||||
bpy.context.scene.BIMCostProperties.active_cost_item_id = 0
|
||||
bpy.context.scene.BIMCostProperties.change_cost_item_parent = False
|
||||
props = cls.get_cost_props()
|
||||
props.active_cost_item_id = 0
|
||||
props.change_cost_item_parent = False
|
||||
|
||||
@classmethod
|
||||
def load_cost_item_quantities(cls, cost_item: Optional[ifcopenshell.entity_instance] = None) -> None:
|
||||
@@ -822,7 +856,7 @@ class Cost(bonsai.core.tool.Cost):
|
||||
|
||||
@classmethod
|
||||
def get_currency_attributes(cls) -> dict[str, str]:
|
||||
props = bpy.context.scene.BIMCostProperties
|
||||
props = cls.get_cost_props()
|
||||
currency = props.currency
|
||||
if currency == "CUSTOM":
|
||||
currency = props.custom_currency
|
||||
|
||||
@@ -42,17 +42,25 @@ from typing import Optional, Any, Union, Literal, TYPE_CHECKING, Iterable
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import bonsai.bim.prop
|
||||
from bonsai.bim.module.sequence.prop import BIMTaskTreeProperties
|
||||
from bonsai.bim.module.sequence.prop import BIMTaskTreeProperties, BIMWorkScheduleProperties, BIMAnimationProperties
|
||||
|
||||
|
||||
class Sequence(bonsai.core.tool.Sequence):
|
||||
|
||||
RELATED_OBJECT_TYPE = Literal["RESOURCE", "PRODUCT", "CONTROL"]
|
||||
|
||||
@classmethod
|
||||
def get_animation_props(cls) -> BIMAnimationProperties:
|
||||
return bpy.context.scene.BIMAnimationProperties
|
||||
|
||||
@classmethod
|
||||
def get_task_tree_props(cls) -> BIMTaskTreeProperties:
|
||||
return bpy.context.scene.BIMTaskTreeProperties
|
||||
|
||||
@classmethod
|
||||
def get_work_schedule_props(cls) -> BIMWorkScheduleProperties:
|
||||
return bpy.context.scene.BIMWorkScheduleProperties
|
||||
|
||||
@classmethod
|
||||
def get_work_plan_attributes(cls) -> dict[str, Any]:
|
||||
import bonsai.bim.module.sequence.helper as helper
|
||||
@@ -119,7 +127,7 @@ class Sequence(bonsai.core.tool.Sequence):
|
||||
attributes[prop.name] = helper.parse_duration(prop.string_value)
|
||||
return True
|
||||
|
||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||
props = cls.get_work_schedule_props()
|
||||
return bonsai.bim.helper.export_attributes(props.work_schedule_attributes, callback)
|
||||
|
||||
@classmethod
|
||||
@@ -129,23 +137,25 @@ class Sequence(bonsai.core.tool.Sequence):
|
||||
prop.string_value = "" if prop.is_null else data[name]
|
||||
return True
|
||||
|
||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||
props = cls.get_work_schedule_props()
|
||||
props.work_schedule_attributes.clear()
|
||||
bonsai.bim.helper.import_attributes2(work_schedule, props.work_schedule_attributes, callback)
|
||||
|
||||
@classmethod
|
||||
def enable_editing_work_schedule(cls, work_schedule: ifcopenshell.entity_instance) -> None:
|
||||
bpy.context.scene.BIMWorkScheduleProperties.active_work_schedule_id = work_schedule.id()
|
||||
bpy.context.scene.BIMWorkScheduleProperties.editing_type = "WORK_SCHEDULE"
|
||||
props = cls.get_work_schedule_props()
|
||||
props.active_work_schedule_id = work_schedule.id()
|
||||
props.editing_type = "WORK_SCHEDULE"
|
||||
|
||||
@classmethod
|
||||
def disable_editing_work_schedule(cls) -> None:
|
||||
bpy.context.scene.BIMWorkScheduleProperties.active_work_schedule_id = 0
|
||||
props = cls.get_work_schedule_props()
|
||||
props.active_work_schedule_id = 0
|
||||
|
||||
@classmethod
|
||||
def enable_editing_work_schedule_tasks(cls, work_schedule: Union[ifcopenshell.entity_instance, None]) -> None:
|
||||
if work_schedule:
|
||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||
props = cls.get_work_schedule_props()
|
||||
props.active_work_schedule_id = work_schedule.id()
|
||||
props.editing_type = "TASKS"
|
||||
|
||||
@@ -153,7 +163,7 @@ class Sequence(bonsai.core.tool.Sequence):
|
||||
def load_task_tree(cls, work_schedule: ifcopenshell.entity_instance) -> None:
|
||||
props = cls.get_task_tree_props()
|
||||
props.tasks.clear()
|
||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||
props = cls.get_work_schedule_props()
|
||||
cls.contracted_tasks = json.loads(props.contracted_tasks)
|
||||
|
||||
related_objects_ids = cls.get_sorted_tasks_ids(ifcopenshell.util.sequence.get_root_tasks(work_schedule))
|
||||
@@ -162,13 +172,15 @@ class Sequence(bonsai.core.tool.Sequence):
|
||||
|
||||
@classmethod
|
||||
def get_sorted_tasks_ids(cls, tasks: list[ifcopenshell.entity_instance]) -> list[int]:
|
||||
props = cls.get_work_schedule_props()
|
||||
|
||||
def get_sort_key(task):
|
||||
# Sorting only applies to actual tasks, not the WBS
|
||||
# for rel in task.IsNestedBy:
|
||||
# for object in rel.RelatedObjects:
|
||||
# if object.is_a("IfcTask"):
|
||||
# return "0000000000" + (task.Identification or "")
|
||||
column_type, name = bpy.context.scene.BIMWorkScheduleProperties.sort_column.split(".")
|
||||
column_type, name = props.sort_column.split(".")
|
||||
if column_type == "IfcTask":
|
||||
return task.get_info(task)[name] or ""
|
||||
elif column_type == "IfcTaskTime" and task.TaskTime:
|
||||
@@ -179,12 +191,12 @@ class Sequence(bonsai.core.tool.Sequence):
|
||||
s = sort_keys[i]
|
||||
return [int(text) if text.isdigit() else text.lower() for text in _nsre.split(s)]
|
||||
|
||||
if bpy.context.scene.BIMWorkScheduleProperties.sort_column:
|
||||
if props.sort_column:
|
||||
sort_keys = {task.id(): get_sort_key(task) for task in tasks}
|
||||
related_object_ids = sorted(sort_keys, key=natural_sort_key)
|
||||
else:
|
||||
related_object_ids = [task.id() for task in tasks]
|
||||
if bpy.context.scene.BIMWorkScheduleProperties.is_sort_reversed:
|
||||
if props.is_sort_reversed:
|
||||
related_object_ids.reverse()
|
||||
return related_object_ids
|
||||
|
||||
@@ -205,7 +217,7 @@ class Sequence(bonsai.core.tool.Sequence):
|
||||
# TODO: task argument is never used?
|
||||
@classmethod
|
||||
def load_task_properties(cls, task: Optional[ifcopenshell.entity_instance] = None) -> None:
|
||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||
props = cls.get_work_schedule_props()
|
||||
task_props = cls.get_task_tree_props()
|
||||
tasks_with_visual_bar = cls.get_task_bar_list()
|
||||
props.is_task_update_enabled = False
|
||||
@@ -270,24 +282,26 @@ class Sequence(bonsai.core.tool.Sequence):
|
||||
|
||||
@classmethod
|
||||
def get_active_work_schedule(cls) -> Union[ifcopenshell.entity_instance, None]:
|
||||
if not bpy.context.scene.BIMWorkScheduleProperties.active_work_schedule_id:
|
||||
props = cls.get_work_schedule_props()
|
||||
if not props.active_work_schedule_id:
|
||||
return None
|
||||
return tool.Ifc.get().by_id(bpy.context.scene.BIMWorkScheduleProperties.active_work_schedule_id)
|
||||
return tool.Ifc.get().by_id(props.active_work_schedule_id)
|
||||
|
||||
@classmethod
|
||||
def expand_task(cls, task: ifcopenshell.entity_instance) -> None:
|
||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||
props = cls.get_work_schedule_props()
|
||||
contracted_tasks = json.loads(props.contracted_tasks)
|
||||
contracted_tasks.remove(task.id())
|
||||
props.contracted_tasks = json.dumps(contracted_tasks)
|
||||
|
||||
@classmethod
|
||||
def expand_all_tasks(cls) -> None:
|
||||
bpy.context.scene.BIMWorkScheduleProperties.contracted_tasks = json.dumps([])
|
||||
props = cls.get_work_schedule_props()
|
||||
props.contracted_tasks = json.dumps([])
|
||||
|
||||
@classmethod
|
||||
def contract_all_tasks(cls) -> None:
|
||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||
props = cls.get_work_schedule_props()
|
||||
tprops = cls.get_task_tree_props()
|
||||
contracted_tasks = json.loads(props.contracted_tasks)
|
||||
for task_item in tprops.tasks:
|
||||
@@ -297,23 +311,24 @@ class Sequence(bonsai.core.tool.Sequence):
|
||||
|
||||
@classmethod
|
||||
def contract_task(cls, task: ifcopenshell.entity_instance) -> None:
|
||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||
props = cls.get_work_schedule_props()
|
||||
contracted_tasks = json.loads(props.contracted_tasks)
|
||||
contracted_tasks.append(task.id())
|
||||
props.contracted_tasks = json.dumps(contracted_tasks)
|
||||
|
||||
@classmethod
|
||||
def disable_work_schedule(cls) -> None:
|
||||
bpy.context.scene.BIMWorkScheduleProperties.active_work_schedule_id = 0
|
||||
props = cls.get_work_schedule_props()
|
||||
props.active_work_schedule_id = 0
|
||||
|
||||
@classmethod
|
||||
def disable_selecting_deleted_task(cls) -> None:
|
||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||
props = cls.get_work_schedule_props()
|
||||
if props.active_task_id not in [
|
||||
task.ifc_definition_id for task in cls.get_task_tree_props().tasks
|
||||
]: # Task was deleted
|
||||
bpy.context.scene.BIMWorkScheduleProperties.active_task_id = 0
|
||||
bpy.context.scene.BIMWorkScheduleProperties.active_task_time_id = 0
|
||||
props.active_task_id = 0
|
||||
props.active_task_time_id = 0
|
||||
|
||||
@classmethod
|
||||
def get_checked_tasks(cls) -> list[ifcopenshell.entity_instance]:
|
||||
@@ -323,11 +338,13 @@ class Sequence(bonsai.core.tool.Sequence):
|
||||
|
||||
@classmethod
|
||||
def get_task_attribute_value(cls, attribute_name: str) -> Any:
|
||||
return bpy.context.scene.BIMWorkScheduleProperties.task_attributes.get(attribute_name).get_value()
|
||||
props = cls.get_work_schedule_props()
|
||||
return props.task_attributes.get(attribute_name).get_value()
|
||||
|
||||
@classmethod
|
||||
def get_active_task(cls) -> ifcopenshell.entity_instance:
|
||||
return tool.Ifc.get().by_id(bpy.context.scene.BIMWorkScheduleProperties.active_task_id)
|
||||
props = cls.get_work_schedule_props()
|
||||
return tool.Ifc.get().by_id(props.active_task_id)
|
||||
|
||||
@classmethod
|
||||
def get_active_work_time(cls) -> ifcopenshell.entity_instance:
|
||||
@@ -339,31 +356,34 @@ class Sequence(bonsai.core.tool.Sequence):
|
||||
|
||||
@classmethod
|
||||
def load_task_attributes(cls, task: ifcopenshell.entity_instance) -> None:
|
||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||
props = cls.get_work_schedule_props()
|
||||
props.task_attributes.clear()
|
||||
bonsai.bim.helper.import_attributes2(task, props.task_attributes)
|
||||
|
||||
@classmethod
|
||||
def enable_editing_task_attributes(cls, task: ifcopenshell.entity_instance) -> None:
|
||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||
props = cls.get_work_schedule_props()
|
||||
props.active_task_id = task.id()
|
||||
props.editing_task_type = "ATTRIBUTES"
|
||||
|
||||
@classmethod
|
||||
def get_task_attributes(cls) -> dict[str, Any]:
|
||||
return bonsai.bim.helper.export_attributes(bpy.context.scene.BIMWorkScheduleProperties.task_attributes)
|
||||
props = cls.get_work_schedule_props()
|
||||
return bonsai.bim.helper.export_attributes(props.task_attributes)
|
||||
|
||||
@classmethod
|
||||
def load_task_time_attributes(cls, task_time: ifcopenshell.entity_instance) -> None:
|
||||
import bonsai.bim.module.sequence.helper as helper
|
||||
|
||||
props = cls.get_work_schedule_props()
|
||||
|
||||
def callback(
|
||||
name: str, prop: Union[bonsai.bim.prop.Attribute, None], data: dict[str, Any]
|
||||
) -> Union[bool, None]:
|
||||
if prop and prop.data_type == "string":
|
||||
# TODO: Check actual attribute type instead of providing attribute names.
|
||||
if name in ("ScheduleDuration", "ActualDuration", "FreeFloat", "TotalFloat"):
|
||||
duration_props = bpy.context.scene.BIMWorkScheduleProperties.durations_attributes.add()
|
||||
duration_props = props.durations_attributes.add()
|
||||
duration_props.name = name
|
||||
if prop.is_null:
|
||||
for key in duration_props.keys():
|
||||
@@ -378,28 +398,30 @@ class Sequence(bonsai.core.tool.Sequence):
|
||||
prop.string_value = "" if prop.is_null else data[name].isoformat()
|
||||
return True
|
||||
|
||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||
props.task_time_attributes.clear()
|
||||
props.durations_attributes.clear()
|
||||
bonsai.bim.helper.import_attributes2(task_time, props.task_time_attributes, callback)
|
||||
|
||||
@classmethod
|
||||
def enable_editing_task_time(cls, task: ifcopenshell.entity_instance) -> None:
|
||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||
props = cls.get_work_schedule_props()
|
||||
props.active_task_id = task.id()
|
||||
props.active_task_time_id = task.TaskTime.id()
|
||||
props.editing_task_type = "TASKTIME"
|
||||
|
||||
@classmethod
|
||||
def disable_editing_task(cls) -> None:
|
||||
bpy.context.scene.BIMWorkScheduleProperties.active_task_id = 0
|
||||
bpy.context.scene.BIMWorkScheduleProperties.active_task_time_id = 0
|
||||
bpy.context.scene.BIMWorkScheduleProperties.editing_task_type = ""
|
||||
props = cls.get_work_schedule_props()
|
||||
props.active_task_id = 0
|
||||
props.active_task_time_id = 0
|
||||
props.editing_task_type = ""
|
||||
|
||||
@classmethod
|
||||
def get_task_time_attributes(cls) -> dict[str, Any]:
|
||||
import bonsai.bim.module.sequence.helper as helper
|
||||
|
||||
props = cls.get_work_schedule_props()
|
||||
|
||||
def callback(attributes, prop):
|
||||
if "Start" in prop.name or "Finish" in prop.name or prop.name == "StatusTime":
|
||||
if prop.is_null:
|
||||
@@ -408,7 +430,6 @@ class Sequence(bonsai.core.tool.Sequence):
|
||||
attributes[prop.name] = helper.parse_datetime(prop.string_value)
|
||||
return True
|
||||
elif prop.name in ["ScheduleDuration", "ActualDuration", "FreeFloat", "TotalFloat"]:
|
||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||
if prop.is_null:
|
||||
attributes[prop.name] = None
|
||||
for value in props.durations_attributes.values():
|
||||
@@ -424,13 +445,12 @@ class Sequence(bonsai.core.tool.Sequence):
|
||||
value = 0
|
||||
return True
|
||||
|
||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||
return bonsai.bim.helper.export_attributes(props.task_time_attributes, callback)
|
||||
|
||||
@classmethod
|
||||
def load_task_resources(cls, task: ifcopenshell.entity_instance) -> None:
|
||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||
rprops = bpy.context.scene.BIMResourceProperties
|
||||
props = cls.get_work_schedule_props()
|
||||
rprops = cls.get_resource_props()
|
||||
props.task_resources.clear()
|
||||
rprops.is_resource_update_enabled = False
|
||||
for resource in cls.get_task_resources(task) or []:
|
||||
@@ -442,12 +462,14 @@ class Sequence(bonsai.core.tool.Sequence):
|
||||
|
||||
@classmethod
|
||||
def get_task_inputs(cls, task: ifcopenshell.entity_instance) -> list[ifcopenshell.entity_instance]:
|
||||
is_deep = bpy.context.scene.BIMWorkScheduleProperties.show_nested_inputs
|
||||
props = cls.get_work_schedule_props()
|
||||
is_deep = props.show_nested_inputs
|
||||
return ifcopenshell.util.sequence.get_task_inputs(task, is_deep)
|
||||
|
||||
@classmethod
|
||||
def get_task_outputs(cls, task: ifcopenshell.entity_instance) -> list[ifcopenshell.entity_instance]:
|
||||
is_deep = bpy.context.scene.BIMWorkScheduleProperties.show_nested_outputs
|
||||
props = cls.get_work_schedule_props()
|
||||
is_deep = props.show_nested_outputs
|
||||
return ifcopenshell.util.sequence.get_task_outputs(task, is_deep)
|
||||
|
||||
@classmethod
|
||||
@@ -468,12 +490,13 @@ class Sequence(bonsai.core.tool.Sequence):
|
||||
) -> Union[list[ifcopenshell.entity_instance], None]:
|
||||
if not task:
|
||||
return
|
||||
is_deep = bpy.context.scene.BIMWorkScheduleProperties.show_nested_resources
|
||||
props = cls.get_work_schedule_props()
|
||||
is_deep = props.show_nested_resources
|
||||
return ifcopenshell.util.sequence.get_task_resources(task, is_deep)
|
||||
|
||||
@classmethod
|
||||
def load_task_inputs(cls, inputs: list[ifcopenshell.entity_instance]) -> None:
|
||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||
props = cls.get_work_schedule_props()
|
||||
props.task_inputs.clear()
|
||||
for input in inputs:
|
||||
new = props.task_inputs.add()
|
||||
@@ -482,7 +505,7 @@ class Sequence(bonsai.core.tool.Sequence):
|
||||
|
||||
@classmethod
|
||||
def load_task_outputs(cls, outputs: list[ifcopenshell.entity_instance]) -> None:
|
||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||
props = cls.get_work_schedule_props()
|
||||
props.task_outputs.clear()
|
||||
if outputs:
|
||||
for output in outputs:
|
||||
@@ -493,10 +516,9 @@ class Sequence(bonsai.core.tool.Sequence):
|
||||
@classmethod
|
||||
def get_highlighted_task(cls) -> Union[ifcopenshell.entity_instance, None]:
|
||||
tasks = cls.get_task_tree_props().tasks
|
||||
if len(tasks) and len(tasks) > bpy.context.scene.BIMWorkScheduleProperties.active_task_index:
|
||||
return tool.Ifc.get().by_id(
|
||||
tasks[bpy.context.scene.BIMWorkScheduleProperties.active_task_index].ifc_definition_id
|
||||
)
|
||||
props = cls.get_work_schedule_props()
|
||||
if len(tasks) and len(tasks) > props.active_task_index:
|
||||
return tool.Ifc.get().by_id(tasks[props.active_task_index].ifc_definition_id)
|
||||
|
||||
@classmethod
|
||||
def get_direct_nested_tasks(cls, task: ifcopenshell.entity_instance) -> list[ifcopenshell.entity_instance]:
|
||||
@@ -648,37 +670,40 @@ class Sequence(bonsai.core.tool.Sequence):
|
||||
|
||||
@classmethod
|
||||
def enable_editing_task_calendar(cls, task: ifcopenshell.entity_instance) -> None:
|
||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||
props = cls.get_work_schedule_props()
|
||||
props.active_task_id = task.id()
|
||||
props.editing_task_type = "CALENDAR"
|
||||
|
||||
@classmethod
|
||||
def enable_editing_task_sequence(cls) -> None:
|
||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||
props = cls.get_work_schedule_props()
|
||||
props.editing_task_type = "SEQUENCE"
|
||||
|
||||
@classmethod
|
||||
def disable_editing_task_time(cls) -> None:
|
||||
bpy.context.scene.BIMWorkScheduleProperties.active_task_id = 0
|
||||
bpy.context.scene.BIMWorkScheduleProperties.active_task_time_id = 0
|
||||
props = cls.get_work_schedule_props()
|
||||
props.active_task_id = 0
|
||||
props.active_task_time_id = 0
|
||||
|
||||
@classmethod
|
||||
def load_rel_sequence_attributes(cls, rel_sequence: ifcopenshell.entity_instance) -> None:
|
||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||
props = cls.get_work_schedule_props()
|
||||
props.sequence_attributes.clear()
|
||||
bonsai.bim.helper.import_attributes2(rel_sequence, props.sequence_attributes)
|
||||
|
||||
@classmethod
|
||||
def enable_editing_rel_sequence_attributes(cls, rel_sequence: ifcopenshell.entity_instance) -> None:
|
||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||
props = cls.get_work_schedule_props()
|
||||
props.active_sequence_id = rel_sequence.id()
|
||||
props.editing_sequence_type = "ATTRIBUTES"
|
||||
|
||||
@classmethod
|
||||
def load_lag_time_attributes(cls, lag_time: ifcopenshell.entity_instance) -> None:
|
||||
props = cls.get_work_schedule_props()
|
||||
|
||||
def callback(name, prop, data):
|
||||
if name == "LagValue":
|
||||
prop = bpy.context.scene.BIMWorkScheduleProperties.lag_time_attributes.add()
|
||||
prop = props.lag_time_attributes.add()
|
||||
prop.name = name
|
||||
prop.is_null = data[name] is None
|
||||
prop.is_optional = False
|
||||
@@ -688,27 +713,29 @@ class Sequence(bonsai.core.tool.Sequence):
|
||||
)
|
||||
return True
|
||||
|
||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||
props.lag_time_attributes.clear()
|
||||
bonsai.bim.helper.import_attributes2(lag_time, props.lag_time_attributes, callback)
|
||||
|
||||
@classmethod
|
||||
def enable_editing_sequence_lag_time(cls, rel_sequence: ifcopenshell.entity_instance) -> None:
|
||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||
props = cls.get_work_schedule_props()
|
||||
props.active_sequence_id = rel_sequence.id()
|
||||
props.editing_sequence_type = "LAG_TIME"
|
||||
|
||||
@classmethod
|
||||
def get_rel_sequence_attributes(cls) -> dict[str, Any]:
|
||||
return bonsai.bim.helper.export_attributes(bpy.context.scene.BIMWorkScheduleProperties.sequence_attributes)
|
||||
props = cls.get_work_schedule_props()
|
||||
return bonsai.bim.helper.export_attributes(props.sequence_attributes)
|
||||
|
||||
@classmethod
|
||||
def disable_editing_rel_sequence(cls) -> None:
|
||||
bpy.context.scene.BIMWorkScheduleProperties.active_sequence_id = 0
|
||||
props = cls.get_work_schedule_props()
|
||||
props.active_sequence_id = 0
|
||||
|
||||
@classmethod
|
||||
def get_lag_time_attributes(cls) -> dict[str, Any]:
|
||||
return bonsai.bim.helper.export_attributes(bpy.context.scene.BIMWorkScheduleProperties.lag_time_attributes)
|
||||
props = cls.get_work_schedule_props()
|
||||
return bonsai.bim.helper.export_attributes(props.lag_time_attributes)
|
||||
|
||||
@classmethod
|
||||
def select_products(cls, products: Iterable[ifcopenshell.entity_instance]) -> None:
|
||||
@@ -719,14 +746,14 @@ class Sequence(bonsai.core.tool.Sequence):
|
||||
|
||||
@classmethod
|
||||
def add_task_column(cls, column_type: str, name: str, data_type: str) -> None:
|
||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||
props = cls.get_work_schedule_props()
|
||||
new = props.columns.add()
|
||||
new.name = f"{column_type}.{name}"
|
||||
new.data_type = data_type
|
||||
|
||||
@classmethod
|
||||
def setup_default_task_columns(cls) -> None:
|
||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||
props = cls.get_work_schedule_props()
|
||||
props.columns.clear()
|
||||
default_columns = ["ScheduleStart", "ScheduleFinish", "ScheduleDuration"]
|
||||
for item in default_columns:
|
||||
@@ -736,14 +763,14 @@ class Sequence(bonsai.core.tool.Sequence):
|
||||
|
||||
@classmethod
|
||||
def remove_task_column(cls, name: str) -> None:
|
||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||
props = cls.get_work_schedule_props()
|
||||
props.columns.remove(props.columns.find(name))
|
||||
if props.sort_column == name:
|
||||
props.sort_column = ""
|
||||
|
||||
@classmethod
|
||||
def set_task_sort_column(cls, column: str) -> None:
|
||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||
props = cls.get_work_schedule_props()
|
||||
props.sort_column = column
|
||||
|
||||
@classmethod
|
||||
@@ -772,12 +799,13 @@ class Sequence(bonsai.core.tool.Sequence):
|
||||
|
||||
@classmethod
|
||||
def is_work_schedule_active(cls, work_schedule):
|
||||
return (
|
||||
True if work_schedule.id() == bpy.context.scene.BIMWorkScheduleProperties.active_work_schedule_id else False
|
||||
)
|
||||
props = cls.get_work_schedule_props()
|
||||
return True if work_schedule.id() == props.active_work_schedule_id else False
|
||||
|
||||
@classmethod
|
||||
def go_to_task(cls, task):
|
||||
props = cls.get_work_schedule_props()
|
||||
|
||||
def get_ancestor_ids(task):
|
||||
ids = []
|
||||
for rel in task.Nests or []:
|
||||
@@ -785,11 +813,11 @@ class Sequence(bonsai.core.tool.Sequence):
|
||||
ids.extend(get_ancestor_ids(rel.RelatingObject))
|
||||
return ids
|
||||
|
||||
contracted_tasks = json.loads(bpy.context.scene.BIMWorkScheduleProperties.contracted_tasks)
|
||||
contracted_tasks = json.loads(props.contracted_tasks)
|
||||
for ancestor_id in get_ancestor_ids(task):
|
||||
if ancestor_id in contracted_tasks:
|
||||
contracted_tasks.remove(ancestor_id)
|
||||
bpy.context.scene.BIMWorkScheduleProperties.contracted_tasks = json.dumps(contracted_tasks)
|
||||
props.contracted_tasks = json.dumps(contracted_tasks)
|
||||
|
||||
work_schedule = cls.get_active_work_schedule()
|
||||
cls.load_task_tree(work_schedule)
|
||||
@@ -797,7 +825,7 @@ class Sequence(bonsai.core.tool.Sequence):
|
||||
|
||||
task_props = cls.get_task_tree_props()
|
||||
expanded_tasks = [item.ifc_definition_id for item in task_props.tasks]
|
||||
bpy.context.scene.BIMWorkScheduleProperties.active_task_index = expanded_tasks.index(task.id()) or 0
|
||||
props.active_task_index = expanded_tasks.index(task.id()) or 0
|
||||
|
||||
# TODO: proper typing
|
||||
@classmethod
|
||||
@@ -808,7 +836,7 @@ class Sequence(bonsai.core.tool.Sequence):
|
||||
def update_visualisation_date(cls, start_date, finish_date):
|
||||
if not (start_date and finish_date):
|
||||
return
|
||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||
props = cls.get_work_schedule_props()
|
||||
props.visualisation_start = ifcopenshell.util.date.canonicalise_time(start_date)
|
||||
props.visualisation_finish = ifcopenshell.util.date.canonicalise_time(finish_date)
|
||||
|
||||
@@ -849,7 +877,7 @@ class Sequence(bonsai.core.tool.Sequence):
|
||||
}
|
||||
|
||||
def create_task_bar_data(tasks, vertical_increment, collection):
|
||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||
props = cls.get_work_schedule_props()
|
||||
settings = {
|
||||
"viz_start": (
|
||||
parser.parse(props.visualisation_start, dayfirst=True, fuzzy=True)
|
||||
@@ -874,7 +902,8 @@ class Sequence(bonsai.core.tool.Sequence):
|
||||
position_shift = task_data["start_frame"] * size_to_duration_ratio
|
||||
bar_size = (task_data["finish_frame"] - task_data["start_frame"]) * size_to_duration_ratio
|
||||
|
||||
color_progress = bpy.context.scene.BIMAnimationProperties.color_progress
|
||||
anim_props = cls.get_animation_props()
|
||||
color_progress = anim_props.color_progress
|
||||
bar = add_bar(
|
||||
material=material_progress,
|
||||
vertical_increment=vertical_increment,
|
||||
@@ -887,7 +916,7 @@ class Sequence(bonsai.core.tool.Sequence):
|
||||
name=task_data["name"] + "/Progress Bar",
|
||||
)
|
||||
|
||||
color_full = bpy.context.scene.BIMAnimationProperties.color_full
|
||||
color_full = anim_props.color_full
|
||||
bar2 = add_bar(
|
||||
material=material_full,
|
||||
vertical_increment=vertical_increment,
|
||||
@@ -1082,7 +1111,7 @@ class Sequence(bonsai.core.tool.Sequence):
|
||||
"Color": (0.2, 0.2, 0.2),
|
||||
},
|
||||
}
|
||||
props = bpy.context.scene.BIMAnimationProperties
|
||||
props = cls.get_animation_props()
|
||||
props.task_output_colors.clear()
|
||||
props.task_input_colors.clear()
|
||||
for group, data in groups.items():
|
||||
@@ -1102,14 +1131,14 @@ class Sequence(bonsai.core.tool.Sequence):
|
||||
|
||||
@classmethod
|
||||
def get_start_date(cls) -> Union[datetime, None]:
|
||||
start = parser.parse(bpy.context.scene.BIMWorkScheduleProperties.visualisation_start, dayfirst=True, fuzzy=True)
|
||||
props = cls.get_work_schedule_props()
|
||||
start = parser.parse(props.visualisation_start, dayfirst=True, fuzzy=True)
|
||||
return start or None
|
||||
|
||||
@classmethod
|
||||
def get_finish_date(cls) -> Union[datetime, None]:
|
||||
finish = parser.parse(
|
||||
bpy.context.scene.BIMWorkScheduleProperties.visualisation_finish, dayfirst=True, fuzzy=True
|
||||
)
|
||||
props = cls.get_work_schedule_props()
|
||||
finish = parser.parse(props.visualisation_finish, dayfirst=True, fuzzy=True)
|
||||
return finish or None
|
||||
|
||||
@classmethod
|
||||
@@ -1241,7 +1270,7 @@ class Sequence(bonsai.core.tool.Sequence):
|
||||
def calculate_using_frames(start, finish, animation_frames, real_duration):
|
||||
return ((finish - start) / real_duration) * animation_frames
|
||||
|
||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||
props = cls.get_work_schedule_props()
|
||||
if not (props.visualisation_start and props.visualisation_finish):
|
||||
return
|
||||
|
||||
@@ -1346,7 +1375,7 @@ class Sequence(bonsai.core.tool.Sequence):
|
||||
|
||||
@classmethod
|
||||
def animate_input(cls, obj, start_frame, product_frame, animation_type):
|
||||
props = bpy.context.scene.BIMAnimationProperties
|
||||
props = cls.get_animation_props()
|
||||
color = props.task_input_colors[product_frame["type"]].color
|
||||
if product_frame["type"] in ["LOGISTIC", "MOVE", "DISPOSAL"]:
|
||||
cls.animate_destruction(obj, start_frame, product_frame, color, animation_type)
|
||||
@@ -1355,7 +1384,7 @@ class Sequence(bonsai.core.tool.Sequence):
|
||||
|
||||
@classmethod
|
||||
def animate_output(cls, obj, start_frame, product_frame, animation_type):
|
||||
props = bpy.context.scene.BIMAnimationProperties
|
||||
props = cls.get_animation_props()
|
||||
color = props.task_output_colors[product_frame["type"]].color
|
||||
if product_frame["type"] in ["CONSTRUCTION", "INSTALLATION", "NOTDEFINED"]:
|
||||
cls.animate_creation(obj, start_frame, product_frame, color)
|
||||
@@ -1466,8 +1495,9 @@ class Sequence(bonsai.core.tool.Sequence):
|
||||
|
||||
obj.data.BIMDateTextProperties.start_frame = settings["start_frame"]
|
||||
obj.data.BIMDateTextProperties.total_frames = int(settings["total_frames"])
|
||||
obj.data.BIMDateTextProperties.start = bpy.context.scene.BIMWorkScheduleProperties.visualisation_start
|
||||
obj.data.BIMDateTextProperties.finish = bpy.context.scene.BIMWorkScheduleProperties.visualisation_finish
|
||||
props = cls.get_work_schedule_props()
|
||||
obj.data.BIMDateTextProperties.start = props.visualisation_start
|
||||
obj.data.BIMDateTextProperties.finish = props.visualisation_finish
|
||||
append_handler(animate_text_handler)
|
||||
|
||||
@classmethod
|
||||
@@ -1573,7 +1603,8 @@ class Sequence(bonsai.core.tool.Sequence):
|
||||
|
||||
@classmethod
|
||||
def is_filter_by_active_schedule(cls) -> bool:
|
||||
return bpy.context.scene.BIMWorkScheduleProperties.filter_by_active_schedule
|
||||
props = cls.get_work_schedule_props()
|
||||
return props.filter_by_active_schedule
|
||||
|
||||
@classmethod
|
||||
def get_tasks_for_product(
|
||||
@@ -1585,7 +1616,7 @@ class Sequence(bonsai.core.tool.Sequence):
|
||||
def load_product_related_tasks(
|
||||
cls, task_inputs: list[ifcopenshell.entity_instance], task_ouputs: list[ifcopenshell.entity_instance]
|
||||
) -> None:
|
||||
props = bpy.context.scene.BIMWorkScheduleProperties
|
||||
props = cls.get_work_schedule_props()
|
||||
props.product_input_tasks.clear()
|
||||
props.product_output_tasks.clear()
|
||||
for task in task_inputs or []:
|
||||
@@ -1617,18 +1648,21 @@ class Sequence(bonsai.core.tool.Sequence):
|
||||
|
||||
@classmethod
|
||||
def is_sorting_enabled(cls):
|
||||
return bpy.context.scene.BIMWorkScheduleProperties.sort_column
|
||||
props = cls.get_work_schedule_props()
|
||||
return props.sort_column
|
||||
|
||||
@classmethod
|
||||
def is_sort_reversed(cls):
|
||||
return bpy.context.scene.BIMWorkScheduleProperties.is_sort_reversed
|
||||
props = cls.get_work_schedule_props()
|
||||
return props.is_sort_reversed
|
||||
|
||||
@classmethod
|
||||
def get_user_predefined_type(cls):
|
||||
predefined_type = bpy.context.scene.BIMWorkScheduleProperties.work_schedule_predefined_types
|
||||
props = cls.get_work_schedule_props()
|
||||
predefined_type = props.work_schedule_predefined_types
|
||||
object_type = None
|
||||
if predefined_type == "USERDEFINED":
|
||||
object_type = bpy.context.scene.BIMWorkScheduleProperties.object_type
|
||||
object_type = props.object_type
|
||||
return predefined_type, object_type
|
||||
|
||||
@classmethod
|
||||
@@ -1649,7 +1683,7 @@ class Sequence(bonsai.core.tool.Sequence):
|
||||
|
||||
@classmethod
|
||||
def save_animation_color_scheme(cls, name: str) -> ifcopenshell.entity_instance:
|
||||
props = bpy.context.scene.BIMAnimationProperties
|
||||
props = cls.get_animation_props()
|
||||
colour_scheme = {
|
||||
"Inputs": {cs.name: cs.color[0:3] for cs in props.task_input_colors},
|
||||
"Outputs": {cs.name: cs.color[0:3] for cs in props.task_output_colors},
|
||||
@@ -1674,7 +1708,7 @@ class Sequence(bonsai.core.tool.Sequence):
|
||||
if data.get("type") == "BBIM_AnimationColorScheme":
|
||||
inputs_color_scheme = data.get("colourscheme").get("Inputs")
|
||||
outputs_color_scheme = data.get("colourscheme").get("Outputs")
|
||||
props = bpy.context.scene.BIMAnimationProperties
|
||||
props = cls.get_animation_props()
|
||||
props.task_input_colors.clear()
|
||||
props.task_output_colors.clear()
|
||||
for value, colour in inputs_color_scheme.items():
|
||||
@@ -1711,26 +1745,30 @@ class Sequence(bonsai.core.tool.Sequence):
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def get_task_bar_list(cls):
|
||||
return json.loads(bpy.context.scene.BIMWorkScheduleProperties.task_bars)
|
||||
def get_task_bar_list(cls) -> list[int]:
|
||||
props = cls.get_work_schedule_props()
|
||||
return json.loads(props.task_bars)
|
||||
|
||||
@classmethod
|
||||
def add_task_bar(cls, task_id):
|
||||
def add_task_bar(cls, task_id: int) -> None:
|
||||
task_bars = cls.get_task_bar_list()
|
||||
task_bars.append(task_id)
|
||||
bpy.context.scene.BIMWorkScheduleProperties.task_bars = json.dumps(task_bars)
|
||||
props = cls.get_work_schedule_props()
|
||||
props.task_bars = json.dumps(task_bars)
|
||||
|
||||
@classmethod
|
||||
def remove_task_bar(cls, task_id):
|
||||
def remove_task_bar(cls, task_id: int) -> None:
|
||||
task_bars = cls.get_task_bar_list()
|
||||
if task_id in task_bars:
|
||||
task_bars.remove(task_id)
|
||||
bpy.context.scene.BIMWorkScheduleProperties.task_bars = json.dumps(task_bars)
|
||||
props = cls.get_work_schedule_props()
|
||||
props.task_bars = json.dumps(task_bars)
|
||||
|
||||
@classmethod
|
||||
def get_animation_color_scheme(cls):
|
||||
if len(bpy.context.scene.BIMAnimationProperties.saved_color_schemes) > 0:
|
||||
return tool.Ifc.get().by_id(int(bpy.context.scene.BIMAnimationProperties.saved_color_schemes))
|
||||
props = cls.get_animation_props()
|
||||
if len(props.saved_color_schemes) > 0:
|
||||
return tool.Ifc.get().by_id(int(props.saved_color_schemes))
|
||||
|
||||
@classmethod
|
||||
def parse_isodate_datetime(cls, datetime_str: str, include_time: bool) -> datetime:
|
||||
|
||||
@@ -456,7 +456,15 @@ class IfcCsv:
|
||||
self.import_pd(ifc_file, df, attributes, null, empty, bool_true, bool_false)
|
||||
|
||||
def import_pd(
|
||||
self, ifc_file, df, attributes=None, null="-", empty="", bool_true="YES", bool_false="NO", concat=", "
|
||||
self,
|
||||
ifc_file: ifcopenshell.file,
|
||||
df: "pd.DataFrame",
|
||||
attributes: Optional[list[Union[str, None]]] = None,
|
||||
null: str = "-",
|
||||
empty: str = "",
|
||||
bool_true: str = "YES",
|
||||
bool_false: str = "NO",
|
||||
concat: str = ", ",
|
||||
) -> None:
|
||||
headers = df.columns.tolist()
|
||||
|
||||
|
||||
@@ -65,28 +65,22 @@ def assign_material(
|
||||
|
||||
:param products: The list of IfcProducts to assign the material or material set
|
||||
to.
|
||||
:type products: list[ifcopenshell.entity_instance]
|
||||
:param type: Choose from "IfcMaterial", "IfcMaterialConstituentSet",
|
||||
"IfcMaterialLayerSet", "IfcMaterialLayerSetUsage",
|
||||
"IfcMaterialProfileSet", "IfcMaterialProfileSetUsage", or
|
||||
"IfcMaterialList". Note that "Set Usages" may only be assigned to
|
||||
occurrences, not types. Defaults to "IfcMaterial".
|
||||
:type type: str
|
||||
:param material: The IfcMaterial or material set you are assigning here.
|
||||
If type is Usage then no need to provide `material`, it will be deduced
|
||||
from the element type automatically.
|
||||
If IfcMaterial is provided as material and type is not IfcMaterial,
|
||||
provided material will be ignored except for IfcMaterialList
|
||||
where it will be used as part of the list.
|
||||
:type material: ifcopenshell.entity_instance, optional
|
||||
:return: IfcRelAssociatesMaterial entity
|
||||
or a list of IfcRelAssociatesMaterial entities
|
||||
(possible if `type` is Usage
|
||||
and `products` require different Usages)
|
||||
or `None` if `products` was empty list.
|
||||
:rtype: Union[
|
||||
ifcopenshell.entity_instance,
|
||||
list[ifcopenshell.entity_instance], None]
|
||||
|
||||
Example:
|
||||
|
||||
|
||||
@@ -62,6 +62,8 @@ def remove_material_set(file: ifcopenshell.file, material: ifcopenshell.entity_i
|
||||
set_items = material.MaterialConstituents or []
|
||||
elif material.is_a("IfcMaterialList"):
|
||||
set_items = []
|
||||
else:
|
||||
raise ValueError(f"Unknown material set type: {material.is_a()}")
|
||||
for set_item in set_items:
|
||||
file.remove(set_item)
|
||||
file.remove(material)
|
||||
|
||||
@@ -32,9 +32,7 @@ def unassign_material(file: ifcopenshell.file, products: list[ifcopenshell.entit
|
||||
If the product does not have a material, nothing happens.
|
||||
|
||||
:param products: The list IfcProducts that may or may not have a material
|
||||
:type product: list[ifcopenshell.entity_instance]
|
||||
:return: None
|
||||
:rtype: None
|
||||
|
||||
Example:
|
||||
|
||||
@@ -54,18 +52,16 @@ def unassign_material(file: ifcopenshell.file, products: list[ifcopenshell.entit
|
||||
"""
|
||||
usecase = Usecase()
|
||||
usecase.file = file
|
||||
usecase.settings = {"products": products}
|
||||
return usecase.execute()
|
||||
return usecase.execute(products)
|
||||
|
||||
|
||||
class Usecase:
|
||||
file: ifcopenshell.file
|
||||
settings: dict[str, Any]
|
||||
|
||||
def execute(self):
|
||||
self.products = set(self.settings["products"])
|
||||
if not self.products:
|
||||
def execute(self, products: list[ifcopenshell.entity_instance]) -> None:
|
||||
if not products:
|
||||
return
|
||||
self.products = set(products)
|
||||
|
||||
self.remove_material_usages_from_types()
|
||||
self.unassign_materials()
|
||||
|
||||
Reference in New Issue
Block a user