You can now bulk copy task attributes to other tasks in the task tree

This commit is contained in:
Dion Moult
2021-06-15 17:29:04 +10:00
parent fa1984e89e
commit 36a18ea0f9
5 changed files with 54 additions and 57 deletions
+10 -1
View File
@@ -8,21 +8,30 @@ from mathutils import Vector
from blenderbim.bim.ifc import IfcStore from blenderbim.bim.ifc import IfcStore
def draw_attributes(props, layout): def draw_attributes(props, layout, copy_operator=None):
for attribute in props: for attribute in props:
row = layout.row(align=True) row = layout.row(align=True)
value = None
if attribute.data_type == "string": if attribute.data_type == "string":
row.prop(attribute, "string_value", text=attribute.name) row.prop(attribute, "string_value", text=attribute.name)
value = attribute.string_value
elif attribute.data_type == "boolean": elif attribute.data_type == "boolean":
row.prop(attribute, "bool_value", text=attribute.name) row.prop(attribute, "bool_value", text=attribute.name)
value = attribute.bool_value
elif attribute.data_type == "integer": elif attribute.data_type == "integer":
row.prop(attribute, "int_value", text=attribute.name) row.prop(attribute, "int_value", text=attribute.name)
value = attribute.int_value
elif attribute.data_type == "float": elif attribute.data_type == "float":
row.prop(attribute, "float_value", text=attribute.name) row.prop(attribute, "float_value", text=attribute.name)
value = attribute.float_value
elif attribute.data_type == "enum": elif attribute.data_type == "enum":
row.prop(attribute, "enum_value", text=attribute.name) row.prop(attribute, "enum_value", text=attribute.name)
value = attribute.enum_value
if attribute.is_optional: if attribute.is_optional:
row.prop(attribute, "is_null", icon="RADIOBUT_OFF" if attribute.is_null else "RADIOBUT_ON", text="") row.prop(attribute, "is_null", icon="RADIOBUT_OFF" if attribute.is_null else "RADIOBUT_ON", text="")
if copy_operator:
op = row.operator(f"{copy_operator}", text="", icon="COPYDOWN")
op.data = json.dumps({"name": attribute.name, "value": value, "is_null": attribute.is_null})
def import_attributes(ifc_class, props, data, callback=None): def import_attributes(ifc_class, props, data, callback=None):
@@ -47,6 +47,7 @@ classes = (
operator.DisableEditingTask, operator.DisableEditingTask,
operator.DisableEditingTaskTime, operator.DisableEditingTaskTime,
operator.EditTask, operator.EditTask,
operator.CopyTaskAttribute,
operator.AssignPredecessor, operator.AssignPredecessor,
operator.AssignSuccessor, operator.AssignSuccessor,
operator.UnassignPredecessor, operator.UnassignPredecessor,
@@ -533,6 +533,30 @@ class EditTask(bpy.types.Operator):
return {"FINISHED"} return {"FINISHED"}
class CopyTaskAttribute(bpy.types.Operator):
bl_idname = "bim.copy_task_attribute"
bl_label = "Copy Task Attribute"
data: bpy.props.StringProperty()
def execute(self, context):
data = json.loads(self.data)
self.file = IfcStore.get_file()
props = context.scene.BIMTaskTreeProperties
for task in props.tasks:
if task.is_selected:
ifcopenshell.api.run(
"sequence.edit_task",
self.file,
**{
"task": self.file.by_id(task.ifc_definition_id),
"attributes": {data["name"]: None if data["is_null"] else data["value"]},
},
)
Data.load(IfcStore.get_file())
bpy.ops.bim.load_task_properties()
return {"FINISHED"}
class AssignPredecessor(bpy.types.Operator): class AssignPredecessor(bpy.types.Operator):
bl_idname = "bim.assign_predecessor" bl_idname = "bim.assign_predecessor"
bl_label = "Assign Predecessor" bl_label = "Assign Predecessor"
@@ -1409,7 +1433,7 @@ class VisualiseWorkScheduleDateRange(bpy.types.Operator):
obj.color = (1.0, 1.0, 1.0, 1) obj.color = (1.0, 1.0, 1.0, 1)
obj.keyframe_insert(data_path="hide_viewport", frame=self.start_frame) obj.keyframe_insert(data_path="hide_viewport", frame=self.start_frame)
obj.keyframe_insert(data_path="color", frame=self.start_frame) obj.keyframe_insert(data_path="color", frame=self.start_frame)
obj.keyframe_insert(data_path="color", frame=product_frames["STARTED"]-1) obj.keyframe_insert(data_path="color", frame=product_frames["STARTED"] - 1)
obj.color = (1.0, 0.0, 0.0, 1) obj.color = (1.0, 0.0, 0.0, 1)
obj.keyframe_insert(data_path="color", frame=product_frames["STARTED"]) obj.keyframe_insert(data_path="color", frame=product_frames["STARTED"])
obj.hide_viewport = True obj.hide_viewport = True
@@ -1420,7 +1444,7 @@ class VisualiseWorkScheduleDateRange(bpy.types.Operator):
def animate_operation(self, obj, product_frames): def animate_operation(self, obj, product_frames):
obj.color = (1.0, 1.0, 1.0, 1) obj.color = (1.0, 1.0, 1.0, 1)
obj.keyframe_insert(data_path="color", frame=self.start_frame) obj.keyframe_insert(data_path="color", frame=self.start_frame)
obj.keyframe_insert(data_path="color", frame=product_frames["STARTED"]-1) obj.keyframe_insert(data_path="color", frame=product_frames["STARTED"] - 1)
obj.color = (0.0, 0.0, 1.0, 1) obj.color = (0.0, 0.0, 1.0, 1)
obj.keyframe_insert(data_path="color", frame=product_frames["STARTED"]) obj.keyframe_insert(data_path="color", frame=product_frames["STARTED"])
obj.color = (1.0, 1.0, 1.0, 1) obj.color = (1.0, 1.0, 1.0, 1)
@@ -176,6 +176,7 @@ class Task(PropertyGroup):
identification: StringProperty(name="Identification", update=updateTaskIdentification) identification: StringProperty(name="Identification", update=updateTaskIdentification)
ifc_definition_id: IntProperty(name="IFC Definition ID") ifc_definition_id: IntProperty(name="IFC Definition ID")
has_children: BoolProperty(name="Has Children") has_children: BoolProperty(name="Has Children")
is_selected: BoolProperty(name="Is Selected")
is_expanded: BoolProperty(name="Is Expanded") is_expanded: BoolProperty(name="Is Expanded")
level_index: IntProperty(name="Level Index") level_index: IntProperty(name="Level Index")
duration: StringProperty(name="Duration", update=updateTaskduration) duration: StringProperty(name="Duration", update=updateTaskduration)
@@ -1,4 +1,5 @@
import isodate import isodate
import blenderbim.bim.helper
from bpy.types import Panel, UIList from bpy.types import Panel, UIList
from blenderbim.bim.ifc import IfcStore from blenderbim.bim.ifc import IfcStore
from ifcopenshell.api.sequence.data import Data from ifcopenshell.api.sequence.data import Data
@@ -229,36 +230,10 @@ class BIM_PT_work_schedules(Panel):
op.sequence = sequence["id"] op.sequence = sequence["id"]
def draw_editable_sequence_attributes_ui(self): def draw_editable_sequence_attributes_ui(self):
for attribute in self.props.sequence_attributes: blenderbim.bim.helper.draw_attributes(self.props.sequence_attributes, self.layout)
row = self.layout.row(align=True)
if attribute.data_type == "string":
row.prop(attribute, "string_value", text=attribute.name)
elif attribute.data_type == "boolean":
row.prop(attribute, "bool_value", text=attribute.name)
elif attribute.data_type == "integer":
row.prop(attribute, "int_value", text=attribute.name)
elif attribute.data_type == "float":
row.prop(attribute, "float_value", text=attribute.name)
elif attribute.data_type == "enum":
row.prop(attribute, "enum_value", text=attribute.name)
if attribute.is_optional:
row.prop(attribute, "is_null", icon="RADIOBUT_OFF" if attribute.is_null else "RADIOBUT_ON", text="")
def draw_editable_sequence_time_lag_ui(self): def draw_editable_sequence_time_lag_ui(self):
for attribute in self.props.time_lag_attributes: blenderbim.bim.helper.draw_attributes(self.props.time_lag_attributes, self.layout)
row = self.layout.row(align=True)
if attribute.data_type == "string":
row.prop(attribute, "string_value", text=attribute.name)
elif attribute.data_type == "boolean":
row.prop(attribute, "bool_value", text=attribute.name)
elif attribute.data_type == "integer":
row.prop(attribute, "int_value", text=attribute.name)
elif attribute.data_type == "float":
row.prop(attribute, "float_value", text=attribute.name)
elif attribute.data_type == "enum":
row.prop(attribute, "enum_value", text=attribute.name)
if attribute.is_optional:
row.prop(attribute, "is_null", icon="RADIOBUT_OFF" if attribute.is_null else "RADIOBUT_ON", text="")
def draw_editable_task_calendar_ui(self): def draw_editable_task_calendar_ui(self):
task = Data.tasks[self.props.active_task_id] task = Data.tasks[self.props.active_task_id]
@@ -277,34 +252,12 @@ class BIM_PT_work_schedules(Panel):
op.task = self.props.active_task_id op.task = self.props.active_task_id
def draw_editable_task_attributes_ui(self): def draw_editable_task_attributes_ui(self):
for attribute in self.props.task_attributes: blenderbim.bim.helper.draw_attributes(
row = self.layout.row(align=True) self.props.task_attributes, self.layout, copy_operator="bim.copy_task_attribute"
if attribute.data_type == "string": )
row.prop(attribute, "string_value", text=attribute.name)
elif attribute.data_type == "boolean":
row.prop(attribute, "bool_value", text=attribute.name)
elif attribute.data_type == "integer":
row.prop(attribute, "int_value", text=attribute.name)
elif attribute.data_type == "enum":
row.prop(attribute, "enum_value", text=attribute.name)
if attribute.is_optional:
row.prop(attribute, "is_null", icon="RADIOBUT_OFF" if attribute.is_null else "RADIOBUT_ON", text="")
def draw_editable_task_time_attributes_ui(self): def draw_editable_task_time_attributes_ui(self):
for attribute in self.props.task_time_attributes: blenderbim.bim.helper.draw_attributes(self.props.task_time_attributes, self.layout)
row = self.layout.row(align=True)
if attribute.data_type == "string":
row.prop(attribute, "string_value", text=attribute.name)
elif attribute.data_type == "boolean":
row.prop(attribute, "bool_value", text=attribute.name)
elif attribute.data_type == "integer":
row.prop(attribute, "int_value", text=attribute.name)
elif attribute.data_type == "float":
row.prop(attribute, "float_value", text=attribute.name)
elif attribute.data_type == "enum":
row.prop(attribute, "enum_value", text=attribute.name)
if attribute.is_optional:
row.prop(attribute, "is_null", icon="RADIOBUT_OFF" if attribute.is_null else "RADIOBUT_ON", text="")
class BIM_UL_tasks(UIList): class BIM_UL_tasks(UIList):
@@ -360,6 +313,15 @@ class BIM_UL_tasks(UIList):
op = row.operator("bim.assign_product", text="", icon="KEYFRAME", emboss=False) op = row.operator("bim.assign_product", text="", icon="KEYFRAME", emboss=False)
op.task = item.ifc_definition_id op.task = item.ifc_definition_id
if props.active_task_id and props.editing_task_type == "ATTRIBUTES":
row.prop(
item,
"is_selected",
icon="CHECKBOX_HLT" if item.is_selected else "CHECKBOX_DEHLT",
text="",
emboss=False,
)
if props.active_task_id == item.ifc_definition_id: if props.active_task_id == item.ifc_definition_id:
if props.editing_task_type == "TASKTIME": if props.editing_task_type == "TASKTIME":
row.operator("bim.edit_task_time", text="", icon="CHECKMARK") row.operator("bim.edit_task_time", text="", icon="CHECKMARK")