Implement task quantity sets for parametric quantification

This commit is contained in:
Dion Moult
2021-08-11 16:50:38 +10:00
parent a8fbdb4c92
commit 0c27caf522
4 changed files with 124 additions and 55 deletions
@@ -11,17 +11,22 @@ classes = (
operator.AddQto,
operator.GuessQuantity,
prop.PsetProperties,
prop.MaterialPsetProperties,
prop.TaskPsetProperties,
ui.BIM_PT_object_psets,
ui.BIM_PT_object_qtos,
ui.BIM_PT_material_psets,
ui.BIM_PT_task_qtos,
)
def register():
bpy.types.Object.PsetProperties = bpy.props.PointerProperty(type=prop.PsetProperties)
bpy.types.Material.PsetProperties = bpy.props.PointerProperty(type=prop.PsetProperties)
bpy.types.Material.PsetProperties = bpy.props.PointerProperty(type=prop.MaterialPsetProperties)
bpy.types.Scene.TaskPsetProperties = bpy.props.PointerProperty(type=prop.TaskPsetProperties)
def unregister():
del bpy.types.Object.PsetProperties
del bpy.types.Material.PsetProperties
del bpy.types.Scene.TaskPsetProperties
@@ -11,6 +11,30 @@ from ifcopenshell.api.cost.data import Data as CostData
from blenderbim.bim.module.pset.qto_calculator import QtoCalculator
def get_pset_props(context, obj, obj_type):
if obj_type == "Object":
obj = bpy.data.objects.get(obj)
return obj.PsetProperties
elif obj_type == "Material":
obj = bpy.data.materials.get(obj)
return obj.PsetProperties
elif obj_type == "Task":
return context.scene.TaskPsetProperties
def get_pset_obj_ifc_definition_id(context, obj, obj_type):
if obj_type == "Object":
obj = bpy.data.objects.get(obj)
return obj.BIMObjectProperties.ifc_definition_id
elif obj_type == "Material":
obj = bpy.data.materials.get(obj)
return obj.BIMObjectProperties.ifc_definition_id
elif obj_type == "Task":
return context.scene.BIMTaskTreeProperties.tasks[
context.scene.BIMWorkScheduleProperties.active_task_index
].ifc_definition_id
class TogglePsetExpansion(bpy.types.Operator):
bl_idname = "bim.toggle_pset_expansion"
bl_label = "Toggle Pset Expansion"
@@ -32,11 +56,7 @@ class EnablePsetEditing(bpy.types.Operator):
obj_type: bpy.props.StringProperty()
def execute(self, context):
if self.obj_type == "Object":
obj = bpy.data.objects.get(self.obj)
elif self.obj_type == "Material":
obj = bpy.data.materials.get(self.obj)
self.props = obj.PsetProperties
self.props = get_pset_props(context, self.obj, self.obj_type)
while len(self.props.properties) > 0:
self.props.properties.remove(0)
@@ -138,11 +158,7 @@ class DisablePsetEditing(bpy.types.Operator):
obj_type: bpy.props.StringProperty()
def execute(self, context):
if self.obj_type == "Object":
obj = bpy.data.objects.get(self.obj)
elif self.obj_type == "Material":
obj = bpy.data.materials.get(self.obj)
props = obj.PsetProperties
props = get_pset_props(context, self.obj, self.obj_type)
props.active_pset_id = 0
return {"FINISHED"}
@@ -161,12 +177,8 @@ class EditPset(bpy.types.Operator):
def _execute(self, context):
self.file = IfcStore.get_file()
if self.obj_type == "Object":
obj = bpy.data.objects.get(self.obj)
elif self.obj_type == "Material":
obj = bpy.data.materials.get(self.obj)
oprops = obj.BIMObjectProperties
props = obj.PsetProperties
props = get_pset_props(context, self.obj, self.obj_type)
ifc_definition_id = get_pset_obj_ifc_definition_id(context, self.obj, self.obj_type)
properties = {}
pset_id = self.pset_id or props.active_pset_id
@@ -213,7 +225,7 @@ class EditPset(bpy.types.Operator):
},
)
CostData.purge()
Data.load(IfcStore.get_file(), oprops.ifc_definition_id)
Data.load(IfcStore.get_file(), ifc_definition_id)
bpy.ops.bim.disable_pset_editing(obj=self.obj, obj_type=self.obj_type)
return {"FINISHED"}
@@ -231,20 +243,17 @@ class RemovePset(bpy.types.Operator):
def _execute(self, context):
self.file = IfcStore.get_file()
if self.obj_type == "Object":
obj = bpy.data.objects.get(self.obj)
elif self.obj_type == "Material":
obj = bpy.data.materials.get(self.obj)
props = obj.BIMObjectProperties
props = get_pset_props(context, self.obj, self.obj_type)
ifc_definition_id = get_pset_obj_ifc_definition_id(context, self.obj, self.obj_type)
ifcopenshell.api.run(
"pset.remove_pset",
self.file,
**{
"product": self.file.by_id(props.ifc_definition_id),
"product": self.file.by_id(ifc_definition_id),
"pset": self.file.by_id(self.pset_id),
},
)
Data.load(IfcStore.get_file(), props.ifc_definition_id)
Data.load(IfcStore.get_file(), ifc_definition_id)
return {"FINISHED"}
@@ -254,36 +263,24 @@ class AddPset(bpy.types.Operator):
bl_options = {"REGISTER", "UNDO"}
obj: bpy.props.StringProperty()
obj_type: bpy.props.StringProperty()
pset_name: bpy.props.StringProperty()
def execute(self, context):
return IfcStore.execute_ifc_operator(self, context)
def _execute(self, context):
self.file = IfcStore.get_file()
if self.obj_type == "Object":
obj = bpy.data.objects.get(self.obj)
elif self.obj_type == "Material":
obj = bpy.data.materials.get(self.obj)
oprops = obj.BIMObjectProperties
props = obj.PsetProperties
if self.pset_name:
pset_name = self.pset_name
elif self.obj_type == "Object":
pset_name = props.pset_name
elif self.obj_type == "Material":
pset_name = props.material_pset_name
props = get_pset_props(context, self.obj, self.obj_type)
ifc_definition_id = get_pset_obj_ifc_definition_id(context, self.obj, self.obj_type)
ifcopenshell.api.run(
"pset.add_pset",
self.file,
**{
"product": self.file.by_id(oprops.ifc_definition_id),
"name": pset_name,
"product": self.file.by_id(ifc_definition_id),
"name": props.pset_name,
},
)
Data.load(IfcStore.get_file(), oprops.ifc_definition_id)
Data.load(IfcStore.get_file(), ifc_definition_id)
return {"FINISHED"}
@@ -291,24 +288,25 @@ class AddQto(bpy.types.Operator):
bl_idname = "bim.add_qto"
bl_label = "Add Qto"
bl_options = {"REGISTER", "UNDO"}
obj: bpy.props.StringProperty()
obj_type: bpy.props.StringProperty()
def execute(self, context):
return IfcStore.execute_ifc_operator(self, context)
def _execute(self, context):
self.file = IfcStore.get_file()
obj = context.active_object
oprops = obj.BIMObjectProperties
props = obj.PsetProperties
props = get_pset_props(context, self.obj, self.obj_type)
ifc_definition_id = get_pset_obj_ifc_definition_id(context, self.obj, self.obj_type)
ifcopenshell.api.run(
"pset.add_qto",
self.file,
**{
"product": self.file.by_id(oprops.ifc_definition_id),
"product": self.file.by_id(ifc_definition_id),
"name": props.qto_name,
},
)
Data.load(IfcStore.get_file(), oprops.ifc_definition_id)
Data.load(IfcStore.get_file(), ifc_definition_id)
return {"FINISHED"}
@@ -52,6 +52,15 @@ def getMaterialPsetNames(self, context):
return psetnames[ifc_class]
def getTaskQtoNames(self, context):
global qtonames
ifc_class = "IfcTask"
if ifc_class not in qtonames:
psets = blenderbim.bim.schema.ifc.psetqto.get_applicable(ifc_class, qto_only=True)
qtonames[ifc_class] = [(p.Name, p.Name, "") for p in psets]
return qtonames[ifc_class]
def getQtoNames(self, context):
global qtonames
if "/" in context.active_object.name:
@@ -69,4 +78,17 @@ class PsetProperties(PropertyGroup):
properties: CollectionProperty(name="Properties", type=Attribute)
pset_name: EnumProperty(items=getPsetNames, name="Pset Name")
qto_name: EnumProperty(items=getQtoNames, name="Qto Name")
material_pset_name: EnumProperty(items=getMaterialPsetNames, name="Pset Name")
class MaterialPsetProperties(PropertyGroup):
active_pset_id: IntProperty(name="Active Pset ID")
active_pset_name: StringProperty(name="Pset Name")
properties: CollectionProperty(name="Properties", type=Attribute)
pset_name: EnumProperty(items=getMaterialPsetNames, name="Pset Name")
class TaskPsetProperties(PropertyGroup):
active_pset_id: IntProperty(name="Active Pset ID")
active_pset_name: StringProperty(name="Pset Name")
properties: CollectionProperty(name="Properties", type=Attribute)
qto_name: EnumProperty(items=getTaskQtoNames, name="Qto Name")
@@ -3,6 +3,14 @@ from ifcopenshell.api.pset.data import Data
from blenderbim.bim.ifc import IfcStore
def get_active_pset_obj_name(context, obj_type):
if obj_type == "Object":
return context.active_object.name
elif obj_type == "Material":
return context.active_object.active_material.name
return ""
def draw_psetqto_ui(context, pset_id, pset, props, layout, obj_type):
box = layout.box()
row = box.row(align=True)
@@ -10,29 +18,30 @@ def draw_psetqto_ui(context, pset_id, pset, props, layout, obj_type):
pset["is_expanded"] = True
icon = "TRIA_DOWN" if pset["is_expanded"] else "TRIA_RIGHT"
row.operator("bim.toggle_pset_expansion", icon=icon, text="", emboss=False).pset_id = pset_id
obj_name = get_active_pset_obj_name(context, obj_type)
if not props.active_pset_id:
row.label(text=pset["Name"], icon="COPY_ID")
op = row.operator("bim.enable_pset_editing", icon="GREASEPENCIL", text="")
op.pset_id = pset_id
op.obj = context.active_object.name if obj_type == "Object" else context.active_object.active_material.name
op.obj = obj_name
op.obj_type = obj_type
op = row.operator("bim.remove_pset", icon="X", text="")
op.pset_id = pset_id
op.obj = context.active_object.name if obj_type == "Object" else context.active_object.active_material.name
op.obj = obj_name
op.obj_type = obj_type
elif props.active_pset_id != pset_id:
row.label(text=pset["Name"], icon="COPY_ID")
op = row.operator("bim.remove_pset", icon="X", text="")
op.pset_id = pset_id
op.obj = context.active_object.name if obj_type == "Object" else context.active_object.active_material.name
op.obj = obj_name
op.obj_type = obj_type
elif props.active_pset_id == pset_id:
row.prop(props, "active_pset_name", icon="COPY_ID", text="")
op = row.operator("bim.edit_pset", icon="CHECKMARK", text="")
op.obj = context.active_object.name if obj_type == "Object" else context.active_object.active_material.name
op.obj = obj_name
op.obj_type = obj_type
op = row.operator("bim.disable_pset_editing", icon="CANCEL", text="")
op.obj = context.active_object.name if obj_type == "Object" else context.active_object.active_material.name
op.obj = obj_name
op.obj_type = obj_type
if pset["is_expanded"]:
if props.active_pset_id == pset_id:
@@ -163,7 +172,9 @@ class BIM_PT_object_qtos(Panel):
Data.load(IfcStore.get_file(), oprops.ifc_definition_id)
row = self.layout.row(align=True)
row.prop(props, "qto_name", text="")
row.operator("bim.add_qto", icon="ADD", text="")
op = row.operator("bim.add_qto", icon="ADD", text="")
op.obj = context.active_object.name
op.obj_type = "Object"
qtos = [(qto_id, Data.qtos[qto_id]) for qto_id in Data.products[oprops.ifc_definition_id]["qtos"]]
for qto_id, qto in sorted(qtos, key = lambda v: v[1]["Name"]):
@@ -202,7 +213,7 @@ class BIM_PT_material_psets(Panel):
if oprops.ifc_definition_id not in Data.products:
Data.load(IfcStore.get_file(), oprops.ifc_definition_id)
row = self.layout.row(align=True)
row.prop(props, "material_pset_name", text="")
row.prop(props, "pset_name", text="")
op = row.operator("bim.add_pset", icon="ADD", text="")
op.obj = context.active_object.active_material.name
op.obj_type = "Material"
@@ -210,3 +221,36 @@ class BIM_PT_material_psets(Panel):
psets = [(pset_id, Data.psets[pset_id]) for pset_id in Data.products[oprops.ifc_definition_id]["psets"]]
for pset_id, pset in sorted(psets, key = lambda v: v[1]["Name"]):
draw_psetqto_ui(context, pset_id, pset, props, self.layout, "Material")
class BIM_PT_task_qtos(Panel):
bl_label = "IFC Task Quantity Sets"
bl_idname = "BIM_PT_task_qtos"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "scene"
bl_parent_id = "BIM_PT_work_schedules"
@classmethod
def poll(cls, context):
props = context.scene.BIMWorkScheduleProperties
total_tasks = len(context.scene.BIMTaskTreeProperties.tasks)
if total_tasks > 0 and props.active_task_index < total_tasks:
return True
return False
def draw(self, context):
props = context.scene.TaskPsetProperties
wprops = context.scene.BIMWorkScheduleProperties
tprops = context.scene.BIMTaskTreeProperties
ifc_definition_id = tprops.tasks[wprops.active_task_index].ifc_definition_id
if ifc_definition_id not in Data.products:
Data.load(IfcStore.get_file(), ifc_definition_id)
row = self.layout.row(align=True)
row.prop(props, "qto_name", text="")
op = row.operator("bim.add_qto", icon="ADD", text="")
op.obj_type = "Task"
qtos = [(qto_id, Data.qtos[qto_id]) for qto_id in Data.products[ifc_definition_id]["qtos"]]
for qto_id, qto in sorted(qtos, key = lambda v: v[1]["Name"]):
draw_psetqto_ui(context, qto_id, qto, props, self.layout, "Task")