mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 01:41:57 +00:00
New Status panel for managing statuses in the costing / scheduling tab.
This commit is contained in:
@@ -146,7 +146,10 @@ classes = [
|
||||
# Structural analysis
|
||||
ui.BIM_PT_tab_structural,
|
||||
# Construction scheduling
|
||||
ui.BIM_PT_tab_4D5D,
|
||||
ui.BIM_PT_tab_status,
|
||||
ui.BIM_PT_tab_resources,
|
||||
ui.BIM_PT_tab_cost,
|
||||
ui.BIM_PT_tab_sequence,
|
||||
# Facility management
|
||||
ui.BIM_PT_tab_handover,
|
||||
ui.BIM_PT_tab_operations,
|
||||
|
||||
@@ -29,7 +29,8 @@ class BIM_PT_cost_schedules(Panel):
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "scene"
|
||||
bl_parent_id = "BIM_PT_tab_4D5D"
|
||||
bl_parent_id = "BIM_PT_tab_cost"
|
||||
bl_options = {"HIDE_HEADER"}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
|
||||
@@ -38,24 +38,24 @@ class CsvAttribute(PropertyGroup):
|
||||
sort: EnumProperty(items=[("NONE", "None", ""), ("ASC", "Ascending", ""), ("DESC", "Descending", "")])
|
||||
group: EnumProperty(
|
||||
items=[
|
||||
("NONE", "None", ""),
|
||||
("GROUP", "Group", "All rows where this value is identical will be merged."),
|
||||
("CONCAT", "Concatenation", "Concatenate values if values vary within a group."),
|
||||
("VARIES", "Varies", "Show a custom value if values vary within a group."),
|
||||
("SUM", "Sum", "Sums the total value of rows in a group."),
|
||||
("AVERAGE", "Average", "Averages the total value of rows in a group."),
|
||||
("MIN", "Min", "Gets the minimum value of rows in a group."),
|
||||
("MAX", "Max", "Gets the maximum value of rows in a group."),
|
||||
("NONE", "None", "Don't group any rows"),
|
||||
("GROUP", "Group", "All rows where this value is identical will be merged"),
|
||||
("CONCAT", "Concatenation", "Concatenate values if values vary within a group"),
|
||||
("VARIES", "Varies", "Show a custom value if values vary within a group"),
|
||||
("SUM", "Sum", "Sums the total value of rows in a group"),
|
||||
("AVERAGE", "Average", "Averages the total value of rows in a group"),
|
||||
("MIN", "Min", "Gets the minimum value of rows in a group"),
|
||||
("MAX", "Max", "Gets the maximum value of rows in a group"),
|
||||
]
|
||||
)
|
||||
varies_value: StringProperty(default="Varies", name="Varies Value")
|
||||
summary: EnumProperty(
|
||||
items=[
|
||||
("NONE", "None", ""),
|
||||
("SUM", "Sum", "Sums the total value of all rows."),
|
||||
("AVERAGE", "Average", "Averages the total value of all rows."),
|
||||
("MIN", "Min", "Gets the minimum value of all rows."),
|
||||
("MAX", "Max", "Gets the maximum value of all rows."),
|
||||
("NONE", "None", "Don't provide a summary row"),
|
||||
("SUM", "Sum", "Sums the total value of all rows"),
|
||||
("AVERAGE", "Average", "Averages the total value of all rows"),
|
||||
("MIN", "Min", "Gets the minimum value of all rows"),
|
||||
("MAX", "Max", "Gets the maximum value of all rows"),
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@@ -28,7 +28,8 @@ class BIM_PT_resources(Panel):
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "scene"
|
||||
bl_parent_id = "BIM_PT_tab_4D5D"
|
||||
bl_parent_id = "BIM_PT_tab_resources"
|
||||
bl_options = {"HIDE_HEADER"}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
|
||||
@@ -118,12 +118,18 @@ classes = (
|
||||
operator.UnassignWorkSchedule,
|
||||
operator.VisualiseWorkScheduleDate,
|
||||
operator.VisualiseWorkScheduleDateRange,
|
||||
operator.EnableStatusFilters,
|
||||
operator.DisableStatusFilters,
|
||||
operator.ActivateStatusFilters,
|
||||
operator.SelectStatusFilter,
|
||||
prop.WorkPlan,
|
||||
prop.BIMWorkPlanProperties,
|
||||
prop.Task,
|
||||
prop.TaskResource,
|
||||
prop.TaskProduct,
|
||||
prop.ISODuration,
|
||||
prop.IFCStatus,
|
||||
prop.BIMStatusProperties,
|
||||
prop.BIMWorkScheduleProperties,
|
||||
prop.BIMTaskTreeProperties,
|
||||
prop.BIMTaskTypeColor,
|
||||
@@ -133,6 +139,7 @@ classes = (
|
||||
prop.BIMWorkCalendarProperties,
|
||||
prop.DatePickerProperties,
|
||||
prop.BIMDateTextProperties,
|
||||
ui.BIM_PT_status,
|
||||
ui.BIM_PT_work_plans,
|
||||
ui.BIM_PT_work_schedules,
|
||||
ui.BIM_PT_work_calendars,
|
||||
@@ -165,6 +172,7 @@ def menu_func_import(self, context):
|
||||
|
||||
|
||||
def register():
|
||||
bpy.types.Scene.BIMStatusProperties = bpy.props.PointerProperty(type=prop.BIMStatusProperties)
|
||||
bpy.types.Scene.BIMWorkPlanProperties = bpy.props.PointerProperty(type=prop.BIMWorkPlanProperties)
|
||||
bpy.types.Scene.BIMWorkScheduleProperties = bpy.props.PointerProperty(type=prop.BIMWorkScheduleProperties)
|
||||
bpy.types.Scene.BIMTaskTreeProperties = bpy.props.PointerProperty(type=prop.BIMTaskTreeProperties)
|
||||
@@ -177,6 +185,7 @@ def register():
|
||||
|
||||
|
||||
def unregister():
|
||||
del bpy.types.Scene.BIMStatusProperties
|
||||
del bpy.types.Scene.BIMWorkPlanProperties
|
||||
del bpy.types.Scene.BIMWorkScheduleProperties
|
||||
del bpy.types.Scene.BIMTaskTreeProperties
|
||||
|
||||
@@ -27,11 +27,98 @@ import webbrowser
|
||||
import blenderbim.core.sequence as core
|
||||
import blenderbim.tool as tool
|
||||
import blenderbim.bim.module.sequence.helper as helper
|
||||
import ifcopenshell.util.sequence
|
||||
import ifcopenshell.util.selector
|
||||
from datetime import datetime
|
||||
from dateutil import parser, relativedelta
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
from bpy_extras.io_utils import ImportHelper
|
||||
import ifcopenshell.util.sequence
|
||||
|
||||
|
||||
class EnableStatusFilters(bpy.types.Operator):
|
||||
bl_idname = "bim.enable_status_filters"
|
||||
bl_label = "Enable Status Filters"
|
||||
|
||||
def execute(self, context):
|
||||
props = context.scene.BIMStatusProperties
|
||||
props.is_enabled = True
|
||||
|
||||
props.statuses.clear()
|
||||
|
||||
statuses = set()
|
||||
for element in tool.Ifc.get().by_type("IfcPropertyEnumeratedValue"):
|
||||
if element.Name == "Status":
|
||||
pset = element.PartOfPset[0]
|
||||
if pset.Name.startswith("Pset_") and pset.Name.endswith("Common"):
|
||||
statuses.update(element.EnumerationValues)
|
||||
elif pset.Name == "EPset_Status": # Our secret sauce
|
||||
statuses.update(element.EnumerationValues)
|
||||
elif element.Name == "UserDefinedStatus":
|
||||
statuses.add(element.NominalValue)
|
||||
|
||||
statuses = ["No Status"] + sorted([s.wrappedValue for s in statuses])
|
||||
|
||||
for status in statuses:
|
||||
new = props.statuses.add()
|
||||
new.name = status
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class DisableStatusFilters(bpy.types.Operator):
|
||||
bl_idname = "bim.disable_status_filters"
|
||||
bl_label = "Disable Status Filters"
|
||||
|
||||
def execute(self, context):
|
||||
props = context.scene.BIMStatusProperties
|
||||
props.is_enabled = False
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class ActivateStatusFilters(bpy.types.Operator):
|
||||
bl_idname = "bim.activate_status_filters"
|
||||
bl_label = "Activate Status Filters"
|
||||
|
||||
def execute(self, context):
|
||||
props = context.scene.BIMStatusProperties
|
||||
|
||||
query = []
|
||||
visible_statuses = {s.name for s in props.statuses if s.is_visible}
|
||||
for name in visible_statuses:
|
||||
if name == "No Status":
|
||||
q = f"IfcProduct, /Pset_.*Common/.Status=NULL, EPset_Status.Status=NULL"
|
||||
else:
|
||||
q = f"IfcProduct, /Pset_.*Common/.Status={name} + IfcProduct, EPset_Status.Status={name}"
|
||||
query.append(q)
|
||||
query = " + ".join(query)
|
||||
|
||||
if not query:
|
||||
return {"FINISHED"}
|
||||
|
||||
visible_elements = ifcopenshell.util.selector.filter_elements(tool.Ifc.get(), query)
|
||||
|
||||
for obj in bpy.context.view_layer.objects:
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
if not element or not element.is_a("IfcProduct"):
|
||||
continue
|
||||
obj.hide_set(element not in visible_elements)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class SelectStatusFilter(bpy.types.Operator):
|
||||
bl_idname = "bim.select_status_filter"
|
||||
bl_label = "Select Status Filter"
|
||||
name: bpy.props.StringProperty()
|
||||
|
||||
def execute(self, context):
|
||||
props = context.scene.BIMStatusProperties
|
||||
query = f"IfcProduct, /Pset_.*Common/.Status={self.name} + IfcProduct, EPset_Status.Status={self.name}"
|
||||
if self.name == "No Status":
|
||||
query = f"IfcProduct, /Pset_.*Common/.Status=NULL, EPset_Status.Status=NULL"
|
||||
for element in ifcopenshell.util.selector.filter_elements(tool.Ifc.get(), query):
|
||||
obj = tool.Ifc.get_object(element)
|
||||
if obj:
|
||||
obj.select_set(True)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class AddWorkPlan(bpy.types.Operator, tool.Ifc.Operator):
|
||||
|
||||
@@ -381,6 +381,16 @@ class ISODuration(PropertyGroup):
|
||||
seconds: IntProperty(name="Seconds", default=0)
|
||||
|
||||
|
||||
class IFCStatus(PropertyGroup):
|
||||
name: StringProperty(name="Name")
|
||||
is_visible: BoolProperty(name="Is Visible", default=True)
|
||||
|
||||
|
||||
class BIMStatusProperties(PropertyGroup):
|
||||
is_enabled: BoolProperty(name="Is Enabled")
|
||||
statuses: CollectionProperty(name="Statuses", type=IFCStatus)
|
||||
|
||||
|
||||
class BIMWorkScheduleProperties(PropertyGroup):
|
||||
work_schedule_predefined_types: EnumProperty(
|
||||
items=get_schedule_predefined_types, name="Predefined Type", default=None
|
||||
|
||||
@@ -30,6 +30,38 @@ from blenderbim.bim.module.sequence.data import (
|
||||
)
|
||||
|
||||
|
||||
class BIM_PT_status(Panel):
|
||||
bl_label = "Status"
|
||||
bl_idname = "BIM_PT_status"
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "scene"
|
||||
bl_parent_id = "BIM_PT_tab_status"
|
||||
bl_options = {"HIDE_HEADER"}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return IfcStore.get_file()
|
||||
|
||||
def draw(self, context):
|
||||
self.props = context.scene.BIMStatusProperties
|
||||
|
||||
if not self.props.is_enabled:
|
||||
row = self.layout.row()
|
||||
row.operator("bim.enable_status_filters", icon="GREASEPENCIL")
|
||||
return
|
||||
|
||||
row = self.layout.row(align=True)
|
||||
row.operator("bim.activate_status_filters", icon="TIME")
|
||||
row.operator("bim.disable_status_filters", icon="CANCEL", text="")
|
||||
|
||||
for status in self.props.statuses:
|
||||
row = self.layout.row()
|
||||
row.label(text=status.name)
|
||||
row.prop(status, "is_visible", text="", emboss=False, icon="HIDE_OFF" if status.is_visible else "HIDE_ON")
|
||||
row.operator("bim.select_status_filter", icon="RESTRICT_SELECT_OFF", text="").name = status.name
|
||||
|
||||
|
||||
class BIM_PT_work_plans(Panel):
|
||||
bl_label = "Work Plans"
|
||||
bl_idname = "BIM_PT_work_plans"
|
||||
@@ -37,7 +69,7 @@ class BIM_PT_work_plans(Panel):
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "scene"
|
||||
bl_parent_id = "BIM_PT_tab_4D5D"
|
||||
bl_parent_id = "BIM_PT_tab_sequence"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
@@ -107,7 +139,7 @@ class BIM_PT_work_schedules(Panel):
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "scene"
|
||||
bl_parent_id = "BIM_PT_tab_4D5D"
|
||||
bl_parent_id = "BIM_PT_tab_sequence"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
@@ -550,7 +582,7 @@ class BIM_PT_animation_Color_Scheme(Panel):
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "scene"
|
||||
bl_parent_id = "BIM_PT_tab_4D5D"
|
||||
bl_parent_id = "BIM_PT_tab_sequence"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
@@ -888,7 +920,7 @@ class BIM_PT_work_calendars(Panel):
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "scene"
|
||||
bl_parent_id = "BIM_PT_tab_4D5D"
|
||||
bl_parent_id = "BIM_PT_tab_sequence"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
|
||||
@@ -408,12 +408,53 @@ class BIM_PT_geometry(Panel):
|
||||
pass
|
||||
|
||||
|
||||
class BIM_PT_tab_4D5D(Panel):
|
||||
bl_label = "Costing and Scheduling"
|
||||
class BIM_PT_tab_status(Panel):
|
||||
bl_label = "Status"
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "scene"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return tool.Blender.is_tab(context, "SCHEDULING") and tool.Ifc.get()
|
||||
|
||||
def draw(self, context):
|
||||
pass
|
||||
|
||||
|
||||
class BIM_PT_tab_resources(Panel):
|
||||
bl_label = "Resources"
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "scene"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return tool.Blender.is_tab(context, "SCHEDULING") and tool.Ifc.get()
|
||||
|
||||
def draw(self, context):
|
||||
pass
|
||||
|
||||
|
||||
class BIM_PT_tab_cost(Panel):
|
||||
bl_label = "Cost"
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "scene"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return tool.Blender.is_tab(context, "SCHEDULING") and tool.Ifc.get()
|
||||
|
||||
def draw(self, context):
|
||||
pass
|
||||
|
||||
|
||||
class BIM_PT_tab_sequence(Panel):
|
||||
bl_label = "Construction Scheduling"
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "scene"
|
||||
bl_options = {"HIDE_HEADER"}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
|
||||
Reference in New Issue
Block a user